mirror of
https://github.com/correl/mage.git
synced 2024-11-15 03:00:16 +00:00
Merge branch 'master' of https://github.com/magefree/mage
This commit is contained in:
commit
34e9c2fdfb
118 changed files with 3090 additions and 1075 deletions
|
@ -168,8 +168,13 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (card instanceof StackAbilityView) {
|
if (card instanceof StackAbilityView) {
|
||||||
|
// replace ability by original card
|
||||||
CardView tmp = ((StackAbilityView) card).getSourceCard();
|
CardView tmp = ((StackAbilityView) card).getSourceCard();
|
||||||
tmp.overrideRules(card.getRules());
|
tmp.overrideRules(card.getRules());
|
||||||
|
tmp.setChoosable(card.isChoosable());
|
||||||
|
tmp.setPlayable(card.isPlayable());
|
||||||
|
tmp.setPlayableAmount(card.getPlayableAmount());
|
||||||
|
tmp.setSelected(card.isSelected());
|
||||||
tmp.setIsAbility(true);
|
tmp.setIsAbility(true);
|
||||||
tmp.overrideTargets(card.getTargets());
|
tmp.overrideTargets(card.getTargets());
|
||||||
tmp.overrideId(card.getId());
|
tmp.overrideId(card.getId());
|
||||||
|
|
|
@ -112,8 +112,13 @@ public class StackDialog extends IDialogPanel {
|
||||||
for (CardView card : cards.values()) {
|
for (CardView card : cards.values()) {
|
||||||
|
|
||||||
if (card instanceof StackAbilityView) {
|
if (card instanceof StackAbilityView) {
|
||||||
|
// replace ability by original card
|
||||||
CardView tmp = ((StackAbilityView) card).getSourceCard();
|
CardView tmp = ((StackAbilityView) card).getSourceCard();
|
||||||
tmp.overrideRules(card.getRules());
|
tmp.overrideRules(card.getRules());
|
||||||
|
tmp.setChoosable(card.isChoosable());
|
||||||
|
tmp.setPlayable(card.isPlayable());
|
||||||
|
tmp.setPlayableAmount(card.getPlayableAmount());
|
||||||
|
tmp.setSelected(card.isSelected());
|
||||||
tmp.setIsAbility(true);
|
tmp.setIsAbility(true);
|
||||||
tmp.overrideTargets(card.getTargets());
|
tmp.overrideTargets(card.getTargets());
|
||||||
tmp.overrideId(card.getId());
|
tmp.overrideId(card.getId());
|
||||||
|
|
|
@ -56,6 +56,21 @@
|
||||||
<artifactId>gson</artifactId>
|
<artifactId>gson</artifactId>
|
||||||
<version>2.8.6</version>
|
<version>2.8.6</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.assertj</groupId>
|
||||||
|
<artifactId>assertj-core</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-lang3</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<!-- to get the reference to local repository with com\googlecode\jspf\jspf-core\0.9.1\ -->
|
<!-- to get the reference to local repository with com\googlecode\jspf\jspf-core\0.9.1\ -->
|
||||||
<repositories>
|
<repositories>
|
||||||
|
@ -82,7 +97,10 @@
|
||||||
<encoding>UTF-8</encoding>
|
<encoding>UTF-8</encoding>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
|
|
||||||
<finalName>mage-common</finalName>
|
<finalName>mage-common</finalName>
|
||||||
|
|
41
Mage.Common/src/main/java/mage/utils/FluentBuilder.java
Normal file
41
Mage.Common/src/main/java/mage/utils/FluentBuilder.java
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
package mage.utils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A base class for fluent, immutable, composable builders.
|
||||||
|
*
|
||||||
|
* @see <a href="https://github.com/fburato/functionalutils/blob/master/utils/src/main/java/com/github/fburato/functionalutils/utils/Builder.java">Builder</a>
|
||||||
|
*/
|
||||||
|
public abstract class FluentBuilder<ToBuild, RealBuilder extends FluentBuilder<ToBuild, RealBuilder>> {
|
||||||
|
|
||||||
|
final ArrayList<Consumer<RealBuilder>> buildSequence;
|
||||||
|
private final Supplier<RealBuilder> newReference;
|
||||||
|
|
||||||
|
protected FluentBuilder(Supplier<RealBuilder> newReference) {
|
||||||
|
this.buildSequence = new ArrayList<>();
|
||||||
|
this.newReference = newReference;
|
||||||
|
}
|
||||||
|
|
||||||
|
private RealBuilder copy() {
|
||||||
|
final RealBuilder realBuilder = newReference.get();
|
||||||
|
realBuilder.buildSequence.addAll(buildSequence);
|
||||||
|
return realBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract ToBuild makeValue();
|
||||||
|
|
||||||
|
public RealBuilder with(Consumer<RealBuilder> consumer) {
|
||||||
|
final RealBuilder nextBuilder = this.copy();
|
||||||
|
nextBuilder.buildSequence.add(consumer);
|
||||||
|
return nextBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ToBuild build() {
|
||||||
|
final RealBuilder instance = this.copy();
|
||||||
|
instance.buildSequence.forEach(c -> c.accept(instance));
|
||||||
|
return instance.makeValue();
|
||||||
|
}
|
||||||
|
}
|
|
@ -121,8 +121,17 @@ public class CardView extends SimpleCardView {
|
||||||
|
|
||||||
protected Card originalCard = null;
|
protected Card originalCard = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Non game usage like deck editor
|
||||||
|
*
|
||||||
|
* @param card
|
||||||
|
*/
|
||||||
public CardView(Card card) {
|
public CardView(Card card) {
|
||||||
this(card, null, false);
|
this(card, (Game) null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CardView(Card card, Game game) {
|
||||||
|
this(card, game, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CardView(Card card, SimpleCardView simpleCardView) {
|
public CardView(Card card, SimpleCardView simpleCardView) {
|
||||||
|
@ -450,7 +459,7 @@ public class CardView extends SimpleCardView {
|
||||||
|
|
||||||
Card secondSideCard = card.getSecondCardFace();
|
Card secondSideCard = card.getSecondCardFace();
|
||||||
if (secondSideCard != null) {
|
if (secondSideCard != null) {
|
||||||
this.secondCardFace = new CardView(secondSideCard);
|
this.secondCardFace = new CardView(secondSideCard, game);
|
||||||
this.alternateName = secondCardFace.getName();
|
this.alternateName = secondCardFace.getName();
|
||||||
this.originalName = card.getName();
|
this.originalName = card.getName();
|
||||||
}
|
}
|
||||||
|
@ -464,7 +473,7 @@ public class CardView extends SimpleCardView {
|
||||||
if (card instanceof ModalDoubleFacesCard) {
|
if (card instanceof ModalDoubleFacesCard) {
|
||||||
this.transformable = true; // enable GUI day/night button
|
this.transformable = true; // enable GUI day/night button
|
||||||
ModalDoubleFacesCard mdfCard = (ModalDoubleFacesCard) card;
|
ModalDoubleFacesCard mdfCard = (ModalDoubleFacesCard) card;
|
||||||
this.secondCardFace = new CardView(mdfCard.getRightHalfCard());
|
this.secondCardFace = new CardView(mdfCard.getRightHalfCard(), game);
|
||||||
this.alternateName = mdfCard.getRightHalfCard().getName();
|
this.alternateName = mdfCard.getRightHalfCard().getName();
|
||||||
this.originalName = card.getName();
|
this.originalName = card.getName();
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ import mage.abilities.effects.Effect;
|
||||||
import mage.cards.Card;
|
import mage.cards.Card;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.GameState;
|
|
||||||
import mage.game.command.Emblem;
|
import mage.game.command.Emblem;
|
||||||
import mage.game.command.Plane;
|
import mage.game.command.Plane;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
|
@ -29,7 +28,7 @@ public class CardsView extends LinkedHashMap<UUID, CardView> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uses for card render tests
|
* Non game usage like card render tests
|
||||||
*
|
*
|
||||||
* @param cardViews
|
* @param cardViews
|
||||||
*/
|
*/
|
||||||
|
@ -39,6 +38,11 @@ public class CardsView extends LinkedHashMap<UUID, CardView> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Non game usage like deck editor
|
||||||
|
*
|
||||||
|
* @param cards
|
||||||
|
*/
|
||||||
public CardsView(Collection<? extends Card> cards) {
|
public CardsView(Collection<? extends Card> cards) {
|
||||||
for (Card card : cards) {
|
for (Card card : cards) {
|
||||||
this.put(card.getId(), new CardView(card));
|
this.put(card.getId(), new CardView(card));
|
||||||
|
@ -116,9 +120,9 @@ public class CardsView extends LinkedHashMap<UUID, CardView> {
|
||||||
if (abilityView == null) {
|
if (abilityView == null) {
|
||||||
CardView sourceCardView;
|
CardView sourceCardView;
|
||||||
if (isPermanent) {
|
if (isPermanent) {
|
||||||
sourceCardView = new CardView((Permanent) sourceObject);
|
sourceCardView = new CardView((Permanent) sourceObject, game);
|
||||||
} else if (isCard) {
|
} else if (isCard) {
|
||||||
sourceCardView = new CardView((Card) sourceObject);
|
sourceCardView = new CardView((Card) sourceObject, game);
|
||||||
} else {
|
} else {
|
||||||
sourceCardView = new CardView(sourceObject, game);
|
sourceCardView = new CardView(sourceObject, game);
|
||||||
}
|
}
|
||||||
|
@ -164,14 +168,4 @@ public class CardsView extends LinkedHashMap<UUID, CardView> {
|
||||||
+ abilities.stream().map(a -> a.getClass().getSimpleName() + " - " + a.getRule()).collect(Collectors.joining("\n")));
|
+ abilities.stream().map(a -> a.getClass().getSimpleName() + " - " + a.getRule()).collect(Collectors.joining("\n")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public CardsView(Collection<? extends Ability> abilities, GameState state) {
|
|
||||||
for (Ability ability : abilities) {
|
|
||||||
Card sourceCard = state.getPermanent(ability.getSourceId());
|
|
||||||
if (sourceCard != null) {
|
|
||||||
this.put(ability.getId(), new AbilityView(ability, sourceCard.getName(), new CardView(sourceCard)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,7 +94,7 @@ public class GameView implements Serializable {
|
||||||
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(), new CardView(card, game, false, false, false)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
stack.put(stackObject.getId(), new StackAbilityView(game, (StackAbility) stackObject, "", new CardView(card)));
|
stack.put(stackObject.getId(), new StackAbilityView(game, (StackAbility) stackObject, "", new CardView(card, game)));
|
||||||
}
|
}
|
||||||
if (card.isTransformable()) {
|
if (card.isTransformable()) {
|
||||||
updateLatestCardView(game, card, stackObject.getId());
|
updateLatestCardView(game, card, stackObject.getId());
|
||||||
|
@ -103,7 +103,7 @@ public class GameView implements Serializable {
|
||||||
} else if (object != null) {
|
} else if (object != null) {
|
||||||
if (object instanceof PermanentToken) {
|
if (object instanceof PermanentToken) {
|
||||||
PermanentToken token = (PermanentToken) object;
|
PermanentToken token = (PermanentToken) object;
|
||||||
stack.put(stackObject.getId(), new StackAbilityView(game, (StackAbility) stackObject, token.getName(), new CardView(token)));
|
stack.put(stackObject.getId(), new StackAbilityView(game, (StackAbility) stackObject, token.getName(), new CardView(token, game)));
|
||||||
checkPaid(stackObject.getId(), (StackAbility) stackObject);
|
checkPaid(stackObject.getId(), (StackAbility) stackObject);
|
||||||
} else if (object instanceof Emblem) {
|
} else if (object instanceof Emblem) {
|
||||||
CardView cardView = new CardView(new EmblemView((Emblem) object));
|
CardView cardView = new CardView(new EmblemView((Emblem) object));
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
|
|
||||||
package mage.view;
|
package mage.view;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.TurnFaceUpAbility;
|
import mage.abilities.common.TurnFaceUpAbility;
|
||||||
import mage.cards.Card;
|
import mage.cards.Card;
|
||||||
|
@ -12,8 +8,11 @@ import mage.game.permanent.Permanent;
|
||||||
import mage.game.permanent.PermanentToken;
|
import mage.game.permanent.PermanentToken;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
*/
|
*/
|
||||||
public class PermanentView extends CardView {
|
public class PermanentView extends CardView {
|
||||||
|
@ -36,8 +35,8 @@ public class PermanentView extends CardView {
|
||||||
private final boolean attachedToPermanent;
|
private final boolean attachedToPermanent;
|
||||||
|
|
||||||
public PermanentView(Permanent permanent, Card card, UUID createdForPlayerId, Game game) {
|
public PermanentView(Permanent permanent, Card card, UUID createdForPlayerId, Game game) {
|
||||||
super(permanent, game, (permanent.getControllerId() == null) ? false : permanent.getControllerId().equals(createdForPlayerId));
|
super(permanent, game, permanent.getControllerId() != null && permanent.getControllerId().equals(createdForPlayerId));
|
||||||
this.controlled = (permanent.getControllerId() == null) ? false : permanent.getControllerId().equals(createdForPlayerId);
|
this.controlled = permanent.getControllerId() != null && permanent.getControllerId().equals(createdForPlayerId);
|
||||||
this.rules = permanent.getRules(game);
|
this.rules = permanent.getRules(game);
|
||||||
this.tapped = permanent.isTapped();
|
this.tapped = permanent.isTapped();
|
||||||
this.flipped = permanent.isFlipped();
|
this.flipped = permanent.isFlipped();
|
||||||
|
@ -59,7 +58,7 @@ public class PermanentView extends CardView {
|
||||||
} else {
|
} else {
|
||||||
if (card != null) {
|
if (card != null) {
|
||||||
// original may not be face down
|
// original may not be face down
|
||||||
original = new CardView(card);
|
original = new CardView(card, game);
|
||||||
} else {
|
} else {
|
||||||
original = null;
|
original = null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,5 @@
|
||||||
|
|
||||||
package mage.view;
|
package mage.view;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.ConcurrentModificationException;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.cards.Card;
|
import mage.cards.Card;
|
||||||
import mage.counters.Counters;
|
import mage.counters.Counters;
|
||||||
import mage.designations.Designation;
|
import mage.designations.Designation;
|
||||||
|
@ -22,6 +14,9 @@ import mage.game.permanent.Permanent;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.players.net.UserData;
|
import mage.players.net.UserData;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
*/
|
*/
|
||||||
|
@ -105,7 +100,7 @@ public class PlayerView implements Serializable {
|
||||||
}
|
}
|
||||||
Card cardOnTop = (player.isTopCardRevealed() && player.getLibrary().hasCards())
|
Card cardOnTop = (player.isTopCardRevealed() && player.getLibrary().hasCards())
|
||||||
? player.getLibrary().getFromTop(game) : null;
|
? player.getLibrary().getFromTop(game) : null;
|
||||||
this.topCard = cardOnTop != null ? new CardView(cardOnTop) : null;
|
this.topCard = cardOnTop != null ? new CardView(cardOnTop, game) : null;
|
||||||
if (player.getUserData() != null) {
|
if (player.getUserData() != null) {
|
||||||
this.userData = player.getUserData();
|
this.userData = player.getUserData();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -27,6 +27,8 @@ public class StackAbilityView extends CardView {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
// in GUI: that's view will be replaced by sourceCard, so don't forget to sync settings like
|
||||||
|
// selectable, chooseable, etc. Search by getSourceCard
|
||||||
private final CardView sourceCard;
|
private final CardView sourceCard;
|
||||||
|
|
||||||
public StackAbilityView(Game game, StackAbility ability, String sourceName, CardView sourceCard) {
|
public StackAbilityView(Game game, StackAbility ability, String sourceName, CardView sourceCard) {
|
||||||
|
|
123
Mage.Common/src/test/java/mage/remote/ConnectionTest.java
Normal file
123
Mage.Common/src/test/java/mage/remote/ConnectionTest.java
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
package mage.remote;
|
||||||
|
|
||||||
|
import mage.utils.FluentBuilder;
|
||||||
|
import org.apache.commons.lang3.RandomStringUtils;
|
||||||
|
import org.apache.commons.lang3.RandomUtils;
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.Nested;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
public class ConnectionTest {
|
||||||
|
|
||||||
|
static class ConnectionBuilder extends FluentBuilder<Connection, ConnectionBuilder> {
|
||||||
|
|
||||||
|
public int port;
|
||||||
|
public String host;
|
||||||
|
public String parameter;
|
||||||
|
|
||||||
|
private ConnectionBuilder() {
|
||||||
|
super(ConnectionBuilder::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Connection makeValue() {
|
||||||
|
final Connection result = new Connection(parameter);
|
||||||
|
result.setHost(host);
|
||||||
|
result.setPort(port);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ConnectionBuilder baseBuilder() {
|
||||||
|
return new ConnectionBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestsTemplate {
|
||||||
|
final ConnectionBuilder testeeBuilder;
|
||||||
|
|
||||||
|
TestsTemplate(ConnectionBuilder testeeBuilder) {
|
||||||
|
this.testeeBuilder = testeeBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("produce the expected scheme")
|
||||||
|
void scheme() throws Exception {
|
||||||
|
final URI testee = make(testeeBuilder);
|
||||||
|
assertThat(testee.getScheme()).isEqualTo("bisocket");
|
||||||
|
}
|
||||||
|
|
||||||
|
URI make(ConnectionBuilder builder) {
|
||||||
|
try {
|
||||||
|
return new URI(builder.build().getURI());
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("generate the expected port")
|
||||||
|
void port() {
|
||||||
|
final int expected = RandomUtils.nextInt(1000, 65000);
|
||||||
|
final int port = make(testeeBuilder.with(c -> c.port = expected)).getPort();
|
||||||
|
|
||||||
|
assertThat(port).isEqualTo(expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("generate the expected serialisation parameter")
|
||||||
|
void serialisation() {
|
||||||
|
final String query = make(testeeBuilder).getQuery();
|
||||||
|
|
||||||
|
assertThat(query).contains("serializationtype=jboss");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("generate the expected threadpool parameter")
|
||||||
|
void threadpool() {
|
||||||
|
final String parameter = RandomStringUtils.randomAlphanumeric(12);
|
||||||
|
final String query = make(testeeBuilder.with(c -> c.parameter = parameter)).getQuery();
|
||||||
|
|
||||||
|
assertThat(query).contains("onewayThreadPool=mage.remote.CustomThreadPool" + parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@DisplayName("getUri when host is localhost should")
|
||||||
|
class LocalhostTest extends TestsTemplate {
|
||||||
|
|
||||||
|
LocalhostTest() {
|
||||||
|
super(baseBuilder().with(c -> c.host = "localhost"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("generate an ipv4 as host")
|
||||||
|
void ipv4Gen() {
|
||||||
|
final String host = make(testeeBuilder).getHost();
|
||||||
|
|
||||||
|
assertThat(host).matches("[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String randomHost = RandomStringUtils.randomAlphabetic(15);
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@DisplayName("getUri when host is not localhost should")
|
||||||
|
class StandardHostTest extends TestsTemplate {
|
||||||
|
StandardHostTest() {
|
||||||
|
super(baseBuilder().with(c -> c.host = randomHost));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("generate the selected host as host")
|
||||||
|
void hostGen() {
|
||||||
|
final String host = make(testeeBuilder).getHost();
|
||||||
|
|
||||||
|
assertThat(host).isEqualTo(randomHost);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
116
Mage.Common/src/test/java/mage/utils/FluentBuilderTest.java
Normal file
116
Mage.Common/src/test/java/mage/utils/FluentBuilderTest.java
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
package mage.utils;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
|
||||||
|
|
||||||
|
public class FluentBuilderTest {
|
||||||
|
|
||||||
|
|
||||||
|
private ABuilder baseBuilder() {
|
||||||
|
return new ABuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("build with default parameters")
|
||||||
|
void testDefault() {
|
||||||
|
final A actual = baseBuilder().build();
|
||||||
|
|
||||||
|
verifyAB(actual, null, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void verifyAB(A actual, String a, int b) {
|
||||||
|
assertThat(actual.getA()).isEqualTo(a);
|
||||||
|
assertThat(actual.getB()).isEqualTo(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("chain with clause and add new parameters")
|
||||||
|
void testBaseChain() {
|
||||||
|
final A actual = baseBuilder().with(a -> a.a = "hello").build();
|
||||||
|
|
||||||
|
verifyAB(actual, "hello", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("chain multiple with clauses and add new parameters")
|
||||||
|
void testMultiChain() {
|
||||||
|
final A actual = baseBuilder().with(a -> a.a = "world").with(a -> a.b = 6).build();
|
||||||
|
|
||||||
|
verifyAB(actual, "world", 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("chain multiple with clauses and override latest writes")
|
||||||
|
void testMultiChainOverride() {
|
||||||
|
final A actual = baseBuilder().with(a -> a.a = "world").with(a -> a.b = 4).with(a -> a.a = "foobar").build();
|
||||||
|
|
||||||
|
verifyAB(actual, "foobar", 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("not mutate the state of previous builder in the chain")
|
||||||
|
void testImmutability() {
|
||||||
|
final ABuilder builder1 = baseBuilder().with(a -> a.a = "world");
|
||||||
|
final ABuilder builder2 = builder1.with(a -> {
|
||||||
|
a.a = "hello";
|
||||||
|
a.b = 42;
|
||||||
|
});
|
||||||
|
|
||||||
|
verifyAB(builder1.build(), "world", 0);
|
||||||
|
verifyAB(builder2.build(), "hello", 42);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("produce different objects")
|
||||||
|
void differentObjects() {
|
||||||
|
final ABuilder builder = baseBuilder().with(a -> {
|
||||||
|
a.a = "hello";
|
||||||
|
a.b = 42;
|
||||||
|
});
|
||||||
|
final A a1 = builder.build();
|
||||||
|
final A a2 = builder.build();
|
||||||
|
|
||||||
|
assertThat(a1).isNotSameAs(a2);
|
||||||
|
verifyAB(a1, "hello", 42);
|
||||||
|
verifyAB(a2, "hello", 42);
|
||||||
|
}
|
||||||
|
|
||||||
|
static class A {
|
||||||
|
public final String a;
|
||||||
|
private int b;
|
||||||
|
|
||||||
|
public A(String a) {
|
||||||
|
this.a = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getA() {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getB() {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setB(int b) {
|
||||||
|
this.b = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ABuilder extends FluentBuilder<A, ABuilder> {
|
||||||
|
public String a;
|
||||||
|
public int b;
|
||||||
|
|
||||||
|
private ABuilder() {
|
||||||
|
super(ABuilder::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected A makeValue() {
|
||||||
|
final A result = new A(a);
|
||||||
|
result.setB(b);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package mage.player.ai;
|
package mage.player.ai;
|
||||||
|
|
||||||
|
import mage.MageObject;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.ActivatedAbility;
|
import mage.abilities.ActivatedAbility;
|
||||||
import mage.abilities.SpellAbility;
|
import mage.abilities.SpellAbility;
|
||||||
|
@ -29,6 +30,7 @@ import mage.player.ai.util.CombatInfo;
|
||||||
import mage.player.ai.util.CombatUtil;
|
import mage.player.ai.util.CombatUtil;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.target.Target;
|
import mage.target.Target;
|
||||||
|
import mage.target.TargetAmount;
|
||||||
import mage.target.TargetCard;
|
import mage.target.TargetCard;
|
||||||
import mage.target.Targets;
|
import mage.target.Targets;
|
||||||
import mage.util.RandomUtil;
|
import mage.util.RandomUtil;
|
||||||
|
@ -37,6 +39,7 @@ import org.apache.log4j.Logger;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author nantuko
|
* @author nantuko
|
||||||
|
@ -155,7 +158,13 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
|
||||||
boolean usedStack = false;
|
boolean usedStack = false;
|
||||||
while (actions.peek() != null) {
|
while (actions.peek() != null) {
|
||||||
Ability ability = actions.poll();
|
Ability ability = actions.poll();
|
||||||
logger.info(new StringBuilder("===> Act [").append(game.getPlayer(playerId).getName()).append("] Action: ").append(ability.toString()).toString());
|
// log example: ===> Act [PlayerA] Action: Cast Blessings of Nature (target 1; target 2)
|
||||||
|
logger.info(new StringBuilder("===> Act [")
|
||||||
|
.append(game.getPlayer(playerId).getName())
|
||||||
|
.append("] Action: ")
|
||||||
|
.append(ability.toString())
|
||||||
|
.append(listTargets(game, ability.getTargets(), " (targeting %s)", ""))
|
||||||
|
.toString());
|
||||||
if (!ability.getTargets().isEmpty()) {
|
if (!ability.getTargets().isEmpty()) {
|
||||||
for (Target target : ability.getTargets()) {
|
for (Target target : ability.getTargets()) {
|
||||||
for (UUID id : target.getTargets()) {
|
for (UUID id : target.getTargets()) {
|
||||||
|
@ -506,7 +515,7 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
|
||||||
StringBuilder sb = new StringBuilder("Sim Prio [").append(depth).append("] #").append(counter)
|
StringBuilder sb = new StringBuilder("Sim Prio [").append(depth).append("] #").append(counter)
|
||||||
.append(" <").append(val).append("> (").append(action)
|
.append(" <").append(val).append("> (").append(action)
|
||||||
.append(action.isModal() ? " Mode = " + action.getModes().getMode().toString() : "")
|
.append(action.isModal() ? " Mode = " + action.getModes().getMode().toString() : "")
|
||||||
.append(listTargets(game, action.getTargets())).append(')')
|
.append(listTargets(game, action.getTargets(), " (targeting %s)", "")).append(')')
|
||||||
.append(logger.isTraceEnabled() ? " #" + newNode.hashCode() : "");
|
.append(logger.isTraceEnabled() ? " #" + newNode.hashCode() : "");
|
||||||
SimulationNode2 logNode = newNode;
|
SimulationNode2 logNode = newNode;
|
||||||
while (logNode.getChildren() != null
|
while (logNode.getChildren() != null
|
||||||
|
@ -541,7 +550,11 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
|
||||||
if (depth == maxDepth) {
|
if (depth == maxDepth) {
|
||||||
GameStateEvaluator2.PlayerEvaluateScore score = GameStateEvaluator2.evaluate(this.getId(), bestNode.game);
|
GameStateEvaluator2.PlayerEvaluateScore score = GameStateEvaluator2.evaluate(this.getId(), bestNode.game);
|
||||||
String scoreInfo = " [" + score.getPlayerInfoShort() + "-" + score.getOpponentInfoShort() + "]";
|
String scoreInfo = " [" + score.getPlayerInfoShort() + "-" + score.getOpponentInfoShort() + "]";
|
||||||
logger.info("Sim Prio [" + depth + "] -- Saved best node yet <" + bestNode.getScore() + scoreInfo + "> " + bestNode.getAbilities().toString());
|
String abilitiesInfo = bestNode.getAbilities()
|
||||||
|
.stream()
|
||||||
|
.map(a -> a.toString() + listTargets(game, a.getTargets(), " (targeting %s)", ""))
|
||||||
|
.collect(Collectors.joining("; "));
|
||||||
|
logger.info("Sim Prio [" + depth + "] -- Saved best node yet <" + bestNode.getScore() + scoreInfo + "> " + abilitiesInfo);
|
||||||
node.children.clear();
|
node.children.clear();
|
||||||
node.children.add(bestNode);
|
node.children.add(bestNode);
|
||||||
node.setScore(bestNode.getScore());
|
node.setScore(bestNode.getScore());
|
||||||
|
@ -1009,17 +1022,36 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
|
||||||
return suggestedActions.size();
|
return suggestedActions.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String listTargets(Game game, Targets targets) {
|
/**
|
||||||
StringBuilder sb = new StringBuilder();
|
* Return info about targets list (targeting objects)
|
||||||
if (targets != null) {
|
*
|
||||||
for (Target target : targets) {
|
* @param game
|
||||||
sb.append('[').append(target.getTargetedName(game)).append(']');
|
* @param targets
|
||||||
}
|
* @param format example: my %s in data
|
||||||
if (sb.length() > 0) {
|
* @param emptyText default text for empty targets list
|
||||||
sb.insert(0, " targeting ");
|
* @return
|
||||||
|
*/
|
||||||
|
protected String listTargets(Game game, Targets targets, String format, String emptyText) {
|
||||||
|
List<String> res = new ArrayList<>();
|
||||||
|
for (Target target : targets) {
|
||||||
|
for (UUID id : target.getTargets()) {
|
||||||
|
MageObject object = game.getObject(id);
|
||||||
|
if (object != null) {
|
||||||
|
String prefix = "";
|
||||||
|
if (target instanceof TargetAmount) {
|
||||||
|
prefix = " " + target.getTargetAmount(id) + "x ";
|
||||||
|
}
|
||||||
|
res.add(prefix + object.getIdName());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return sb.toString();
|
String info = String.join("; ", res);
|
||||||
|
|
||||||
|
if (info.isEmpty()) {
|
||||||
|
return emptyText;
|
||||||
|
} else {
|
||||||
|
return String.format(format, info);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1130,7 +1130,8 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.warn("No proper AI target handling: " + target.getClass().getName());
|
// it's ok on no targets available
|
||||||
|
log.warn("No proper AI target handling or can't find permanents/cards to target: " + target.getClass().getName());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -238,7 +238,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.api-client</groupId>
|
<groupId>com.google.api-client</groupId>
|
||||||
<artifactId>google-api-client</artifactId>
|
<artifactId>google-api-client</artifactId>
|
||||||
<version>1.30.10</version>
|
<version>1.31.1</version>
|
||||||
<type>jar</type>
|
<type>jar</type>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -256,7 +256,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.oauth-client</groupId>
|
<groupId>com.google.oauth-client</groupId>
|
||||||
<artifactId>google-oauth-client-jetty</artifactId>
|
<artifactId>google-oauth-client-jetty</artifactId>
|
||||||
<version>1.31.0</version>
|
<version>1.31.2</version>
|
||||||
<type>jar</type>
|
<type>jar</type>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -285,6 +285,18 @@
|
||||||
<artifactId>sqlite-jdbc</artifactId>
|
<artifactId>sqlite-jdbc</artifactId>
|
||||||
<version>3.32.3.2</version>
|
<version>3.32.3.2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Test dependencies -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.assertj</groupId>
|
||||||
|
<artifactId>assertj-core</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -358,6 +370,10 @@
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
|
|
||||||
<finalName>mage-server</finalName>
|
<finalName>mage-server</finalName>
|
||||||
|
|
|
@ -5,8 +5,8 @@ import mage.cards.repository.CardRepository;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.server.exceptions.UserNotFoundException;
|
import mage.server.exceptions.UserNotFoundException;
|
||||||
import mage.server.game.GameController;
|
import mage.server.game.GameController;
|
||||||
import mage.server.game.GameManager;
|
import mage.server.managers.ChatManager;
|
||||||
import mage.server.game.GamesRoomManager;
|
import mage.server.managers.ManagerFactory;
|
||||||
import mage.server.util.SystemUtil;
|
import mage.server.util.SystemUtil;
|
||||||
import mage.view.ChatMessage.MessageColor;
|
import mage.view.ChatMessage.MessageColor;
|
||||||
import mage.view.ChatMessage.MessageType;
|
import mage.view.ChatMessage.MessageType;
|
||||||
|
@ -26,21 +26,27 @@ import java.util.stream.Collectors;
|
||||||
/**
|
/**
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
*/
|
*/
|
||||||
public enum ChatManager {
|
public class ChatManagerImpl implements ChatManager {
|
||||||
|
|
||||||
instance;
|
private static final Logger logger = Logger.getLogger(ChatManagerImpl.class);
|
||||||
private static final Logger logger = Logger.getLogger(ChatManager.class);
|
|
||||||
private static final HashMap<String, String> userMessages = new HashMap<>();
|
private static final HashMap<String, String> userMessages = new HashMap<>();
|
||||||
|
|
||||||
|
private final ManagerFactory managerFactory;
|
||||||
private final ConcurrentHashMap<UUID, ChatSession> chatSessions = new ConcurrentHashMap<>();
|
private final ConcurrentHashMap<UUID, ChatSession> chatSessions = new ConcurrentHashMap<>();
|
||||||
private final ReadWriteLock lock = new ReentrantReadWriteLock();
|
private final ReadWriteLock lock = new ReentrantReadWriteLock();
|
||||||
|
|
||||||
|
public ChatManagerImpl(ManagerFactory managerFactory) {
|
||||||
|
this.managerFactory = managerFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public UUID createChatSession(String info) {
|
public UUID createChatSession(String info) {
|
||||||
ChatSession chatSession = new ChatSession(info);
|
ChatSession chatSession = new ChatSession(managerFactory, info);
|
||||||
chatSessions.put(chatSession.getChatId(), chatSession);
|
chatSessions.put(chatSession.getChatId(), chatSession);
|
||||||
return chatSession.getChatId();
|
return chatSession.getChatId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void joinChat(UUID chatId, UUID userId) {
|
public void joinChat(UUID chatId, UUID userId) {
|
||||||
ChatSession chatSession = chatSessions.get(chatId);
|
ChatSession chatSession = chatSessions.get(chatId);
|
||||||
if (chatSession != null) {
|
if (chatSession != null) {
|
||||||
|
@ -51,10 +57,12 @@ public enum ChatManager {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void clearUserMessageStorage() {
|
public void clearUserMessageStorage() {
|
||||||
userMessages.clear();
|
userMessages.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void leaveChat(UUID chatId, UUID userId) {
|
public void leaveChat(UUID chatId, UUID userId) {
|
||||||
ChatSession chatSession = chatSessions.get(chatId);
|
ChatSession chatSession = chatSessions.get(chatId);
|
||||||
if (chatSession != null && chatSession.hasUser(userId)) {
|
if (chatSession != null && chatSession.hasUser(userId)) {
|
||||||
|
@ -62,6 +70,7 @@ public enum ChatManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void destroyChatSession(UUID chatId) {
|
public void destroyChatSession(UUID chatId) {
|
||||||
if (chatId != null) {
|
if (chatId != null) {
|
||||||
ChatSession chatSession = chatSessions.get(chatId);
|
ChatSession chatSession = chatSessions.get(chatId);
|
||||||
|
@ -84,11 +93,12 @@ public enum ChatManager {
|
||||||
|
|
||||||
final Pattern cardNamePattern = Pattern.compile("\\[(.*?)\\]");
|
final Pattern cardNamePattern = Pattern.compile("\\[(.*?)\\]");
|
||||||
|
|
||||||
|
@Override
|
||||||
public void broadcast(UUID chatId, String userName, String message, MessageColor color, boolean withTime, Game game, MessageType messageType, SoundToPlay soundToPlay) {
|
public void broadcast(UUID chatId, String userName, String message, MessageColor color, boolean withTime, Game game, MessageType messageType, SoundToPlay soundToPlay) {
|
||||||
ChatSession chatSession = chatSessions.get(chatId);
|
ChatSession chatSession = chatSessions.get(chatId);
|
||||||
if (chatSession != null) {
|
if (chatSession != null) {
|
||||||
if (message.startsWith("\\") || message.startsWith("/")) {
|
if (message.startsWith("\\") || message.startsWith("/")) {
|
||||||
Optional<User> user = UserManager.instance.getUserByName(userName);
|
Optional<User> user = managerFactory.userManager().getUserByName(userName);
|
||||||
if (user.isPresent()) {
|
if (user.isPresent()) {
|
||||||
if (!performUserCommand(user.get(), message, chatId, false)) {
|
if (!performUserCommand(user.get(), message, chatId, false)) {
|
||||||
performUserCommand(user.get(), message, chatId, true);
|
performUserCommand(user.get(), message, chatId, true);
|
||||||
|
@ -98,7 +108,7 @@ public enum ChatManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (messageType != MessageType.GAME && !userName.isEmpty()) {
|
if (messageType != MessageType.GAME && !userName.isEmpty()) {
|
||||||
Optional<User> u = UserManager.instance.getUserByName(userName);
|
Optional<User> u = managerFactory.userManager().getUserByName(userName);
|
||||||
if (u.isPresent()) {
|
if (u.isPresent()) {
|
||||||
|
|
||||||
User user = u.get();
|
User user = u.get();
|
||||||
|
@ -184,12 +194,12 @@ public enum ChatManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command.startsWith("H ") || command.startsWith("HISTORY ")) {
|
if (command.startsWith("H ") || command.startsWith("HISTORY ")) {
|
||||||
message += "<br/>" + UserManager.instance.getUserHistory(message.substring(command.startsWith("H ") ? 3 : 9));
|
message += "<br/>" + managerFactory.userManager().getUserHistory(message.substring(command.startsWith("H ") ? 3 : 9));
|
||||||
chatSessions.get(chatId).broadcastInfoToUser(user, message);
|
chatSessions.get(chatId).broadcastInfoToUser(user, message);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (command.equals("ME")) {
|
if (command.equals("ME")) {
|
||||||
message += "<br/>" + UserManager.instance.getUserHistory(user.getName());
|
message += "<br/>" + managerFactory.userManager().getUserHistory(user.getName());
|
||||||
chatSessions.get(chatId).broadcastInfoToUser(user, message);
|
chatSessions.get(chatId).broadcastInfoToUser(user, message);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -200,7 +210,7 @@ public enum ChatManager {
|
||||||
String gameId = session.getInfo();
|
String gameId = session.getInfo();
|
||||||
if (gameId.startsWith("Game ")) {
|
if (gameId.startsWith("Game ")) {
|
||||||
UUID id = java.util.UUID.fromString(gameId.substring(5));
|
UUID id = java.util.UUID.fromString(gameId.substring(5));
|
||||||
for (Entry<UUID, GameController> entry : GameManager.instance.getGameController().entrySet()) {
|
for (Entry<UUID, GameController> entry : managerFactory.gameManager().getGameController().entrySet()) {
|
||||||
if (entry.getKey().equals(id)) {
|
if (entry.getKey().equals(id)) {
|
||||||
GameController controller = entry.getValue();
|
GameController controller = entry.getValue();
|
||||||
if (controller != null) {
|
if (controller != null) {
|
||||||
|
@ -221,7 +231,7 @@ public enum ChatManager {
|
||||||
String gameId = session.getInfo();
|
String gameId = session.getInfo();
|
||||||
if (gameId.startsWith("Game ")) {
|
if (gameId.startsWith("Game ")) {
|
||||||
UUID id = java.util.UUID.fromString(gameId.substring(5));
|
UUID id = java.util.UUID.fromString(gameId.substring(5));
|
||||||
for (Entry<UUID, GameController> entry : GameManager.instance.getGameController().entrySet()) {
|
for (Entry<UUID, GameController> entry : managerFactory.gameManager().getGameController().entrySet()) {
|
||||||
if (entry.getKey().equals(id)) {
|
if (entry.getKey().equals(id)) {
|
||||||
GameController controller = entry.getValue();
|
GameController controller = entry.getValue();
|
||||||
if (controller != null) {
|
if (controller != null) {
|
||||||
|
@ -242,7 +252,7 @@ public enum ChatManager {
|
||||||
String gameId = session.getInfo();
|
String gameId = session.getInfo();
|
||||||
if (gameId.startsWith("Game ")) {
|
if (gameId.startsWith("Game ")) {
|
||||||
UUID id = java.util.UUID.fromString(gameId.substring(5));
|
UUID id = java.util.UUID.fromString(gameId.substring(5));
|
||||||
for (Entry<UUID, GameController> entry : GameManager.instance.getGameController().entrySet()) {
|
for (Entry<UUID, GameController> entry : managerFactory.gameManager().getGameController().entrySet()) {
|
||||||
if (entry.getKey().equals(id)) {
|
if (entry.getKey().equals(id)) {
|
||||||
GameController controller = entry.getValue();
|
GameController controller = entry.getValue();
|
||||||
if (controller != null) {
|
if (controller != null) {
|
||||||
|
@ -281,7 +291,7 @@ public enum ChatManager {
|
||||||
if (first > 1) {
|
if (first > 1) {
|
||||||
String userToName = rest.substring(0, first);
|
String userToName = rest.substring(0, first);
|
||||||
rest = rest.substring(first + 1).trim();
|
rest = rest.substring(first + 1).trim();
|
||||||
Optional<User> userTo = UserManager.instance.getUserByName(userToName);
|
Optional<User> userTo = managerFactory.userManager().getUserByName(userToName);
|
||||||
if (userTo.isPresent()) {
|
if (userTo.isPresent()) {
|
||||||
if (!chatSessions.get(chatId).broadcastWhisperToUser(user, userTo.get(), rest)) {
|
if (!chatSessions.get(chatId).broadcastWhisperToUser(user, userTo.get(), rest)) {
|
||||||
message += new StringBuilder("<br/>User ").append(userToName).append(" not found").toString();
|
message += new StringBuilder("<br/>User ").append(userToName).append(" not found").toString();
|
||||||
|
@ -312,8 +322,9 @@ public enum ChatManager {
|
||||||
* @param color
|
* @param color
|
||||||
* @throws mage.server.exceptions.UserNotFoundException
|
* @throws mage.server.exceptions.UserNotFoundException
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void broadcast(UUID userId, String message, MessageColor color) throws UserNotFoundException {
|
public void broadcast(UUID userId, String message, MessageColor color) throws UserNotFoundException {
|
||||||
UserManager.instance.getUser(userId).ifPresent(user -> {
|
managerFactory.userManager().getUser(userId).ifPresent(user -> {
|
||||||
getChatSessions()
|
getChatSessions()
|
||||||
.stream()
|
.stream()
|
||||||
.filter(chat -> chat.hasUser(userId))
|
.filter(chat -> chat.hasUser(userId))
|
||||||
|
@ -322,8 +333,9 @@ public enum ChatManager {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void sendReconnectMessage(UUID userId) {
|
public void sendReconnectMessage(UUID userId) {
|
||||||
UserManager.instance.getUser(userId).ifPresent(user
|
managerFactory.userManager().getUser(userId).ifPresent(user
|
||||||
-> getChatSessions()
|
-> getChatSessions()
|
||||||
.stream()
|
.stream()
|
||||||
.filter(chat -> chat.hasUser(userId))
|
.filter(chat -> chat.hasUser(userId))
|
||||||
|
@ -331,8 +343,9 @@ public enum ChatManager {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void sendLostConnectionMessage(UUID userId, DisconnectReason reason) {
|
public void sendLostConnectionMessage(UUID userId, DisconnectReason reason) {
|
||||||
UserManager.instance.getUser(userId).ifPresent(user -> sendMessageToUserChats(userId, user.getName() + " " + reason.getMessage()));
|
managerFactory.userManager().getUser(userId).ifPresent(user -> sendMessageToUserChats(userId, user.getName() + " " + reason.getMessage()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -341,10 +354,11 @@ public enum ChatManager {
|
||||||
* @param userId
|
* @param userId
|
||||||
* @param message
|
* @param message
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void sendMessageToUserChats(UUID userId, String message) {
|
public void sendMessageToUserChats(UUID userId, String message) {
|
||||||
UserManager.instance.getUser(userId).ifPresent(user -> {
|
managerFactory.userManager().getUser(userId).ifPresent(user -> {
|
||||||
List<ChatSession> chatSessions = getChatSessions().stream()
|
List<ChatSession> chatSessions = getChatSessions().stream()
|
||||||
.filter(chat -> !chat.getChatId().equals(GamesRoomManager.instance.getMainChatId())) // ignore main lobby
|
.filter(chat -> !chat.getChatId().equals(managerFactory.gamesRoomManager().getMainChatId())) // ignore main lobby
|
||||||
.filter(chat -> chat.hasUser(userId))
|
.filter(chat -> chat.hasUser(userId))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
@ -355,6 +369,7 @@ public enum ChatManager {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void removeUser(UUID userId, DisconnectReason reason) {
|
public void removeUser(UUID userId, DisconnectReason reason) {
|
||||||
for (ChatSession chatSession : getChatSessions()) {
|
for (ChatSession chatSession : getChatSessions()) {
|
||||||
if (chatSession.hasUser(userId)) {
|
if (chatSession.hasUser(userId)) {
|
||||||
|
@ -363,6 +378,7 @@ public enum ChatManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public List<ChatSession> getChatSessions() {
|
public List<ChatSession> getChatSessions() {
|
||||||
final Lock r = lock.readLock();
|
final Lock r = lock.readLock();
|
||||||
r.lock();
|
r.lock();
|
|
@ -3,6 +3,7 @@ package mage.server;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.interfaces.callback.ClientCallback;
|
import mage.interfaces.callback.ClientCallback;
|
||||||
import mage.interfaces.callback.ClientCallbackMethod;
|
import mage.interfaces.callback.ClientCallbackMethod;
|
||||||
|
import mage.server.managers.ManagerFactory;
|
||||||
import mage.view.ChatMessage;
|
import mage.view.ChatMessage;
|
||||||
import mage.view.ChatMessage.MessageColor;
|
import mage.view.ChatMessage.MessageColor;
|
||||||
import mage.view.ChatMessage.MessageType;
|
import mage.view.ChatMessage.MessageType;
|
||||||
|
@ -25,6 +26,7 @@ public class ChatSession {
|
||||||
private static final Logger logger = Logger.getLogger(ChatSession.class);
|
private static final Logger logger = Logger.getLogger(ChatSession.class);
|
||||||
private static final DateFormat timeFormatter = DateFormat.getTimeInstance(DateFormat.SHORT);
|
private static final DateFormat timeFormatter = DateFormat.getTimeInstance(DateFormat.SHORT);
|
||||||
|
|
||||||
|
private final ManagerFactory managerFactory;
|
||||||
private final ReadWriteLock lock = new ReentrantReadWriteLock();
|
private final ReadWriteLock lock = new ReentrantReadWriteLock();
|
||||||
|
|
||||||
private final ConcurrentMap<UUID, String> clients = new ConcurrentHashMap<>();
|
private final ConcurrentMap<UUID, String> clients = new ConcurrentHashMap<>();
|
||||||
|
@ -32,14 +34,15 @@ public class ChatSession {
|
||||||
private final Date createTime;
|
private final Date createTime;
|
||||||
private final String info;
|
private final String info;
|
||||||
|
|
||||||
public ChatSession(String info) {
|
public ChatSession(ManagerFactory managerFactory, String info) {
|
||||||
|
this.managerFactory = managerFactory;
|
||||||
chatId = UUID.randomUUID();
|
chatId = UUID.randomUUID();
|
||||||
this.createTime = new Date();
|
this.createTime = new Date();
|
||||||
this.info = info;
|
this.info = info;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void join(UUID userId) {
|
public void join(UUID userId) {
|
||||||
UserManager.instance.getUser(userId).ifPresent(user -> {
|
managerFactory.userManager().getUser(userId).ifPresent(user -> {
|
||||||
if (!clients.containsKey(userId)) {
|
if (!clients.containsKey(userId)) {
|
||||||
String userName = user.getName();
|
String userName = user.getName();
|
||||||
final Lock w = lock.writeLock();
|
final Lock w = lock.writeLock();
|
||||||
|
@ -121,7 +124,7 @@ public class ChatSession {
|
||||||
r.unlock();
|
r.unlock();
|
||||||
}
|
}
|
||||||
for (UUID userId : chatUserIds) {
|
for (UUID userId : chatUserIds) {
|
||||||
Optional<User> user = UserManager.instance.getUser(userId);
|
Optional<User> user = managerFactory.userManager().getUser(userId);
|
||||||
if (user.isPresent()) {
|
if (user.isPresent()) {
|
||||||
user.get().fireCallback(clientCallback);
|
user.get().fireCallback(clientCallback);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,91 +0,0 @@
|
||||||
package mage.server;
|
|
||||||
|
|
||||||
import com.google.api.client.auth.oauth2.Credential;
|
|
||||||
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
|
|
||||||
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
|
|
||||||
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
|
|
||||||
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
|
|
||||||
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
|
|
||||||
import com.google.api.client.http.HttpTransport;
|
|
||||||
import com.google.api.client.json.JsonFactory;
|
|
||||||
import com.google.api.client.json.jackson2.JacksonFactory;
|
|
||||||
import com.google.api.client.util.Base64;
|
|
||||||
import com.google.api.client.util.store.FileDataStoreFactory;
|
|
||||||
import com.google.api.services.gmail.Gmail;
|
|
||||||
import com.google.api.services.gmail.Gmail.Builder;
|
|
||||||
import com.google.api.services.gmail.GmailScopes;
|
|
||||||
import com.google.api.services.gmail.model.Message;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.FileReader;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.security.GeneralSecurityException;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Properties;
|
|
||||||
import javax.mail.MessagingException;
|
|
||||||
import javax.mail.Session;
|
|
||||||
import javax.mail.internet.InternetAddress;
|
|
||||||
import javax.mail.internet.MimeMessage;
|
|
||||||
import mage.server.util.ConfigSettings;
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
|
|
||||||
public final class GmailClient {
|
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(Main.class);
|
|
||||||
private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
|
|
||||||
private static final java.io.File DATA_STORE_DIR = new java.io.File(System.getProperty("user.home"), ".store/xmage");
|
|
||||||
private static FileDataStoreFactory dataStoreFactory;
|
|
||||||
private static HttpTransport httpTransport;
|
|
||||||
private static Credential credential;
|
|
||||||
|
|
||||||
public static boolean initilize() {
|
|
||||||
try {
|
|
||||||
dataStoreFactory = new FileDataStoreFactory(DATA_STORE_DIR);
|
|
||||||
httpTransport = GoogleNetHttpTransport.newTrustedTransport();
|
|
||||||
|
|
||||||
GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new FileReader("client_secrets.json"));
|
|
||||||
if (clientSecrets.getDetails().getClientId().startsWith("Enter")
|
|
||||||
|| clientSecrets.getDetails().getClientSecret().startsWith("Enter ")) {
|
|
||||||
logger.error("client_secrets.json not found");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
|
|
||||||
httpTransport, JSON_FACTORY, clientSecrets,
|
|
||||||
Collections.singleton(GmailScopes.GMAIL_COMPOSE)).setDataStoreFactory(
|
|
||||||
dataStoreFactory).build();
|
|
||||||
|
|
||||||
credential = new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
|
|
||||||
return true;
|
|
||||||
} catch (IOException | GeneralSecurityException ex) {
|
|
||||||
logger.error("Error initializing GmailClient", ex);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean sendMessage(String email, String subject, String text) {
|
|
||||||
if (email.isEmpty()) {
|
|
||||||
logger.info("Email is not sent because the address is empty");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
Gmail gmail = new Builder(httpTransport, JSON_FACTORY, credential).setApplicationName("XMage Server").build();
|
|
||||||
|
|
||||||
MimeMessage mimeMessage = new MimeMessage(Session.getDefaultInstance(new Properties()));
|
|
||||||
mimeMessage.addRecipient(javax.mail.Message.RecipientType.TO, new InternetAddress(email));
|
|
||||||
mimeMessage.setSubject(subject);
|
|
||||||
mimeMessage.setText(text);
|
|
||||||
|
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
||||||
mimeMessage.writeTo(baos);
|
|
||||||
Message message = new Message();
|
|
||||||
message.setRaw(Base64.encodeBase64URLSafeString(baos.toByteArray()));
|
|
||||||
|
|
||||||
gmail.users().messages().send(ConfigSettings.instance.getGoogleAccount()
|
|
||||||
+ (ConfigSettings.instance.getGoogleAccount().endsWith("@gmail.com") ? "" : "@gmail.com"), message).execute();
|
|
||||||
return true;
|
|
||||||
} catch (MessagingException | IOException ex) {
|
|
||||||
logger.error("Error sending message", ex);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -23,15 +23,14 @@ import mage.players.PlayerType;
|
||||||
import mage.players.net.UserData;
|
import mage.players.net.UserData;
|
||||||
import mage.remote.MageVersionException;
|
import mage.remote.MageVersionException;
|
||||||
import mage.server.draft.CubeFactory;
|
import mage.server.draft.CubeFactory;
|
||||||
import mage.server.draft.DraftManager;
|
import mage.server.game.GameFactory;
|
||||||
import mage.server.game.*;
|
import mage.server.game.GamesRoom;
|
||||||
|
import mage.server.game.PlayerFactory;
|
||||||
|
import mage.server.managers.ManagerFactory;
|
||||||
import mage.server.services.impl.FeedbackServiceImpl;
|
import mage.server.services.impl.FeedbackServiceImpl;
|
||||||
import mage.server.tournament.TournamentFactory;
|
import mage.server.tournament.TournamentFactory;
|
||||||
import mage.server.tournament.TournamentManager;
|
|
||||||
import mage.server.util.ConfigSettings;
|
|
||||||
import mage.server.util.ServerMessagesUtil;
|
import mage.server.util.ServerMessagesUtil;
|
||||||
import mage.server.util.SystemUtil;
|
import mage.server.util.SystemUtil;
|
||||||
import mage.server.util.ThreadExecutor;
|
|
||||||
import mage.utils.*;
|
import mage.utils.*;
|
||||||
import mage.view.*;
|
import mage.view.*;
|
||||||
import mage.view.ChatMessage.MessageColor;
|
import mage.view.ChatMessage.MessageColor;
|
||||||
|
@ -49,9 +48,10 @@ import java.util.concurrent.ExecutorService;
|
||||||
public class MageServerImpl implements MageServer {
|
public class MageServerImpl implements MageServer {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(MageServerImpl.class);
|
private static final Logger logger = Logger.getLogger(MageServerImpl.class);
|
||||||
private static final ExecutorService callExecutor = ThreadExecutor.instance.getCallExecutor();
|
private final ExecutorService callExecutor;
|
||||||
private static final SecureRandom RANDOM = new SecureRandom();
|
private static final SecureRandom RANDOM = new SecureRandom();
|
||||||
|
|
||||||
|
private final ManagerFactory managerFactory;
|
||||||
private final String adminPassword;
|
private final String adminPassword;
|
||||||
private final boolean testMode;
|
private final boolean testMode;
|
||||||
private final LinkedHashMap<String, String> activeAuthTokens = new LinkedHashMap<String, String>() {
|
private final LinkedHashMap<String, String> activeAuthTokens = new LinkedHashMap<String, String>() {
|
||||||
|
@ -62,15 +62,17 @@ public class MageServerImpl implements MageServer {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public MageServerImpl(String adminPassword, boolean testMode) {
|
public MageServerImpl(ManagerFactory managerFactory, String adminPassword, boolean testMode) {
|
||||||
|
this.managerFactory = managerFactory;
|
||||||
this.adminPassword = adminPassword;
|
this.adminPassword = adminPassword;
|
||||||
this.testMode = testMode;
|
this.testMode = testMode;
|
||||||
|
this.callExecutor = managerFactory.threadExecutor().getCallExecutor();
|
||||||
ServerMessagesUtil.instance.getMessages();
|
ServerMessagesUtil.instance.getMessages();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean registerUser(String sessionId, String userName, String password, String email) throws MageException {
|
public boolean registerUser(String sessionId, String userName, String password, String email) throws MageException {
|
||||||
return SessionManager.instance.registerUser(sessionId, userName, password, email);
|
return managerFactory.sessionManager().registerUser(sessionId, userName, password, email);
|
||||||
}
|
}
|
||||||
|
|
||||||
// generateAuthToken returns a uniformly distributed 6-digits string.
|
// generateAuthToken returns a uniformly distributed 6-digits string.
|
||||||
|
@ -80,7 +82,7 @@ public class MageServerImpl implements MageServer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean emailAuthToken(String sessionId, String email) throws MageException {
|
public boolean emailAuthToken(String sessionId, String email) throws MageException {
|
||||||
if (!ConfigSettings.instance.isAuthenticationActivated()) {
|
if (!managerFactory.configSettings().isAuthenticationActivated()) {
|
||||||
sendErrorMessageToClient(sessionId, "Registration is disabled by the server config");
|
sendErrorMessageToClient(sessionId, "Registration is disabled by the server config");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -96,10 +98,10 @@ public class MageServerImpl implements MageServer {
|
||||||
String text = "Use this auth token to reset " + authorizedUser.name + "'s password: " + authToken + '\n'
|
String text = "Use this auth token to reset " + authorizedUser.name + "'s password: " + authToken + '\n'
|
||||||
+ "It's valid until the next server restart.";
|
+ "It's valid until the next server restart.";
|
||||||
boolean success;
|
boolean success;
|
||||||
if (!ConfigSettings.instance.getMailUser().isEmpty()) {
|
if (!managerFactory.configSettings().getMailUser().isEmpty()) {
|
||||||
success = MailClient.sendMessage(email, subject, text);
|
success = managerFactory.mailClient().sendMessage(email, subject, text);
|
||||||
} else {
|
} else {
|
||||||
success = MailgunClient.sendMessage(email, subject, text);
|
success = managerFactory.mailgunClient().sendMessage(email, subject, text);
|
||||||
}
|
}
|
||||||
if (!success) {
|
if (!success) {
|
||||||
sendErrorMessageToClient(sessionId, "There was an error inside the server while emailing an auth token");
|
sendErrorMessageToClient(sessionId, "There was an error inside the server while emailing an auth token");
|
||||||
|
@ -110,7 +112,7 @@ public class MageServerImpl implements MageServer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean resetPassword(String sessionId, String email, String authToken, String password) throws MageException {
|
public boolean resetPassword(String sessionId, String email, String authToken, String password) throws MageException {
|
||||||
if (!ConfigSettings.instance.isAuthenticationActivated()) {
|
if (!managerFactory.configSettings().isAuthenticationActivated()) {
|
||||||
sendErrorMessageToClient(sessionId, "Registration is disabled by the server config");
|
sendErrorMessageToClient(sessionId, "Registration is disabled by the server config");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -139,7 +141,7 @@ public class MageServerImpl implements MageServer {
|
||||||
logger.info("MageVersionException: userName=" + userName + ", version=" + version + " sessionId=" + sessionId);
|
logger.info("MageVersionException: userName=" + userName + ", version=" + version + " sessionId=" + sessionId);
|
||||||
throw new MageVersionException(version, Main.getVersion());
|
throw new MageVersionException(version, Main.getVersion());
|
||||||
}
|
}
|
||||||
return SessionManager.instance.connectUser(sessionId, userName, password, userIdStr);
|
return managerFactory.sessionManager().connectUser(sessionId, userName, password, userIdStr);
|
||||||
} catch (MageException ex) {
|
} catch (MageException ex) {
|
||||||
if (ex instanceof MageVersionException) {
|
if (ex instanceof MageVersionException) {
|
||||||
throw ex;
|
throw ex;
|
||||||
|
@ -154,7 +156,7 @@ public class MageServerImpl implements MageServer {
|
||||||
return executeWithResult("setUserData", sessionId, new ActionWithBooleanResult() {
|
return executeWithResult("setUserData", sessionId, new ActionWithBooleanResult() {
|
||||||
@Override
|
@Override
|
||||||
public Boolean execute() throws MageException {
|
public Boolean execute() throws MageException {
|
||||||
return SessionManager.instance.setUserData(userName, sessionId, userData, clientVersion, userIdStr);
|
return managerFactory.sessionManager().setUserData(userName, sessionId, userData, clientVersion, userIdStr);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -168,7 +170,7 @@ public class MageServerImpl implements MageServer {
|
||||||
if (!adminPassword.equals(this.adminPassword)) {
|
if (!adminPassword.equals(this.adminPassword)) {
|
||||||
throw new MageException("Wrong password");
|
throw new MageException("Wrong password");
|
||||||
}
|
}
|
||||||
return SessionManager.instance.connectAdmin(sessionId);
|
return managerFactory.sessionManager().connectAdmin(sessionId);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
handleException(ex);
|
handleException(ex);
|
||||||
}
|
}
|
||||||
|
@ -186,13 +188,13 @@ public class MageServerImpl implements MageServer {
|
||||||
@Override
|
@Override
|
||||||
public TableView execute() throws MageException {
|
public TableView execute() throws MageException {
|
||||||
try {
|
try {
|
||||||
Optional<Session> session = SessionManager.instance.getSession(sessionId);
|
Optional<Session> session = managerFactory.sessionManager().getSession(sessionId);
|
||||||
if (!session.isPresent()) {
|
if (!session.isPresent()) {
|
||||||
logger.error("Session to found : " + sessionId);
|
logger.error("Session to found : " + sessionId);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
UUID userId = session.get().getUserId();
|
UUID userId = session.get().getUserId();
|
||||||
Optional<User> _user = UserManager.instance.getUser(userId);
|
Optional<User> _user = managerFactory.userManager().getUser(userId);
|
||||||
if (!_user.isPresent()) {
|
if (!_user.isPresent()) {
|
||||||
logger.error("User for session not found. session = " + sessionId);
|
logger.error("User for session not found. session = " + sessionId);
|
||||||
return null;
|
return null;
|
||||||
|
@ -205,7 +207,7 @@ public class MageServerImpl implements MageServer {
|
||||||
throw new MageException("No message");
|
throw new MageException("No message");
|
||||||
}
|
}
|
||||||
// check AI players max
|
// check AI players max
|
||||||
String maxAiOpponents = ConfigSettings.instance.getMaxAiOpponents();
|
String maxAiOpponents = managerFactory.configSettings().getMaxAiOpponents();
|
||||||
if (maxAiOpponents != null) {
|
if (maxAiOpponents != null) {
|
||||||
int aiPlayers = 0;
|
int aiPlayers = 0;
|
||||||
for (PlayerType playerType : options.getPlayerTypes()) {
|
for (PlayerType playerType : options.getPlayerTypes()) {
|
||||||
|
@ -241,7 +243,7 @@ public class MageServerImpl implements MageServer {
|
||||||
user.showUserMessage("Create tournament", message);
|
user.showUserMessage("Create tournament", message);
|
||||||
throw new MageException("No message");
|
throw new MageException("No message");
|
||||||
}
|
}
|
||||||
Optional<GamesRoom> room = GamesRoomManager.instance.getRoom(roomId);
|
Optional<GamesRoom> room = managerFactory.gamesRoomManager().getRoom(roomId);
|
||||||
if (!room.isPresent()) {
|
if (!room.isPresent()) {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -260,9 +262,9 @@ public class MageServerImpl implements MageServer {
|
||||||
@Override
|
@Override
|
||||||
public void removeTable(final String sessionId, final UUID roomId, final UUID tableId) throws MageException {
|
public void removeTable(final String sessionId, final UUID roomId, final UUID tableId) throws MageException {
|
||||||
execute("removeTable", sessionId, () -> {
|
execute("removeTable", sessionId, () -> {
|
||||||
SessionManager.instance.getSession(sessionId).ifPresent(session -> {
|
managerFactory.sessionManager().getSession(sessionId).ifPresent(session -> {
|
||||||
UUID userId = session.getUserId();
|
UUID userId = session.getUserId();
|
||||||
TableManager.instance.removeTable(userId, tableId);
|
managerFactory.tableManager().removeTable(userId, tableId);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -272,7 +274,7 @@ public class MageServerImpl implements MageServer {
|
||||||
return executeWithResult("joinTable", sessionId, new ActionWithBooleanResult() {
|
return executeWithResult("joinTable", sessionId, new ActionWithBooleanResult() {
|
||||||
@Override
|
@Override
|
||||||
public Boolean execute() throws MageException {
|
public Boolean execute() throws MageException {
|
||||||
Optional<Session> session = SessionManager.instance.getSession(sessionId);
|
Optional<Session> session = managerFactory.sessionManager().getSession(sessionId);
|
||||||
if (!session.isPresent()) {
|
if (!session.isPresent()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -282,7 +284,7 @@ public class MageServerImpl implements MageServer {
|
||||||
logger.fatal("Got no userId from sessionId" + sessionId + " tableId" + tableId);
|
logger.fatal("Got no userId from sessionId" + sessionId + " tableId" + tableId);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Optional<GamesRoom> room = GamesRoomManager.instance.getRoom(roomId);
|
Optional<GamesRoom> room = managerFactory.gamesRoomManager().getRoom(roomId);
|
||||||
if (!room.isPresent()) {
|
if (!room.isPresent()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -297,20 +299,20 @@ public class MageServerImpl implements MageServer {
|
||||||
return executeWithResult("joinTournamentTable", sessionId, new ActionWithBooleanResult() {
|
return executeWithResult("joinTournamentTable", sessionId, new ActionWithBooleanResult() {
|
||||||
@Override
|
@Override
|
||||||
public Boolean execute() throws MageException {
|
public Boolean execute() throws MageException {
|
||||||
Optional<Session> session = SessionManager.instance.getSession(sessionId);
|
Optional<Session> session = managerFactory.sessionManager().getSession(sessionId);
|
||||||
if (!session.isPresent()) {
|
if (!session.isPresent()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
UUID userId = session.get().getUserId();
|
UUID userId = session.get().getUserId();
|
||||||
if (logger.isTraceEnabled()) {
|
if (logger.isTraceEnabled()) {
|
||||||
Optional<User> user = UserManager.instance.getUser(userId);
|
Optional<User> user = managerFactory.userManager().getUser(userId);
|
||||||
user.ifPresent(user1 -> logger.trace("join tourn. tableId: " + tableId + ' ' + name));
|
user.ifPresent(user1 -> logger.trace("join tourn. tableId: " + tableId + ' ' + name));
|
||||||
}
|
}
|
||||||
if (userId == null) {
|
if (userId == null) {
|
||||||
logger.fatal("Got no userId from sessionId" + sessionId + " tableId" + tableId);
|
logger.fatal("Got no userId from sessionId" + sessionId + " tableId" + tableId);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Optional<GamesRoom> room = GamesRoomManager.instance.getRoom(roomId);
|
Optional<GamesRoom> room = managerFactory.gamesRoomManager().getRoom(roomId);
|
||||||
if (room.isPresent()) {
|
if (room.isPresent()) {
|
||||||
return room.get().joinTournamentTable(userId, tableId, name, playerType, skill, deckList, password);
|
return room.get().joinTournamentTable(userId, tableId, name, playerType, skill, deckList, password);
|
||||||
}
|
}
|
||||||
|
@ -325,12 +327,12 @@ public class MageServerImpl implements MageServer {
|
||||||
return executeWithResult("submitDeck", sessionId, new ActionWithBooleanResult() {
|
return executeWithResult("submitDeck", sessionId, new ActionWithBooleanResult() {
|
||||||
@Override
|
@Override
|
||||||
public Boolean execute() throws MageException {
|
public Boolean execute() throws MageException {
|
||||||
Optional<Session> session = SessionManager.instance.getSession(sessionId);
|
Optional<Session> session = managerFactory.sessionManager().getSession(sessionId);
|
||||||
if (!session.isPresent()) {
|
if (!session.isPresent()) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
UUID userId = session.get().getUserId();
|
UUID userId = session.get().getUserId();
|
||||||
boolean ret = TableManager.instance.submitDeck(userId, tableId, deckList);
|
boolean ret = managerFactory.tableManager().submitDeck(userId, tableId, deckList);
|
||||||
logger.debug("Session " + sessionId + " submitted deck");
|
logger.debug("Session " + sessionId + " submitted deck");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -341,13 +343,13 @@ public class MageServerImpl implements MageServer {
|
||||||
@Override
|
@Override
|
||||||
public void updateDeck(final String sessionId, final UUID tableId, final DeckCardLists deckList) throws MageException {
|
public void updateDeck(final String sessionId, final UUID tableId, final DeckCardLists deckList) throws MageException {
|
||||||
execute("updateDeck", sessionId, () -> {
|
execute("updateDeck", sessionId, () -> {
|
||||||
Optional<Session> session = SessionManager.instance.getSession(sessionId);
|
Optional<Session> session = managerFactory.sessionManager().getSession(sessionId);
|
||||||
if (!session.isPresent()) {
|
if (!session.isPresent()) {
|
||||||
logger.error("Session not found : " + sessionId);
|
logger.error("Session not found : " + sessionId);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
UUID userId = session.get().getUserId();
|
UUID userId = session.get().getUserId();
|
||||||
TableManager.instance.updateDeck(userId, tableId, deckList);
|
managerFactory.tableManager().updateDeck(userId, tableId, deckList);
|
||||||
logger.trace("Session " + sessionId + " updated deck");
|
logger.trace("Session " + sessionId + " updated deck");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -357,7 +359,7 @@ public class MageServerImpl implements MageServer {
|
||||||
//FIXME: why no sessionId here???
|
//FIXME: why no sessionId here???
|
||||||
public List<TableView> getTables(UUID roomId) throws MageException {
|
public List<TableView> getTables(UUID roomId) throws MageException {
|
||||||
try {
|
try {
|
||||||
Optional<GamesRoom> room = GamesRoomManager.instance.getRoom(roomId);
|
Optional<GamesRoom> room = managerFactory.gamesRoomManager().getRoom(roomId);
|
||||||
if (room.isPresent()) {
|
if (room.isPresent()) {
|
||||||
return room.get().getTables();
|
return room.get().getTables();
|
||||||
} else {
|
} else {
|
||||||
|
@ -373,7 +375,7 @@ public class MageServerImpl implements MageServer {
|
||||||
//FIXME: why no sessionId here???
|
//FIXME: why no sessionId here???
|
||||||
public List<MatchView> getFinishedMatches(UUID roomId) throws MageException {
|
public List<MatchView> getFinishedMatches(UUID roomId) throws MageException {
|
||||||
try {
|
try {
|
||||||
return GamesRoomManager.instance.getRoom(roomId).map(GamesRoom::getFinished).orElse(new ArrayList<>());
|
return managerFactory.gamesRoomManager().getRoom(roomId).map(GamesRoom::getFinished).orElse(new ArrayList<>());
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
handleException(ex);
|
handleException(ex);
|
||||||
}
|
}
|
||||||
|
@ -383,7 +385,7 @@ public class MageServerImpl implements MageServer {
|
||||||
@Override
|
@Override
|
||||||
public List<RoomUsersView> getRoomUsers(UUID roomId) throws MageException {
|
public List<RoomUsersView> getRoomUsers(UUID roomId) throws MageException {
|
||||||
try {
|
try {
|
||||||
Optional<GamesRoom> room = GamesRoomManager.instance.getRoom(roomId);
|
Optional<GamesRoom> room = managerFactory.gamesRoomManager().getRoom(roomId);
|
||||||
if (room.isPresent()) {
|
if (room.isPresent()) {
|
||||||
return room.get().getRoomUsersInfo();
|
return room.get().getRoomUsersInfo();
|
||||||
} else {
|
} else {
|
||||||
|
@ -399,7 +401,7 @@ public class MageServerImpl implements MageServer {
|
||||||
//FIXME: why no sessionId here???
|
//FIXME: why no sessionId here???
|
||||||
public TableView getTable(UUID roomId, UUID tableId) throws MageException {
|
public TableView getTable(UUID roomId, UUID tableId) throws MageException {
|
||||||
try {
|
try {
|
||||||
Optional<GamesRoom> room = GamesRoomManager.instance.getRoom(roomId);
|
Optional<GamesRoom> room = managerFactory.gamesRoomManager().getRoom(roomId);
|
||||||
return room.flatMap(r -> r.getTable(tableId)).orElse(null);
|
return room.flatMap(r -> r.getTable(tableId)).orElse(null);
|
||||||
|
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
|
@ -410,22 +412,12 @@ public class MageServerImpl implements MageServer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean ping(String sessionId, String pingInfo) {
|
public boolean ping(String sessionId, String pingInfo) {
|
||||||
return SessionManager.instance.extendUserSession(sessionId, pingInfo);
|
return managerFactory.sessionManager().extendUserSession(sessionId, pingInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Override
|
|
||||||
// public void deregisterClient(final String sessionId) throws MageException {
|
|
||||||
// execute("deregisterClient", sessionId, new Action() {
|
|
||||||
// @Override
|
|
||||||
// public void execute() {
|
|
||||||
// SessionManager.instance.disconnect(sessionId, true);
|
|
||||||
// logger.debug("Client deregistered ...");
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
@Override
|
@Override
|
||||||
public boolean startMatch(final String sessionId, final UUID roomId, final UUID tableId) throws MageException {
|
public boolean startMatch(final String sessionId, final UUID roomId, final UUID tableId) throws MageException {
|
||||||
Optional<TableController> controller = TableManager.instance.getController(tableId);
|
Optional<TableController> controller = managerFactory.tableManager().getController(tableId);
|
||||||
if (!controller.isPresent()) {
|
if (!controller.isPresent()) {
|
||||||
logger.error("table not found : " + tableId);
|
logger.error("table not found : " + tableId);
|
||||||
return false;
|
return false;
|
||||||
|
@ -434,30 +426,20 @@ public class MageServerImpl implements MageServer {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
execute("startMatch", sessionId, () -> {
|
execute("startMatch", sessionId, () -> {
|
||||||
Optional<Session> session = SessionManager.instance.getSession(sessionId);
|
Optional<Session> session = managerFactory.sessionManager().getSession(sessionId);
|
||||||
if (!session.isPresent()) {
|
if (!session.isPresent()) {
|
||||||
logger.error("Session not found : " + sessionId);
|
logger.error("Session not found : " + sessionId);
|
||||||
} else {
|
} else {
|
||||||
UUID userId = session.get().getUserId();
|
UUID userId = session.get().getUserId();
|
||||||
TableManager.instance.startMatch(userId, roomId, tableId);
|
managerFactory.tableManager().startMatch(userId, roomId, tableId);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Override
|
|
||||||
// public void startChallenge(final String sessionId, final UUID roomId, final UUID tableId, final UUID challengeId) throws MageException {
|
|
||||||
// execute("startChallenge", sessionId, new Action() {
|
|
||||||
// @Override
|
|
||||||
// public void execute() {
|
|
||||||
// UUID userId = SessionManager.instance.getSession(sessionId).getUserId();
|
|
||||||
// TableManager.instance.startChallenge(userId, roomId, tableId, challengeId);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
@Override
|
@Override
|
||||||
public boolean startTournament(final String sessionId, final UUID roomId, final UUID tableId) throws MageException {
|
public boolean startTournament(final String sessionId, final UUID roomId, final UUID tableId) throws MageException {
|
||||||
Optional<TableController> controller = TableManager.instance.getController(tableId);
|
Optional<TableController> controller = managerFactory.tableManager().getController(tableId);
|
||||||
if (!controller.isPresent()) {
|
if (!controller.isPresent()) {
|
||||||
logger.error("table not found : " + tableId);
|
logger.error("table not found : " + tableId);
|
||||||
return false;
|
return false;
|
||||||
|
@ -466,12 +448,12 @@ public class MageServerImpl implements MageServer {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
execute("startTournament", sessionId, () -> {
|
execute("startTournament", sessionId, () -> {
|
||||||
Optional<Session> session = SessionManager.instance.getSession(sessionId);
|
Optional<Session> session = managerFactory.sessionManager().getSession(sessionId);
|
||||||
if (!session.isPresent()) {
|
if (!session.isPresent()) {
|
||||||
logger.error("Session not found : " + sessionId);
|
logger.error("Session not found : " + sessionId);
|
||||||
} else {
|
} else {
|
||||||
UUID userId = session.get().getUserId();
|
UUID userId = session.get().getUserId();
|
||||||
TableManager.instance.startTournament(userId, roomId, tableId);
|
managerFactory.tableManager().startTournament(userId, roomId, tableId);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
|
@ -481,7 +463,7 @@ public class MageServerImpl implements MageServer {
|
||||||
//FIXME: why no sessionId here???
|
//FIXME: why no sessionId here???
|
||||||
public TournamentView getTournament(UUID tournamentId) throws MageException {
|
public TournamentView getTournament(UUID tournamentId) throws MageException {
|
||||||
try {
|
try {
|
||||||
return TournamentManager.instance.getTournamentView(tournamentId);
|
return managerFactory.tournamentManager().getTournamentView(tournamentId);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
handleException(ex);
|
handleException(ex);
|
||||||
}
|
}
|
||||||
|
@ -493,7 +475,7 @@ public class MageServerImpl implements MageServer {
|
||||||
public void sendChatMessage(final UUID chatId, final String userName, final String message) throws MageException {
|
public void sendChatMessage(final UUID chatId, final String userName, final String message) throws MageException {
|
||||||
try {
|
try {
|
||||||
callExecutor.execute(
|
callExecutor.execute(
|
||||||
() -> ChatManager.instance.broadcast(chatId, userName, StringEscapeUtils.escapeHtml4(message), MessageColor.BLUE, true, null, ChatMessage.MessageType.TALK, null)
|
() -> managerFactory.chatManager().broadcast(chatId, userName, StringEscapeUtils.escapeHtml4(message), MessageColor.BLUE, true, null, ChatMessage.MessageType.TALK, null)
|
||||||
);
|
);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
handleException(ex);
|
handleException(ex);
|
||||||
|
@ -503,10 +485,10 @@ public class MageServerImpl implements MageServer {
|
||||||
@Override
|
@Override
|
||||||
public void joinChat(final UUID chatId, final String sessionId, final String userName) throws MageException {
|
public void joinChat(final UUID chatId, final String sessionId, final String userName) throws MageException {
|
||||||
execute("joinChat", sessionId, () -> {
|
execute("joinChat", sessionId, () -> {
|
||||||
SessionManager.instance.getSession(sessionId).ifPresent(session -> {
|
managerFactory.sessionManager().getSession(sessionId).ifPresent(session -> {
|
||||||
|
|
||||||
UUID userId = session.getUserId();
|
UUID userId = session.getUserId();
|
||||||
ChatManager.instance.joinChat(chatId, userId);
|
managerFactory.chatManager().joinChat(chatId, userId);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -515,9 +497,9 @@ public class MageServerImpl implements MageServer {
|
||||||
public void leaveChat(final UUID chatId, final String sessionId) throws MageException {
|
public void leaveChat(final UUID chatId, final String sessionId) throws MageException {
|
||||||
execute("leaveChat", sessionId, () -> {
|
execute("leaveChat", sessionId, () -> {
|
||||||
if (chatId != null) {
|
if (chatId != null) {
|
||||||
SessionManager.instance.getSession(sessionId).ifPresent(session -> {
|
managerFactory.sessionManager().getSession(sessionId).ifPresent(session -> {
|
||||||
UUID userId = session.getUserId();
|
UUID userId = session.getUserId();
|
||||||
ChatManager.instance.leaveChat(chatId, userId);
|
managerFactory.chatManager().leaveChat(chatId, userId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -527,7 +509,7 @@ public class MageServerImpl implements MageServer {
|
||||||
//FIXME: why no sessionId here???
|
//FIXME: why no sessionId here???
|
||||||
public UUID getMainRoomId() throws MageException {
|
public UUID getMainRoomId() throws MageException {
|
||||||
try {
|
try {
|
||||||
return GamesRoomManager.instance.getMainRoomId();
|
return managerFactory.gamesRoomManager().getMainRoomId();
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
handleException(ex);
|
handleException(ex);
|
||||||
}
|
}
|
||||||
|
@ -538,7 +520,7 @@ public class MageServerImpl implements MageServer {
|
||||||
//FIXME: why no sessionId here???
|
//FIXME: why no sessionId here???
|
||||||
public UUID getRoomChatId(UUID roomId) throws MageException {
|
public UUID getRoomChatId(UUID roomId) throws MageException {
|
||||||
try {
|
try {
|
||||||
Optional<GamesRoom> room = GamesRoomManager.instance.getRoom(roomId);
|
Optional<GamesRoom> room = managerFactory.gamesRoomManager().getRoom(roomId);
|
||||||
if (!room.isPresent()) {
|
if (!room.isPresent()) {
|
||||||
logger.error("roomId not found : " + roomId);
|
logger.error("roomId not found : " + roomId);
|
||||||
return null;
|
return null;
|
||||||
|
@ -555,12 +537,12 @@ public class MageServerImpl implements MageServer {
|
||||||
return executeWithResult("isTableOwner", sessionId, new ActionWithBooleanResult() {
|
return executeWithResult("isTableOwner", sessionId, new ActionWithBooleanResult() {
|
||||||
@Override
|
@Override
|
||||||
public Boolean execute() {
|
public Boolean execute() {
|
||||||
Optional<Session> session = SessionManager.instance.getSession(sessionId);
|
Optional<Session> session = managerFactory.sessionManager().getSession(sessionId);
|
||||||
if (!session.isPresent()) {
|
if (!session.isPresent()) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
UUID userId = session.get().getUserId();
|
UUID userId = session.get().getUserId();
|
||||||
return TableManager.instance.isTableOwner(tableId, userId);
|
return managerFactory.tableManager().isTableOwner(tableId, userId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -569,16 +551,16 @@ public class MageServerImpl implements MageServer {
|
||||||
@Override
|
@Override
|
||||||
public void swapSeats(final String sessionId, final UUID roomId, final UUID tableId, final int seatNum1, final int seatNum2) throws MageException {
|
public void swapSeats(final String sessionId, final UUID roomId, final UUID tableId, final int seatNum1, final int seatNum2) throws MageException {
|
||||||
execute("swapSeats", sessionId, () -> {
|
execute("swapSeats", sessionId, () -> {
|
||||||
SessionManager.instance.getSession(sessionId).ifPresent(session -> {
|
managerFactory.sessionManager().getSession(sessionId).ifPresent(session -> {
|
||||||
UUID userId = session.getUserId();
|
UUID userId = session.getUserId();
|
||||||
TableManager.instance.swapSeats(tableId, userId, seatNum1, seatNum2);
|
managerFactory.tableManager().swapSeats(tableId, userId, seatNum1, seatNum2);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean leaveTable(final String sessionId, final UUID roomId, final UUID tableId) throws MageException {
|
public boolean leaveTable(final String sessionId, final UUID roomId, final UUID tableId) throws MageException {
|
||||||
Optional<TableController> tableController = TableManager.instance.getController(tableId);
|
Optional<TableController> tableController = managerFactory.tableManager().getController(tableId);
|
||||||
if (tableController.isPresent()) {
|
if (tableController.isPresent()) {
|
||||||
TableState tableState = tableController.get().getTableState();
|
TableState tableState = tableController.get().getTableState();
|
||||||
if (tableState != TableState.WAITING && tableState != TableState.READY_TO_START) {
|
if (tableState != TableState.WAITING && tableState != TableState.READY_TO_START) {
|
||||||
|
@ -586,9 +568,9 @@ public class MageServerImpl implements MageServer {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
execute("leaveTable", sessionId, () -> {
|
execute("leaveTable", sessionId, () -> {
|
||||||
SessionManager.instance.getSession(sessionId).ifPresent(session -> {
|
managerFactory.sessionManager().getSession(sessionId).ifPresent(session -> {
|
||||||
UUID userId = session.getUserId();
|
UUID userId = session.getUserId();
|
||||||
GamesRoomManager.instance.getRoom(roomId).ifPresent(room ->
|
managerFactory.gamesRoomManager().getRoom(roomId).ifPresent(room ->
|
||||||
room.leaveTable(userId, tableId));
|
room.leaveTable(userId, tableId));
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -604,7 +586,7 @@ public class MageServerImpl implements MageServer {
|
||||||
//FIXME: why no sessionId here???
|
//FIXME: why no sessionId here???
|
||||||
public UUID getTableChatId(UUID tableId) throws MageException {
|
public UUID getTableChatId(UUID tableId) throws MageException {
|
||||||
try {
|
try {
|
||||||
return TableManager.instance.getChatId(tableId).orElse(null);
|
return managerFactory.tableManager().getChatId(tableId).orElse(null);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
handleException(ex);
|
handleException(ex);
|
||||||
}
|
}
|
||||||
|
@ -614,9 +596,9 @@ public class MageServerImpl implements MageServer {
|
||||||
@Override
|
@Override
|
||||||
public void joinGame(final UUID gameId, final String sessionId) throws MageException {
|
public void joinGame(final UUID gameId, final String sessionId) throws MageException {
|
||||||
execute("joinGame", sessionId, () -> {
|
execute("joinGame", sessionId, () -> {
|
||||||
SessionManager.instance.getSession(sessionId).ifPresent(session -> {
|
managerFactory.sessionManager().getSession(sessionId).ifPresent(session -> {
|
||||||
UUID userId = session.getUserId();
|
UUID userId = session.getUserId();
|
||||||
GameManager.instance.joinGame(gameId, userId);
|
managerFactory.gameManager().joinGame(gameId, userId);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -624,9 +606,9 @@ public class MageServerImpl implements MageServer {
|
||||||
@Override
|
@Override
|
||||||
public void joinDraft(final UUID draftId, final String sessionId) throws MageException {
|
public void joinDraft(final UUID draftId, final String sessionId) throws MageException {
|
||||||
execute("joinDraft", sessionId, () -> {
|
execute("joinDraft", sessionId, () -> {
|
||||||
SessionManager.instance.getSession(sessionId).ifPresent(session -> {
|
managerFactory.sessionManager().getSession(sessionId).ifPresent(session -> {
|
||||||
UUID userId = session.getUserId();
|
UUID userId = session.getUserId();
|
||||||
DraftManager.instance.joinDraft(draftId, userId);
|
managerFactory.draftManager().joinDraft(draftId, userId);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -634,12 +616,12 @@ public class MageServerImpl implements MageServer {
|
||||||
@Override
|
@Override
|
||||||
public void joinTournament(final UUID tournamentId, final String sessionId) throws MageException {
|
public void joinTournament(final UUID tournamentId, final String sessionId) throws MageException {
|
||||||
execute("joinTournament", sessionId, () -> {
|
execute("joinTournament", sessionId, () -> {
|
||||||
Optional<Session> session = SessionManager.instance.getSession(sessionId);
|
Optional<Session> session = managerFactory.sessionManager().getSession(sessionId);
|
||||||
if (!session.isPresent()) {
|
if (!session.isPresent()) {
|
||||||
logger.error("Session not found : " + sessionId);
|
logger.error("Session not found : " + sessionId);
|
||||||
} else {
|
} else {
|
||||||
UUID userId = session.get().getUserId();
|
UUID userId = session.get().getUserId();
|
||||||
TournamentManager.instance.joinTournament(tournamentId, userId);
|
managerFactory.tournamentManager().joinTournament(tournamentId, userId);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -648,7 +630,7 @@ public class MageServerImpl implements MageServer {
|
||||||
//FIXME: why no sessionId here???
|
//FIXME: why no sessionId here???
|
||||||
public UUID getGameChatId(UUID gameId) throws MageException {
|
public UUID getGameChatId(UUID gameId) throws MageException {
|
||||||
try {
|
try {
|
||||||
return GameManager.instance.getChatId(gameId).orElse(null);
|
return managerFactory.gameManager().getChatId(gameId).orElse(null);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
handleException(ex);
|
handleException(ex);
|
||||||
}
|
}
|
||||||
|
@ -659,7 +641,7 @@ public class MageServerImpl implements MageServer {
|
||||||
//FIXME: why no sessionId here???
|
//FIXME: why no sessionId here???
|
||||||
public UUID getTournamentChatId(UUID tournamentId) throws MageException {
|
public UUID getTournamentChatId(UUID tournamentId) throws MageException {
|
||||||
try {
|
try {
|
||||||
return TournamentManager.instance.getChatId(tournamentId).orElse(null);
|
return managerFactory.tournamentManager().getChatId(tournamentId).orElse(null);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
handleException(ex);
|
handleException(ex);
|
||||||
}
|
}
|
||||||
|
@ -669,9 +651,8 @@ public class MageServerImpl implements MageServer {
|
||||||
@Override
|
@Override
|
||||||
public void sendPlayerUUID(final UUID gameId, final String sessionId, final UUID data) throws MageException {
|
public void sendPlayerUUID(final UUID gameId, final String sessionId, final UUID data) throws MageException {
|
||||||
execute("sendPlayerUUID", sessionId, () -> {
|
execute("sendPlayerUUID", sessionId, () -> {
|
||||||
Optional<User> user = SessionManager.instance.getUser(sessionId);
|
Optional<User> user = managerFactory.sessionManager().getUser(sessionId);
|
||||||
if (user.isPresent()) {
|
if (user.isPresent()) {
|
||||||
// logger.warn("sendPlayerUUID gameId=" + gameId + " sessionId=" + sessionId + " username=" + user.getName());
|
|
||||||
user.get().sendPlayerUUID(gameId, data);
|
user.get().sendPlayerUUID(gameId, data);
|
||||||
} else {
|
} else {
|
||||||
logger.warn("Your session expired: gameId=" + gameId + ", sessionId=" + sessionId);
|
logger.warn("Your session expired: gameId=" + gameId + ", sessionId=" + sessionId);
|
||||||
|
@ -682,7 +663,7 @@ public class MageServerImpl implements MageServer {
|
||||||
@Override
|
@Override
|
||||||
public void sendPlayerString(final UUID gameId, final String sessionId, final String data) throws MageException {
|
public void sendPlayerString(final UUID gameId, final String sessionId, final String data) throws MageException {
|
||||||
execute("sendPlayerString", sessionId, () -> {
|
execute("sendPlayerString", sessionId, () -> {
|
||||||
Optional<User> user = SessionManager.instance.getUser(sessionId);
|
Optional<User> user = managerFactory.sessionManager().getUser(sessionId);
|
||||||
if (user.isPresent()) {
|
if (user.isPresent()) {
|
||||||
user.get().sendPlayerString(gameId, data);
|
user.get().sendPlayerString(gameId, data);
|
||||||
} else {
|
} else {
|
||||||
|
@ -694,7 +675,7 @@ public class MageServerImpl implements MageServer {
|
||||||
@Override
|
@Override
|
||||||
public void sendPlayerManaType(final UUID gameId, final UUID playerId, final String sessionId, final ManaType data) throws MageException {
|
public void sendPlayerManaType(final UUID gameId, final UUID playerId, final String sessionId, final ManaType data) throws MageException {
|
||||||
execute("sendPlayerManaType", sessionId, () -> {
|
execute("sendPlayerManaType", sessionId, () -> {
|
||||||
Optional<User> user = SessionManager.instance.getUser(sessionId);
|
Optional<User> user = managerFactory.sessionManager().getUser(sessionId);
|
||||||
if (user.isPresent()) {
|
if (user.isPresent()) {
|
||||||
user.get().sendPlayerManaType(gameId, playerId, data);
|
user.get().sendPlayerManaType(gameId, playerId, data);
|
||||||
} else {
|
} else {
|
||||||
|
@ -706,7 +687,7 @@ public class MageServerImpl implements MageServer {
|
||||||
@Override
|
@Override
|
||||||
public void sendPlayerBoolean(final UUID gameId, final String sessionId, final Boolean data) throws MageException {
|
public void sendPlayerBoolean(final UUID gameId, final String sessionId, final Boolean data) throws MageException {
|
||||||
execute("sendPlayerBoolean", sessionId, () -> {
|
execute("sendPlayerBoolean", sessionId, () -> {
|
||||||
Optional<User> user = SessionManager.instance.getUser(sessionId);
|
Optional<User> user = managerFactory.sessionManager().getUser(sessionId);
|
||||||
if (user.isPresent()) {
|
if (user.isPresent()) {
|
||||||
user.get().sendPlayerBoolean(gameId, data);
|
user.get().sendPlayerBoolean(gameId, data);
|
||||||
} else {
|
} else {
|
||||||
|
@ -718,7 +699,7 @@ public class MageServerImpl implements MageServer {
|
||||||
@Override
|
@Override
|
||||||
public void sendPlayerInteger(final UUID gameId, final String sessionId, final Integer data) throws MageException {
|
public void sendPlayerInteger(final UUID gameId, final String sessionId, final Integer data) throws MageException {
|
||||||
execute("sendPlayerInteger", sessionId, () -> {
|
execute("sendPlayerInteger", sessionId, () -> {
|
||||||
Optional<User> user = SessionManager.instance.getUser(sessionId);
|
Optional<User> user = managerFactory.sessionManager().getUser(sessionId);
|
||||||
if (user.isPresent()) {
|
if (user.isPresent()) {
|
||||||
user.get().sendPlayerInteger(gameId, data);
|
user.get().sendPlayerInteger(gameId, data);
|
||||||
} else {
|
} else {
|
||||||
|
@ -735,9 +716,9 @@ public class MageServerImpl implements MageServer {
|
||||||
@Override
|
@Override
|
||||||
public void sendCardMark(final UUID draftId, final String sessionId, final UUID cardPick) throws MageException {
|
public void sendCardMark(final UUID draftId, final String sessionId, final UUID cardPick) throws MageException {
|
||||||
execute("sendCardMark", sessionId, () -> {
|
execute("sendCardMark", sessionId, () -> {
|
||||||
SessionManager.instance.getSession(sessionId).ifPresent(session -> {
|
managerFactory.sessionManager().getSession(sessionId).ifPresent(session -> {
|
||||||
UUID userId = session.getUserId();
|
UUID userId = session.getUserId();
|
||||||
DraftManager.instance.sendCardMark(draftId, userId, cardPick);
|
managerFactory.draftManager().sendCardMark(draftId, userId, cardPick);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -748,9 +729,9 @@ public class MageServerImpl implements MageServer {
|
||||||
try {
|
try {
|
||||||
callExecutor.execute(
|
callExecutor.execute(
|
||||||
() -> {
|
() -> {
|
||||||
SessionManager.instance.getSession(sessionId).ifPresent(session -> {
|
managerFactory.sessionManager().getSession(sessionId).ifPresent(session -> {
|
||||||
UUID userId = session.getUserId();
|
UUID userId = session.getUserId();
|
||||||
GameManager.instance.quitMatch(gameId, userId);
|
managerFactory.gameManager().quitMatch(gameId, userId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -766,10 +747,10 @@ public class MageServerImpl implements MageServer {
|
||||||
try {
|
try {
|
||||||
callExecutor.execute(
|
callExecutor.execute(
|
||||||
() -> {
|
() -> {
|
||||||
SessionManager.instance.getSession(sessionId).ifPresent(session -> {
|
managerFactory.sessionManager().getSession(sessionId).ifPresent(session -> {
|
||||||
UUID userId = session.getUserId();
|
UUID userId = session.getUserId();
|
||||||
|
|
||||||
TournamentManager.instance.quit(tournamentId, userId);
|
managerFactory.tournamentManager().quit(tournamentId, userId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -786,14 +767,14 @@ public class MageServerImpl implements MageServer {
|
||||||
try {
|
try {
|
||||||
callExecutor.execute(
|
callExecutor.execute(
|
||||||
() -> {
|
() -> {
|
||||||
SessionManager.instance.getSession(sessionId).ifPresent(
|
managerFactory.sessionManager().getSession(sessionId).ifPresent(
|
||||||
session -> {
|
session -> {
|
||||||
UUID userId = session.getUserId();
|
UUID userId = session.getUserId();
|
||||||
UUID tableId = DraftManager.instance.getControllerByDraftId(draftId).getTableId();
|
UUID tableId = managerFactory.draftManager().getControllerByDraftId(draftId).getTableId();
|
||||||
Table table = TableManager.instance.getTable(tableId);
|
Table table = managerFactory.tableManager().getTable(tableId);
|
||||||
if (table.isTournament()) {
|
if (table.isTournament()) {
|
||||||
UUID tournamentId = table.getTournament().getId();
|
UUID tournamentId = table.getTournament().getId();
|
||||||
TournamentManager.instance.quit(tournamentId, userId);
|
managerFactory.tournamentManager().quit(tournamentId, userId);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -808,9 +789,9 @@ public class MageServerImpl implements MageServer {
|
||||||
@Override
|
@Override
|
||||||
public void sendPlayerAction(final PlayerAction playerAction, final UUID gameId, final String sessionId, final Object data) throws MageException {
|
public void sendPlayerAction(final PlayerAction playerAction, final UUID gameId, final String sessionId, final Object data) throws MageException {
|
||||||
execute("sendPlayerAction", sessionId, () -> {
|
execute("sendPlayerAction", sessionId, () -> {
|
||||||
SessionManager.instance.getSession(sessionId).ifPresent(session -> {
|
managerFactory.sessionManager().getSession(sessionId).ifPresent(session -> {
|
||||||
UUID userId = session.getUserId();
|
UUID userId = session.getUserId();
|
||||||
GameManager.instance.sendPlayerAction(playerAction, gameId, userId, data);
|
managerFactory.gameManager().sendPlayerAction(playerAction, gameId, userId, data);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -820,14 +801,14 @@ public class MageServerImpl implements MageServer {
|
||||||
return executeWithResult("setUserData", sessionId, new ActionWithBooleanResult() {
|
return executeWithResult("setUserData", sessionId, new ActionWithBooleanResult() {
|
||||||
@Override
|
@Override
|
||||||
public Boolean execute() throws MageException {
|
public Boolean execute() throws MageException {
|
||||||
Optional<Session> session = SessionManager.instance.getSession(sessionId);
|
Optional<Session> session = managerFactory.sessionManager().getSession(sessionId);
|
||||||
if (!session.isPresent()) {
|
if (!session.isPresent()) {
|
||||||
logger.error("Session not found : " + sessionId);
|
logger.error("Session not found : " + sessionId);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
UUID userId = session.get().getUserId();
|
UUID userId = session.get().getUserId();
|
||||||
if (GamesRoomManager.instance.getRoom(roomId).isPresent()) {
|
if (managerFactory.gamesRoomManager().getRoom(roomId).isPresent()) {
|
||||||
return GamesRoomManager.instance.getRoom(roomId).get().watchTable(userId, tableId);
|
return managerFactory.gamesRoomManager().getRoom(roomId).get().watchTable(userId, tableId);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -846,10 +827,10 @@ public class MageServerImpl implements MageServer {
|
||||||
return executeWithResult("watchGame", sessionId, new ActionWithResult<Boolean>() {
|
return executeWithResult("watchGame", sessionId, new ActionWithResult<Boolean>() {
|
||||||
@Override
|
@Override
|
||||||
public Boolean execute() throws MageException {
|
public Boolean execute() throws MageException {
|
||||||
return SessionManager.instance.getSession(sessionId)
|
return managerFactory.sessionManager().getSession(sessionId)
|
||||||
.map(session -> {
|
.map(session -> {
|
||||||
UUID userId = session.getUserId();
|
UUID userId = session.getUserId();
|
||||||
return GameManager.instance.watchGame(gameId, userId);
|
return managerFactory.gameManager().watchGame(gameId, userId);
|
||||||
}).orElse(false);
|
}).orElse(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -863,10 +844,10 @@ public class MageServerImpl implements MageServer {
|
||||||
@Override
|
@Override
|
||||||
public void stopWatching(final UUID gameId, final String sessionId) throws MageException {
|
public void stopWatching(final UUID gameId, final String sessionId) throws MageException {
|
||||||
execute("stopWatching", sessionId, () -> {
|
execute("stopWatching", sessionId, () -> {
|
||||||
SessionManager.instance.getSession(sessionId).ifPresent(session -> {
|
managerFactory.sessionManager().getSession(sessionId).ifPresent(session -> {
|
||||||
UUID userId = session.getUserId();
|
UUID userId = session.getUserId();
|
||||||
UserManager.instance.getUser(userId).ifPresent(user -> {
|
managerFactory.userManager().getUser(userId).ifPresent(user -> {
|
||||||
GameManager.instance.stopWatching(gameId, userId);
|
managerFactory.gameManager().stopWatching(gameId, userId);
|
||||||
user.removeGameWatchInfo(gameId);
|
user.removeGameWatchInfo(gameId);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -877,9 +858,9 @@ public class MageServerImpl implements MageServer {
|
||||||
@Override
|
@Override
|
||||||
public void replayGame(final UUID gameId, final String sessionId) throws MageException {
|
public void replayGame(final UUID gameId, final String sessionId) throws MageException {
|
||||||
execute("replayGame", sessionId, () -> {
|
execute("replayGame", sessionId, () -> {
|
||||||
SessionManager.instance.getSession(sessionId).ifPresent(session -> {
|
managerFactory.sessionManager().getSession(sessionId).ifPresent(session -> {
|
||||||
UUID userId = session.getUserId();
|
UUID userId = session.getUserId();
|
||||||
ReplayManager.instance.replayGame(gameId, userId);
|
managerFactory.replayManager().replayGame(gameId, userId);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -887,9 +868,9 @@ public class MageServerImpl implements MageServer {
|
||||||
@Override
|
@Override
|
||||||
public void startReplay(final UUID gameId, final String sessionId) throws MageException {
|
public void startReplay(final UUID gameId, final String sessionId) throws MageException {
|
||||||
execute("startReplay", sessionId, () -> {
|
execute("startReplay", sessionId, () -> {
|
||||||
SessionManager.instance.getSession(sessionId).ifPresent(session -> {
|
managerFactory.sessionManager().getSession(sessionId).ifPresent(session -> {
|
||||||
UUID userId = session.getUserId();
|
UUID userId = session.getUserId();
|
||||||
ReplayManager.instance.startReplay(gameId, userId);
|
managerFactory.replayManager().startReplay(gameId, userId);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -897,12 +878,12 @@ public class MageServerImpl implements MageServer {
|
||||||
@Override
|
@Override
|
||||||
public void stopReplay(final UUID gameId, final String sessionId) throws MageException {
|
public void stopReplay(final UUID gameId, final String sessionId) throws MageException {
|
||||||
execute("stopReplay", sessionId, () -> {
|
execute("stopReplay", sessionId, () -> {
|
||||||
Optional<Session> session = SessionManager.instance.getSession(sessionId);
|
Optional<Session> session = managerFactory.sessionManager().getSession(sessionId);
|
||||||
if (!session.isPresent()) {
|
if (!session.isPresent()) {
|
||||||
logger.error("Session not found : " + sessionId);
|
logger.error("Session not found : " + sessionId);
|
||||||
} else {
|
} else {
|
||||||
UUID userId = session.get().getUserId();
|
UUID userId = session.get().getUserId();
|
||||||
ReplayManager.instance.stopReplay(gameId, userId);
|
managerFactory.replayManager().stopReplay(gameId, userId);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -910,12 +891,12 @@ public class MageServerImpl implements MageServer {
|
||||||
@Override
|
@Override
|
||||||
public void nextPlay(final UUID gameId, final String sessionId) throws MageException {
|
public void nextPlay(final UUID gameId, final String sessionId) throws MageException {
|
||||||
execute("nextPlay", sessionId, () -> {
|
execute("nextPlay", sessionId, () -> {
|
||||||
Optional<Session> session = SessionManager.instance.getSession(sessionId);
|
Optional<Session> session = managerFactory.sessionManager().getSession(sessionId);
|
||||||
if (!session.isPresent()) {
|
if (!session.isPresent()) {
|
||||||
logger.error("Session not found : " + sessionId);
|
logger.error("Session not found : " + sessionId);
|
||||||
} else {
|
} else {
|
||||||
UUID userId = session.get().getUserId();
|
UUID userId = session.get().getUserId();
|
||||||
ReplayManager.instance.nextPlay(gameId, userId);
|
managerFactory.replayManager().nextPlay(gameId, userId);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -923,12 +904,12 @@ public class MageServerImpl implements MageServer {
|
||||||
@Override
|
@Override
|
||||||
public void previousPlay(final UUID gameId, final String sessionId) throws MageException {
|
public void previousPlay(final UUID gameId, final String sessionId) throws MageException {
|
||||||
execute("previousPlay", sessionId, () -> {
|
execute("previousPlay", sessionId, () -> {
|
||||||
Optional<Session> session = SessionManager.instance.getSession(sessionId);
|
Optional<Session> session = managerFactory.sessionManager().getSession(sessionId);
|
||||||
if (!session.isPresent()) {
|
if (!session.isPresent()) {
|
||||||
logger.error("Session not found : " + sessionId);
|
logger.error("Session not found : " + sessionId);
|
||||||
} else {
|
} else {
|
||||||
UUID userId = session.get().getUserId();
|
UUID userId = session.get().getUserId();
|
||||||
ReplayManager.instance.previousPlay(gameId, userId);
|
managerFactory.replayManager().previousPlay(gameId, userId);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -936,12 +917,12 @@ public class MageServerImpl implements MageServer {
|
||||||
@Override
|
@Override
|
||||||
public void skipForward(final UUID gameId, final String sessionId, final int moves) throws MageException {
|
public void skipForward(final UUID gameId, final String sessionId, final int moves) throws MageException {
|
||||||
execute("skipForward", sessionId, () -> {
|
execute("skipForward", sessionId, () -> {
|
||||||
Optional<Session> session = SessionManager.instance.getSession(sessionId);
|
Optional<Session> session = managerFactory.sessionManager().getSession(sessionId);
|
||||||
if (!session.isPresent()) {
|
if (!session.isPresent()) {
|
||||||
logger.error("Session not found : " + sessionId);
|
logger.error("Session not found : " + sessionId);
|
||||||
} else {
|
} else {
|
||||||
UUID userId = session.get().getUserId();
|
UUID userId = session.get().getUserId();
|
||||||
ReplayManager.instance.skipForward(gameId, userId, moves);
|
managerFactory.replayManager().skipForward(gameId, userId, moves);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -971,9 +952,9 @@ public class MageServerImpl implements MageServer {
|
||||||
public void cheat(final UUID gameId, final String sessionId, final UUID playerId, final DeckCardLists deckList) throws MageException {
|
public void cheat(final UUID gameId, final String sessionId, final UUID playerId, final DeckCardLists deckList) throws MageException {
|
||||||
execute("cheat", sessionId, () -> {
|
execute("cheat", sessionId, () -> {
|
||||||
if (testMode) {
|
if (testMode) {
|
||||||
SessionManager.instance.getSession(sessionId).ifPresent(session -> {
|
managerFactory.sessionManager().getSession(sessionId).ifPresent(session -> {
|
||||||
UUID userId = session.getUserId();
|
UUID userId = session.getUserId();
|
||||||
GameManager.instance.cheat(gameId, userId, playerId, deckList);
|
managerFactory.gameManager().cheat(gameId, userId, playerId, deckList);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -985,12 +966,12 @@ public class MageServerImpl implements MageServer {
|
||||||
@Override
|
@Override
|
||||||
public Boolean execute() {
|
public Boolean execute() {
|
||||||
if (testMode) {
|
if (testMode) {
|
||||||
Optional<Session> session = SessionManager.instance.getSession(sessionId);
|
Optional<Session> session = managerFactory.sessionManager().getSession(sessionId);
|
||||||
if (!session.isPresent()) {
|
if (!session.isPresent()) {
|
||||||
logger.error("Session not found : " + sessionId);
|
logger.error("Session not found : " + sessionId);
|
||||||
} else {
|
} else {
|
||||||
UUID userId = session.get().getUserId();
|
UUID userId = session.get().getUserId();
|
||||||
return GameManager.instance.cheat(gameId, userId, playerId, cardName);
|
return managerFactory.gameManager().cheat(gameId, userId, playerId, cardName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -1024,13 +1005,13 @@ public class MageServerImpl implements MageServer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void disconnectUser(final String sessionId, final String userSessionId) throws MageException {
|
public void disconnectUser(final String sessionId, final String userSessionId) throws MageException {
|
||||||
execute("disconnectUser", sessionId, () -> SessionManager.instance.disconnectUser(sessionId, userSessionId));
|
execute("disconnectUser", sessionId, () -> managerFactory.sessionManager().disconnectUser(sessionId, userSessionId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void muteUser(final String sessionId, final String userName, final long durationMinutes) throws MageException {
|
public void muteUser(final String sessionId, final String userName, final long durationMinutes) throws MageException {
|
||||||
execute("muteUser", sessionId, () -> {
|
execute("muteUser", sessionId, () -> {
|
||||||
UserManager.instance.getUserByName(userName).ifPresent(user -> {
|
managerFactory.userManager().getUserByName(userName).ifPresent(user -> {
|
||||||
Date muteUntil = new Date(Calendar.getInstance().getTimeInMillis() + (durationMinutes * Timer.ONE_MINUTE));
|
Date muteUntil = new Date(Calendar.getInstance().getTimeInMillis() + (durationMinutes * Timer.ONE_MINUTE));
|
||||||
user.showUserMessage("Admin info", "You were muted for chat messages until " + SystemUtil.dateFormat.format(muteUntil) + '.');
|
user.showUserMessage("Admin info", "You were muted for chat messages until " + SystemUtil.dateFormat.format(muteUntil) + '.');
|
||||||
user.setChatLockedUntil(muteUntil);
|
user.setChatLockedUntil(muteUntil);
|
||||||
|
@ -1042,12 +1023,12 @@ public class MageServerImpl implements MageServer {
|
||||||
@Override
|
@Override
|
||||||
public void lockUser(final String sessionId, final String userName, final long durationMinutes) throws MageException {
|
public void lockUser(final String sessionId, final String userName, final long durationMinutes) throws MageException {
|
||||||
execute("lockUser", sessionId, () -> {
|
execute("lockUser", sessionId, () -> {
|
||||||
UserManager.instance.getUserByName(userName).ifPresent(user -> {
|
managerFactory.userManager().getUserByName(userName).ifPresent(user -> {
|
||||||
Date lockUntil = new Date(Calendar.getInstance().getTimeInMillis() + (durationMinutes * Timer.ONE_MINUTE));
|
Date lockUntil = new Date(Calendar.getInstance().getTimeInMillis() + (durationMinutes * Timer.ONE_MINUTE));
|
||||||
user.showUserMessage("Admin info", "Your user profile was locked until " + SystemUtil.dateFormat.format(lockUntil) + '.');
|
user.showUserMessage("Admin info", "Your user profile was locked until " + SystemUtil.dateFormat.format(lockUntil) + '.');
|
||||||
user.setLockedUntil(lockUntil);
|
user.setLockedUntil(lockUntil);
|
||||||
if (user.isConnected()) {
|
if (user.isConnected()) {
|
||||||
SessionManager.instance.disconnectUser(sessionId, user.getSessionId());
|
managerFactory.sessionManager().disconnectUser(sessionId, user.getSessionId());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1058,15 +1039,15 @@ public class MageServerImpl implements MageServer {
|
||||||
public void setActivation(final String sessionId, final String userName, boolean active) throws MageException {
|
public void setActivation(final String sessionId, final String userName, boolean active) throws MageException {
|
||||||
execute("setActivation", sessionId, () -> {
|
execute("setActivation", sessionId, () -> {
|
||||||
AuthorizedUser authorizedUser = AuthorizedUserRepository.instance.getByName(userName);
|
AuthorizedUser authorizedUser = AuthorizedUserRepository.instance.getByName(userName);
|
||||||
Optional<User> u = UserManager.instance.getUserByName(userName);
|
Optional<User> u = managerFactory.userManager().getUserByName(userName);
|
||||||
if (u.isPresent()) {
|
if (u.isPresent()) {
|
||||||
User user = u.get();
|
User user = u.get();
|
||||||
user.setActive(active);
|
user.setActive(active);
|
||||||
if (!user.isActive() && user.isConnected()) {
|
if (!user.isActive() && user.isConnected()) {
|
||||||
SessionManager.instance.disconnectUser(sessionId, user.getSessionId());
|
managerFactory.sessionManager().disconnectUser(sessionId, user.getSessionId());
|
||||||
}
|
}
|
||||||
} else if (authorizedUser != null) {
|
} else if (authorizedUser != null) {
|
||||||
User theUser = new User(userName, "localhost", authorizedUser);
|
User theUser = new User(managerFactory, userName, "localhost", authorizedUser);
|
||||||
theUser.setActive(active);
|
theUser.setActive(active);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1076,18 +1057,18 @@ public class MageServerImpl implements MageServer {
|
||||||
@Override
|
@Override
|
||||||
public void toggleActivation(final String sessionId, final String userName) throws MageException {
|
public void toggleActivation(final String sessionId, final String userName) throws MageException {
|
||||||
execute("toggleActivation", sessionId, ()
|
execute("toggleActivation", sessionId, ()
|
||||||
-> UserManager.instance.getUserByName(userName).ifPresent(user
|
-> managerFactory.userManager().getUserByName(userName).ifPresent(user
|
||||||
-> {
|
-> {
|
||||||
user.setActive(!user.isActive());
|
user.setActive(!user.isActive());
|
||||||
if (!user.isActive() && user.isConnected()) {
|
if (!user.isActive() && user.isConnected()) {
|
||||||
SessionManager.instance.disconnectUser(sessionId, user.getSessionId());
|
managerFactory.sessionManager().disconnectUser(sessionId, user.getSessionId());
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void endUserSession(final String sessionId, final String userSessionId) throws MageException {
|
public void endUserSession(final String sessionId, final String userSessionId) throws MageException {
|
||||||
execute("endUserSession", sessionId, () -> SessionManager.instance.endUserSession(sessionId, userSessionId));
|
execute("endUserSession", sessionId, () -> managerFactory.sessionManager().endUserSession(sessionId, userSessionId));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1100,9 +1081,9 @@ public class MageServerImpl implements MageServer {
|
||||||
@Override
|
@Override
|
||||||
public void removeTable(final String sessionId, final UUID tableId) throws MageException {
|
public void removeTable(final String sessionId, final UUID tableId) throws MageException {
|
||||||
execute("removeTable", sessionId, () -> {
|
execute("removeTable", sessionId, () -> {
|
||||||
SessionManager.instance.getSession(sessionId).ifPresent(session -> {
|
managerFactory.sessionManager().getSession(sessionId).ifPresent(session -> {
|
||||||
UUID userId = session.getUserId();
|
UUID userId = session.getUserId();
|
||||||
TableManager.instance.removeTable(userId, tableId);
|
managerFactory.tableManager().removeTable(userId, tableId);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1116,7 +1097,7 @@ public class MageServerImpl implements MageServer {
|
||||||
public void sendFeedbackMessage(final String sessionId, final String username, final String title, final String type, final String message, final String email) throws MageException {
|
public void sendFeedbackMessage(final String sessionId, final String username, final String title, final String type, final String message, final String email) throws MageException {
|
||||||
if (title != null && message != null) {
|
if (title != null && message != null) {
|
||||||
execute("sendFeedbackMessage", sessionId, ()
|
execute("sendFeedbackMessage", sessionId, ()
|
||||||
-> SessionManager.instance.getSession(sessionId).ifPresent(
|
-> managerFactory.sessionManager().getSession(sessionId).ifPresent(
|
||||||
session -> FeedbackServiceImpl.instance.feedback(username, title, type, message, email, session.getHost())
|
session -> FeedbackServiceImpl.instance.feedback(username, title, type, message, email, session.getHost())
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -1126,7 +1107,7 @@ public class MageServerImpl implements MageServer {
|
||||||
public void sendBroadcastMessage(final String sessionId, final String message) throws MageException {
|
public void sendBroadcastMessage(final String sessionId, final String message) throws MageException {
|
||||||
if (message != null) {
|
if (message != null) {
|
||||||
execute("sendBroadcastMessage", sessionId, () -> {
|
execute("sendBroadcastMessage", sessionId, () -> {
|
||||||
for (User user : UserManager.instance.getUsers()) {
|
for (User user : managerFactory.userManager().getUsers()) {
|
||||||
if (message.toLowerCase(Locale.ENGLISH).startsWith("warn")) {
|
if (message.toLowerCase(Locale.ENGLISH).startsWith("warn")) {
|
||||||
user.fireCallback(new ClientCallback(ClientCallbackMethod.SERVER_MESSAGE, null, new ChatMessage("SERVER", message, null, null, MessageColor.RED)));
|
user.fireCallback(new ClientCallback(ClientCallbackMethod.SERVER_MESSAGE, null, new ChatMessage("SERVER", message, null, null, MessageColor.RED)));
|
||||||
} else {
|
} else {
|
||||||
|
@ -1138,12 +1119,12 @@ public class MageServerImpl implements MageServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendErrorMessageToClient(final String sessionId, final String message) throws MageException {
|
private void sendErrorMessageToClient(final String sessionId, final String message) throws MageException {
|
||||||
execute("sendErrorMessageToClient", sessionId, () -> SessionManager.instance.sendErrorMessageToClient(sessionId, message));
|
execute("sendErrorMessageToClient", sessionId, () -> managerFactory.sessionManager().sendErrorMessageToClient(sessionId, message));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void execute(final String actionName, final String sessionId, final Action action, boolean checkAdminRights) throws MageException {
|
protected void execute(final String actionName, final String sessionId, final Action action, boolean checkAdminRights) throws MageException {
|
||||||
if (checkAdminRights) {
|
if (checkAdminRights) {
|
||||||
if (!SessionManager.instance.isAdmin(sessionId)) {
|
if (!managerFactory.sessionManager().isAdmin(sessionId)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1151,11 +1132,11 @@ public class MageServerImpl implements MageServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void execute(final String actionName, final String sessionId, final Action action) throws MageException {
|
protected void execute(final String actionName, final String sessionId, final Action action) throws MageException {
|
||||||
if (SessionManager.instance.isValidSession(sessionId)) {
|
if (managerFactory.sessionManager().isValidSession(sessionId)) {
|
||||||
try {
|
try {
|
||||||
callExecutor.execute(
|
callExecutor.execute(
|
||||||
() -> {
|
() -> {
|
||||||
if (SessionManager.instance.isValidSession(sessionId)) {
|
if (managerFactory.sessionManager().isValidSession(sessionId)) {
|
||||||
try {
|
try {
|
||||||
action.execute();
|
action.execute();
|
||||||
} catch (MageException me) {
|
} catch (MageException me) {
|
||||||
|
@ -1172,7 +1153,7 @@ public class MageServerImpl implements MageServer {
|
||||||
|
|
||||||
protected <T> T executeWithResult(String actionName, final String sessionId, final ActionWithResult<T> action, boolean checkAdminRights) throws MageException {
|
protected <T> T executeWithResult(String actionName, final String sessionId, final ActionWithResult<T> action, boolean checkAdminRights) throws MageException {
|
||||||
if (checkAdminRights) {
|
if (checkAdminRights) {
|
||||||
if (!SessionManager.instance.isAdmin(sessionId)) {
|
if (!managerFactory.sessionManager().isAdmin(sessionId)) {
|
||||||
return action.negativeResult();
|
return action.negativeResult();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1181,7 +1162,7 @@ public class MageServerImpl implements MageServer {
|
||||||
|
|
||||||
//TODO: also run in threads with future task
|
//TODO: also run in threads with future task
|
||||||
protected <T> T executeWithResult(String actionName, final String sessionId, final ActionWithResult<T> action) throws MageException {
|
protected <T> T executeWithResult(String actionName, final String sessionId, final ActionWithResult<T> action) throws MageException {
|
||||||
if (SessionManager.instance.isValidSession(sessionId)) {
|
if (managerFactory.sessionManager().isValidSession(sessionId)) {
|
||||||
try {
|
try {
|
||||||
return action.execute();
|
return action.execute();
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
|
@ -1218,15 +1199,15 @@ public class MageServerImpl implements MageServer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ListActionWithNullNegativeResult extends ActionWithNullNegativeResult<List<UserView>> {
|
private class ListActionWithNullNegativeResult extends ActionWithNullNegativeResult<List<UserView>> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserView> execute() throws MageException {
|
public List<UserView> execute() throws MageException {
|
||||||
return UserManager.instance.getUserInfoList();
|
return managerFactory.userManager().getUserInfoList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class GameViewActionWithNullNegativeResult extends ActionWithNullNegativeResult<GameView> {
|
private class GameViewActionWithNullNegativeResult extends ActionWithNullNegativeResult<GameView> {
|
||||||
|
|
||||||
private final String sessionId;
|
private final String sessionId;
|
||||||
private final UUID gameId;
|
private final UUID gameId;
|
||||||
|
@ -1240,18 +1221,18 @@ public class MageServerImpl implements MageServer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GameView execute() throws MageException {
|
public GameView execute() throws MageException {
|
||||||
Optional<Session> session = SessionManager.instance.getSession(sessionId);
|
Optional<Session> session = managerFactory.sessionManager().getSession(sessionId);
|
||||||
if (!session.isPresent()) {
|
if (!session.isPresent()) {
|
||||||
logger.error("Session not found : " + sessionId);
|
logger.error("Session not found : " + sessionId);
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
//UUID userId = session.get().getUserId();
|
//UUID userId = session.get().getUserId();
|
||||||
return GameManager.instance.getGameView(gameId, playerId);
|
return managerFactory.gameManager().getGameView(gameId, playerId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class MyActionWithBooleanResult extends ActionWithBooleanResult {
|
private class MyActionWithBooleanResult extends ActionWithBooleanResult {
|
||||||
|
|
||||||
private final String sessionId;
|
private final String sessionId;
|
||||||
private final UUID tableId;
|
private final UUID tableId;
|
||||||
|
@ -1263,17 +1244,17 @@ public class MageServerImpl implements MageServer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Boolean execute() throws MageException {
|
public Boolean execute() throws MageException {
|
||||||
Optional<Session> session = SessionManager.instance.getSession(sessionId);
|
Optional<Session> session = managerFactory.sessionManager().getSession(sessionId);
|
||||||
if (!session.isPresent()) {
|
if (!session.isPresent()) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
UUID userId = session.get().getUserId();
|
UUID userId = session.get().getUserId();
|
||||||
return TableManager.instance.watchTable(userId, tableId);
|
return managerFactory.tableManager().watchTable(userId, tableId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class DraftPickViewActionWithNullNegativeResult extends ActionWithNullNegativeResult<DraftPickView> {
|
private class DraftPickViewActionWithNullNegativeResult extends ActionWithNullNegativeResult<DraftPickView> {
|
||||||
|
|
||||||
private final String sessionId;
|
private final String sessionId;
|
||||||
private final UUID draftId;
|
private final UUID draftId;
|
||||||
|
@ -1289,9 +1270,9 @@ public class MageServerImpl implements MageServer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DraftPickView execute() {
|
public DraftPickView execute() {
|
||||||
Optional<Session> session = SessionManager.instance.getSession(sessionId);
|
Optional<Session> session = managerFactory.sessionManager().getSession(sessionId);
|
||||||
if (session.isPresent()) {
|
if (session.isPresent()) {
|
||||||
return DraftManager.instance.sendCardPick(draftId, session.get().getUserId(), cardPick, hiddenCards);
|
return managerFactory.draftManager().sendCardPick(draftId, session.get().getUserId(), cardPick, hiddenCards);
|
||||||
} else {
|
} else {
|
||||||
logger.error("Session not found sessionId: " + sessionId + " draftId:" + draftId);
|
logger.error("Session not found sessionId: " + sessionId + " draftId:" + draftId);
|
||||||
}
|
}
|
||||||
|
@ -1299,7 +1280,7 @@ public class MageServerImpl implements MageServer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class MyActionWithTableViewResult extends ActionWithTableViewResult {
|
private class MyActionWithTableViewResult extends ActionWithTableViewResult {
|
||||||
|
|
||||||
private final String sessionId;
|
private final String sessionId;
|
||||||
private final MatchOptions options;
|
private final MatchOptions options;
|
||||||
|
@ -1313,12 +1294,12 @@ public class MageServerImpl implements MageServer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TableView execute() throws MageException {
|
public TableView execute() throws MageException {
|
||||||
Optional<Session> session = SessionManager.instance.getSession(sessionId);
|
Optional<Session> session = managerFactory.sessionManager().getSession(sessionId);
|
||||||
if (!session.isPresent()) {
|
if (!session.isPresent()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
UUID userId = session.get().getUserId();
|
UUID userId = session.get().getUserId();
|
||||||
Optional<User> _user = UserManager.instance.getUser(userId);
|
Optional<User> _user = managerFactory.userManager().getUser(userId);
|
||||||
if (!_user.isPresent()) {
|
if (!_user.isPresent()) {
|
||||||
logger.error("User for session not found. session = " + sessionId);
|
logger.error("User for session not found. session = " + sessionId);
|
||||||
return null;
|
return null;
|
||||||
|
@ -1349,13 +1330,13 @@ public class MageServerImpl implements MageServer {
|
||||||
user.showUserMessage("Create table", message);
|
user.showUserMessage("Create table", message);
|
||||||
throw new MageException("No message");
|
throw new MageException("No message");
|
||||||
}
|
}
|
||||||
Optional<GamesRoom> room = GamesRoomManager.instance.getRoom(roomId);
|
Optional<GamesRoom> room = managerFactory.gamesRoomManager().getRoom(roomId);
|
||||||
if (room.isPresent()) {
|
if (room.isPresent()) {
|
||||||
TableView table = room.get().createTable(userId, options);
|
TableView table = room.get().createTable(userId, options);
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("TABLE created - tableId: " + table.getTableId() + ' ' + table.getTableName());
|
logger.debug("TABLE created - tableId: " + table.getTableId() + ' ' + table.getTableName());
|
||||||
logger.debug("- " + user.getName() + " userId: " + user.getId());
|
logger.debug("- " + user.getName() + " userId: " + user.getId());
|
||||||
logger.debug("- chatId: " + TableManager.instance.getChatId(table.getTableId()));
|
logger.debug("- chatId: " + managerFactory.tableManager().getChatId(table.getTableId()));
|
||||||
}
|
}
|
||||||
return table;
|
return table;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,25 +1,32 @@
|
||||||
package mage.server;
|
package mage.server;
|
||||||
|
|
||||||
import java.util.Properties;
|
import mage.server.managers.ConfigSettings;
|
||||||
|
import mage.server.managers.MailClient;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import javax.mail.Message;
|
import javax.mail.Message;
|
||||||
import javax.mail.MessagingException;
|
import javax.mail.MessagingException;
|
||||||
import javax.mail.Session;
|
import javax.mail.Session;
|
||||||
import javax.mail.Transport;
|
import javax.mail.Transport;
|
||||||
import javax.mail.internet.InternetAddress;
|
import javax.mail.internet.InternetAddress;
|
||||||
import javax.mail.internet.MimeMessage;
|
import javax.mail.internet.MimeMessage;
|
||||||
import mage.server.util.ConfigSettings;
|
import java.util.Properties;
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
|
|
||||||
public final class MailClient {
|
public class MailClientImpl implements MailClient {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(Main.class);
|
private static final Logger logger = Logger.getLogger(Main.class);
|
||||||
|
|
||||||
public static boolean sendMessage(String email, String subject, String text) {
|
private final ConfigSettings config;
|
||||||
|
|
||||||
|
public MailClientImpl(ConfigSettings config) {
|
||||||
|
this.config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean sendMessage(String email, String subject, String text) {
|
||||||
if (email.isEmpty()) {
|
if (email.isEmpty()) {
|
||||||
logger.info("Email is not sent because the address is empty");
|
logger.info("Email is not sent because the address is empty");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ConfigSettings config = ConfigSettings.instance;
|
|
||||||
|
|
||||||
Properties properties = System.getProperties();
|
Properties properties = System.getProperties();
|
||||||
properties.setProperty("mail.smtps.host", config.getMailSmtpHost());
|
properties.setProperty("mail.smtps.host", config.getMailSmtpHost());
|
||||||
|
@ -30,7 +37,7 @@ public final class MailClient {
|
||||||
|
|
||||||
Session session = Session.getDefaultInstance(properties);
|
Session session = Session.getDefaultInstance(properties);
|
||||||
|
|
||||||
try{
|
try {
|
||||||
MimeMessage message = new MimeMessage(session);
|
MimeMessage message = new MimeMessage(session);
|
||||||
message.setFrom(new InternetAddress(config.getMailFromAddress()));
|
message.setFrom(new InternetAddress(config.getMailFromAddress()));
|
||||||
message.addRecipient(Message.RecipientType.TO, new InternetAddress(email));
|
message.addRecipient(Message.RecipientType.TO, new InternetAddress(email));
|
||||||
|
@ -44,7 +51,7 @@ public final class MailClient {
|
||||||
trnsport.close();
|
trnsport.close();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}catch (MessagingException ex) {
|
} catch (MessagingException ex) {
|
||||||
logger.error("Error sending message to " + email, ex);
|
logger.error("Error sending message to " + email, ex);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
|
@ -5,29 +5,37 @@ import com.sun.jersey.api.client.ClientResponse;
|
||||||
import com.sun.jersey.api.client.WebResource;
|
import com.sun.jersey.api.client.WebResource;
|
||||||
import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
|
import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
|
||||||
import com.sun.jersey.core.util.MultivaluedMapImpl;
|
import com.sun.jersey.core.util.MultivaluedMapImpl;
|
||||||
import javax.ws.rs.core.MediaType;
|
import mage.server.managers.ConfigSettings;
|
||||||
import mage.server.util.ConfigSettings;
|
import mage.server.managers.MailClient;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
public final class MailgunClient {
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
|
public class MailgunClientImpl implements MailClient {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(Main.class);
|
private static final Logger logger = Logger.getLogger(Main.class);
|
||||||
|
|
||||||
public static boolean sendMessage(String email, String subject, String text) {
|
private final ConfigSettings config;
|
||||||
|
|
||||||
|
public MailgunClientImpl(ConfigSettings config) {
|
||||||
|
this.config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean sendMessage(String email, String subject, String text) {
|
||||||
if (email.isEmpty()) {
|
if (email.isEmpty()) {
|
||||||
logger.info("Email is not sent because the address is empty");
|
logger.info("Email is not sent because the address is empty");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Client client = Client.create();
|
Client client = Client.create();
|
||||||
client.addFilter(new HTTPBasicAuthFilter("api", ConfigSettings.instance.getMailgunApiKey()));
|
client.addFilter(new HTTPBasicAuthFilter("api", config.getMailgunApiKey()));
|
||||||
String domain = ConfigSettings.instance.getMailgunDomain();
|
String domain = config.getMailgunDomain();
|
||||||
WebResource webResource = client.resource("https://api.mailgun.net/v3/" + domain + "/messages");
|
WebResource webResource = client.resource("https://api.mailgun.net/v3/" + domain + "/messages");
|
||||||
MultivaluedMapImpl formData = new MultivaluedMapImpl();
|
MultivaluedMapImpl formData = new MultivaluedMapImpl();
|
||||||
formData.add("from", "XMage <postmaster@" + domain + '>');
|
formData.add("from", "XMage <postmaster@" + domain + '>');
|
||||||
formData.add("to", email);
|
formData.add("to", email);
|
||||||
formData.add("subject", subject);
|
formData.add("subject", subject);
|
||||||
formData.add("text", text);
|
formData.add("text", text);
|
||||||
ClientResponse response = webResource.type(MediaType.APPLICATION_FORM_URLENCODED).post(ClientResponse.class, formData);
|
ClientResponse response = webResource.type(MediaType.APPLICATION_FORM_URLENCODED).post(ClientResponse.class, formData);
|
||||||
boolean succeeded = response.getStatus() == 200;
|
boolean succeeded = response.getStatus() == 200;
|
||||||
if (!succeeded) {
|
if (!succeeded) {
|
||||||
logger.error("Error sending message to " + email + ". Status code: " + response.getStatus());
|
logger.error("Error sending message to " + email + ". Status code: " + response.getStatus());
|
|
@ -14,12 +14,11 @@ import mage.remote.Connection;
|
||||||
import mage.server.draft.CubeFactory;
|
import mage.server.draft.CubeFactory;
|
||||||
import mage.server.game.GameFactory;
|
import mage.server.game.GameFactory;
|
||||||
import mage.server.game.PlayerFactory;
|
import mage.server.game.PlayerFactory;
|
||||||
|
import mage.server.managers.ConfigSettings;
|
||||||
|
import mage.server.managers.ManagerFactory;
|
||||||
import mage.server.record.UserStatsRepository;
|
import mage.server.record.UserStatsRepository;
|
||||||
import mage.server.tournament.TournamentFactory;
|
import mage.server.tournament.TournamentFactory;
|
||||||
import mage.server.util.ConfigSettings;
|
import mage.server.util.*;
|
||||||
import mage.server.util.PluginClassLoader;
|
|
||||||
import mage.server.util.ServerMessagesUtil;
|
|
||||||
import mage.server.util.SystemUtil;
|
|
||||||
import mage.server.util.config.GamePlugin;
|
import mage.server.util.config.GamePlugin;
|
||||||
import mage.server.util.config.Plugin;
|
import mage.server.util.config.Plugin;
|
||||||
import mage.utils.MageVersion;
|
import mage.utils.MageVersion;
|
||||||
|
@ -40,6 +39,7 @@ import java.io.IOException;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
import java.nio.file.Paths;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -53,9 +53,16 @@ public final class Main {
|
||||||
private static final String testModeArg = "-testMode=";
|
private static final String testModeArg = "-testMode=";
|
||||||
private static final String fastDBModeArg = "-fastDbMode=";
|
private static final String fastDBModeArg = "-fastDbMode=";
|
||||||
private static final String adminPasswordArg = "-adminPassword=";
|
private static final String adminPasswordArg = "-adminPassword=";
|
||||||
|
/**
|
||||||
|
* The property that holds the path to the configuration file. Defaults to "config/config.xml".
|
||||||
|
*
|
||||||
|
* To set up a different one, start the application with the java option "-Dxmage.config.path=<path>"
|
||||||
|
*/
|
||||||
|
private static final String configPathProp = "xmage.config.path";
|
||||||
|
|
||||||
private static final File pluginFolder = new File("plugins");
|
private static final File pluginFolder = new File("plugins");
|
||||||
private static final File extensionFolder = new File("extensions");
|
private static final File extensionFolder = new File("extensions");
|
||||||
|
private static final String defaultConfigPath = Paths.get("config", "config.xml").toString();
|
||||||
|
|
||||||
public static final PluginClassLoader classLoader = new PluginClassLoader();
|
public static final PluginClassLoader classLoader = new PluginClassLoader();
|
||||||
private static TransporterServer server;
|
private static TransporterServer server;
|
||||||
|
@ -70,7 +77,6 @@ public final class Main {
|
||||||
logger.info("Starting MAGE server version " + version);
|
logger.info("Starting MAGE server version " + version);
|
||||||
logger.info("Logging level: " + logger.getEffectiveLevel());
|
logger.info("Logging level: " + logger.getEffectiveLevel());
|
||||||
logger.info("Default charset: " + Charset.defaultCharset());
|
logger.info("Default charset: " + Charset.defaultCharset());
|
||||||
|
|
||||||
String adminPassword = "";
|
String adminPassword = "";
|
||||||
for (String arg : args) {
|
for (String arg : args) {
|
||||||
if (arg.startsWith(testModeArg)) {
|
if (arg.startsWith(testModeArg)) {
|
||||||
|
@ -83,7 +89,14 @@ public final class Main {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ConfigSettings.instance.isAuthenticationActivated()) {
|
final String configPath = Optional.ofNullable(System.getProperty(configPathProp))
|
||||||
|
.orElse(defaultConfigPath);
|
||||||
|
|
||||||
|
logger.info(String.format("Reading configuration from path=%s", configPath));
|
||||||
|
final ConfigWrapper config = new ConfigWrapper(ConfigFactory.loadFromFile(configPath));
|
||||||
|
|
||||||
|
|
||||||
|
if (config.isAuthenticationActivated()) {
|
||||||
logger.info("Check authorized user DB version ...");
|
logger.info("Check authorized user DB version ...");
|
||||||
if (!AuthorizedUserRepository.instance.checkAlterAndMigrateAuthorizedUser()) {
|
if (!AuthorizedUserRepository.instance.checkAlterAndMigrateAuthorizedUser()) {
|
||||||
logger.fatal("Failed to start server.");
|
logger.fatal("Failed to start server.");
|
||||||
|
@ -148,7 +161,6 @@ public final class Main {
|
||||||
UserStatsRepository.instance.updateUserStats();
|
UserStatsRepository.instance.updateUserStats();
|
||||||
logger.info("Done.");
|
logger.info("Done.");
|
||||||
deleteSavedGames();
|
deleteSavedGames();
|
||||||
ConfigSettings config = ConfigSettings.instance;
|
|
||||||
for (GamePlugin plugin : config.getGameTypes()) {
|
for (GamePlugin plugin : config.getGameTypes()) {
|
||||||
GameFactory.instance.addGameType(plugin.getName(), loadGameType(plugin), loadPlugin(plugin));
|
GameFactory.instance.addGameType(plugin.getName(), loadGameType(plugin), loadPlugin(plugin));
|
||||||
}
|
}
|
||||||
|
@ -206,11 +218,12 @@ public final class Main {
|
||||||
Connection connection = new Connection("&maxPoolSize=" + config.getMaxPoolSize());
|
Connection connection = new Connection("&maxPoolSize=" + config.getMaxPoolSize());
|
||||||
connection.setHost(config.getServerAddress());
|
connection.setHost(config.getServerAddress());
|
||||||
connection.setPort(config.getPort());
|
connection.setPort(config.getPort());
|
||||||
|
final ManagerFactory managerFactory = new MainManagerFactory(config);
|
||||||
try {
|
try {
|
||||||
// Parameter: serializationtype => jboss
|
// Parameter: serializationtype => jboss
|
||||||
InvokerLocator serverLocator = new InvokerLocator(connection.getURI());
|
InvokerLocator serverLocator = new InvokerLocator(connection.getURI());
|
||||||
if (!isAlreadyRunning(serverLocator)) {
|
if (!isAlreadyRunning(config, serverLocator)) {
|
||||||
server = new MageTransporterServer(serverLocator, new MageServerImpl(adminPassword, testMode), MageServer.class.getName(), new MageServerInvocationHandler());
|
server = new MageTransporterServer(managerFactory, serverLocator, new MageServerImpl(managerFactory, adminPassword, testMode), MageServer.class.getName(), new MageServerInvocationHandler(managerFactory));
|
||||||
server.start();
|
server.start();
|
||||||
logger.info("Started MAGE server - listening on " + connection.toString());
|
logger.info("Started MAGE server - listening on " + connection.toString());
|
||||||
|
|
||||||
|
@ -230,9 +243,9 @@ public final class Main {
|
||||||
ServerMessagesUtil.instance.setStartDate(System.currentTimeMillis());
|
ServerMessagesUtil.instance.setStartDate(System.currentTimeMillis());
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean isAlreadyRunning(InvokerLocator serverLocator) {
|
static boolean isAlreadyRunning(ConfigSettings config, InvokerLocator serverLocator) {
|
||||||
Map<String, String> metadata = new HashMap<>();
|
Map<String, String> metadata = new HashMap<>();
|
||||||
metadata.put(SocketWrapper.WRITE_TIMEOUT, String.valueOf(ConfigSettings.instance.getSocketWriteTimeout()));
|
metadata.put(SocketWrapper.WRITE_TIMEOUT, String.valueOf(config.getSocketWriteTimeout()));
|
||||||
metadata.put("generalizeSocketException", "true");
|
metadata.put("generalizeSocketException", "true");
|
||||||
try {
|
try {
|
||||||
MageServer testServer = (MageServer) TransporterClient.createTransporterClient(serverLocator.getLocatorURI(), MageServer.class, metadata);
|
MageServer testServer = (MageServer) TransporterClient.createTransporterClient(serverLocator.getLocatorURI(), MageServer.class, metadata);
|
||||||
|
@ -248,16 +261,22 @@ public final class Main {
|
||||||
|
|
||||||
static class ClientConnectionListener implements ConnectionListener {
|
static class ClientConnectionListener implements ConnectionListener {
|
||||||
|
|
||||||
|
private final ManagerFactory managerFactory;
|
||||||
|
|
||||||
|
public ClientConnectionListener(ManagerFactory managerFactory) {
|
||||||
|
this.managerFactory = managerFactory;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleConnectionException(Throwable throwable, Client client) {
|
public void handleConnectionException(Throwable throwable, Client client) {
|
||||||
String sessionId = client.getSessionId();
|
String sessionId = client.getSessionId();
|
||||||
Optional<Session> session = SessionManager.instance.getSession(sessionId);
|
Optional<Session> session = managerFactory.sessionManager().getSession(sessionId);
|
||||||
if (!session.isPresent()) {
|
if (!session.isPresent()) {
|
||||||
logger.trace("Session not found : " + sessionId);
|
logger.trace("Session not found : " + sessionId);
|
||||||
} else {
|
} else {
|
||||||
UUID userId = session.get().getUserId();
|
UUID userId = session.get().getUserId();
|
||||||
StringBuilder sessionInfo = new StringBuilder();
|
StringBuilder sessionInfo = new StringBuilder();
|
||||||
Optional<User> user = UserManager.instance.getUser(userId);
|
Optional<User> user = managerFactory.userManager().getUser(userId);
|
||||||
if (user.isPresent()) {
|
if (user.isPresent()) {
|
||||||
sessionInfo.append(user.get().getName()).append(" [").append(user.get().getGameInfo()).append(']');
|
sessionInfo.append(user.get().getName()).append(" [").append(user.get().getGameInfo()).append(']');
|
||||||
} else {
|
} else {
|
||||||
|
@ -267,12 +286,12 @@ public final class Main {
|
||||||
if (throwable instanceof ClientDisconnectedException) {
|
if (throwable instanceof ClientDisconnectedException) {
|
||||||
// Seems like the random diconnects from public server land here and should not be handled as explicit disconnects
|
// Seems like the random diconnects from public server land here and should not be handled as explicit disconnects
|
||||||
// So it should be possible to reconnect to server and continue games if DisconnectReason is set to LostConnection
|
// So it should be possible to reconnect to server and continue games if DisconnectReason is set to LostConnection
|
||||||
//SessionManager.instance.disconnect(client.getSessionId(), DisconnectReason.Disconnected);
|
//managerFactory.sessionManager().disconnect(client.getSessionId(), DisconnectReason.Disconnected);
|
||||||
SessionManager.instance.disconnect(client.getSessionId(), DisconnectReason.LostConnection);
|
managerFactory.sessionManager().disconnect(client.getSessionId(), DisconnectReason.LostConnection);
|
||||||
logger.info("CLIENT DISCONNECTED - " + sessionInfo);
|
logger.info("CLIENT DISCONNECTED - " + sessionInfo);
|
||||||
logger.debug("Stack Trace", throwable);
|
logger.debug("Stack Trace", throwable);
|
||||||
} else {
|
} else {
|
||||||
SessionManager.instance.disconnect(client.getSessionId(), DisconnectReason.LostConnection);
|
managerFactory.sessionManager().disconnect(client.getSessionId(), DisconnectReason.LostConnection);
|
||||||
logger.info("LOST CONNECTION - " + sessionInfo);
|
logger.info("LOST CONNECTION - " + sessionInfo);
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
if (throwable == null) {
|
if (throwable == null) {
|
||||||
|
@ -292,11 +311,11 @@ public final class Main {
|
||||||
|
|
||||||
protected Connector connector;
|
protected Connector connector;
|
||||||
|
|
||||||
public MageTransporterServer(InvokerLocator locator, Object target, String subsystem, MageServerInvocationHandler serverInvocationHandler) throws Exception {
|
public MageTransporterServer(ManagerFactory managerFactory, InvokerLocator locator, Object target, String subsystem, MageServerInvocationHandler serverInvocationHandler) throws Exception {
|
||||||
super(locator, target, subsystem);
|
super(locator, target, subsystem);
|
||||||
connector.addInvocationHandler("callback", serverInvocationHandler);
|
connector.addInvocationHandler("callback", serverInvocationHandler);
|
||||||
connector.setLeasePeriod(ConfigSettings.instance.getLeasePeriod());
|
connector.setLeasePeriod(managerFactory.configSettings().getLeasePeriod());
|
||||||
connector.addConnectionListener(new ClientConnectionListener());
|
connector.addConnectionListener(new ClientConnectionListener(managerFactory));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Connector getConnector() throws Exception {
|
public Connector getConnector() throws Exception {
|
||||||
|
@ -313,6 +332,12 @@ public final class Main {
|
||||||
|
|
||||||
static class MageServerInvocationHandler implements ServerInvocationHandler {
|
static class MageServerInvocationHandler implements ServerInvocationHandler {
|
||||||
|
|
||||||
|
private final ManagerFactory managerFactory;
|
||||||
|
|
||||||
|
public MageServerInvocationHandler(ManagerFactory managerFactory) {
|
||||||
|
this.managerFactory = managerFactory;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setMBeanServer(MBeanServer server) {
|
public void setMBeanServer(MBeanServer server) {
|
||||||
/**
|
/**
|
||||||
|
@ -333,9 +358,9 @@ public final class Main {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setInvoker(ServerInvoker invoker) {
|
public void setInvoker(ServerInvoker invoker) {
|
||||||
((BisocketServerInvoker) invoker).setSecondaryBindPort(ConfigSettings.instance.getSecondaryBindPort());
|
((BisocketServerInvoker) invoker).setSecondaryBindPort(managerFactory.configSettings().getSecondaryBindPort());
|
||||||
((BisocketServerInvoker) invoker).setBacklog(ConfigSettings.instance.getBacklogSize());
|
((BisocketServerInvoker) invoker).setBacklog(managerFactory.configSettings().getBacklogSize());
|
||||||
((BisocketServerInvoker) invoker).setNumAcceptThreads(ConfigSettings.instance.getNumAcceptThreads());
|
((BisocketServerInvoker) invoker).setNumAcceptThreads(managerFactory.configSettings().getNumAcceptThreads());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -344,7 +369,7 @@ public final class Main {
|
||||||
ServerInvokerCallbackHandler handler = (ServerInvokerCallbackHandler) callbackHandler;
|
ServerInvokerCallbackHandler handler = (ServerInvokerCallbackHandler) callbackHandler;
|
||||||
try {
|
try {
|
||||||
String sessionId = handler.getClientSessionId();
|
String sessionId = handler.getClientSessionId();
|
||||||
SessionManager.instance.createSession(sessionId, callbackHandler);
|
managerFactory.sessionManager().createSession(sessionId, callbackHandler);
|
||||||
} catch (Throwable ex) {
|
} catch (Throwable ex) {
|
||||||
logger.fatal("", ex);
|
logger.fatal("", ex);
|
||||||
}
|
}
|
||||||
|
@ -362,7 +387,7 @@ public final class Main {
|
||||||
} else {
|
} else {
|
||||||
host = "localhost";
|
host = "localhost";
|
||||||
}
|
}
|
||||||
Optional<Session> session = SessionManager.instance.getSession(sessionId);
|
Optional<Session> session = managerFactory.sessionManager().getSession(sessionId);
|
||||||
if (!session.isPresent()) {
|
if (!session.isPresent()) {
|
||||||
logger.error("Session not found : " + sessionId);
|
logger.error("Session not found : " + sessionId);
|
||||||
} else {
|
} else {
|
||||||
|
@ -375,7 +400,7 @@ public final class Main {
|
||||||
public void removeListener(InvokerCallbackHandler callbackHandler) {
|
public void removeListener(InvokerCallbackHandler callbackHandler) {
|
||||||
ServerInvokerCallbackHandler handler = (ServerInvokerCallbackHandler) callbackHandler;
|
ServerInvokerCallbackHandler handler = (ServerInvokerCallbackHandler) callbackHandler;
|
||||||
String sessionId = handler.getClientSessionId();
|
String sessionId = handler.getClientSessionId();
|
||||||
SessionManager.instance.disconnect(sessionId, DisconnectReason.Disconnected);
|
managerFactory.sessionManager().disconnect(sessionId, DisconnectReason.Disconnected);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
124
Mage.Server/src/main/java/mage/server/MainManagerFactory.java
Normal file
124
Mage.Server/src/main/java/mage/server/MainManagerFactory.java
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
package mage.server;
|
||||||
|
|
||||||
|
import mage.server.draft.DraftManagerImpl;
|
||||||
|
import mage.server.game.GameManagerImpl;
|
||||||
|
import mage.server.game.GamesRoomManagerImpl;
|
||||||
|
import mage.server.game.ReplayManagerImpl;
|
||||||
|
import mage.server.managers.*;
|
||||||
|
import mage.server.tournament.TournamentManagerImpl;
|
||||||
|
import mage.server.util.ThreadExecutorImpl;
|
||||||
|
|
||||||
|
public class MainManagerFactory implements ManagerFactory {
|
||||||
|
|
||||||
|
private final ConfigSettings configSettings;
|
||||||
|
private final ThreadExecutor threadExecutor;
|
||||||
|
private final ChatManager chatManager;
|
||||||
|
private final DraftManager draftManager;
|
||||||
|
private final GameManager gameManager;
|
||||||
|
private final GamesRoomManager gamesRoomManager;
|
||||||
|
private final MailClient mailClient;
|
||||||
|
private final MailClient mailgunClient;
|
||||||
|
private final ReplayManager replayManager;
|
||||||
|
private final SessionManager sessionManager;
|
||||||
|
private final TableManager tableManager;
|
||||||
|
private final UserManager userManager;
|
||||||
|
private final TournamentManager tournamentManager;
|
||||||
|
|
||||||
|
|
||||||
|
public MainManagerFactory(ConfigSettings configSettings) {
|
||||||
|
this.configSettings = configSettings;
|
||||||
|
// ThreadExecutorImpl, MailClientImpl and MailGunClient depend only on the config, so they are initialised first
|
||||||
|
this.threadExecutor = new ThreadExecutorImpl(configSettings);
|
||||||
|
this.mailClient = new MailClientImpl(configSettings);
|
||||||
|
this.mailgunClient = new MailgunClientImpl(configSettings);
|
||||||
|
// Chat, Draft, Game, Replay, Session and Tournament managers only require access to the ManagerFactory
|
||||||
|
// but do not use them in initialisation
|
||||||
|
this.chatManager = new ChatManagerImpl(this);
|
||||||
|
this.draftManager = new DraftManagerImpl(this);
|
||||||
|
this.gameManager = new GameManagerImpl(this);
|
||||||
|
this.replayManager = new ReplayManagerImpl(this);
|
||||||
|
this.sessionManager = new SessionManagerImpl(this);
|
||||||
|
this.tournamentManager = new TournamentManagerImpl(this);
|
||||||
|
// GamesRoom, Table, User managers depend on the ManagerFactory and have an initialisation block which is delayed
|
||||||
|
// to the end of the construction
|
||||||
|
final GamesRoomManagerImpl gamesRoomManager = new GamesRoomManagerImpl(this);
|
||||||
|
final TableManagerImpl tableManager = new TableManagerImpl(this);
|
||||||
|
final UserManagerImpl userManager = new UserManagerImpl(this);
|
||||||
|
this.gamesRoomManager = gamesRoomManager;
|
||||||
|
this.tableManager = tableManager;
|
||||||
|
this.userManager = userManager;
|
||||||
|
// execute the initialisation block of the relevant manager (they start the executor services)
|
||||||
|
startThreads(gamesRoomManager, tableManager, userManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startThreads(GamesRoomManagerImpl gamesRoomManager, TableManagerImpl tableManager, UserManagerImpl userManager) {
|
||||||
|
userManager.init();
|
||||||
|
tableManager.init();
|
||||||
|
gamesRoomManager.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChatManager chatManager() {
|
||||||
|
return chatManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DraftManager draftManager() {
|
||||||
|
return draftManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GameManager gameManager() {
|
||||||
|
return gameManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GamesRoomManager gamesRoomManager() {
|
||||||
|
return gamesRoomManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MailClient mailClient() {
|
||||||
|
return mailClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MailClient mailgunClient() {
|
||||||
|
return mailgunClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ReplayManager replayManager() {
|
||||||
|
return replayManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SessionManager sessionManager() {
|
||||||
|
return sessionManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TableManager tableManager() {
|
||||||
|
return tableManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UserManager userManager() {
|
||||||
|
return userManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ConfigSettings configSettings() {
|
||||||
|
return configSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ThreadExecutor threadExecutor() {
|
||||||
|
return threadExecutor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TournamentManager tournamentManager() {
|
||||||
|
return tournamentManager;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +1,10 @@
|
||||||
|
|
||||||
|
|
||||||
package mage.server;
|
package mage.server;
|
||||||
|
|
||||||
|
import mage.server.managers.ChatManager;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
*/
|
*/
|
||||||
public abstract class RoomImpl implements Room {
|
public abstract class RoomImpl implements Room {
|
||||||
|
@ -13,9 +12,9 @@ public abstract class RoomImpl implements Room {
|
||||||
private final UUID chatId;
|
private final UUID chatId;
|
||||||
private final UUID roomId;
|
private final UUID roomId;
|
||||||
|
|
||||||
public RoomImpl() {
|
public RoomImpl(ChatManager chatManager) {
|
||||||
roomId = UUID.randomUUID();
|
roomId = UUID.randomUUID();
|
||||||
chatId = ChatManager.instance.createChatSession("Room " + roomId);
|
chatId = chatManager.createChatSession("Room " + roomId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,5 +34,4 @@ public abstract class RoomImpl implements Room {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,8 @@ import mage.interfaces.callback.ClientCallbackMethod;
|
||||||
import mage.players.net.UserData;
|
import mage.players.net.UserData;
|
||||||
import mage.players.net.UserGroup;
|
import mage.players.net.UserGroup;
|
||||||
import mage.server.game.GamesRoom;
|
import mage.server.game.GamesRoom;
|
||||||
import mage.server.game.GamesRoomManager;
|
import mage.server.managers.ConfigSettings;
|
||||||
import mage.server.util.ConfigSettings;
|
import mage.server.managers.ManagerFactory;
|
||||||
import mage.server.util.SystemUtil;
|
import mage.server.util.SystemUtil;
|
||||||
import mage.util.RandomUtil;
|
import mage.util.RandomUtil;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
@ -34,6 +34,7 @@ public class Session {
|
||||||
private static final Pattern alphabetsPattern = Pattern.compile("[a-zA-Z]");
|
private static final Pattern alphabetsPattern = Pattern.compile("[a-zA-Z]");
|
||||||
private static final Pattern digitsPattern = Pattern.compile("[0-9]");
|
private static final Pattern digitsPattern = Pattern.compile("[0-9]");
|
||||||
|
|
||||||
|
private final ManagerFactory managerFactory;
|
||||||
private final String sessionId;
|
private final String sessionId;
|
||||||
private UUID userId;
|
private UUID userId;
|
||||||
private String host;
|
private String host;
|
||||||
|
@ -46,7 +47,8 @@ public class Session {
|
||||||
private final ReentrantLock lock;
|
private final ReentrantLock lock;
|
||||||
private final ReentrantLock callBackLock;
|
private final ReentrantLock callBackLock;
|
||||||
|
|
||||||
public Session(String sessionId, InvokerCallbackHandler callbackHandler) {
|
public Session(ManagerFactory managerFactory, String sessionId, InvokerCallbackHandler callbackHandler) {
|
||||||
|
this.managerFactory = managerFactory;
|
||||||
this.sessionId = sessionId;
|
this.sessionId = sessionId;
|
||||||
this.callbackHandler = (AsynchInvokerCallbackHandler) callbackHandler;
|
this.callbackHandler = (AsynchInvokerCallbackHandler) callbackHandler;
|
||||||
this.isAdmin = false;
|
this.isAdmin = false;
|
||||||
|
@ -56,7 +58,7 @@ public class Session {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String registerUser(String userName, String password, String email) throws MageException {
|
public String registerUser(String userName, String password, String email) throws MageException {
|
||||||
if (!ConfigSettings.instance.isAuthenticationActivated()) {
|
if (!managerFactory.configSettings().isAuthenticationActivated()) {
|
||||||
String returnMessage = "Registration is disabled by the server config";
|
String returnMessage = "Registration is disabled by the server config";
|
||||||
sendErrorMessageToClient(returnMessage);
|
sendErrorMessageToClient(returnMessage);
|
||||||
return returnMessage;
|
return returnMessage;
|
||||||
|
@ -86,10 +88,10 @@ public class Session {
|
||||||
|
|
||||||
boolean success;
|
boolean success;
|
||||||
String subject = "XMage Registration Completed";
|
String subject = "XMage Registration Completed";
|
||||||
if (!ConfigSettings.instance.getMailUser().isEmpty()) {
|
if (!managerFactory.configSettings().getMailUser().isEmpty()) {
|
||||||
success = MailClient.sendMessage(email, subject, text);
|
success = managerFactory.mailClient().sendMessage(email, subject, text);
|
||||||
} else {
|
} else {
|
||||||
success = MailgunClient.sendMessage(email, subject, text);
|
success = managerFactory.mailgunClient().sendMessage(email, subject, text);
|
||||||
}
|
}
|
||||||
if (success) {
|
if (success) {
|
||||||
String ok = "Sent a registration confirmation / initial password email to " + email + " for " + userName;
|
String ok = "Sent a registration confirmation / initial password email to " + email + " for " + userName;
|
||||||
|
@ -109,18 +111,18 @@ public class Session {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String validateUserName(String userName) {
|
private String validateUserName(String userName) {
|
||||||
if (userName.equals("Admin")) {
|
if (userName.equals("Admin")) {
|
||||||
return "User name Admin already in use";
|
return "User name Admin already in use";
|
||||||
}
|
}
|
||||||
ConfigSettings config = ConfigSettings.instance;
|
ConfigSettings config = managerFactory.configSettings();
|
||||||
if (userName.length() < config.getMinUserNameLength()) {
|
if (userName.length() < config.getMinUserNameLength()) {
|
||||||
return "User name may not be shorter than " + config.getMinUserNameLength() + " characters";
|
return "User name may not be shorter than " + config.getMinUserNameLength() + " characters";
|
||||||
}
|
}
|
||||||
if (userName.length() > config.getMaxUserNameLength()) {
|
if (userName.length() > config.getMaxUserNameLength()) {
|
||||||
return "User name may not be longer than " + config.getMaxUserNameLength() + " characters";
|
return "User name may not be longer than " + config.getMaxUserNameLength() + " characters";
|
||||||
}
|
}
|
||||||
Pattern invalidUserNamePattern = Pattern.compile(ConfigSettings.instance.getInvalidUserNamePattern(), Pattern.CASE_INSENSITIVE);
|
Pattern invalidUserNamePattern = Pattern.compile(managerFactory.configSettings().getInvalidUserNamePattern(), Pattern.CASE_INSENSITIVE);
|
||||||
Matcher m = invalidUserNamePattern.matcher(userName);
|
Matcher m = invalidUserNamePattern.matcher(userName);
|
||||||
if (m.find()) {
|
if (m.find()) {
|
||||||
return "User name '" + userName + "' includes not allowed characters: use a-z, A-Z and 0-9";
|
return "User name '" + userName + "' includes not allowed characters: use a-z, A-Z and 0-9";
|
||||||
|
@ -132,8 +134,8 @@ public class Session {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String validatePassword(String password, String userName) {
|
private String validatePassword(String password, String userName) {
|
||||||
ConfigSettings config = ConfigSettings.instance;
|
ConfigSettings config = managerFactory.configSettings();
|
||||||
if (password.length() < config.getMinPasswordLength()) {
|
if (password.length() < config.getMinPasswordLength()) {
|
||||||
return "Password may not be shorter than " + config.getMinPasswordLength() + " characters";
|
return "Password may not be shorter than " + config.getMinPasswordLength() + " characters";
|
||||||
}
|
}
|
||||||
|
@ -178,7 +180,7 @@ public class Session {
|
||||||
public String connectUserHandling(String userName, String password) throws MageException {
|
public String connectUserHandling(String userName, String password) throws MageException {
|
||||||
this.isAdmin = false;
|
this.isAdmin = false;
|
||||||
AuthorizedUser authorizedUser = null;
|
AuthorizedUser authorizedUser = null;
|
||||||
if (ConfigSettings.instance.isAuthenticationActivated()) {
|
if (managerFactory.configSettings().isAuthenticationActivated()) {
|
||||||
authorizedUser = AuthorizedUserRepository.instance.getByName(userName);
|
authorizedUser = AuthorizedUserRepository.instance.getByName(userName);
|
||||||
String errorMsg = "Wrong username or password. In case you haven't, please register your account first.";
|
String errorMsg = "Wrong username or password. In case you haven't, please register your account first.";
|
||||||
if (authorizedUser == null) {
|
if (authorizedUser == null) {
|
||||||
|
@ -196,7 +198,7 @@ public class Session {
|
||||||
if (authorizedUser.lockedUntil.compareTo(Calendar.getInstance().getTime()) > 0) {
|
if (authorizedUser.lockedUntil.compareTo(Calendar.getInstance().getTime()) > 0) {
|
||||||
return "Your profile is deactivated until " + SystemUtil.dateFormat.format(authorizedUser.lockedUntil);
|
return "Your profile is deactivated until " + SystemUtil.dateFormat.format(authorizedUser.lockedUntil);
|
||||||
} else {
|
} else {
|
||||||
UserManager.instance.createUser(userName, host, authorizedUser).ifPresent(user
|
managerFactory.userManager().createUser(userName, host, authorizedUser).ifPresent(user
|
||||||
-> user.setLockedUntil(null)
|
-> user.setLockedUntil(null)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -204,15 +206,15 @@ public class Session {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<User> selectUser = UserManager.instance.createUser(userName, host, authorizedUser);
|
Optional<User> selectUser = managerFactory.userManager().createUser(userName, host, authorizedUser);
|
||||||
boolean reconnect = false;
|
boolean reconnect = false;
|
||||||
if (!selectUser.isPresent()) {
|
if (!selectUser.isPresent()) {
|
||||||
// user already connected
|
// user already connected
|
||||||
selectUser = UserManager.instance.getUserByName(userName);
|
selectUser = managerFactory.userManager().getUserByName(userName);
|
||||||
if (selectUser.isPresent()) {
|
if (selectUser.isPresent()) {
|
||||||
User user = selectUser.get();
|
User user = selectUser.get();
|
||||||
// If authentication is not activated, check the identity using IP address.
|
// If authentication is not activated, check the identity using IP address.
|
||||||
if (ConfigSettings.instance.isAuthenticationActivated() || user.getHost().equals(host)) {
|
if (managerFactory.configSettings().isAuthenticationActivated() || user.getHost().equals(host)) {
|
||||||
user.updateLastActivity(null); // minimizes possible expiration
|
user.updateLastActivity(null); // minimizes possible expiration
|
||||||
this.userId = user.getId();
|
this.userId = user.getId();
|
||||||
if (user.getSessionId().isEmpty()) {
|
if (user.getSessionId().isEmpty()) {
|
||||||
|
@ -221,7 +223,7 @@ public class Session {
|
||||||
} else {
|
} else {
|
||||||
//disconnect previous session
|
//disconnect previous session
|
||||||
logger.info("Disconnecting another user instance: " + userName);
|
logger.info("Disconnecting another user instance: " + userName);
|
||||||
SessionManager.instance.disconnect(user.getSessionId(), DisconnectReason.ConnectingOtherInstance);
|
managerFactory.sessionManager().disconnect(user.getSessionId(), DisconnectReason.ConnectingOtherInstance);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return "User name " + userName + " already in use (or your IP address changed)";
|
return "User name " + userName + " already in use (or your IP address changed)";
|
||||||
|
@ -232,18 +234,18 @@ public class Session {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
User user = selectUser.get();
|
User user = selectUser.get();
|
||||||
if (!UserManager.instance.connectToSession(sessionId, user.getId())) {
|
if (!managerFactory.userManager().connectToSession(sessionId, user.getId())) {
|
||||||
return "Error connecting " + userName;
|
return "Error connecting " + userName;
|
||||||
}
|
}
|
||||||
this.userId = user.getId();
|
this.userId = user.getId();
|
||||||
if (reconnect) { // must be connected to receive the message
|
if (reconnect) { // must be connected to receive the message
|
||||||
Optional<GamesRoom> room = GamesRoomManager.instance.getRoom(GamesRoomManager.instance.getMainRoomId());
|
Optional<GamesRoom> room = managerFactory.gamesRoomManager().getRoom(managerFactory.gamesRoomManager().getMainRoomId());
|
||||||
if (!room.isPresent()) {
|
if (!room.isPresent()) {
|
||||||
logger.warn("main room not found"); // after server restart users try to use old rooms on reconnect
|
logger.warn("main room not found"); // after server restart users try to use old rooms on reconnect
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ChatManager.instance.joinChat(room.get().getChatId(), userId);
|
managerFactory.chatManager().joinChat(room.get().getChatId(), userId);
|
||||||
ChatManager.instance.sendReconnectMessage(userId);
|
managerFactory.chatManager().sendReconnectMessage(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -251,12 +253,12 @@ public class Session {
|
||||||
|
|
||||||
public void connectAdmin() {
|
public void connectAdmin() {
|
||||||
this.isAdmin = true;
|
this.isAdmin = true;
|
||||||
User user = UserManager.instance.createUser("Admin", host, null).orElse(
|
User user = managerFactory.userManager().createUser("Admin", host, null).orElse(
|
||||||
UserManager.instance.getUserByName("Admin").get());
|
managerFactory.userManager().getUserByName("Admin").get());
|
||||||
UserData adminUserData = UserData.getDefaultUserDataView();
|
UserData adminUserData = UserData.getDefaultUserDataView();
|
||||||
adminUserData.setGroupId(UserGroup.ADMIN.getGroupId());
|
adminUserData.setGroupId(UserGroup.ADMIN.getGroupId());
|
||||||
user.setUserData(adminUserData);
|
user.setUserData(adminUserData);
|
||||||
if (!UserManager.instance.connectToSession(sessionId, user.getId())) {
|
if (!managerFactory.userManager().connectToSession(sessionId, user.getId())) {
|
||||||
logger.info("Error connecting Admin!");
|
logger.info("Error connecting Admin!");
|
||||||
} else {
|
} else {
|
||||||
user.setUserState(User.UserState.Connected);
|
user.setUserState(User.UserState.Connected);
|
||||||
|
@ -265,7 +267,7 @@ public class Session {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean setUserData(String userName, UserData userData, String clientVersion, String userIdStr) {
|
public boolean setUserData(String userName, UserData userData, String clientVersion, String userIdStr) {
|
||||||
Optional<User> _user = UserManager.instance.getUserByName(userName);
|
Optional<User> _user = managerFactory.userManager().getUserByName(userName);
|
||||||
_user.ifPresent(user -> {
|
_user.ifPresent(user -> {
|
||||||
if (clientVersion != null) {
|
if (clientVersion != null) {
|
||||||
user.setClientVersion(clientVersion);
|
user.setClientVersion(clientVersion);
|
||||||
|
@ -313,7 +315,7 @@ public class Session {
|
||||||
|
|
||||||
// because different threads can activate this
|
// because different threads can activate this
|
||||||
public void userLostConnection() {
|
public void userLostConnection() {
|
||||||
Optional<User> _user = UserManager.instance.getUser(userId);
|
Optional<User> _user = managerFactory.userManager().getUser(userId);
|
||||||
if (!_user.isPresent()) {
|
if (!_user.isPresent()) {
|
||||||
return; //user was already disconnected by other thread
|
return; //user was already disconnected by other thread
|
||||||
}
|
}
|
||||||
|
@ -338,7 +340,7 @@ public class Session {
|
||||||
} else {
|
} else {
|
||||||
logger.error("SESSION LOCK - kill: userId " + userId);
|
logger.error("SESSION LOCK - kill: userId " + userId);
|
||||||
}
|
}
|
||||||
UserManager.instance.removeUserFromAllTablesAndChat(userId, reason);
|
managerFactory.userManager().removeUserFromAllTablesAndChat(userId, reason);
|
||||||
} catch (InterruptedException ex) {
|
} catch (InterruptedException ex) {
|
||||||
logger.error("SESSION LOCK - kill: userId " + userId, ex);
|
logger.error("SESSION LOCK - kill: userId " + userId, ex);
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -372,11 +374,11 @@ public class Session {
|
||||||
logger.warn("SESSION LOCK - fireCallback - userId: " + userId + " messageId: " + call.getMessageId(), ex);
|
logger.warn("SESSION LOCK - fireCallback - userId: " + userId + " messageId: " + call.getMessageId(), ex);
|
||||||
} catch (HandleCallbackException ex) {
|
} catch (HandleCallbackException ex) {
|
||||||
this.valid = false;
|
this.valid = false;
|
||||||
UserManager.instance.getUser(userId).ifPresent(user -> {
|
managerFactory.userManager().getUser(userId).ifPresent(user -> {
|
||||||
user.setUserState(User.UserState.Disconnected);
|
user.setUserState(User.UserState.Disconnected);
|
||||||
logger.warn("SESSION CALLBACK EXCEPTION - " + user.getName() + " userId " + userId + " messageId: " + call.getMessageId() + " - cause: " + getBasicCause(ex).toString());
|
logger.warn("SESSION CALLBACK EXCEPTION - " + user.getName() + " userId " + userId + " messageId: " + call.getMessageId() + " - cause: " + getBasicCause(ex).toString());
|
||||||
logger.trace("Stack trace:", ex);
|
logger.trace("Stack trace:", ex);
|
||||||
SessionManager.instance.disconnect(sessionId, LostConnection);
|
managerFactory.sessionManager().disconnect(sessionId, LostConnection);
|
||||||
});
|
});
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
logger.warn("Unspecific exception:", ex);
|
logger.warn("Unspecific exception:", ex);
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
|
|
||||||
package mage.server;
|
package mage.server;
|
||||||
|
|
||||||
import mage.MageException;
|
import mage.MageException;
|
||||||
import mage.players.net.UserData;
|
import mage.players.net.UserData;
|
||||||
|
import mage.server.managers.SessionManager;
|
||||||
|
import mage.server.managers.ManagerFactory;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
import org.jboss.remoting.callback.InvokerCallbackHandler;
|
import org.jboss.remoting.callback.InvokerCallbackHandler;
|
||||||
|
|
||||||
|
@ -13,21 +14,25 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||||
/**
|
/**
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
*/
|
*/
|
||||||
public enum SessionManager {
|
public class SessionManagerImpl implements SessionManager {
|
||||||
|
|
||||||
instance;
|
private static final Logger logger = Logger.getLogger(SessionManagerImpl.class);
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(SessionManager.class);
|
|
||||||
|
|
||||||
|
private final ManagerFactory managerFactory;
|
||||||
private final ConcurrentHashMap<String, Session> sessions = new ConcurrentHashMap<>();
|
private final ConcurrentHashMap<String, Session> sessions = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
public SessionManagerImpl(ManagerFactory managerFactory) {
|
||||||
|
this.managerFactory = managerFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Optional<Session> getSession(@Nonnull String sessionId) {
|
public Optional<Session> getSession(@Nonnull String sessionId) {
|
||||||
Session session = sessions.get(sessionId);
|
Session session = sessions.get(sessionId);
|
||||||
if (session == null) {
|
if (session == null) {
|
||||||
logger.trace("Session with sessionId " + sessionId + " is not found");
|
logger.trace("Session with sessionId " + sessionId + " is not found");
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
if (session.getUserId() != null && !UserManager.instance.getUser(session.getUserId()).isPresent()) {
|
if (session.getUserId() != null && !managerFactory.userManager().getUser(session.getUserId()).isPresent()) {
|
||||||
logger.error("User for session " + sessionId + " with userId " + session.getUserId() + " is missing. Session removed.");
|
logger.error("User for session " + sessionId + " with userId " + session.getUserId() + " is missing. Session removed.");
|
||||||
// can happen if user from same host signs in multiple time with multiple clients, after they disconnect with one client
|
// can happen if user from same host signs in multiple time with multiple clients, after they disconnect with one client
|
||||||
disconnect(sessionId, DisconnectReason.ConnectingOtherInstance, session); // direct disconnect
|
disconnect(sessionId, DisconnectReason.ConnectingOtherInstance, session); // direct disconnect
|
||||||
|
@ -36,11 +41,13 @@ public enum SessionManager {
|
||||||
return Optional.of(session);
|
return Optional.of(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void createSession(String sessionId, InvokerCallbackHandler callbackHandler) {
|
public void createSession(String sessionId, InvokerCallbackHandler callbackHandler) {
|
||||||
Session session = new Session(sessionId, callbackHandler);
|
Session session = new Session(managerFactory, sessionId, callbackHandler);
|
||||||
sessions.put(sessionId, session);
|
sessions.put(sessionId, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean registerUser(String sessionId, String userName, String password, String email) throws MageException {
|
public boolean registerUser(String sessionId, String userName, String password, String email) throws MageException {
|
||||||
Session session = sessions.get(sessionId);
|
Session session = sessions.get(sessionId);
|
||||||
if (session == null) {
|
if (session == null) {
|
||||||
|
@ -59,6 +66,7 @@ public enum SessionManager {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean connectUser(String sessionId, String userName, String password, String userIdStr) throws MageException {
|
public boolean connectUser(String sessionId, String userName, String password, String userIdStr) throws MageException {
|
||||||
Session session = sessions.get(sessionId);
|
Session session = sessions.get(sessionId);
|
||||||
if (session != null) {
|
if (session != null) {
|
||||||
|
@ -78,6 +86,7 @@ public enum SessionManager {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean connectAdmin(String sessionId) {
|
public boolean connectAdmin(String sessionId) {
|
||||||
Session session = sessions.get(sessionId);
|
Session session = sessions.get(sessionId);
|
||||||
if (session != null) {
|
if (session != null) {
|
||||||
|
@ -88,17 +97,20 @@ public enum SessionManager {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean setUserData(String userName, String sessionId, UserData userData, String clientVersion, String userIdStr) throws MageException {
|
public boolean setUserData(String userName, String sessionId, UserData userData, String clientVersion, String userIdStr) throws MageException {
|
||||||
return getSession(sessionId)
|
return getSession(sessionId)
|
||||||
.map(session -> session.setUserData(userName,userData, clientVersion, userIdStr))
|
.map(session -> session.setUserData(userName, userData, clientVersion, userIdStr))
|
||||||
.orElse(false);
|
.orElse(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void disconnect(String sessionId, DisconnectReason reason) {
|
public void disconnect(String sessionId, DisconnectReason reason) {
|
||||||
disconnect(sessionId, reason, null);
|
disconnect(sessionId, reason, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void disconnect(String sessionId, DisconnectReason reason, Session directSession) {
|
public void disconnect(String sessionId, DisconnectReason reason, Session directSession) {
|
||||||
if (directSession == null) {
|
if (directSession == null) {
|
||||||
// find real session to disconnects
|
// find real session to disconnects
|
||||||
|
@ -115,13 +127,13 @@ public enum SessionManager {
|
||||||
break;
|
break;
|
||||||
case ConnectingOtherInstance:
|
case ConnectingOtherInstance:
|
||||||
case Disconnected: // regular session end or wrong client version
|
case Disconnected: // regular session end or wrong client version
|
||||||
UserManager.instance.disconnect(session.getUserId(), reason);
|
managerFactory.userManager().disconnect(session.getUserId(), reason);
|
||||||
break;
|
break;
|
||||||
case SessionExpired: // session ends after no reconnect happens in the defined time span
|
case SessionExpired: // session ends after no reconnect happens in the defined time span
|
||||||
break;
|
break;
|
||||||
case LostConnection: // user lost connection - session expires countdown starts
|
case LostConnection: // user lost connection - session expires countdown starts
|
||||||
session.userLostConnection();
|
session.userLostConnection();
|
||||||
UserManager.instance.disconnect(session.getUserId(), reason);
|
managerFactory.userManager().disconnect(session.getUserId(), reason);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
logger.trace("endSession: unexpected reason " + reason.toString() + " - sessionId: " + sessionId);
|
logger.trace("endSession: unexpected reason " + reason.toString() + " - sessionId: " + sessionId);
|
||||||
|
@ -141,6 +153,7 @@ public enum SessionManager {
|
||||||
* @param sessionId
|
* @param sessionId
|
||||||
* @param userSessionId
|
* @param userSessionId
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void disconnectUser(String sessionId, String userSessionId) {
|
public void disconnectUser(String sessionId, String userSessionId) {
|
||||||
if (isAdmin(sessionId)) {
|
if (isAdmin(sessionId)) {
|
||||||
getUserFromSession(sessionId).ifPresent(admin -> {
|
getUserFromSession(sessionId).ifPresent(admin -> {
|
||||||
|
@ -159,40 +172,46 @@ public enum SessionManager {
|
||||||
|
|
||||||
private Optional<User> getUserFromSession(String sessionId) {
|
private Optional<User> getUserFromSession(String sessionId) {
|
||||||
return getSession(sessionId)
|
return getSession(sessionId)
|
||||||
.flatMap(s -> UserManager.instance.getUser(s.getUserId()));
|
.flatMap(s -> managerFactory.userManager().getUser(s.getUserId()));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void endUserSession(String sessionId, String userSessionId) {
|
public void endUserSession(String sessionId, String userSessionId) {
|
||||||
if (isAdmin(sessionId)) {
|
if (isAdmin(sessionId)) {
|
||||||
disconnect(userSessionId, DisconnectReason.AdminDisconnect);
|
disconnect(userSessionId, DisconnectReason.AdminDisconnect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isAdmin(String sessionId) {
|
public boolean isAdmin(String sessionId) {
|
||||||
return getSession(sessionId).map(Session::isAdmin).orElse(false);
|
return getSession(sessionId).map(Session::isAdmin).orElse(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isValidSession(@Nonnull String sessionId) {
|
public boolean isValidSession(@Nonnull String sessionId) {
|
||||||
return sessions.containsKey(sessionId);
|
return sessions.containsKey(sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Optional<User> getUser(@Nonnull String sessionId) {
|
public Optional<User> getUser(@Nonnull String sessionId) {
|
||||||
Session session = sessions.get(sessionId);
|
Session session = sessions.get(sessionId);
|
||||||
if (session != null) {
|
if (session != null) {
|
||||||
return UserManager.instance.getUser(sessions.get(sessionId).getUserId());
|
return managerFactory.userManager().getUser(sessions.get(sessionId).getUserId());
|
||||||
}
|
}
|
||||||
logger.error(String.format("Session %s could not be found", sessionId));
|
logger.error(String.format("Session %s could not be found", sessionId));
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean extendUserSession(String sessionId, String pingInfo) {
|
public boolean extendUserSession(String sessionId, String pingInfo) {
|
||||||
return getSession(sessionId)
|
return getSession(sessionId)
|
||||||
.map(session -> UserManager.instance.extendUserSession(session.getUserId(), pingInfo))
|
.map(session -> managerFactory.userManager().extendUserSession(session.getUserId(), pingInfo))
|
||||||
.orElse(false);
|
.orElse(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void sendErrorMessageToClient(String sessionId, String message) {
|
public void sendErrorMessageToClient(String sessionId, String message) {
|
||||||
Session session = sessions.get(sessionId);
|
Session session = sessions.get(sessionId);
|
||||||
if (session == null) {
|
if (session == null) {
|
|
@ -20,16 +20,12 @@ import mage.game.tournament.TournamentOptions;
|
||||||
import mage.game.tournament.TournamentPlayer;
|
import mage.game.tournament.TournamentPlayer;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.players.PlayerType;
|
import mage.players.PlayerType;
|
||||||
import mage.server.draft.DraftManager;
|
|
||||||
import mage.server.game.GameFactory;
|
import mage.server.game.GameFactory;
|
||||||
import mage.server.game.GameManager;
|
|
||||||
import mage.server.game.PlayerFactory;
|
import mage.server.game.PlayerFactory;
|
||||||
|
import mage.server.managers.ManagerFactory;
|
||||||
import mage.server.record.TableRecorderImpl;
|
import mage.server.record.TableRecorderImpl;
|
||||||
import mage.server.tournament.TournamentFactory;
|
import mage.server.tournament.TournamentFactory;
|
||||||
import mage.server.tournament.TournamentManager;
|
|
||||||
import mage.server.util.ConfigSettings;
|
|
||||||
import mage.server.util.ServerMessagesUtil;
|
import mage.server.util.ServerMessagesUtil;
|
||||||
import mage.server.util.ThreadExecutor;
|
|
||||||
import mage.view.ChatMessage;
|
import mage.view.ChatMessage;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
@ -47,6 +43,7 @@ public class TableController {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(TableController.class);
|
private static final Logger logger = Logger.getLogger(TableController.class);
|
||||||
|
|
||||||
|
private final ManagerFactory managerFactory;
|
||||||
private final UUID userId;
|
private final UUID userId;
|
||||||
private final UUID chatId;
|
private final UUID chatId;
|
||||||
private final String controllerName;
|
private final String controllerName;
|
||||||
|
@ -58,32 +55,36 @@ public class TableController {
|
||||||
private Tournament tournament;
|
private Tournament tournament;
|
||||||
|
|
||||||
private ScheduledFuture<?> futureTimeout;
|
private ScheduledFuture<?> futureTimeout;
|
||||||
protected static final ScheduledExecutorService timeoutExecutor = ThreadExecutor.instance.getTimeoutExecutor();
|
protected final ScheduledExecutorService timeoutExecutor;
|
||||||
|
|
||||||
public TableController(UUID roomId, UUID userId, MatchOptions options) {
|
public TableController(ManagerFactory managerFactory, UUID roomId, UUID userId, MatchOptions options) {
|
||||||
|
this.managerFactory = managerFactory;
|
||||||
|
timeoutExecutor = managerFactory.threadExecutor().getTimeoutExecutor();
|
||||||
this.userId = userId;
|
this.userId = userId;
|
||||||
this.options = options;
|
this.options = options;
|
||||||
match = GameFactory.instance.createMatch(options.getGameType(), options);
|
match = GameFactory.instance.createMatch(options.getGameType(), options);
|
||||||
if (userId != null) {
|
if (userId != null) {
|
||||||
Optional<User> user = UserManager.instance.getUser(userId);
|
Optional<User> user = managerFactory.userManager().getUser(userId);
|
||||||
// TODO: Handle if user == null
|
// TODO: Handle if user == null
|
||||||
controllerName = user.map(User::getName).orElse("undefined");
|
controllerName = user.map(User::getName).orElse("undefined");
|
||||||
} else {
|
} else {
|
||||||
controllerName = "System";
|
controllerName = "System";
|
||||||
}
|
}
|
||||||
table = new Table(roomId, options.getGameType(), options.getName(), controllerName, DeckValidatorFactory.instance.createDeckValidator(options.getDeckType()),
|
table = new Table(roomId, options.getGameType(), options.getName(), controllerName, DeckValidatorFactory.instance.createDeckValidator(options.getDeckType()),
|
||||||
options.getPlayerTypes(), TableRecorderImpl.instance, match, options.getBannedUsers(), options.isPlaneChase());
|
options.getPlayerTypes(), new TableRecorderImpl(managerFactory.userManager()), match, options.getBannedUsers(), options.isPlaneChase());
|
||||||
chatId = ChatManager.instance.createChatSession("Match Table " + table.getId());
|
chatId = managerFactory.chatManager().createChatSession("Match Table " + table.getId());
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
public TableController(UUID roomId, UUID userId, TournamentOptions options) {
|
public TableController(ManagerFactory managerFactory, UUID roomId, UUID userId, TournamentOptions options) {
|
||||||
|
this.managerFactory = managerFactory;
|
||||||
|
this.timeoutExecutor = managerFactory.threadExecutor().getTimeoutExecutor();
|
||||||
this.userId = userId;
|
this.userId = userId;
|
||||||
tournament = TournamentFactory.instance.createTournament(options.getTournamentType(), options);
|
tournament = TournamentFactory.instance.createTournament(options.getTournamentType(), options);
|
||||||
if (userId != null) {
|
if (userId != null) {
|
||||||
Optional<User> user = UserManager.instance.getUser(userId);
|
Optional<User> user = managerFactory.userManager().getUser(userId);
|
||||||
if (!user.isPresent()) {
|
if (!user.isPresent()) {
|
||||||
logger.fatal(new StringBuilder("User for userId ").append(userId).append(" could not be retrieved from UserManager").toString());
|
logger.fatal(new StringBuilder("User for userId ").append(userId).append(" could not be retrieved from UserManagerImpl").toString());
|
||||||
controllerName = "[unknown]";
|
controllerName = "[unknown]";
|
||||||
} else {
|
} else {
|
||||||
controllerName = user.get().getName();
|
controllerName = user.get().getName();
|
||||||
|
@ -92,8 +93,8 @@ public class TableController {
|
||||||
controllerName = "System";
|
controllerName = "System";
|
||||||
}
|
}
|
||||||
table = new Table(roomId, options.getTournamentType(), options.getName(), controllerName, DeckValidatorFactory.instance.createDeckValidator(options.getMatchOptions().getDeckType()),
|
table = new Table(roomId, options.getTournamentType(), options.getName(), controllerName, DeckValidatorFactory.instance.createDeckValidator(options.getMatchOptions().getDeckType()),
|
||||||
options.getPlayerTypes(), TableRecorderImpl.instance, tournament, options.getMatchOptions().getBannedUsers(), options.isPlaneChase());
|
options.getPlayerTypes(), new TableRecorderImpl(managerFactory.userManager()), tournament, options.getMatchOptions().getBannedUsers(), options.isPlaneChase());
|
||||||
chatId = ChatManager.instance.createChatSession("Tourn. table " + table.getId());
|
chatId = managerFactory.chatManager().createChatSession("Tourn. table " + table.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void init() {
|
private void init() {
|
||||||
|
@ -121,7 +122,7 @@ public class TableController {
|
||||||
if (seat == null) {
|
if (seat == null) {
|
||||||
throw new GameException("No available seats.");
|
throw new GameException("No available seats.");
|
||||||
}
|
}
|
||||||
Optional<User> _user = UserManager.instance.getUser(userId);
|
Optional<User> _user = managerFactory.userManager().getUser(userId);
|
||||||
if (!_user.isPresent()) {
|
if (!_user.isPresent()) {
|
||||||
logger.fatal("couldn't get user " + name + " for join tournament userId = " + userId);
|
logger.fatal("couldn't get user " + name + " for join tournament userId = " + userId);
|
||||||
return false;
|
return false;
|
||||||
|
@ -156,7 +157,7 @@ public class TableController {
|
||||||
user.showUserMessage("Join Table", sb.toString());
|
user.showUserMessage("Join Table", sb.toString());
|
||||||
if (isOwner(userId)) {
|
if (isOwner(userId)) {
|
||||||
logger.debug("New table removed because owner submitted invalid deck tableId " + table.getId());
|
logger.debug("New table removed because owner submitted invalid deck tableId " + table.getId());
|
||||||
TableManager.instance.removeTable(table.getId());
|
managerFactory.tableManager().removeTable(table.getId());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -231,12 +232,12 @@ public class TableController {
|
||||||
newTournamentPlayer.setState(oldTournamentPlayer.getState());
|
newTournamentPlayer.setState(oldTournamentPlayer.getState());
|
||||||
newTournamentPlayer.setReplacedTournamentPlayer(oldTournamentPlayer);
|
newTournamentPlayer.setReplacedTournamentPlayer(oldTournamentPlayer);
|
||||||
|
|
||||||
DraftManager.instance.getController(table.getId()).ifPresent(controller -> controller.replacePlayer(oldPlayer, newPlayer));
|
managerFactory.draftManager().getController(table.getId()).ifPresent(controller -> controller.replacePlayer(oldPlayer, newPlayer));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized boolean joinTable(UUID userId, String name, PlayerType playerType, int skill, DeckCardLists deckList, String password) throws MageException {
|
public synchronized boolean joinTable(UUID userId, String name, PlayerType playerType, int skill, DeckCardLists deckList, String password) throws MageException {
|
||||||
Optional<User> _user = UserManager.instance.getUser(userId);
|
Optional<User> _user = managerFactory.userManager().getUser(userId);
|
||||||
if (!_user.isPresent()) {
|
if (!_user.isPresent()) {
|
||||||
logger.error("Join Table: can't find user to join " + name + " Id = " + userId);
|
logger.error("Join Table: can't find user to join " + name + " Id = " + userId);
|
||||||
return false;
|
return false;
|
||||||
|
@ -274,7 +275,7 @@ public class TableController {
|
||||||
user.showUserMessage("Join Table", sb.toString());
|
user.showUserMessage("Join Table", sb.toString());
|
||||||
if (isOwner(userId)) {
|
if (isOwner(userId)) {
|
||||||
logger.debug("New table removed because owner submitted invalid deck tableId " + table.getId());
|
logger.debug("New table removed because owner submitted invalid deck tableId " + table.getId());
|
||||||
TableManager.instance.removeTable(table.getId());
|
managerFactory.tableManager().removeTable(table.getId());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -420,7 +421,7 @@ public class TableController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!Main.isTestMode() && !table.getValidator().validate(deck)) {
|
if (!Main.isTestMode() && !table.getValidator().validate(deck)) {
|
||||||
Optional<User> _user = UserManager.instance.getUser(userId);
|
Optional<User> _user = managerFactory.userManager().getUser(userId);
|
||||||
if (!_user.isPresent()) {
|
if (!_user.isPresent()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -453,10 +454,10 @@ public class TableController {
|
||||||
private void submitDeck(UUID userId, UUID playerId, Deck deck) {
|
private void submitDeck(UUID userId, UUID playerId, Deck deck) {
|
||||||
if (table.getState() == TableState.SIDEBOARDING) {
|
if (table.getState() == TableState.SIDEBOARDING) {
|
||||||
match.submitDeck(playerId, deck);
|
match.submitDeck(playerId, deck);
|
||||||
UserManager.instance.getUser(userId).ifPresent(user -> user.removeSideboarding(table.getId()));
|
managerFactory.userManager().getUser(userId).ifPresent(user -> user.removeSideboarding(table.getId()));
|
||||||
} else {
|
} else {
|
||||||
TournamentManager.instance.submitDeck(tournament.getId(), playerId, deck);
|
managerFactory.tournamentManager().submitDeck(tournament.getId(), playerId, deck);
|
||||||
UserManager.instance.getUser(userId).ifPresent(user -> user.removeConstructing(playerId));
|
managerFactory.userManager().getUser(userId).ifPresent(user -> user.removeConstructing(playerId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -464,7 +465,7 @@ public class TableController {
|
||||||
boolean validDeck = true;
|
boolean validDeck = true;
|
||||||
if (table.isTournament()) {
|
if (table.isTournament()) {
|
||||||
if (tournament != null) {
|
if (tournament != null) {
|
||||||
validDeck = TournamentManager.instance.updateDeck(tournament.getId(), playerId, deck);
|
validDeck = managerFactory.tournamentManager().updateDeck(tournament.getId(), playerId, deck);
|
||||||
} else {
|
} else {
|
||||||
logger.fatal("Tournament == null table: " + table.getId() + " userId: " + userId);
|
logger.fatal("Tournament == null table: " + table.getId() + " userId: " + userId);
|
||||||
}
|
}
|
||||||
|
@ -478,7 +479,7 @@ public class TableController {
|
||||||
|
|
||||||
public boolean watchTable(UUID userId) {
|
public boolean watchTable(UUID userId) {
|
||||||
if (table.isTournament()) {
|
if (table.isTournament()) {
|
||||||
UserManager.instance.getUser(userId).ifPresent(user -> user.ccShowTournament(table.getTournament().getId()));
|
managerFactory.userManager().getUser(userId).ifPresent(user -> user.ccShowTournament(table.getTournament().getId()));
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
if (table.isTournamentSubTable() && !table.getTournament().getOptions().isWatchingAllowed()) {
|
if (table.isTournamentSubTable() && !table.getTournament().getOptions().isWatchingAllowed()) {
|
||||||
|
@ -491,7 +492,7 @@ public class TableController {
|
||||||
if (userPlayerMap.get(userId) != null) {
|
if (userPlayerMap.get(userId) != null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Optional<User> _user = UserManager.instance.getUser(userId);
|
Optional<User> _user = managerFactory.userManager().getUser(userId);
|
||||||
if (!_user.isPresent()) {
|
if (!_user.isPresent()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -533,7 +534,7 @@ public class TableController {
|
||||||
&& (table.getState() == TableState.WAITING
|
&& (table.getState() == TableState.WAITING
|
||||||
|| table.getState() == TableState.READY_TO_START)) {
|
|| table.getState() == TableState.READY_TO_START)) {
|
||||||
// table not started yet and user is the owner, removeUserFromAllTablesAndChat the table
|
// table not started yet and user is the owner, removeUserFromAllTablesAndChat the table
|
||||||
TableManager.instance.removeTable(table.getId());
|
managerFactory.tableManager().removeTable(table.getId());
|
||||||
} else {
|
} else {
|
||||||
UUID playerId = userPlayerMap.get(userId);
|
UUID playerId = userPlayerMap.get(userId);
|
||||||
if (playerId != null) {
|
if (playerId != null) {
|
||||||
|
@ -544,9 +545,9 @@ public class TableController {
|
||||||
} else {
|
} else {
|
||||||
match.quitMatch(playerId);
|
match.quitMatch(playerId);
|
||||||
}
|
}
|
||||||
Optional<User> user = UserManager.instance.getUser(userId);
|
Optional<User> user = managerFactory.userManager().getUser(userId);
|
||||||
if (user.isPresent()) {
|
if (user.isPresent()) {
|
||||||
ChatManager.instance.broadcast(chatId, user.get().getName(), "has left the table", ChatMessage.MessageColor.BLUE, true, null, ChatMessage.MessageType.STATUS, ChatMessage.SoundToPlay.PlayerLeft);
|
managerFactory.chatManager().broadcast(chatId, user.get().getName(), "has left the table", ChatMessage.MessageColor.BLUE, true, null, ChatMessage.MessageType.STATUS, ChatMessage.SoundToPlay.PlayerLeft);
|
||||||
if (!table.isTournamentSubTable()) {
|
if (!table.isTournamentSubTable()) {
|
||||||
user.get().removeTable(playerId);
|
user.get().removeTable(playerId);
|
||||||
}
|
}
|
||||||
|
@ -557,9 +558,9 @@ public class TableController {
|
||||||
} else if (table.getState() != TableState.FINISHED) {
|
} else if (table.getState() != TableState.FINISHED) {
|
||||||
if (table.isTournament()) {
|
if (table.isTournament()) {
|
||||||
logger.debug("Quit tournament sub tables for userId: " + userId);
|
logger.debug("Quit tournament sub tables for userId: " + userId);
|
||||||
TableManager.instance.userQuitTournamentSubTables(tournament.getId(), userId);
|
managerFactory.tableManager().userQuitTournamentSubTables(tournament.getId(), userId);
|
||||||
logger.debug("Quit tournament Id: " + table.getTournament().getId() + '(' + table.getTournament().getTournamentState() + ')');
|
logger.debug("Quit tournament Id: " + table.getTournament().getId() + '(' + table.getTournament().getTournamentState() + ')');
|
||||||
TournamentManager.instance.quit(tournament.getId(), userId);
|
managerFactory.tournamentManager().quit(tournament.getId(), userId);
|
||||||
} else {
|
} else {
|
||||||
MatchPlayer matchPlayer = match.getPlayer(playerId);
|
MatchPlayer matchPlayer = match.getPlayer(playerId);
|
||||||
if (matchPlayer != null && !match.hasEnded() && !matchPlayer.hasQuit()) {
|
if (matchPlayer != null && !match.hasEnded() && !matchPlayer.hasQuit()) {
|
||||||
|
@ -567,7 +568,7 @@ public class TableController {
|
||||||
if (game != null && !game.hasEnded()) {
|
if (game != null && !game.hasEnded()) {
|
||||||
Player player = match.getPlayer(playerId).getPlayer();
|
Player player = match.getPlayer(playerId).getPlayer();
|
||||||
if (player != null && player.isInGame()) {
|
if (player != null && player.isInGame()) {
|
||||||
GameManager.instance.quitMatch(game.getId(), userId);
|
managerFactory.gameManager().quitMatch(game.getId(), userId);
|
||||||
}
|
}
|
||||||
match.quitMatch(playerId);
|
match.quitMatch(playerId);
|
||||||
} else {
|
} else {
|
||||||
|
@ -605,7 +606,7 @@ public class TableController {
|
||||||
if (table.isTournamentSubTable()) {
|
if (table.isTournamentSubTable()) {
|
||||||
logger.info("Tourn. match started id:" + match.getId() + " tournId: " + table.getTournament().getId());
|
logger.info("Tourn. match started id:" + match.getId() + " tournId: " + table.getTournament().getId());
|
||||||
} else {
|
} else {
|
||||||
UserManager.instance.getUser(userId).ifPresent(user -> {
|
managerFactory.userManager().getUser(userId).ifPresent(user -> {
|
||||||
logger.info("MATCH started [" + match.getName() + "] " + match.getId() + '(' + user.getName() + ')');
|
logger.info("MATCH started [" + match.getName() + "] " + match.getId() + '(' + user.getName() + ')');
|
||||||
logger.debug("- " + match.getOptions().getGameType() + " - " + match.getOptions().getDeckType());
|
logger.debug("- " + match.getOptions().getGameType() + " - " + match.getOptions().getDeckType());
|
||||||
});
|
});
|
||||||
|
@ -628,12 +629,12 @@ public class TableController {
|
||||||
gameOptions.bannedUsers = match.getOptions().getBannedUsers();
|
gameOptions.bannedUsers = match.getOptions().getBannedUsers();
|
||||||
gameOptions.planeChase = match.getOptions().isPlaneChase();
|
gameOptions.planeChase = match.getOptions().isPlaneChase();
|
||||||
match.getGame().setGameOptions(gameOptions);
|
match.getGame().setGameOptions(gameOptions);
|
||||||
GameManager.instance.createGameSession(match.getGame(), userPlayerMap, table.getId(), choosingPlayerId, gameOptions);
|
managerFactory.gameManager().createGameSession(match.getGame(), userPlayerMap, table.getId(), choosingPlayerId, gameOptions);
|
||||||
String creator = null;
|
String creator = null;
|
||||||
StringBuilder opponent = new StringBuilder();
|
StringBuilder opponent = new StringBuilder();
|
||||||
for (Entry<UUID, UUID> entry : userPlayerMap.entrySet()) { // do only for no AI players
|
for (Entry<UUID, UUID> entry : userPlayerMap.entrySet()) { // do only for no AI players
|
||||||
if (match.getPlayer(entry.getValue()) != null && !match.getPlayer(entry.getValue()).hasQuit()) {
|
if (match.getPlayer(entry.getValue()) != null && !match.getPlayer(entry.getValue()).hasQuit()) {
|
||||||
Optional<User> _user = UserManager.instance.getUser(entry.getKey());
|
Optional<User> _user = managerFactory.userManager().getUser(entry.getKey());
|
||||||
if (_user.isPresent()) {
|
if (_user.isPresent()) {
|
||||||
User user = _user.get();
|
User user = _user.get();
|
||||||
user.ccGameStarted(match.getGame().getId(), entry.getValue());
|
user.ccGameStarted(match.getGame().getId(), entry.getValue());
|
||||||
|
@ -670,17 +671,17 @@ public class TableController {
|
||||||
logger.info("GAME started " + (match.getGame() != null ? match.getGame().getId() : "no Game") + " [" + match.getName() + "] " + creator + " - " + opponent.toString());
|
logger.info("GAME started " + (match.getGame() != null ? match.getGame().getId() : "no Game") + " [" + match.getName() + "] " + creator + " - " + opponent.toString());
|
||||||
logger.debug("- matchId: " + match.getId() + " [" + match.getName() + ']');
|
logger.debug("- matchId: " + match.getId() + " [" + match.getName() + ']');
|
||||||
if (match.getGame() != null) {
|
if (match.getGame() != null) {
|
||||||
logger.debug("- chatId: " + GameManager.instance.getChatId(match.getGame().getId()));
|
logger.debug("- chatId: " + managerFactory.gameManager().getChatId(match.getGame().getId()));
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
logger.fatal("Error starting game table: " + table.getId(), ex);
|
logger.fatal("Error starting game table: " + table.getId(), ex);
|
||||||
if (table != null) {
|
if (table != null) {
|
||||||
TableManager.instance.removeTable(table.getId());
|
managerFactory.tableManager().removeTable(table.getId());
|
||||||
}
|
}
|
||||||
if (match != null) {
|
if (match != null) {
|
||||||
Game game = match.getGame();
|
Game game = match.getGame();
|
||||||
if (game != null) {
|
if (game != null) {
|
||||||
GameManager.instance.removeGame(game.getId());
|
managerFactory.gameManager().removeGame(game.getId());
|
||||||
// game ended by error, so don't add it to ended stats
|
// game ended by error, so don't add it to ended stats
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -691,9 +692,9 @@ public class TableController {
|
||||||
try {
|
try {
|
||||||
if (userId.equals(this.userId) && table.getState() == TableState.STARTING) {
|
if (userId.equals(this.userId) && table.getState() == TableState.STARTING) {
|
||||||
tournament.setStartTime();
|
tournament.setStartTime();
|
||||||
TournamentManager.instance.createTournamentSession(tournament, userPlayerMap, table.getId());
|
managerFactory.tournamentManager().createTournamentSession(tournament, userPlayerMap, table.getId());
|
||||||
for (Entry<UUID, UUID> entry : userPlayerMap.entrySet()) {
|
for (Entry<UUID, UUID> entry : userPlayerMap.entrySet()) {
|
||||||
UserManager.instance.getUser(entry.getKey()).ifPresent(user -> {
|
managerFactory.userManager().getUser(entry.getKey()).ifPresent(user -> {
|
||||||
logger.info(new StringBuilder("User ").append(user.getName()).append(" tournament started: ").append(tournament.getId()).append(" userId: ").append(user.getId()));
|
logger.info(new StringBuilder("User ").append(user.getName()).append(" tournament started: ").append(tournament.getId()).append(" userId: ").append(user.getId()));
|
||||||
user.ccTournamentStarted(tournament.getId(), entry.getValue());
|
user.ccTournamentStarted(tournament.getId(), entry.getValue());
|
||||||
});
|
});
|
||||||
|
@ -702,16 +703,16 @@ public class TableController {
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
logger.fatal("Error starting tournament", ex);
|
logger.fatal("Error starting tournament", ex);
|
||||||
TableManager.instance.removeTable(table.getId());
|
managerFactory.tableManager().removeTable(table.getId());
|
||||||
TournamentManager.instance.quit(tournament.getId(), userId);
|
managerFactory.tournamentManager().quit(tournament.getId(), userId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startDraft(Draft draft) {
|
public void startDraft(Draft draft) {
|
||||||
table.initDraft();
|
table.initDraft();
|
||||||
DraftManager.instance.createDraftSession(draft, userPlayerMap, table.getId());
|
managerFactory.draftManager().createDraftSession(draft, userPlayerMap, table.getId());
|
||||||
for (Entry<UUID, UUID> entry : userPlayerMap.entrySet()) {
|
for (Entry<UUID, UUID> entry : userPlayerMap.entrySet()) {
|
||||||
Optional<User> user = UserManager.instance.getUser(entry.getKey());
|
Optional<User> user = managerFactory.userManager().getUser(entry.getKey());
|
||||||
if (user.isPresent()) {
|
if (user.isPresent()) {
|
||||||
logger.info(new StringBuilder("User ").append(user.get().getName()).append(" draft started: ").append(draft.getId()).append(" userId: ").append(user.get().getId()));
|
logger.info(new StringBuilder("User ").append(user.get().getName()).append(" draft started: ").append(draft.getId()).append(" userId: ").append(user.get().getId()));
|
||||||
user.get().ccDraftStarted(draft.getId(), entry.getValue());
|
user.get().ccDraftStarted(draft.getId(), entry.getValue());
|
||||||
|
@ -725,7 +726,7 @@ public class TableController {
|
||||||
|
|
||||||
for (Entry<UUID, UUID> entry : userPlayerMap.entrySet()) {
|
for (Entry<UUID, UUID> entry : userPlayerMap.entrySet()) {
|
||||||
if (entry.getValue().equals(playerId)) {
|
if (entry.getValue().equals(playerId)) {
|
||||||
Optional<User> user = UserManager.instance.getUser(entry.getKey());
|
Optional<User> user = managerFactory.userManager().getUser(entry.getKey());
|
||||||
int remaining = (int) futureTimeout.getDelay(TimeUnit.SECONDS);
|
int remaining = (int) futureTimeout.getDelay(TimeUnit.SECONDS);
|
||||||
user.ifPresent(user1 -> user1.ccSideboard(deck, table.getId(), remaining, options.isLimited()));
|
user.ifPresent(user1 -> user1.ccSideboard(deck, table.getId(), remaining, options.isLimited()));
|
||||||
break;
|
break;
|
||||||
|
@ -767,12 +768,12 @@ public class TableController {
|
||||||
}
|
}
|
||||||
UUID choosingPlayerId = match.getChooser();
|
UUID choosingPlayerId = match.getChooser();
|
||||||
match.endGame();
|
match.endGame();
|
||||||
if (ConfigSettings.instance.isSaveGameActivated() && !game.isSimulation()) {
|
if (managerFactory.configSettings().isSaveGameActivated() && !game.isSimulation()) {
|
||||||
if (GameManager.instance.saveGame(game.getId())) {
|
if (managerFactory.gameManager().saveGame(game.getId())) {
|
||||||
match.setReplayAvailable(true);
|
match.setReplayAvailable(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GameManager.instance.removeGame(game.getId());
|
managerFactory.gameManager().removeGame(game.getId());
|
||||||
ServerMessagesUtil.instance.incGamesEnded();
|
ServerMessagesUtil.instance.incGamesEnded();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -835,7 +836,7 @@ public class TableController {
|
||||||
// opponent(s) left during sideboarding
|
// opponent(s) left during sideboarding
|
||||||
if (matchPlayer != null) {
|
if (matchPlayer != null) {
|
||||||
if (!matchPlayer.hasQuit()) {
|
if (!matchPlayer.hasQuit()) {
|
||||||
UserManager.instance.getUser(entry.getKey()).ifPresent(user -> {
|
managerFactory.userManager().getUser(entry.getKey()).ifPresent(user -> {
|
||||||
if (table.getState() == TableState.SIDEBOARDING) {
|
if (table.getState() == TableState.SIDEBOARDING) {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
if (table.isTournamentSubTable()) {
|
if (table.isTournamentSubTable()) {
|
||||||
|
@ -860,7 +861,7 @@ public class TableController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// free resources no longer needed
|
// free resources no longer needed
|
||||||
match.cleanUpOnMatchEnd(ConfigSettings.instance.isSaveGameActivated(), table.isTournament());
|
match.cleanUpOnMatchEnd(managerFactory.configSettings().isSaveGameActivated(), table.isTournament());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -932,13 +933,13 @@ public class TableController {
|
||||||
public boolean isTournamentStillValid() {
|
public boolean isTournamentStillValid() {
|
||||||
if (table.getTournament() != null) {
|
if (table.getTournament() != null) {
|
||||||
if (table.getState() != TableState.WAITING && table.getState() != TableState.READY_TO_START && table.getState() != TableState.STARTING) {
|
if (table.getState() != TableState.WAITING && table.getState() != TableState.READY_TO_START && table.getState() != TableState.STARTING) {
|
||||||
return TournamentManager.instance.getTournamentController(table.getTournament().getId())
|
return managerFactory.tournamentManager().getTournamentController(table.getTournament().getId())
|
||||||
.map(tc -> tc.isTournamentStillValid(table.getState()))
|
.map(tc -> tc.isTournamentStillValid(table.getState()))
|
||||||
.orElse(false);
|
.orElse(false);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// check if table creator is still a valid user, if not removeUserFromAllTablesAndChat table
|
// check if table creator is still a valid user, if not removeUserFromAllTablesAndChat table
|
||||||
return UserManager.instance.getUser(userId).isPresent();
|
return managerFactory.userManager().getUser(userId).isPresent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -1004,7 +1005,7 @@ public class TableController {
|
||||||
|| table.getState() == TableState.READY_TO_START)
|
|| table.getState() == TableState.READY_TO_START)
|
||||||
|| !match.isDoneSideboarding()
|
|| !match.isDoneSideboarding()
|
||||||
|| (!matchPlayer.hasQuit() && match.getGame() != null && matchPlayer.getPlayer().isInGame())) {
|
|| (!matchPlayer.hasQuit() && match.getGame() != null && matchPlayer.getPlayer().isInGame())) {
|
||||||
Optional<User> user = UserManager.instance.getUser(userPlayerEntry.getKey());
|
Optional<User> user = managerFactory.userManager().getUser(userPlayerEntry.getKey());
|
||||||
if (!user.isPresent() || !user.get().isActive()) {
|
if (!user.isPresent() || !user.get().isActive()) {
|
||||||
logger.warn("- Active user of match is missing: " + matchPlayer.getName());
|
logger.warn("- Active user of match is missing: " + matchPlayer.getName());
|
||||||
logger.warn("-- matchId:" + match.getId());
|
logger.warn("-- matchId:" + match.getId());
|
||||||
|
@ -1028,12 +1029,12 @@ public class TableController {
|
||||||
void cleanUp() {
|
void cleanUp() {
|
||||||
if (!table.isTournamentSubTable()) {
|
if (!table.isTournamentSubTable()) {
|
||||||
for (Map.Entry<UUID, UUID> entry : userPlayerMap.entrySet()) {
|
for (Map.Entry<UUID, UUID> entry : userPlayerMap.entrySet()) {
|
||||||
UserManager.instance.getUser(entry.getKey()).ifPresent(user
|
managerFactory.userManager().getUser(entry.getKey()).ifPresent(user
|
||||||
-> user.removeTable(entry.getValue()));
|
-> user.removeTable(entry.getValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
ChatManager.instance.destroyChatSession(chatId);
|
managerFactory.chatManager().destroyChatSession(chatId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized TableState getTableState() {
|
public synchronized TableState getTableState() {
|
||||||
|
|
|
@ -14,9 +14,8 @@ import mage.game.tournament.TournamentOptions;
|
||||||
import mage.game.tournament.TournamentPlayer;
|
import mage.game.tournament.TournamentPlayer;
|
||||||
import mage.players.PlayerType;
|
import mage.players.PlayerType;
|
||||||
import mage.server.game.GameController;
|
import mage.server.game.GameController;
|
||||||
import mage.server.game.GameManager;
|
import mage.server.managers.TableManager;
|
||||||
import mage.server.game.GamesRoomManager;
|
import mage.server.managers.ManagerFactory;
|
||||||
import mage.server.util.ThreadExecutor;
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
|
@ -34,12 +33,12 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
/**
|
/**
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
*/
|
*/
|
||||||
public enum TableManager {
|
public class TableManagerImpl implements TableManager {
|
||||||
instance;
|
|
||||||
protected final ScheduledExecutorService expireExecutor = Executors.newSingleThreadScheduledExecutor();
|
protected final ScheduledExecutorService expireExecutor = Executors.newSingleThreadScheduledExecutor();
|
||||||
|
|
||||||
// protected static ScheduledExecutorService expireExecutor = ThreadExecutor.getInstance().getExpireExecutor();
|
// protected static ScheduledExecutorService expireExecutor = ThreadExecutorImpl.getInstance().getExpireExecutor();
|
||||||
private final Logger logger = Logger.getLogger(TableManager.class);
|
private final ManagerFactory managerFactory;
|
||||||
|
private final Logger logger = Logger.getLogger(TableManagerImpl.class);
|
||||||
private final DateFormat formatter = new SimpleDateFormat("HH:mm:ss");
|
private final DateFormat formatter = new SimpleDateFormat("HH:mm:ss");
|
||||||
|
|
||||||
private final ConcurrentHashMap<UUID, TableController> controllers = new ConcurrentHashMap<>();
|
private final ConcurrentHashMap<UUID, TableController> controllers = new ConcurrentHashMap<>();
|
||||||
|
@ -55,10 +54,14 @@ public enum TableManager {
|
||||||
*/
|
*/
|
||||||
private static final int EXPIRE_CHECK_PERIOD = 10;
|
private static final int EXPIRE_CHECK_PERIOD = 10;
|
||||||
|
|
||||||
TableManager() {
|
public TableManagerImpl(ManagerFactory managerFactory) {
|
||||||
|
this.managerFactory = managerFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init() {
|
||||||
expireExecutor.scheduleAtFixedRate(() -> {
|
expireExecutor.scheduleAtFixedRate(() -> {
|
||||||
try {
|
try {
|
||||||
ChatManager.instance.clearUserMessageStorage();
|
managerFactory.chatManager().clearUserMessageStorage();
|
||||||
checkTableHealthState();
|
checkTableHealthState();
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
logger.fatal("Check table health state job error:", ex);
|
logger.fatal("Check table health state job error:", ex);
|
||||||
|
@ -66,22 +69,25 @@ public enum TableManager {
|
||||||
}, EXPIRE_CHECK_PERIOD, EXPIRE_CHECK_PERIOD, TimeUnit.MINUTES);
|
}, EXPIRE_CHECK_PERIOD, EXPIRE_CHECK_PERIOD, TimeUnit.MINUTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Table createTable(UUID roomId, UUID userId, MatchOptions options) {
|
public Table createTable(UUID roomId, UUID userId, MatchOptions options) {
|
||||||
TableController tableController = new TableController(roomId, userId, options);
|
TableController tableController = new TableController(managerFactory, roomId, userId, options);
|
||||||
putControllers(tableController.getTable().getId(), tableController);
|
putControllers(tableController.getTable().getId(), tableController);
|
||||||
putTables(tableController.getTable().getId(), tableController.getTable());
|
putTables(tableController.getTable().getId(), tableController.getTable());
|
||||||
return tableController.getTable();
|
return tableController.getTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Table createTable(UUID roomId, MatchOptions options) {
|
public Table createTable(UUID roomId, MatchOptions options) {
|
||||||
TableController tableController = new TableController(roomId, null, options);
|
TableController tableController = new TableController(managerFactory, roomId, null, options);
|
||||||
putControllers(tableController.getTable().getId(), tableController);
|
putControllers(tableController.getTable().getId(), tableController);
|
||||||
putTables(tableController.getTable().getId(), tableController.getTable());
|
putTables(tableController.getTable().getId(), tableController.getTable());
|
||||||
return tableController.getTable();
|
return tableController.getTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Table createTournamentTable(UUID roomId, UUID userId, TournamentOptions options) {
|
public Table createTournamentTable(UUID roomId, UUID userId, TournamentOptions options) {
|
||||||
TableController tableController = new TableController(roomId, userId, options);
|
TableController tableController = new TableController(managerFactory, roomId, userId, options);
|
||||||
putControllers(tableController.getTable().getId(), tableController);
|
putControllers(tableController.getTable().getId(), tableController);
|
||||||
putTables(tableController.getTable().getId(), tableController.getTable());
|
putTables(tableController.getTable().getId(), tableController.getTable());
|
||||||
return tableController.getTable();
|
return tableController.getTable();
|
||||||
|
@ -107,10 +113,12 @@ public enum TableManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Table getTable(UUID tableId) {
|
public Table getTable(UUID tableId) {
|
||||||
return tables.get(tableId);
|
return tables.get(tableId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Optional<Match> getMatch(UUID tableId) {
|
public Optional<Match> getMatch(UUID tableId) {
|
||||||
if (controllers.containsKey(tableId)) {
|
if (controllers.containsKey(tableId)) {
|
||||||
return Optional.of(controllers.get(tableId).getMatch());
|
return Optional.of(controllers.get(tableId).getMatch());
|
||||||
|
@ -118,6 +126,7 @@ public enum TableManager {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Collection<Table> getTables() {
|
public Collection<Table> getTables() {
|
||||||
Collection<Table> newTables = new ArrayList<>();
|
Collection<Table> newTables = new ArrayList<>();
|
||||||
final Lock r = tablesLock.readLock();
|
final Lock r = tablesLock.readLock();
|
||||||
|
@ -130,6 +139,7 @@ public enum TableManager {
|
||||||
return newTables;
|
return newTables;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Collection<TableController> getControllers() {
|
public Collection<TableController> getControllers() {
|
||||||
Collection<TableController> newControllers = new ArrayList<>();
|
Collection<TableController> newControllers = new ArrayList<>();
|
||||||
final Lock r = controllersLock.readLock();
|
final Lock r = controllersLock.readLock();
|
||||||
|
@ -142,6 +152,7 @@ public enum TableManager {
|
||||||
return newControllers;
|
return newControllers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Optional<TableController> getController(UUID tableId) {
|
public Optional<TableController> getController(UUID tableId) {
|
||||||
if (controllers.containsKey(tableId)) {
|
if (controllers.containsKey(tableId)) {
|
||||||
return Optional.of(controllers.get(tableId));
|
return Optional.of(controllers.get(tableId));
|
||||||
|
@ -149,6 +160,7 @@ public enum TableManager {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean joinTable(UUID userId, UUID tableId, String name, PlayerType playerType, int skill, DeckCardLists deckList, String password) throws MageException {
|
public boolean joinTable(UUID userId, UUID tableId, String name, PlayerType playerType, int skill, DeckCardLists deckList, String password) throws MageException {
|
||||||
if (controllers.containsKey(tableId)) {
|
if (controllers.containsKey(tableId)) {
|
||||||
return controllers.get(tableId).joinTable(userId, name, playerType, skill, deckList, password);
|
return controllers.get(tableId).joinTable(userId, name, playerType, skill, deckList, password);
|
||||||
|
@ -156,6 +168,7 @@ public enum TableManager {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean joinTournament(UUID userId, UUID tableId, String name, PlayerType playerType, int skill, DeckCardLists deckList, String password) throws GameException {
|
public boolean joinTournament(UUID userId, UUID tableId, String name, PlayerType playerType, int skill, DeckCardLists deckList, String password) throws GameException {
|
||||||
if (controllers.containsKey(tableId)) {
|
if (controllers.containsKey(tableId)) {
|
||||||
return controllers.get(tableId).joinTournament(userId, name, playerType, skill, deckList, password);
|
return controllers.get(tableId).joinTournament(userId, name, playerType, skill, deckList, password);
|
||||||
|
@ -163,11 +176,12 @@ public enum TableManager {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean submitDeck(UUID userId, UUID tableId, DeckCardLists deckList) throws MageException {
|
public boolean submitDeck(UUID userId, UUID tableId, DeckCardLists deckList) throws MageException {
|
||||||
if (controllers.containsKey(tableId)) {
|
if (controllers.containsKey(tableId)) {
|
||||||
return controllers.get(tableId).submitDeck(userId, deckList);
|
return controllers.get(tableId).submitDeck(userId, deckList);
|
||||||
}
|
}
|
||||||
UserManager.instance.getUser(userId).ifPresent(user -> {
|
managerFactory.userManager().getUser(userId).ifPresent(user -> {
|
||||||
user.removeSideboarding(tableId);
|
user.removeSideboarding(tableId);
|
||||||
user.showUserMessage("Submit deck", "Table no longer active");
|
user.showUserMessage("Submit deck", "Table no longer active");
|
||||||
|
|
||||||
|
@ -176,6 +190,7 @@ public enum TableManager {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void updateDeck(UUID userId, UUID tableId, DeckCardLists deckList) throws MageException {
|
public void updateDeck(UUID userId, UUID tableId, DeckCardLists deckList) throws MageException {
|
||||||
if (controllers.containsKey(tableId)) {
|
if (controllers.containsKey(tableId)) {
|
||||||
controllers.get(tableId).updateDeck(userId, deckList);
|
controllers.get(tableId).updateDeck(userId, deckList);
|
||||||
|
@ -183,6 +198,7 @@ public enum TableManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
// removeUserFromAllTablesAndChat user from all tournament sub tables
|
// removeUserFromAllTablesAndChat user from all tournament sub tables
|
||||||
|
@Override
|
||||||
public void userQuitTournamentSubTables(UUID userId) {
|
public void userQuitTournamentSubTables(UUID userId) {
|
||||||
for (TableController controller : getControllers()) {
|
for (TableController controller : getControllers()) {
|
||||||
if (controller.getTable() != null) {
|
if (controller.getTable() != null) {
|
||||||
|
@ -190,12 +206,13 @@ public enum TableManager {
|
||||||
controller.leaveTable(userId);
|
controller.leaveTable(userId);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.error("TableManager.userQuitTournamentSubTables table == null - userId " + userId);
|
logger.error("TableManagerImpl.userQuitTournamentSubTables table == null - userId " + userId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// removeUserFromAllTablesAndChat user from all sub tables of a tournament
|
// removeUserFromAllTablesAndChat user from all sub tables of a tournament
|
||||||
|
@Override
|
||||||
public void userQuitTournamentSubTables(UUID tournamentId, UUID userId) {
|
public void userQuitTournamentSubTables(UUID tournamentId, UUID userId) {
|
||||||
for (TableController controller : getControllers()) {
|
for (TableController controller : getControllers()) {
|
||||||
if (controller.getTable().isTournamentSubTable() && controller.getTable().getTournament().getId().equals(tournamentId)) {
|
if (controller.getTable().isTournamentSubTable() && controller.getTable().getTournament().getId().equals(tournamentId)) {
|
||||||
|
@ -206,6 +223,7 @@ public enum TableManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isTableOwner(UUID tableId, UUID userId) {
|
public boolean isTableOwner(UUID tableId, UUID userId) {
|
||||||
if (controllers.containsKey(tableId)) {
|
if (controllers.containsKey(tableId)) {
|
||||||
return controllers.get(tableId).isOwner(userId);
|
return controllers.get(tableId).isOwner(userId);
|
||||||
|
@ -213,13 +231,14 @@ public enum TableManager {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean removeTable(UUID userId, UUID tableId) {
|
public boolean removeTable(UUID userId, UUID tableId) {
|
||||||
if (isTableOwner(tableId, userId) || UserManager.instance.isAdmin(userId)) {
|
if (isTableOwner(tableId, userId) || managerFactory.userManager().isAdmin(userId)) {
|
||||||
logger.debug("Table remove request - userId: " + userId + " tableId: " + tableId);
|
logger.debug("Table remove request - userId: " + userId + " tableId: " + tableId);
|
||||||
TableController tableController = controllers.get(tableId);
|
TableController tableController = controllers.get(tableId);
|
||||||
if (tableController != null) {
|
if (tableController != null) {
|
||||||
tableController.leaveTableAll();
|
tableController.leaveTableAll();
|
||||||
ChatManager.instance.destroyChatSession(tableController.getChatId());
|
managerFactory.chatManager().destroyChatSession(tableController.getChatId());
|
||||||
removeTable(tableId);
|
removeTable(tableId);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -227,6 +246,7 @@ public enum TableManager {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void leaveTable(UUID userId, UUID tableId) {
|
public void leaveTable(UUID userId, UUID tableId) {
|
||||||
TableController tableController = controllers.get(tableId);
|
TableController tableController = controllers.get(tableId);
|
||||||
if (tableController != null) {
|
if (tableController != null) {
|
||||||
|
@ -234,6 +254,7 @@ public enum TableManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Optional<UUID> getChatId(UUID tableId) {
|
public Optional<UUID> getChatId(UUID tableId) {
|
||||||
if (controllers.containsKey(tableId)) {
|
if (controllers.containsKey(tableId)) {
|
||||||
return Optional.of(controllers.get(tableId).getChatId());
|
return Optional.of(controllers.get(tableId).getChatId());
|
||||||
|
@ -248,11 +269,12 @@ public enum TableManager {
|
||||||
* @param roomId
|
* @param roomId
|
||||||
* @param tableId
|
* @param tableId
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void startMatch(UUID userId, UUID roomId, UUID tableId) {
|
public void startMatch(UUID userId, UUID roomId, UUID tableId) {
|
||||||
if (controllers.containsKey(tableId)) {
|
if (controllers.containsKey(tableId)) {
|
||||||
controllers.get(tableId).startMatch(userId);
|
controllers.get(tableId).startMatch(userId);
|
||||||
// chat of start dialog can be killed
|
// chat of start dialog can be killed
|
||||||
ChatManager.instance.destroyChatSession(controllers.get(tableId).getChatId());
|
managerFactory.chatManager().destroyChatSession(controllers.get(tableId).getChatId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,25 +284,29 @@ public enum TableManager {
|
||||||
* @param roomId
|
* @param roomId
|
||||||
* @param tableId
|
* @param tableId
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void startTournamentSubMatch(UUID roomId, UUID tableId) {
|
public void startTournamentSubMatch(UUID roomId, UUID tableId) {
|
||||||
if (controllers.containsKey(tableId)) {
|
if (controllers.containsKey(tableId)) {
|
||||||
controllers.get(tableId).startMatch();
|
controllers.get(tableId).startMatch();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void startTournament(UUID userId, UUID roomId, UUID tableId) {
|
public void startTournament(UUID userId, UUID roomId, UUID tableId) {
|
||||||
if (controllers.containsKey(tableId)) {
|
if (controllers.containsKey(tableId)) {
|
||||||
controllers.get(tableId).startTournament(userId);
|
controllers.get(tableId).startTournament(userId);
|
||||||
ChatManager.instance.destroyChatSession(controllers.get(tableId).getChatId());
|
managerFactory.chatManager().destroyChatSession(controllers.get(tableId).getChatId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void startDraft(UUID tableId, Draft draft) {
|
public void startDraft(UUID tableId, Draft draft) {
|
||||||
if (controllers.containsKey(tableId)) {
|
if (controllers.containsKey(tableId)) {
|
||||||
controllers.get(tableId).startDraft(draft);
|
controllers.get(tableId).startDraft(draft);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean watchTable(UUID userId, UUID tableId) {
|
public boolean watchTable(UUID userId, UUID tableId) {
|
||||||
if (controllers.containsKey(tableId)) {
|
if (controllers.containsKey(tableId)) {
|
||||||
return controllers.get(tableId).watchTable(userId);
|
return controllers.get(tableId).watchTable(userId);
|
||||||
|
@ -288,6 +314,7 @@ public enum TableManager {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void endGame(UUID tableId) {
|
public void endGame(UUID tableId) {
|
||||||
if (controllers.containsKey(tableId)) {
|
if (controllers.containsKey(tableId)) {
|
||||||
if (controllers.get(tableId).endGameAndStartNextGame()) {
|
if (controllers.get(tableId).endGameAndStartNextGame()) {
|
||||||
|
@ -296,42 +323,49 @@ public enum TableManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void endDraft(UUID tableId, Draft draft) {
|
public void endDraft(UUID tableId, Draft draft) {
|
||||||
if (controllers.containsKey(tableId)) {
|
if (controllers.containsKey(tableId)) {
|
||||||
controllers.get(tableId).endDraft(draft);
|
controllers.get(tableId).endDraft(draft);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void endTournament(UUID tableId, Tournament tournament) {
|
public void endTournament(UUID tableId, Tournament tournament) {
|
||||||
if (controllers.containsKey(tableId)) {
|
if (controllers.containsKey(tableId)) {
|
||||||
controllers.get(tableId).endTournament(tournament);
|
controllers.get(tableId).endTournament(tournament);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void swapSeats(UUID tableId, UUID userId, int seatNum1, int seatNum2) {
|
public void swapSeats(UUID tableId, UUID userId, int seatNum1, int seatNum2) {
|
||||||
if (controllers.containsKey(tableId) && isTableOwner(tableId, userId)) {
|
if (controllers.containsKey(tableId) && isTableOwner(tableId, userId)) {
|
||||||
controllers.get(tableId).swapSeats(seatNum1, seatNum2);
|
controllers.get(tableId).swapSeats(seatNum1, seatNum2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void construct(UUID tableId) {
|
public void construct(UUID tableId) {
|
||||||
if (controllers.containsKey(tableId)) {
|
if (controllers.containsKey(tableId)) {
|
||||||
controllers.get(tableId).construct();
|
controllers.get(tableId).construct();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void initTournament(UUID tableId) {
|
public void initTournament(UUID tableId) {
|
||||||
if (controllers.containsKey(tableId)) {
|
if (controllers.containsKey(tableId)) {
|
||||||
controllers.get(tableId).initTournament();
|
controllers.get(tableId).initTournament();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void addPlayer(UUID userId, UUID tableId, TournamentPlayer player) throws GameException {
|
public void addPlayer(UUID userId, UUID tableId, TournamentPlayer player) throws GameException {
|
||||||
if (controllers.containsKey(tableId)) {
|
if (controllers.containsKey(tableId)) {
|
||||||
controllers.get(tableId).addPlayer(userId, player.getPlayer(), player.getPlayerType(), player.getDeck());
|
controllers.get(tableId).addPlayer(userId, player.getPlayer(), player.getPlayerType(), player.getDeck());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void removeTable(UUID tableId) {
|
public void removeTable(UUID tableId) {
|
||||||
TableController tableController = controllers.get(tableId);
|
TableController tableController = controllers.get(tableId);
|
||||||
if (tableController != null) {
|
if (tableController != null) {
|
||||||
|
@ -365,21 +399,22 @@ public enum TableManager {
|
||||||
// If table is not finished, the table has to be removed completly because it's not a normal state (if finished it will be removed in GamesRoomImpl.Update())
|
// If table is not finished, the table has to be removed completly because it's not a normal state (if finished it will be removed in GamesRoomImpl.Update())
|
||||||
if (table.getState() != TableState.FINISHED) {
|
if (table.getState() != TableState.FINISHED) {
|
||||||
if (game != null) {
|
if (game != null) {
|
||||||
GameManager.instance.removeGame(game.getId());
|
managerFactory.gameManager().removeGame(game.getId());
|
||||||
// something goes wrong, so don't add it to ended stats
|
// something goes wrong, so don't add it to ended stats
|
||||||
}
|
}
|
||||||
GamesRoomManager.instance.removeTable(tableId);
|
managerFactory.gamesRoomManager().removeTable(tableId);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void debugServerState() {
|
public void debugServerState() {
|
||||||
logger.debug("--- Server state ----------------------------------------------");
|
logger.debug("--- Server state ----------------------------------------------");
|
||||||
Collection<User> users = UserManager.instance.getUsers();
|
Collection<User> users = managerFactory.userManager().getUsers();
|
||||||
logger.debug("--------User: " + users.size() + " [userId | since | lock | name -----------------------");
|
logger.debug("--------User: " + users.size() + " [userId | since | lock | name -----------------------");
|
||||||
for (User user : users) {
|
for (User user : users) {
|
||||||
Optional<Session> session = SessionManager.instance.getSession(user.getSessionId());
|
Optional<Session> session = managerFactory.sessionManager().getSession(user.getSessionId());
|
||||||
String sessionState = "N";
|
String sessionState = "N";
|
||||||
if (session.isPresent()) {
|
if (session.isPresent()) {
|
||||||
if (session.get().isLocked()) {
|
if (session.get().isLocked()) {
|
||||||
|
@ -393,14 +428,14 @@ public enum TableManager {
|
||||||
+ " | " + sessionState
|
+ " | " + sessionState
|
||||||
+ " | " + user.getName() + " (" + user.getUserState().toString() + " - " + user.getPingInfo() + ')');
|
+ " | " + user.getName() + " (" + user.getUserState().toString() + " - " + user.getPingInfo() + ')');
|
||||||
}
|
}
|
||||||
List<ChatSession> chatSessions = ChatManager.instance.getChatSessions();
|
List<ChatSession> chatSessions = managerFactory.chatManager().getChatSessions();
|
||||||
logger.debug("------- ChatSessions: " + chatSessions.size() + " ----------------------------------");
|
logger.debug("------- ChatSessions: " + chatSessions.size() + " ----------------------------------");
|
||||||
for (ChatSession chatSession : chatSessions) {
|
for (ChatSession chatSession : chatSessions) {
|
||||||
logger.debug(chatSession.getChatId() + " " + formatter.format(chatSession.getCreateTime()) + ' ' + chatSession.getInfo() + ' ' + chatSession.getClients().values().toString());
|
logger.debug(chatSession.getChatId() + " " + formatter.format(chatSession.getCreateTime()) + ' ' + chatSession.getInfo() + ' ' + chatSession.getClients().values().toString());
|
||||||
}
|
}
|
||||||
logger.debug("------- Games: " + GameManager.instance.getNumberActiveGames() + " --------------------------------------------");
|
logger.debug("------- Games: " + managerFactory.gameManager().getNumberActiveGames() + " --------------------------------------------");
|
||||||
logger.debug(" Active Game Worker: " + ThreadExecutor.instance.getActiveThreads(ThreadExecutor.instance.getGameExecutor()));
|
logger.debug(" Active Game Worker: " + managerFactory.threadExecutor().getActiveThreads(managerFactory.threadExecutor().getGameExecutor()));
|
||||||
for (Entry<UUID, GameController> entry : GameManager.instance.getGameController().entrySet()) {
|
for (Entry<UUID, GameController> entry : managerFactory.gameManager().getGameController().entrySet()) {
|
||||||
logger.debug(entry.getKey() + entry.getValue().getPlayerNameList());
|
logger.debug(entry.getKey() + entry.getValue().getPlayerNameList());
|
||||||
}
|
}
|
||||||
logger.debug("--- Server state END ------------------------------------------");
|
logger.debug("--- Server state END ------------------------------------------");
|
|
@ -10,14 +10,13 @@ import mage.interfaces.callback.ClientCallback;
|
||||||
import mage.interfaces.callback.ClientCallbackMethod;
|
import mage.interfaces.callback.ClientCallbackMethod;
|
||||||
import mage.players.net.UserData;
|
import mage.players.net.UserData;
|
||||||
import mage.server.draft.DraftSession;
|
import mage.server.draft.DraftSession;
|
||||||
import mage.server.game.GameManager;
|
|
||||||
import mage.server.game.GameSessionPlayer;
|
import mage.server.game.GameSessionPlayer;
|
||||||
|
import mage.server.managers.ManagerFactory;
|
||||||
import mage.server.rating.GlickoRating;
|
import mage.server.rating.GlickoRating;
|
||||||
import mage.server.rating.GlickoRatingSystem;
|
import mage.server.rating.GlickoRatingSystem;
|
||||||
import mage.server.record.UserStats;
|
import mage.server.record.UserStats;
|
||||||
import mage.server.record.UserStatsRepository;
|
import mage.server.record.UserStatsRepository;
|
||||||
import mage.server.tournament.TournamentController;
|
import mage.server.tournament.TournamentController;
|
||||||
import mage.server.tournament.TournamentManager;
|
|
||||||
import mage.server.tournament.TournamentSession;
|
import mage.server.tournament.TournamentSession;
|
||||||
import mage.server.util.ServerMessagesUtil;
|
import mage.server.util.ServerMessagesUtil;
|
||||||
import mage.server.util.SystemUtil;
|
import mage.server.util.SystemUtil;
|
||||||
|
@ -43,6 +42,7 @@ public class User {
|
||||||
Offline // set if the user was disconnected and expired or regularly left XMage. Removed is the user later after some time
|
Offline // set if the user was disconnected and expired or regularly left XMage. Removed is the user later after some time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final ManagerFactory managerFactory;
|
||||||
private final UUID userId;
|
private final UUID userId;
|
||||||
private final String userName;
|
private final String userName;
|
||||||
private final String host;
|
private final String host;
|
||||||
|
@ -68,7 +68,8 @@ public class User {
|
||||||
private String clientVersion;
|
private String clientVersion;
|
||||||
private String userIdStr;
|
private String userIdStr;
|
||||||
|
|
||||||
public User(String userName, String host, AuthorizedUser authorizedUser) {
|
public User(ManagerFactory managerFactory, String userName, String host, AuthorizedUser authorizedUser) {
|
||||||
|
this.managerFactory = managerFactory;
|
||||||
this.userId = UUID.randomUUID();
|
this.userId = UUID.randomUUID();
|
||||||
this.userName = userName;
|
this.userName = userName;
|
||||||
this.host = host;
|
this.host = host;
|
||||||
|
@ -181,7 +182,7 @@ public class User {
|
||||||
// Because watched games don't get restored after reconnection call stop watching
|
// Because watched games don't get restored after reconnection call stop watching
|
||||||
for (Iterator<UUID> iterator = watchedGames.iterator(); iterator.hasNext(); ) {
|
for (Iterator<UUID> iterator = watchedGames.iterator(); iterator.hasNext(); ) {
|
||||||
UUID gameId = iterator.next();
|
UUID gameId = iterator.next();
|
||||||
GameManager.instance.stopWatching(gameId, userId);
|
managerFactory.gameManager().stopWatching(gameId, userId);
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
}
|
}
|
||||||
ServerMessagesUtil.instance.incLostConnection();
|
ServerMessagesUtil.instance.incLostConnection();
|
||||||
|
@ -227,7 +228,7 @@ public class User {
|
||||||
|
|
||||||
public void fireCallback(final ClientCallback call) {
|
public void fireCallback(final ClientCallback call) {
|
||||||
if (isConnected()) {
|
if (isConnected()) {
|
||||||
SessionManager.instance.getSession(sessionId).ifPresent(session
|
managerFactory.sessionManager().getSession(sessionId).ifPresent(session
|
||||||
-> session.fireCallback(call)
|
-> session.fireCallback(call)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -288,27 +289,27 @@ public class User {
|
||||||
|
|
||||||
public void sendPlayerUUID(final UUID gameId, final UUID data) {
|
public void sendPlayerUUID(final UUID gameId, final UUID data) {
|
||||||
lastActivity = new Date();
|
lastActivity = new Date();
|
||||||
GameManager.instance.sendPlayerUUID(gameId, userId, data);
|
managerFactory.gameManager().sendPlayerUUID(gameId, userId, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendPlayerString(final UUID gameId, final String data) {
|
public void sendPlayerString(final UUID gameId, final String data) {
|
||||||
lastActivity = new Date();
|
lastActivity = new Date();
|
||||||
GameManager.instance.sendPlayerString(gameId, userId, data);
|
managerFactory.gameManager().sendPlayerString(gameId, userId, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendPlayerManaType(final UUID gameId, final UUID playerId, final ManaType data) {
|
public void sendPlayerManaType(final UUID gameId, final UUID playerId, final ManaType data) {
|
||||||
lastActivity = new Date();
|
lastActivity = new Date();
|
||||||
GameManager.instance.sendPlayerManaType(gameId, playerId, userId, data);
|
managerFactory.gameManager().sendPlayerManaType(gameId, playerId, userId, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendPlayerBoolean(final UUID gameId, final Boolean data) {
|
public void sendPlayerBoolean(final UUID gameId, final Boolean data) {
|
||||||
lastActivity = new Date();
|
lastActivity = new Date();
|
||||||
GameManager.instance.sendPlayerBoolean(gameId, userId, data);
|
managerFactory.gameManager().sendPlayerBoolean(gameId, userId, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendPlayerInteger(final UUID gameId, final Integer data) {
|
public void sendPlayerInteger(final UUID gameId, final Integer data) {
|
||||||
lastActivity = new Date();
|
lastActivity = new Date();
|
||||||
GameManager.instance.sendPlayerInteger(gameId, userId, data);
|
managerFactory.gameManager().sendPlayerInteger(gameId, userId, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateLastActivity(String pingInfo) {
|
public void updateLastActivity(String pingInfo) {
|
||||||
|
@ -338,7 +339,7 @@ public class User {
|
||||||
}
|
}
|
||||||
for (Iterator<Entry<UUID, UUID>> iterator = userTournaments.entrySet().iterator(); iterator.hasNext(); ) {
|
for (Iterator<Entry<UUID, UUID>> iterator = userTournaments.entrySet().iterator(); iterator.hasNext(); ) {
|
||||||
Entry<UUID, UUID> next = iterator.next();
|
Entry<UUID, UUID> next = iterator.next();
|
||||||
Optional<TournamentController> tournamentController = TournamentManager.instance.getTournamentController(next.getValue());
|
Optional<TournamentController> tournamentController = managerFactory.tournamentManager().getTournamentController(next.getValue());
|
||||||
if (tournamentController.isPresent()) {
|
if (tournamentController.isPresent()) {
|
||||||
ccTournamentStarted(next.getValue(), next.getKey());
|
ccTournamentStarted(next.getValue(), next.getKey());
|
||||||
tournamentController.get().rejoin(next.getKey());
|
tournamentController.get().rejoin(next.getKey());
|
||||||
|
@ -349,7 +350,7 @@ public class User {
|
||||||
for (Entry<UUID, GameSessionPlayer> entry : gameSessions.entrySet()) {
|
for (Entry<UUID, GameSessionPlayer> entry : gameSessions.entrySet()) {
|
||||||
ccGameStarted(entry.getValue().getGameId(), entry.getKey());
|
ccGameStarted(entry.getValue().getGameId(), entry.getKey());
|
||||||
entry.getValue().init();
|
entry.getValue().init();
|
||||||
GameManager.instance.sendPlayerString(entry.getValue().getGameId(), userId, "");
|
managerFactory.gameManager().sendPlayerString(entry.getValue().getGameId(), userId, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Entry<UUID, DraftSession> entry : draftSessions.entrySet()) {
|
for (Entry<UUID, DraftSession> entry : draftSessions.entrySet()) {
|
||||||
|
@ -362,7 +363,7 @@ public class User {
|
||||||
entry.getValue().construct(0); // TODO: Check if this is correct
|
entry.getValue().construct(0); // TODO: Check if this is correct
|
||||||
}
|
}
|
||||||
for (Entry<UUID, Deck> entry : sideboarding.entrySet()) {
|
for (Entry<UUID, Deck> entry : sideboarding.entrySet()) {
|
||||||
Optional<TableController> controller = TableManager.instance.getController(entry.getKey());
|
Optional<TableController> controller = managerFactory.tableManager().getController(entry.getKey());
|
||||||
if (controller.isPresent()) {
|
if (controller.isPresent()) {
|
||||||
ccSideboard(entry.getValue(), entry.getKey(), controller.get().getRemainingTime(), controller.get().getOptions().isLimited());
|
ccSideboard(entry.getValue(), entry.getKey(), controller.get().getRemainingTime(), controller.get().getOptions().isLimited());
|
||||||
} else {
|
} else {
|
||||||
|
@ -427,32 +428,32 @@ public class User {
|
||||||
draftSessions.clear();
|
draftSessions.clear();
|
||||||
logger.trace("REMOVE " + userName + " Tournament sessions " + userTournaments.size());
|
logger.trace("REMOVE " + userName + " Tournament sessions " + userTournaments.size());
|
||||||
for (UUID tournamentId : userTournaments.values()) {
|
for (UUID tournamentId : userTournaments.values()) {
|
||||||
TournamentManager.instance.quit(tournamentId, userId);
|
managerFactory.tournamentManager().quit(tournamentId, userId);
|
||||||
}
|
}
|
||||||
userTournaments.clear();
|
userTournaments.clear();
|
||||||
constructing.clear();
|
constructing.clear();
|
||||||
logger.trace("REMOVE " + userName + " Tables " + tables.size());
|
logger.trace("REMOVE " + userName + " Tables " + tables.size());
|
||||||
for (Entry<UUID, Table> entry : tables.entrySet()) {
|
for (Entry<UUID, Table> entry : tables.entrySet()) {
|
||||||
logger.debug("-- leave tableId: " + entry.getValue().getId());
|
logger.debug("-- leave tableId: " + entry.getValue().getId());
|
||||||
TableManager.instance.leaveTable(userId, entry.getValue().getId());
|
managerFactory.tableManager().leaveTable(userId, entry.getValue().getId());
|
||||||
}
|
}
|
||||||
tables.clear();
|
tables.clear();
|
||||||
sideboarding.clear();
|
sideboarding.clear();
|
||||||
logger.trace("REMOVE " + userName + " Game sessions: " + gameSessions.size());
|
logger.trace("REMOVE " + userName + " Game sessions: " + gameSessions.size());
|
||||||
for (GameSessionPlayer gameSessionPlayer : gameSessions.values()) {
|
for (GameSessionPlayer gameSessionPlayer : gameSessions.values()) {
|
||||||
logger.debug("-- kill game session of gameId: " + gameSessionPlayer.getGameId());
|
logger.debug("-- kill game session of gameId: " + gameSessionPlayer.getGameId());
|
||||||
GameManager.instance.quitMatch(gameSessionPlayer.getGameId(), userId);
|
managerFactory.gameManager().quitMatch(gameSessionPlayer.getGameId(), userId);
|
||||||
gameSessionPlayer.quitGame();
|
gameSessionPlayer.quitGame();
|
||||||
}
|
}
|
||||||
gameSessions.clear();
|
gameSessions.clear();
|
||||||
logger.trace("REMOVE " + userName + " watched Games " + watchedGames.size());
|
logger.trace("REMOVE " + userName + " watched Games " + watchedGames.size());
|
||||||
for (Iterator<UUID> it = watchedGames.iterator(); it.hasNext(); ) { // Iterator to prevent ConcurrentModificationException
|
for (Iterator<UUID> it = watchedGames.iterator(); it.hasNext(); ) { // Iterator to prevent ConcurrentModificationException
|
||||||
UUID gameId = it.next();
|
UUID gameId = it.next();
|
||||||
GameManager.instance.stopWatching(gameId, userId);
|
managerFactory.gameManager().stopWatching(gameId, userId);
|
||||||
}
|
}
|
||||||
watchedGames.clear();
|
watchedGames.clear();
|
||||||
logger.trace("REMOVE " + userName + " Chats ");
|
logger.trace("REMOVE " + userName + " Chats ");
|
||||||
ChatManager.instance.removeUser(userId, reason);
|
managerFactory.chatManager().removeUser(userId, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUserData(UserData userData) {
|
public void setUserData(UserData userData) {
|
||||||
|
@ -788,7 +789,7 @@ public class User {
|
||||||
if (table.getState() == TableState.FINISHED) {
|
if (table.getState() == TableState.FINISHED) {
|
||||||
number++;
|
number++;
|
||||||
} else {
|
} else {
|
||||||
Optional<TableController> tableController = TableManager.instance.getController(table.getId());
|
Optional<TableController> tableController = managerFactory.tableManager().getController(table.getId());
|
||||||
if (!tableController.isPresent()) {
|
if (!tableController.isPresent()) {
|
||||||
logger.error("table not found : " + table.getId());
|
logger.error("table not found : " + table.getId());
|
||||||
} else if (tableController.get().isUserStillActive(userId)) {
|
} else if (tableController.get().isUserStillActive(userId)) {
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
package mage.server;
|
package mage.server;
|
||||||
|
|
||||||
import mage.server.User.UserState;
|
import mage.server.User.UserState;
|
||||||
|
import mage.server.managers.UserManager;
|
||||||
|
import mage.server.managers.ManagerFactory;
|
||||||
import mage.server.record.UserStats;
|
import mage.server.record.UserStats;
|
||||||
import mage.server.record.UserStatsRepository;
|
import mage.server.record.UserStatsRepository;
|
||||||
import mage.server.util.ThreadExecutor;
|
|
||||||
import mage.view.UserView;
|
import mage.view.UserView;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
@ -19,37 +20,43 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
*
|
*
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
*/
|
*/
|
||||||
public enum UserManager {
|
public class UserManagerImpl implements UserManager {
|
||||||
instance;
|
|
||||||
|
|
||||||
private static final int SERVER_TIMEOUTS_USER_INFORM_OPPONENTS_ABOUT_DISCONNECT_AFTER_SECS = 30; // send to chat info about disconnection troubles, must be more than ping timeout
|
private static final int SERVER_TIMEOUTS_USER_INFORM_OPPONENTS_ABOUT_DISCONNECT_AFTER_SECS = 30; // send to chat info about disconnection troubles, must be more than ping timeout
|
||||||
private static final int SERVER_TIMEOUTS_USER_DISCONNECT_FROM_SERVER_AFTER_SECS = 3 * 60; // removes from all games and chats too (can be seen in users list with disconnected status)
|
private static final int SERVER_TIMEOUTS_USER_DISCONNECT_FROM_SERVER_AFTER_SECS = 3 * 60; // removes from all games and chats too (can be seen in users list with disconnected status)
|
||||||
private static final int SERVER_TIMEOUTS_USER_REMOVE_FROM_SERVER_AFTER_SECS = 8 * 60; // removes from users list
|
private static final int SERVER_TIMEOUTS_USER_REMOVE_FROM_SERVER_AFTER_SECS = 8 * 60; // removes from users list
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(UserManager.class);
|
private static final Logger logger = Logger.getLogger(UserManagerImpl.class);
|
||||||
|
|
||||||
protected final ScheduledExecutorService expireExecutor = Executors.newSingleThreadScheduledExecutor();
|
protected final ScheduledExecutorService expireExecutor = Executors.newSingleThreadScheduledExecutor();
|
||||||
protected final ScheduledExecutorService userListExecutor = Executors.newSingleThreadScheduledExecutor();
|
protected final ScheduledExecutorService userListExecutor = Executors.newSingleThreadScheduledExecutor();
|
||||||
|
|
||||||
private List<UserView> userInfoList = new ArrayList<>();
|
private List<UserView> userInfoList = new ArrayList<>();
|
||||||
|
private final ManagerFactory managerFactory;
|
||||||
|
|
||||||
|
|
||||||
private final ReadWriteLock lock = new ReentrantReadWriteLock();
|
private final ReadWriteLock lock = new ReentrantReadWriteLock();
|
||||||
private final ConcurrentHashMap<UUID, User> users = new ConcurrentHashMap<>();
|
private final ConcurrentHashMap<UUID, User> users = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private static final ExecutorService USER_EXECUTOR = ThreadExecutor.instance.getCallExecutor();
|
private ExecutorService USER_EXECUTOR;
|
||||||
|
|
||||||
UserManager() {
|
public UserManagerImpl(ManagerFactory managerFactory) {
|
||||||
|
this.managerFactory = managerFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init() {
|
||||||
|
USER_EXECUTOR = managerFactory.threadExecutor().getCallExecutor();
|
||||||
expireExecutor.scheduleAtFixedRate(this::checkExpired, 60, 60, TimeUnit.SECONDS);
|
expireExecutor.scheduleAtFixedRate(this::checkExpired, 60, 60, TimeUnit.SECONDS);
|
||||||
|
|
||||||
userListExecutor.scheduleAtFixedRate(this::updateUserInfoList, 4, 4, TimeUnit.SECONDS);
|
userListExecutor.scheduleAtFixedRate(this::updateUserInfoList, 4, 4, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Optional<User> createUser(String userName, String host, AuthorizedUser authorizedUser) {
|
public Optional<User> createUser(String userName, String host, AuthorizedUser authorizedUser) {
|
||||||
if (getUserByName(userName).isPresent()) {
|
if (getUserByName(userName).isPresent()) {
|
||||||
return Optional.empty(); //user already exists
|
return Optional.empty(); //user already exists
|
||||||
}
|
}
|
||||||
User user = new User(userName, host, authorizedUser);
|
User user = new User(managerFactory, userName, host, authorizedUser);
|
||||||
final Lock w = lock.writeLock();
|
final Lock w = lock.writeLock();
|
||||||
w.lock();
|
w.lock();
|
||||||
try {
|
try {
|
||||||
|
@ -60,6 +67,7 @@ public enum UserManager {
|
||||||
return Optional.of(user);
|
return Optional.of(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Optional<User> getUser(UUID userId) {
|
public Optional<User> getUser(UUID userId) {
|
||||||
if (!users.containsKey(userId)) {
|
if (!users.containsKey(userId)) {
|
||||||
//logger.warn(String.format("User with id %s could not be found", userId), new Throwable()); // TODO: remove after session freezes fixed
|
//logger.warn(String.format("User with id %s could not be found", userId), new Throwable()); // TODO: remove after session freezes fixed
|
||||||
|
@ -69,6 +77,7 @@ public enum UserManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Optional<User> getUserByName(String userName) {
|
public Optional<User> getUserByName(String userName) {
|
||||||
final Lock r = lock.readLock();
|
final Lock r = lock.readLock();
|
||||||
r.lock();
|
r.lock();
|
||||||
|
@ -81,6 +90,7 @@ public enum UserManager {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Collection<User> getUsers() {
|
public Collection<User> getUsers() {
|
||||||
List<User> userList = new ArrayList<>();
|
List<User> userList = new ArrayList<>();
|
||||||
final Lock r = lock.readLock();
|
final Lock r = lock.readLock();
|
||||||
|
@ -93,6 +103,7 @@ public enum UserManager {
|
||||||
return userList;
|
return userList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean connectToSession(String sessionId, UUID userId) {
|
public boolean connectToSession(String sessionId, UUID userId) {
|
||||||
if (userId != null) {
|
if (userId != null) {
|
||||||
User user = users.get(userId);
|
User user = users.get(userId);
|
||||||
|
@ -104,19 +115,19 @@ public enum UserManager {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void disconnect(UUID userId, DisconnectReason reason) {
|
public void disconnect(UUID userId, DisconnectReason reason) {
|
||||||
Optional<User> user = UserManager.instance.getUser(userId);
|
Optional<User> user = getUser(userId);
|
||||||
if (user.isPresent()) {
|
if (user.isPresent()) {
|
||||||
user.get().setSessionId("");
|
user.get().setSessionId("");
|
||||||
if (reason == DisconnectReason.Disconnected) {
|
if (reason == DisconnectReason.Disconnected) {
|
||||||
removeUserFromAllTablesAndChat(userId, reason);
|
removeUserFromAllTablesAndChat(userId, reason);
|
||||||
user.get().setUserState(UserState.Offline);
|
user.get().setUserState(UserState.Offline);
|
||||||
} else {
|
|
||||||
// ChatManager.instance.sendLostConnectionMessage(userId, reason);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isAdmin(UUID userId) {
|
public boolean isAdmin(UUID userId) {
|
||||||
if (userId != null) {
|
if (userId != null) {
|
||||||
User user = users.get(userId);
|
User user = users.get(userId);
|
||||||
|
@ -127,6 +138,7 @@ public enum UserManager {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void removeUserFromAllTablesAndChat(final UUID userId, final DisconnectReason reason) {
|
public void removeUserFromAllTablesAndChat(final UUID userId, final DisconnectReason reason) {
|
||||||
if (userId != null) {
|
if (userId != null) {
|
||||||
getUser(userId).ifPresent(user
|
getUser(userId).ifPresent(user
|
||||||
|
@ -135,7 +147,7 @@ public enum UserManager {
|
||||||
try {
|
try {
|
||||||
logger.info("USER REMOVE - " + user.getName() + " (" + reason.toString() + ") userId: " + userId + " [" + user.getGameInfo() + ']');
|
logger.info("USER REMOVE - " + user.getName() + " (" + reason.toString() + ") userId: " + userId + " [" + user.getGameInfo() + ']');
|
||||||
user.removeUserFromAllTables(reason);
|
user.removeUserFromAllTables(reason);
|
||||||
ChatManager.instance.removeUser(user.getId(), reason);
|
managerFactory.chatManager().removeUser(user.getId(), reason);
|
||||||
logger.debug("USER REMOVE END - " + user.getName());
|
logger.debug("USER REMOVE END - " + user.getName());
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
handleException(ex);
|
handleException(ex);
|
||||||
|
@ -146,13 +158,14 @@ public enum UserManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void informUserOpponents(final UUID userId, final String message) {
|
public void informUserOpponents(final UUID userId, final String message) {
|
||||||
if (userId != null) {
|
if (userId != null) {
|
||||||
getUser(userId).ifPresent(user
|
getUser(userId).ifPresent(user
|
||||||
-> USER_EXECUTOR.execute(
|
-> USER_EXECUTOR.execute(
|
||||||
() -> {
|
() -> {
|
||||||
try {
|
try {
|
||||||
ChatManager.instance.sendMessageToUserChats(user.getId(), message);
|
managerFactory.chatManager().sendMessageToUserChats(user.getId(), message);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
handleException(ex);
|
handleException(ex);
|
||||||
}
|
}
|
||||||
|
@ -161,6 +174,7 @@ public enum UserManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean extendUserSession(UUID userId, String pingInfo) {
|
public boolean extendUserSession(UUID userId, String pingInfo) {
|
||||||
if (userId != null) {
|
if (userId != null) {
|
||||||
User user = users.get(userId);
|
User user = users.get(userId);
|
||||||
|
@ -245,7 +259,7 @@ public enum UserManager {
|
||||||
private void updateUserInfoList() {
|
private void updateUserInfoList() {
|
||||||
try {
|
try {
|
||||||
List<UserView> newUserInfoList = new ArrayList<>();
|
List<UserView> newUserInfoList = new ArrayList<>();
|
||||||
for (User user : UserManager.instance.getUsers()) {
|
for (User user : getUsers()) {
|
||||||
newUserInfoList.add(new UserView(
|
newUserInfoList.add(new UserView(
|
||||||
user.getName(),
|
user.getName(),
|
||||||
user.getHost(),
|
user.getHost(),
|
||||||
|
@ -266,10 +280,12 @@ public enum UserManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public List<UserView> getUserInfoList() {
|
public List<UserView> getUserInfoList() {
|
||||||
return userInfoList;
|
return userInfoList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void handleException(Exception ex) {
|
public void handleException(Exception ex) {
|
||||||
if (ex != null) {
|
if (ex != null) {
|
||||||
logger.fatal("User manager exception ", ex);
|
logger.fatal("User manager exception ", ex);
|
||||||
|
@ -281,6 +297,7 @@ public enum UserManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getUserHistory(String userName) {
|
public String getUserHistory(String userName) {
|
||||||
Optional<User> user = getUserByName(userName);
|
Optional<User> user = getUserByName(userName);
|
||||||
if (user.isPresent()) {
|
if (user.isPresent()) {
|
||||||
|
@ -295,6 +312,7 @@ public enum UserManager {
|
||||||
return "User " + userName + " not found";
|
return "User " + userName + " not found";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void updateUserHistory() {
|
public void updateUserHistory() {
|
||||||
USER_EXECUTOR.execute(() -> {
|
USER_EXECUTOR.execute(() -> {
|
||||||
for (String updatedUser : UserStatsRepository.instance.updateUserStats()) {
|
for (String updatedUser : UserStatsRepository.instance.updateUserStats()) {
|
|
@ -1,5 +1,3 @@
|
||||||
|
|
||||||
|
|
||||||
package mage.server.draft;
|
package mage.server.draft;
|
||||||
|
|
||||||
import mage.MageException;
|
import mage.MageException;
|
||||||
|
@ -9,10 +7,8 @@ import mage.game.events.Listener;
|
||||||
import mage.game.events.PlayerQueryEvent;
|
import mage.game.events.PlayerQueryEvent;
|
||||||
import mage.game.events.TableEvent;
|
import mage.game.events.TableEvent;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.server.TableManager;
|
|
||||||
import mage.server.UserManager;
|
|
||||||
import mage.server.game.GameController;
|
import mage.server.game.GameController;
|
||||||
import mage.server.util.ThreadExecutor;
|
import mage.server.managers.ManagerFactory;
|
||||||
import mage.view.DraftPickView;
|
import mage.view.DraftPickView;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
@ -25,7 +21,6 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
*/
|
*/
|
||||||
public class DraftController {
|
public class DraftController {
|
||||||
|
@ -33,6 +28,7 @@ public class DraftController {
|
||||||
private static final Logger logger = Logger.getLogger(GameController.class);
|
private static final Logger logger = Logger.getLogger(GameController.class);
|
||||||
public static final String INIT_FILE_PATH = "config" + File.separator + "init.txt";
|
public static final String INIT_FILE_PATH = "config" + File.separator + "init.txt";
|
||||||
|
|
||||||
|
private final ManagerFactory managerFactory;
|
||||||
private final ConcurrentMap<UUID, DraftSession> draftSessions = new ConcurrentHashMap<>();
|
private final ConcurrentMap<UUID, DraftSession> draftSessions = new ConcurrentHashMap<>();
|
||||||
private final ConcurrentMap<UUID, UUID> userPlayerMap;
|
private final ConcurrentMap<UUID, UUID> userPlayerMap;
|
||||||
private final UUID draftSessionId;
|
private final UUID draftSessionId;
|
||||||
|
@ -40,7 +36,8 @@ public class DraftController {
|
||||||
private final UUID tableId;
|
private final UUID tableId;
|
||||||
private final UUID markedCard;
|
private final UUID markedCard;
|
||||||
|
|
||||||
public DraftController(Draft draft, ConcurrentHashMap<UUID, UUID> userPlayerMap, UUID tableId) {
|
public DraftController(ManagerFactory managerFactory, Draft draft, ConcurrentHashMap<UUID, UUID> userPlayerMap, UUID tableId) {
|
||||||
|
this.managerFactory = managerFactory;
|
||||||
draftSessionId = UUID.randomUUID();
|
draftSessionId = UUID.randomUUID();
|
||||||
this.userPlayerMap = userPlayerMap;
|
this.userPlayerMap = userPlayerMap;
|
||||||
this.draft = draft;
|
this.draft = draft;
|
||||||
|
@ -61,8 +58,7 @@ public class DraftController {
|
||||||
endDraft();
|
endDraft();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
} catch (MageException ex) {
|
||||||
catch (MageException ex) {
|
|
||||||
logger.fatal("Table event listener error", ex);
|
logger.fatal("Table event listener error", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,13 +71,12 @@ public class DraftController {
|
||||||
pickCard(event.getPlayerId(), event.getMax());
|
pickCard(event.getPlayerId(), event.getMax());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
} catch (MageException ex) {
|
||||||
catch (MageException ex) {
|
|
||||||
logger.fatal("Table event listener error", ex);
|
logger.fatal("Table event listener error", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
for (DraftPlayer player: draft.getPlayers()) {
|
for (DraftPlayer player : draft.getPlayers()) {
|
||||||
if (!player.getPlayer().isHuman()) {
|
if (!player.getPlayer().isHuman()) {
|
||||||
player.setJoined();
|
player.setJoined();
|
||||||
logger.debug("player " + player.getPlayer().getId() + " has joined draft " + draft.getId());
|
logger.debug("player " + player.getPlayer().getId() + " has joined draft " + draft.getId());
|
||||||
|
@ -96,13 +91,13 @@ public class DraftController {
|
||||||
|
|
||||||
public void join(UUID userId) {
|
public void join(UUID userId) {
|
||||||
UUID playerId = userPlayerMap.get(userId);
|
UUID playerId = userPlayerMap.get(userId);
|
||||||
DraftSession draftSession = new DraftSession(draft, userId, playerId);
|
DraftSession draftSession = new DraftSession(managerFactory, draft, userId, playerId);
|
||||||
draftSessions.put(playerId, draftSession);
|
draftSessions.put(playerId, draftSession);
|
||||||
UserManager.instance.getUser(userId).ifPresent(user-> {
|
managerFactory.userManager().getUser(userId).ifPresent(user -> {
|
||||||
user.addDraft(playerId, draftSession);
|
user.addDraft(playerId, draftSession);
|
||||||
logger.debug("User " + user.getName() + " has joined draft " + draft.getId());
|
logger.debug("User " + user.getName() + " has joined draft " + draft.getId());
|
||||||
draft.getPlayer(playerId).setJoined();
|
draft.getPlayer(playerId).setJoined();
|
||||||
});
|
});
|
||||||
checkStart();
|
checkStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +109,7 @@ public class DraftController {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean replacePlayer(Player oldPlayer, Player newPlayer) {
|
public boolean replacePlayer(Player oldPlayer, Player newPlayer) {
|
||||||
if (draft.replacePlayer(oldPlayer, newPlayer)) {
|
if (draft.replacePlayer(oldPlayer, newPlayer)) {
|
||||||
DraftSession draftSession = draftSessions.get(oldPlayer.getId());
|
DraftSession draftSession = draftSessions.get(oldPlayer.getId());
|
||||||
if (draftSession != null) {
|
if (draftSession != null) {
|
||||||
draftSession.draftOver(); // closes the draft panel of the replaced player
|
draftSession.draftOver(); // closes the draft panel of the replaced player
|
||||||
|
@ -128,12 +123,12 @@ public class DraftController {
|
||||||
private synchronized void checkStart() {
|
private synchronized void checkStart() {
|
||||||
if (!draft.isStarted() && allJoined()) {
|
if (!draft.isStarted() && allJoined()) {
|
||||||
draft.setStarted();
|
draft.setStarted();
|
||||||
ThreadExecutor.instance.getCallExecutor().execute(this::startDraft);
|
managerFactory.threadExecutor().getCallExecutor().execute(this::startDraft);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startDraft() {
|
private void startDraft() {
|
||||||
for (final Entry<UUID, DraftSession> entry: draftSessions.entrySet()) {
|
for (final Entry<UUID, DraftSession> entry : draftSessions.entrySet()) {
|
||||||
if (!entry.getValue().init()) {
|
if (!entry.getValue().init()) {
|
||||||
logger.fatal("Unable to initialize client for playerId " + entry.getKey());
|
logger.fatal("Unable to initialize client for playerId " + entry.getKey());
|
||||||
//TODO: generate client error message
|
//TODO: generate client error message
|
||||||
|
@ -147,7 +142,7 @@ public class DraftController {
|
||||||
if (!draft.allJoined()) {
|
if (!draft.allJoined()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (DraftPlayer player: draft.getPlayers()) {
|
for (DraftPlayer player : draft.getPlayers()) {
|
||||||
if (player.getPlayer().isHuman() && !draftSessions.containsKey(player.getPlayer().getId())) {
|
if (player.getPlayer().isHuman() && !draftSessions.containsKey(player.getPlayer().getId())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -160,12 +155,12 @@ public class DraftController {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void endDraft() throws MageException {
|
private void endDraft() throws MageException {
|
||||||
for (final DraftSession draftSession: draftSessions.values()) {
|
for (final DraftSession draftSession : draftSessions.values()) {
|
||||||
draftSession.draftOver();
|
draftSession.draftOver();
|
||||||
draftSession.removeDraft();
|
draftSession.removeDraft();
|
||||||
}
|
}
|
||||||
TableManager.instance.endDraft(tableId, draft);
|
managerFactory.tableManager().endDraft(tableId, draft);
|
||||||
DraftManager.instance.removeDraft(draft.getId());
|
managerFactory.draftManager().removeDraft(draft.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void kill(UUID userId) {
|
public void kill(UUID userId) {
|
||||||
|
@ -210,7 +205,7 @@ public class DraftController {
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void updateDraft() throws MageException {
|
private synchronized void updateDraft() throws MageException {
|
||||||
for (final Entry<UUID, DraftSession> entry: draftSessions.entrySet()) {
|
for (final Entry<UUID, DraftSession> entry : draftSessions.entrySet()) {
|
||||||
entry.getValue().update();
|
entry.getValue().update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -229,7 +224,7 @@ public class DraftController {
|
||||||
draft.setAbort(true);
|
draft.setAbort(true);
|
||||||
try {
|
try {
|
||||||
endDraft();
|
endDraft();
|
||||||
} catch(MageException ex) {
|
} catch (MageException ex) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,69 +1,83 @@
|
||||||
|
|
||||||
|
|
||||||
package mage.server.draft;
|
package mage.server.draft;
|
||||||
|
|
||||||
|
import mage.game.draft.Draft;
|
||||||
|
import mage.server.managers.DraftManager;
|
||||||
|
import mage.server.managers.ManagerFactory;
|
||||||
|
import mage.view.DraftPickView;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
import mage.game.draft.Draft;
|
|
||||||
import mage.view.DraftPickView;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
*/
|
*/
|
||||||
public enum DraftManager {
|
public class DraftManagerImpl implements DraftManager {
|
||||||
instance;
|
|
||||||
|
|
||||||
|
private final ManagerFactory managerFactory;
|
||||||
private final ConcurrentMap<UUID, DraftController> draftControllers = new ConcurrentHashMap<>();
|
private final ConcurrentMap<UUID, DraftController> draftControllers = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
public DraftManagerImpl(ManagerFactory managerFactory) {
|
||||||
|
this.managerFactory = managerFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public UUID createDraftSession(Draft draft, ConcurrentHashMap<UUID, UUID> userPlayerMap, UUID tableId) {
|
public UUID createDraftSession(Draft draft, ConcurrentHashMap<UUID, UUID> userPlayerMap, UUID tableId) {
|
||||||
DraftController draftController = new DraftController(draft, userPlayerMap, tableId);
|
DraftController draftController = new DraftController(managerFactory, draft, userPlayerMap, tableId);
|
||||||
draftControllers.put(draft.getId(), draftController);
|
draftControllers.put(draft.getId(), draftController);
|
||||||
return draftController.getSessionId();
|
return draftController.getSessionId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void joinDraft(UUID draftId, UUID userId) {
|
public void joinDraft(UUID draftId, UUID userId) {
|
||||||
draftControllers.get(draftId).join(userId);
|
draftControllers.get(draftId).join(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void destroyChatSession(UUID gameId) {
|
public void destroyChatSession(UUID gameId) {
|
||||||
draftControllers.remove(gameId);
|
draftControllers.remove(gameId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public DraftPickView sendCardPick(UUID draftId, UUID userId, UUID cardId, Set<UUID> hiddenCards) {
|
public DraftPickView sendCardPick(UUID draftId, UUID userId, UUID cardId, Set<UUID> hiddenCards) {
|
||||||
return draftControllers.get(draftId).sendCardPick(userId, cardId, hiddenCards);
|
return draftControllers.get(draftId).sendCardPick(userId, cardId, hiddenCards);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void sendCardMark(UUID draftId, UUID userId, UUID cardId) {
|
public void sendCardMark(UUID draftId, UUID userId, UUID cardId) {
|
||||||
draftControllers.get(draftId).sendCardMark(userId, cardId);
|
draftControllers.get(draftId).sendCardMark(userId, cardId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void removeSession(UUID userId) {
|
public void removeSession(UUID userId) {
|
||||||
for (DraftController controller: draftControllers.values()) {
|
for (DraftController controller : draftControllers.values()) {
|
||||||
controller.kill(userId);
|
controller.kill(userId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void kill(UUID draftId, UUID userId) {
|
public void kill(UUID draftId, UUID userId) {
|
||||||
draftControllers.get(draftId).kill(userId);
|
draftControllers.get(draftId).kill(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void timeout(UUID gameId, UUID userId) {
|
public void timeout(UUID gameId, UUID userId) {
|
||||||
draftControllers.get(gameId).timeout(userId);
|
draftControllers.get(gameId).timeout(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void removeDraft(UUID draftId) {
|
public void removeDraft(UUID draftId) {
|
||||||
draftControllers.remove(draftId);
|
draftControllers.remove(draftId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public DraftController getControllerByDraftId(UUID draftId) {
|
public DraftController getControllerByDraftId(UUID draftId) {
|
||||||
return draftControllers.get(draftId);
|
return draftControllers.get(draftId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Optional<DraftController> getController(UUID tableId) {
|
public Optional<DraftController> getController(UUID tableId) {
|
||||||
return draftControllers.values().stream().filter(controller -> controller.getTableId().equals(tableId)).findFirst();
|
return draftControllers.values().stream().filter(controller -> controller.getTableId().equals(tableId)).findFirst();
|
||||||
}
|
}
|
|
@ -1,6 +1,15 @@
|
||||||
|
|
||||||
package mage.server.draft;
|
package mage.server.draft;
|
||||||
|
|
||||||
|
import mage.game.draft.Draft;
|
||||||
|
import mage.interfaces.callback.ClientCallback;
|
||||||
|
import mage.interfaces.callback.ClientCallbackMethod;
|
||||||
|
import mage.server.User;
|
||||||
|
import mage.server.managers.ManagerFactory;
|
||||||
|
import mage.view.DraftClientMessage;
|
||||||
|
import mage.view.DraftPickView;
|
||||||
|
import mage.view.DraftView;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import java.rmi.RemoteException;
|
import java.rmi.RemoteException;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -8,16 +17,6 @@ import java.util.UUID;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.ScheduledFuture;
|
import java.util.concurrent.ScheduledFuture;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import mage.game.draft.Draft;
|
|
||||||
import mage.interfaces.callback.ClientCallback;
|
|
||||||
import mage.interfaces.callback.ClientCallbackMethod;
|
|
||||||
import mage.server.User;
|
|
||||||
import mage.server.UserManager;
|
|
||||||
import mage.server.util.ThreadExecutor;
|
|
||||||
import mage.view.DraftClientMessage;
|
|
||||||
import mage.view.DraftPickView;
|
|
||||||
import mage.view.DraftView;
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
|
@ -26,6 +25,7 @@ public class DraftSession {
|
||||||
|
|
||||||
protected static final Logger logger = Logger.getLogger(DraftSession.class);
|
protected static final Logger logger = Logger.getLogger(DraftSession.class);
|
||||||
|
|
||||||
|
private final ManagerFactory managerFactory;
|
||||||
protected final UUID userId;
|
protected final UUID userId;
|
||||||
protected final UUID playerId;
|
protected final UUID playerId;
|
||||||
protected final Draft draft;
|
protected final Draft draft;
|
||||||
|
@ -33,9 +33,11 @@ public class DraftSession {
|
||||||
protected UUID markedCard;
|
protected UUID markedCard;
|
||||||
|
|
||||||
private ScheduledFuture<?> futureTimeout;
|
private ScheduledFuture<?> futureTimeout;
|
||||||
protected static final ScheduledExecutorService timeoutExecutor = ThreadExecutor.instance.getTimeoutExecutor();
|
protected final ScheduledExecutorService timeoutExecutor;
|
||||||
|
|
||||||
public DraftSession(Draft draft, UUID userId, UUID playerId) {
|
public DraftSession(ManagerFactory managerFactory, Draft draft, UUID userId, UUID playerId) {
|
||||||
|
this.managerFactory = managerFactory;
|
||||||
|
this.timeoutExecutor = managerFactory.threadExecutor().getTimeoutExecutor();
|
||||||
this.userId = userId;
|
this.userId = userId;
|
||||||
this.draft = draft;
|
this.draft = draft;
|
||||||
this.playerId = playerId;
|
this.playerId = playerId;
|
||||||
|
@ -44,12 +46,12 @@ public class DraftSession {
|
||||||
|
|
||||||
public boolean init() {
|
public boolean init() {
|
||||||
if (!killed) {
|
if (!killed) {
|
||||||
Optional<User> user = UserManager.instance.getUser(userId);
|
Optional<User> user = managerFactory.userManager().getUser(userId);
|
||||||
if (user.isPresent()) {
|
if (user.isPresent()) {
|
||||||
if (futureTimeout != null && !futureTimeout.isDone()) {
|
if (futureTimeout != null && !futureTimeout.isDone()) {
|
||||||
int remaining = (int) futureTimeout.getDelay(TimeUnit.SECONDS);
|
int remaining = (int) futureTimeout.getDelay(TimeUnit.SECONDS);
|
||||||
user.get().fireCallback(new ClientCallback(ClientCallbackMethod.DRAFT_INIT, draft.getId(),
|
user.get().fireCallback(new ClientCallback(ClientCallbackMethod.DRAFT_INIT, draft.getId(),
|
||||||
new DraftClientMessage(getDraftView(), getDraftPickView(remaining))));
|
new DraftClientMessage(getDraftView(), getDraftPickView(remaining))));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -59,16 +61,16 @@ public class DraftSession {
|
||||||
|
|
||||||
public void update() {
|
public void update() {
|
||||||
if (!killed) {
|
if (!killed) {
|
||||||
UserManager.instance
|
managerFactory.userManager()
|
||||||
.getUser(userId).
|
.getUser(userId).
|
||||||
ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.DRAFT_UPDATE, draft.getId(),
|
ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.DRAFT_UPDATE, draft.getId(),
|
||||||
new DraftClientMessage(getDraftView(), null))));
|
new DraftClientMessage(getDraftView(), null))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void draftOver() {
|
public void draftOver() {
|
||||||
if (!killed) {
|
if (!killed) {
|
||||||
UserManager.instance
|
managerFactory.userManager()
|
||||||
.getUser(userId)
|
.getUser(userId)
|
||||||
.ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.DRAFT_OVER, draft.getId())));
|
.ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.DRAFT_OVER, draft.getId())));
|
||||||
}
|
}
|
||||||
|
@ -77,10 +79,10 @@ public class DraftSession {
|
||||||
public void pickCard(int timeout) {
|
public void pickCard(int timeout) {
|
||||||
if (!killed) {
|
if (!killed) {
|
||||||
setupTimeout(timeout);
|
setupTimeout(timeout);
|
||||||
UserManager.instance
|
managerFactory.userManager()
|
||||||
.getUser(userId)
|
.getUser(userId)
|
||||||
.ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.DRAFT_PICK, draft.getId(),
|
.ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.DRAFT_PICK, draft.getId(),
|
||||||
new DraftClientMessage(getDraftView(), getDraftPickView(timeout)))));
|
new DraftClientMessage(getDraftView(), getDraftPickView(timeout)))));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,7 +91,7 @@ public class DraftSession {
|
||||||
cancelTimeout();
|
cancelTimeout();
|
||||||
if (seconds > 0) {
|
if (seconds > 0) {
|
||||||
futureTimeout = timeoutExecutor.schedule(
|
futureTimeout = timeoutExecutor.schedule(
|
||||||
() -> DraftManager.instance.timeout(draft.getId(), userId),
|
() -> managerFactory.draftManager().timeout(draft.getId(), userId),
|
||||||
seconds, TimeUnit.SECONDS
|
seconds, TimeUnit.SECONDS
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -103,7 +105,7 @@ public class DraftSession {
|
||||||
|
|
||||||
protected void handleRemoteException(RemoteException ex) {
|
protected void handleRemoteException(RemoteException ex) {
|
||||||
logger.fatal("DraftSession error ", ex);
|
logger.fatal("DraftSession error ", ex);
|
||||||
DraftManager.instance.kill(draft.getId(), userId);
|
managerFactory.draftManager().kill(draft.getId(), userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setKilled() {
|
public void setKilled() {
|
||||||
|
@ -119,7 +121,7 @@ public class DraftSession {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeDraft() {
|
public void removeDraft() {
|
||||||
UserManager.instance.getUser(userId).ifPresent(user -> user.removeDraft(playerId));
|
managerFactory.userManager().getUser(userId).ifPresent(user -> user.removeDraft(playerId));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,11 +23,11 @@ import mage.game.permanent.Permanent;
|
||||||
import mage.game.turn.Phase;
|
import mage.game.turn.Phase;
|
||||||
import mage.interfaces.Action;
|
import mage.interfaces.Action;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.server.*;
|
import mage.server.Main;
|
||||||
import mage.server.util.ConfigSettings;
|
import mage.server.User;
|
||||||
|
import mage.server.managers.ManagerFactory;
|
||||||
import mage.server.util.Splitter;
|
import mage.server.util.Splitter;
|
||||||
import mage.server.util.SystemUtil;
|
import mage.server.util.SystemUtil;
|
||||||
import mage.server.util.ThreadExecutor;
|
|
||||||
import mage.utils.StreamUtils;
|
import mage.utils.StreamUtils;
|
||||||
import mage.utils.timer.PriorityTimer;
|
import mage.utils.timer.PriorityTimer;
|
||||||
import mage.view.*;
|
import mage.view.*;
|
||||||
|
@ -53,13 +53,14 @@ public class GameController implements GameCallback {
|
||||||
private static final int GAME_TIMEOUTS_CHECK_JOINING_STATUS_EVERY_SECS = 10; // checks and inform players about joining status
|
private static final int GAME_TIMEOUTS_CHECK_JOINING_STATUS_EVERY_SECS = 10; // checks and inform players about joining status
|
||||||
private static final int GAME_TIMEOUTS_CANCEL_PLAYER_GAME_JOINING_AFTER_INACTIVE_SECS = 2 * 60; // leave player from game if it don't join and inactive on server
|
private static final int GAME_TIMEOUTS_CANCEL_PLAYER_GAME_JOINING_AFTER_INACTIVE_SECS = 2 * 60; // leave player from game if it don't join and inactive on server
|
||||||
|
|
||||||
private static final ExecutorService gameExecutor = ThreadExecutor.instance.getGameExecutor();
|
private final ExecutorService gameExecutor;
|
||||||
private static final Logger logger = Logger.getLogger(GameController.class);
|
private static final Logger logger = Logger.getLogger(GameController.class);
|
||||||
|
|
||||||
protected final ScheduledExecutorService joinWaitingExecutor = Executors.newSingleThreadScheduledExecutor();
|
protected final ScheduledExecutorService joinWaitingExecutor = Executors.newSingleThreadScheduledExecutor();
|
||||||
|
|
||||||
private ScheduledFuture<?> futureTimeout;
|
private ScheduledFuture<?> futureTimeout;
|
||||||
protected static final ScheduledExecutorService timeoutIdleExecutor = ThreadExecutor.instance.getTimeoutIdleExecutor();
|
private final ManagerFactory managerFactory;
|
||||||
|
protected final ScheduledExecutorService timeoutIdleExecutor;
|
||||||
|
|
||||||
private final ConcurrentMap<UUID, GameSessionPlayer> gameSessions = new ConcurrentHashMap<>();
|
private final ConcurrentMap<UUID, GameSessionPlayer> gameSessions = new ConcurrentHashMap<>();
|
||||||
private final ReadWriteLock gameSessionsLock = new ReentrantReadWriteLock();
|
private final ReadWriteLock gameSessionsLock = new ReentrantReadWriteLock();
|
||||||
|
@ -83,13 +84,16 @@ public class GameController implements GameCallback {
|
||||||
private int turnsToRollback;
|
private int turnsToRollback;
|
||||||
private int requestsOpen;
|
private int requestsOpen;
|
||||||
|
|
||||||
public GameController(Game game, ConcurrentMap<UUID, UUID> userPlayerMap, UUID tableId, UUID choosingPlayerId, GameOptions gameOptions) {
|
public GameController(ManagerFactory managerFactory, Game game, ConcurrentMap<UUID, UUID> userPlayerMap, UUID tableId, UUID choosingPlayerId, GameOptions gameOptions) {
|
||||||
|
this.managerFactory = managerFactory;
|
||||||
|
gameExecutor = managerFactory.threadExecutor().getGameExecutor();
|
||||||
|
timeoutIdleExecutor = managerFactory.threadExecutor().getTimeoutIdleExecutor();
|
||||||
gameSessionId = UUID.randomUUID();
|
gameSessionId = UUID.randomUUID();
|
||||||
this.userPlayerMap = userPlayerMap;
|
this.userPlayerMap = userPlayerMap;
|
||||||
chatId = ChatManager.instance.createChatSession("Game " + game.getId());
|
chatId = managerFactory.chatManager().createChatSession("Game " + game.getId());
|
||||||
this.userReqestingRollback = null;
|
this.userReqestingRollback = null;
|
||||||
this.game = game;
|
this.game = game;
|
||||||
this.game.setSaveGame(ConfigSettings.instance.isSaveGameActivated());
|
this.game.setSaveGame(managerFactory.configSettings().isSaveGameActivated());
|
||||||
this.tableId = tableId;
|
this.tableId = tableId;
|
||||||
this.choosingPlayerId = choosingPlayerId;
|
this.choosingPlayerId = choosingPlayerId;
|
||||||
this.gameOptions = gameOptions;
|
this.gameOptions = gameOptions;
|
||||||
|
@ -103,7 +107,7 @@ public class GameController implements GameCallback {
|
||||||
for (GameSessionPlayer gameSessionPlayer : getGameSessions()) {
|
for (GameSessionPlayer gameSessionPlayer : getGameSessions()) {
|
||||||
gameSessionPlayer.cleanUp();
|
gameSessionPlayer.cleanUp();
|
||||||
}
|
}
|
||||||
ChatManager.instance.destroyChatSession(chatId);
|
managerFactory.chatManager().destroyChatSession(chatId);
|
||||||
for (PriorityTimer priorityTimer : timers.values()) {
|
for (PriorityTimer priorityTimer : timers.values()) {
|
||||||
priorityTimer.cancel();
|
priorityTimer.cancel();
|
||||||
}
|
}
|
||||||
|
@ -120,11 +124,11 @@ public class GameController implements GameCallback {
|
||||||
updateGame();
|
updateGame();
|
||||||
break;
|
break;
|
||||||
case INFO:
|
case INFO:
|
||||||
ChatManager.instance.broadcast(chatId, "", event.getMessage(), MessageColor.BLACK, true, event.getGame(), MessageType.GAME, null);
|
managerFactory.chatManager().broadcast(chatId, "", event.getMessage(), MessageColor.BLACK, true, event.getGame(), MessageType.GAME, null);
|
||||||
logger.trace(game.getId() + " " + event.getMessage());
|
logger.trace(game.getId() + " " + event.getMessage());
|
||||||
break;
|
break;
|
||||||
case STATUS:
|
case STATUS:
|
||||||
ChatManager.instance.broadcast(chatId, "", event.getMessage(), MessageColor.ORANGE, event.getWithTime(), event.getWithTurnInfo() ? event.getGame() : null, MessageType.GAME, null);
|
managerFactory.chatManager().broadcast(chatId, "", event.getMessage(), MessageColor.ORANGE, event.getWithTime(), event.getWithTurnInfo() ? event.getGame() : null, MessageType.GAME, null);
|
||||||
logger.trace(game.getId() + " " + event.getMessage());
|
logger.trace(game.getId() + " " + event.getMessage());
|
||||||
break;
|
break;
|
||||||
case ERROR:
|
case ERROR:
|
||||||
|
@ -273,7 +277,7 @@ public class GameController implements GameCallback {
|
||||||
logger.fatal("- userId: " + userId);
|
logger.fatal("- userId: " + userId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Optional<User> user = UserManager.instance.getUser(userId);
|
Optional<User> user = managerFactory.userManager().getUser(userId);
|
||||||
if (!user.isPresent()) {
|
if (!user.isPresent()) {
|
||||||
logger.fatal("User not found : " + userId);
|
logger.fatal("User not found : " + userId);
|
||||||
return;
|
return;
|
||||||
|
@ -286,7 +290,7 @@ public class GameController implements GameCallback {
|
||||||
GameSessionPlayer gameSession = gameSessions.get(playerId);
|
GameSessionPlayer gameSession = gameSessions.get(playerId);
|
||||||
String joinType;
|
String joinType;
|
||||||
if (gameSession == null) {
|
if (gameSession == null) {
|
||||||
gameSession = new GameSessionPlayer(game, userId, playerId);
|
gameSession = new GameSessionPlayer(managerFactory, game, userId, playerId);
|
||||||
final Lock w = gameSessionsLock.writeLock();
|
final Lock w = gameSessionsLock.writeLock();
|
||||||
w.lock();
|
w.lock();
|
||||||
try {
|
try {
|
||||||
|
@ -300,7 +304,7 @@ public class GameController implements GameCallback {
|
||||||
}
|
}
|
||||||
user.get().addGame(playerId, gameSession);
|
user.get().addGame(playerId, gameSession);
|
||||||
logger.debug("Player " + player.getName() + ' ' + playerId + " has " + joinType + " gameId: " + game.getId());
|
logger.debug("Player " + player.getName() + ' ' + playerId + " has " + joinType + " gameId: " + game.getId());
|
||||||
ChatManager.instance.broadcast(chatId, "", game.getPlayer(playerId).getLogName() + " has " + joinType + " the game", MessageColor.ORANGE, true, game, MessageType.GAME, null);
|
managerFactory.chatManager().broadcast(chatId, "", game.getPlayer(playerId).getLogName() + " has " + joinType + " the game", MessageColor.ORANGE, true, game, MessageType.GAME, null);
|
||||||
checkStart();
|
checkStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,7 +339,7 @@ public class GameController implements GameCallback {
|
||||||
// join the game because player has not joined or was removed because of disconnect
|
// join the game because player has not joined or was removed because of disconnect
|
||||||
String problemPlayerFixes;
|
String problemPlayerFixes;
|
||||||
user.removeConstructing(player.getId());
|
user.removeConstructing(player.getId());
|
||||||
GameManager.instance.joinGame(game.getId(), user.getId());
|
managerFactory.gameManager().joinGame(game.getId(), user.getId());
|
||||||
logger.warn("Forced join of player " + player.getName() + " (" + user.getUserState() + ") to gameId: " + game.getId());
|
logger.warn("Forced join of player " + player.getName() + " (" + user.getUserState() + ") to gameId: " + game.getId());
|
||||||
if (user.isConnected()) {
|
if (user.isConnected()) {
|
||||||
// init game session, see reconnect()
|
// init game session, see reconnect()
|
||||||
|
@ -345,7 +349,7 @@ public class GameController implements GameCallback {
|
||||||
logger.warn("Send forced game start event for player " + player.getName() + " in gameId: " + game.getId());
|
logger.warn("Send forced game start event for player " + player.getName() + " in gameId: " + game.getId());
|
||||||
user.ccGameStarted(session.getGameId(), player.getId());
|
user.ccGameStarted(session.getGameId(), player.getId());
|
||||||
session.init();
|
session.init();
|
||||||
GameManager.instance.sendPlayerString(session.getGameId(), user.getId(), "");
|
managerFactory.gameManager().sendPlayerString(session.getGameId(), user.getId(), "");
|
||||||
} else {
|
} else {
|
||||||
problemPlayerFixes = "leave on broken game session";
|
problemPlayerFixes = "leave on broken game session";
|
||||||
logger.error("Can't find game session for forced join, leave it: player " + player.getName() + " in gameId: " + game.getId());
|
logger.error("Can't find game session for forced join, leave it: player " + player.getName() + " in gameId: " + game.getId());
|
||||||
|
@ -357,7 +361,7 @@ public class GameController implements GameCallback {
|
||||||
player.leave();
|
player.leave();
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatManager.instance.broadcast(chatId, player.getName(), user.getPingInfo()
|
managerFactory.chatManager().broadcast(chatId, player.getName(), user.getPingInfo()
|
||||||
+ " is forced to join the game (waiting ends after "
|
+ " is forced to join the game (waiting ends after "
|
||||||
+ GAME_TIMEOUTS_CANCEL_PLAYER_GAME_JOINING_AFTER_INACTIVE_SECS
|
+ GAME_TIMEOUTS_CANCEL_PLAYER_GAME_JOINING_AFTER_INACTIVE_SECS
|
||||||
+ " secs, applied fixes: " + problemPlayerFixes + ")",
|
+ " secs, applied fixes: " + problemPlayerFixes + ")",
|
||||||
|
@ -382,7 +386,7 @@ public class GameController implements GameCallback {
|
||||||
private Optional<User> getUserByPlayerId(UUID playerId) {
|
private Optional<User> getUserByPlayerId(UUID playerId) {
|
||||||
for (Map.Entry<UUID, UUID> entry : userPlayerMap.entrySet()) {
|
for (Map.Entry<UUID, UUID> entry : userPlayerMap.entrySet()) {
|
||||||
if (entry.getValue().equals(playerId)) {
|
if (entry.getValue().equals(playerId)) {
|
||||||
return UserManager.instance.getUser(entry.getKey());
|
return managerFactory.userManager().getUser(entry.getKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
|
@ -391,7 +395,7 @@ public class GameController implements GameCallback {
|
||||||
private void checkStart() {
|
private void checkStart() {
|
||||||
if (allJoined()) {
|
if (allJoined()) {
|
||||||
joinWaitingExecutor.shutdownNow();
|
joinWaitingExecutor.shutdownNow();
|
||||||
ThreadExecutor.instance.getCallExecutor().execute(this::startGame);
|
managerFactory.threadExecutor().getCallExecutor().execute(this::startGame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -423,14 +427,14 @@ public class GameController implements GameCallback {
|
||||||
}
|
}
|
||||||
if (!isAllowedToWatch(userId)) {
|
if (!isAllowedToWatch(userId)) {
|
||||||
// Dont want people on our ignore list to stalk us
|
// Dont want people on our ignore list to stalk us
|
||||||
UserManager.instance.getUser(userId).ifPresent(user -> {
|
managerFactory.userManager().getUser(userId).ifPresent(user -> {
|
||||||
user.showUserMessage("Not allowed", "You are banned from watching this game");
|
user.showUserMessage("Not allowed", "You are banned from watching this game");
|
||||||
ChatManager.instance.broadcast(chatId, user.getName(), " tried to join, but is banned", MessageColor.BLUE, true, game, ChatMessage.MessageType.STATUS, null);
|
managerFactory.chatManager().broadcast(chatId, user.getName(), " tried to join, but is banned", MessageColor.BLUE, true, game, ChatMessage.MessageType.STATUS, null);
|
||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
UserManager.instance.getUser(userId).ifPresent(user -> {
|
managerFactory.userManager().getUser(userId).ifPresent(user -> {
|
||||||
GameSessionWatcher gameWatcher = new GameSessionWatcher(userId, game, false);
|
GameSessionWatcher gameWatcher = new GameSessionWatcher(managerFactory.userManager(), userId, game, false);
|
||||||
final Lock w = gameWatchersLock.writeLock();
|
final Lock w = gameWatchersLock.writeLock();
|
||||||
w.lock();
|
w.lock();
|
||||||
try {
|
try {
|
||||||
|
@ -440,7 +444,7 @@ public class GameController implements GameCallback {
|
||||||
}
|
}
|
||||||
gameWatcher.init();
|
gameWatcher.init();
|
||||||
user.addGameWatchInfo(game.getId());
|
user.addGameWatchInfo(game.getId());
|
||||||
ChatManager.instance.broadcast(chatId, user.getName(), " has started watching", MessageColor.BLUE, true, game, ChatMessage.MessageType.STATUS, null);
|
managerFactory.chatManager().broadcast(chatId, user.getName(), " has started watching", MessageColor.BLUE, true, game, ChatMessage.MessageType.STATUS, null);
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -453,8 +457,8 @@ public class GameController implements GameCallback {
|
||||||
} finally {
|
} finally {
|
||||||
w.unlock();
|
w.unlock();
|
||||||
}
|
}
|
||||||
UserManager.instance.getUser(userId).ifPresent(user -> {
|
managerFactory.userManager().getUser(userId).ifPresent(user -> {
|
||||||
ChatManager.instance.broadcast(chatId, user.getName(), " has stopped watching", MessageColor.BLUE, true, game, ChatMessage.MessageType.STATUS, null);
|
managerFactory.chatManager().broadcast(chatId, user.getName(), " has stopped watching", MessageColor.BLUE, true, game, ChatMessage.MessageType.STATUS, null);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -628,7 +632,7 @@ public class GameController implements GameCallback {
|
||||||
gameSession.requestPermissionToSeeHandCards(userIdRequester);
|
gameSession.requestPermissionToSeeHandCards(userIdRequester);
|
||||||
} else {
|
} else {
|
||||||
// player does not allow the request
|
// player does not allow the request
|
||||||
UserManager.instance.getUser(userIdRequester).ifPresent(requester -> {
|
managerFactory.userManager().getUser(userIdRequester).ifPresent(requester -> {
|
||||||
requester.showUserMessage("Request to show hand cards", "Player " + grantingPlayer.getName() + " does not allow to request to show hand cards!");
|
requester.showUserMessage("Request to show hand cards", "Player " + grantingPlayer.getName() + " does not allow to request to show hand cards!");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -640,7 +644,7 @@ public class GameController implements GameCallback {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// user can already see the cards
|
// user can already see the cards
|
||||||
UserManager.instance.getUser(userIdRequester).ifPresent(requester -> {
|
managerFactory.userManager().getUser(userIdRequester).ifPresent(requester -> {
|
||||||
requester.showUserMessage("Request to show hand cards", "You can see already the hand cards of player " + grantingPlayer.getName() + '!');
|
requester.showUserMessage("Request to show hand cards", "You can see already the hand cards of player " + grantingPlayer.getName() + '!');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -653,9 +657,9 @@ public class GameController implements GameCallback {
|
||||||
Player viewLimitedDeckPlayer = game.getPlayer(userIdRequester);
|
Player viewLimitedDeckPlayer = game.getPlayer(userIdRequester);
|
||||||
if (viewLimitedDeckPlayer != null) {
|
if (viewLimitedDeckPlayer != null) {
|
||||||
if (viewLimitedDeckPlayer.isHuman()) {
|
if (viewLimitedDeckPlayer.isHuman()) {
|
||||||
for (MatchPlayer p : TableManager.instance.getTable(tableId).getMatch().getPlayers()) {
|
for (MatchPlayer p : managerFactory.tableManager().getTable(tableId).getMatch().getPlayers()) {
|
||||||
if (p.getPlayer().getId().equals(userIdRequester)) {
|
if (p.getPlayer().getId().equals(userIdRequester)) {
|
||||||
Optional<User> u = UserManager.instance.getUser(origId);
|
Optional<User> u = managerFactory.userManager().getUser(origId);
|
||||||
if (u.isPresent() && p.getDeck() != null) {
|
if (u.isPresent() && p.getDeck() != null) {
|
||||||
u.get().ccViewLimitedDeck(p.getDeck(), tableId, requestsOpen, true);
|
u.get().ccViewLimitedDeck(p.getDeck(), tableId, requestsOpen, true);
|
||||||
}
|
}
|
||||||
|
@ -698,8 +702,8 @@ public class GameController implements GameCallback {
|
||||||
if (player != null) {
|
if (player != null) {
|
||||||
String sb = player.getLogName()
|
String sb = player.getLogName()
|
||||||
+ " has timed out (player had priority and was not active for "
|
+ " has timed out (player had priority and was not active for "
|
||||||
+ ConfigSettings.instance.getMaxSecondsIdle() + " seconds ) - Auto concede.";
|
+ managerFactory.configSettings().getMaxSecondsIdle() + " seconds ) - Auto concede.";
|
||||||
ChatManager.instance.broadcast(chatId, "", sb, MessageColor.BLACK, true, game, MessageType.STATUS, null);
|
managerFactory.chatManager().broadcast(chatId, "", sb, MessageColor.BLACK, true, game, MessageType.STATUS, null);
|
||||||
game.idleTimeout(playerId);
|
game.idleTimeout(playerId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -712,7 +716,7 @@ public class GameController implements GameCallback {
|
||||||
for (final GameSessionWatcher gameWatcher : getGameSessionWatchers()) {
|
for (final GameSessionWatcher gameWatcher : getGameSessionWatchers()) {
|
||||||
gameWatcher.gameOver(message);
|
gameWatcher.gameOver(message);
|
||||||
}
|
}
|
||||||
TableManager.instance.endGame(tableId);
|
managerFactory.tableManager().endGame(tableId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public UUID getSessionId() {
|
public UUID getSessionId() {
|
||||||
|
@ -763,7 +767,7 @@ public class GameController implements GameCallback {
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void endGameInfo() {
|
private synchronized void endGameInfo() {
|
||||||
Table table = TableManager.instance.getTable(tableId);
|
Table table = managerFactory.tableManager().getTable(tableId);
|
||||||
if (table != null) {
|
if (table != null) {
|
||||||
if (table.getMatch() != null) {
|
if (table.getMatch() != null) {
|
||||||
for (final GameSessionPlayer gameSession : getGameSessions()) {
|
for (final GameSessionPlayer gameSession : getGameSessions()) {
|
||||||
|
@ -784,7 +788,7 @@ public class GameController implements GameCallback {
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void choosePile(UUID playerId, final String message, final List<? extends Card> pile1, final List<? extends Card> pile2) throws MageException {
|
private synchronized void choosePile(UUID playerId, final String message, final List<? extends Card> pile1, final List<? extends Card> pile2) throws MageException {
|
||||||
perform(playerId, playerId1 -> getGameSession(playerId1).choosePile(message, new CardsView(pile1), new CardsView(pile2)));
|
perform(playerId, playerId1 -> getGameSession(playerId1).choosePile(message, new CardsView(game, pile1), new CardsView(game, pile2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void chooseMode(UUID playerId, final Map<UUID, String> modes, final String message) throws MageException {
|
private synchronized void chooseMode(UUID playerId, final Map<UUID, String> modes, final String message) throws MageException {
|
||||||
|
@ -1012,7 +1016,7 @@ public class GameController implements GameCallback {
|
||||||
cancelTimeout();
|
cancelTimeout();
|
||||||
futureTimeout = timeoutIdleExecutor.schedule(
|
futureTimeout = timeoutIdleExecutor.schedule(
|
||||||
() -> idleTimeout(playerId),
|
() -> idleTimeout(playerId),
|
||||||
Main.isTestMode() ? 3600 : ConfigSettings.instance.getMaxSecondsIdle(),
|
Main.isTestMode() ? 3600 : managerFactory.configSettings().getMaxSecondsIdle(),
|
||||||
TimeUnit.SECONDS
|
TimeUnit.SECONDS
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1094,7 +1098,7 @@ public class GameController implements GameCallback {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAllowedToWatch(UUID userId) {
|
public boolean isAllowedToWatch(UUID userId) {
|
||||||
Optional<User> user = UserManager.instance.getUser(userId);
|
Optional<User> user = managerFactory.userManager().getUser(userId);
|
||||||
if (user.isPresent()) {
|
if (user.isPresent()) {
|
||||||
return !gameOptions.bannedUsers.contains(user.get().getName());
|
return !gameOptions.bannedUsers.contains(user.get().getName());
|
||||||
}
|
}
|
||||||
|
@ -1208,7 +1212,7 @@ public class GameController implements GameCallback {
|
||||||
public String getPingsInfo() {
|
public String getPingsInfo() {
|
||||||
List<String> usersInfo = new ArrayList<>();
|
List<String> usersInfo = new ArrayList<>();
|
||||||
for (Map.Entry<UUID, UUID> entry : userPlayerMap.entrySet()) {
|
for (Map.Entry<UUID, UUID> entry : userPlayerMap.entrySet()) {
|
||||||
Optional<User> user = UserManager.instance.getUser(entry.getKey());
|
Optional<User> user = managerFactory.userManager().getUser(entry.getKey());
|
||||||
user.ifPresent(u -> usersInfo.add("* " + u.getName() + ": " + u.getPingInfo()));
|
user.ifPresent(u -> usersInfo.add("* " + u.getName() + ": " + u.getPingInfo()));
|
||||||
}
|
}
|
||||||
Collections.sort(usersInfo);
|
Collections.sort(usersInfo);
|
||||||
|
@ -1216,7 +1220,7 @@ public class GameController implements GameCallback {
|
||||||
|
|
||||||
List<String> watchersinfo = new ArrayList<>();
|
List<String> watchersinfo = new ArrayList<>();
|
||||||
for (Map.Entry<UUID, GameSessionWatcher> entry : watchers.entrySet()) {
|
for (Map.Entry<UUID, GameSessionWatcher> entry : watchers.entrySet()) {
|
||||||
Optional<User> user = UserManager.instance.getUser(entry.getValue().userId);
|
Optional<User> user = managerFactory.userManager().getUser(entry.getValue().userId);
|
||||||
user.ifPresent(u -> watchersinfo.add("* " + u.getName() + ": " + u.getPingInfo()));
|
user.ifPresent(u -> watchersinfo.add("* " + u.getName() + ": " + u.getPingInfo()));
|
||||||
}
|
}
|
||||||
Collections.sort(watchersinfo);
|
Collections.sort(watchersinfo);
|
||||||
|
|
|
@ -5,6 +5,8 @@ import mage.constants.ManaType;
|
||||||
import mage.constants.PlayerAction;
|
import mage.constants.PlayerAction;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.GameOptions;
|
import mage.game.GameOptions;
|
||||||
|
import mage.server.managers.GameManager;
|
||||||
|
import mage.server.managers.ManagerFactory;
|
||||||
import mage.view.GameView;
|
import mage.view.GameView;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -20,14 +22,19 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
/**
|
/**
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
*/
|
*/
|
||||||
public enum GameManager {
|
public class GameManagerImpl implements GameManager {
|
||||||
instance;
|
|
||||||
|
|
||||||
|
private final ManagerFactory managerFactory;
|
||||||
private final ConcurrentMap<UUID, GameController> gameControllers = new ConcurrentHashMap<>();
|
private final ConcurrentMap<UUID, GameController> gameControllers = new ConcurrentHashMap<>();
|
||||||
private final ReadWriteLock gameControllersLock = new ReentrantReadWriteLock();
|
private final ReadWriteLock gameControllersLock = new ReentrantReadWriteLock();
|
||||||
|
|
||||||
|
public GameManagerImpl(ManagerFactory managerFactory) {
|
||||||
|
this.managerFactory = managerFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public UUID createGameSession(Game game, ConcurrentHashMap<UUID, UUID> userPlayerMap, UUID tableId, UUID choosingPlayerId, GameOptions gameOptions) {
|
public UUID createGameSession(Game game, ConcurrentHashMap<UUID, UUID> userPlayerMap, UUID tableId, UUID choosingPlayerId, GameOptions gameOptions) {
|
||||||
GameController gameController = new GameController(game, userPlayerMap, tableId, choosingPlayerId, gameOptions);
|
GameController gameController = new GameController(managerFactory, game, userPlayerMap, tableId, choosingPlayerId, gameOptions);
|
||||||
final Lock w = gameControllersLock.writeLock();
|
final Lock w = gameControllersLock.writeLock();
|
||||||
w.lock();
|
w.lock();
|
||||||
try {
|
try {
|
||||||
|
@ -48,6 +55,7 @@ public enum GameManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void joinGame(UUID gameId, UUID userId) {
|
public void joinGame(UUID gameId, UUID userId) {
|
||||||
GameController gameController = getGameControllerSafe(gameId);
|
GameController gameController = getGameControllerSafe(gameId);
|
||||||
if (gameController != null) {
|
if (gameController != null) {
|
||||||
|
@ -55,6 +63,7 @@ public enum GameManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Optional<UUID> getChatId(UUID gameId) {
|
public Optional<UUID> getChatId(UUID gameId) {
|
||||||
GameController gameController = getGameControllerSafe(gameId);
|
GameController gameController = getGameControllerSafe(gameId);
|
||||||
if (gameController != null) {
|
if (gameController != null) {
|
||||||
|
@ -63,6 +72,7 @@ public enum GameManager {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void sendPlayerUUID(UUID gameId, UUID userId, UUID data) {
|
public void sendPlayerUUID(UUID gameId, UUID userId, UUID data) {
|
||||||
GameController gameController = getGameControllerSafe(gameId);
|
GameController gameController = getGameControllerSafe(gameId);
|
||||||
if (gameController != null) {
|
if (gameController != null) {
|
||||||
|
@ -70,6 +80,7 @@ public enum GameManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void sendPlayerString(UUID gameId, UUID userId, String data) {
|
public void sendPlayerString(UUID gameId, UUID userId, String data) {
|
||||||
GameController gameController = getGameControllerSafe(gameId);
|
GameController gameController = getGameControllerSafe(gameId);
|
||||||
if (gameController != null) {
|
if (gameController != null) {
|
||||||
|
@ -77,6 +88,7 @@ public enum GameManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void sendPlayerManaType(UUID gameId, UUID playerId, UUID userId, ManaType data) {
|
public void sendPlayerManaType(UUID gameId, UUID playerId, UUID userId, ManaType data) {
|
||||||
GameController gameController = getGameControllerSafe(gameId);
|
GameController gameController = getGameControllerSafe(gameId);
|
||||||
if (gameController != null) {
|
if (gameController != null) {
|
||||||
|
@ -84,6 +96,7 @@ public enum GameManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void sendPlayerBoolean(UUID gameId, UUID userId, Boolean data) {
|
public void sendPlayerBoolean(UUID gameId, UUID userId, Boolean data) {
|
||||||
GameController gameController = getGameControllerSafe(gameId);
|
GameController gameController = getGameControllerSafe(gameId);
|
||||||
if (gameController != null) {
|
if (gameController != null) {
|
||||||
|
@ -91,6 +104,7 @@ public enum GameManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void sendPlayerInteger(UUID gameId, UUID userId, Integer data) {
|
public void sendPlayerInteger(UUID gameId, UUID userId, Integer data) {
|
||||||
GameController gameController = getGameControllerSafe(gameId);
|
GameController gameController = getGameControllerSafe(gameId);
|
||||||
if (gameController != null) {
|
if (gameController != null) {
|
||||||
|
@ -98,6 +112,7 @@ public enum GameManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void quitMatch(UUID gameId, UUID userId) {
|
public void quitMatch(UUID gameId, UUID userId) {
|
||||||
GameController gameController = getGameControllerSafe(gameId);
|
GameController gameController = getGameControllerSafe(gameId);
|
||||||
if (gameController != null) {
|
if (gameController != null) {
|
||||||
|
@ -105,6 +120,7 @@ public enum GameManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void sendPlayerAction(PlayerAction playerAction, UUID gameId, UUID userId, Object data) {
|
public void sendPlayerAction(PlayerAction playerAction, UUID gameId, UUID userId, Object data) {
|
||||||
GameController gameController = getGameControllerSafe(gameId);
|
GameController gameController = getGameControllerSafe(gameId);
|
||||||
if (gameController != null) {
|
if (gameController != null) {
|
||||||
|
@ -112,6 +128,7 @@ public enum GameManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean watchGame(UUID gameId, UUID userId) {
|
public boolean watchGame(UUID gameId, UUID userId) {
|
||||||
GameController gameController = getGameControllerSafe(gameId);
|
GameController gameController = getGameControllerSafe(gameId);
|
||||||
if (gameController != null) {
|
if (gameController != null) {
|
||||||
|
@ -120,6 +137,7 @@ public enum GameManager {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void stopWatching(UUID gameId, UUID userId) {
|
public void stopWatching(UUID gameId, UUID userId) {
|
||||||
GameController gameController = getGameControllerSafe(gameId);
|
GameController gameController = getGameControllerSafe(gameId);
|
||||||
if (gameController != null) {
|
if (gameController != null) {
|
||||||
|
@ -127,6 +145,7 @@ public enum GameManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void cheat(UUID gameId, UUID userId, UUID playerId, DeckCardLists deckList) {
|
public void cheat(UUID gameId, UUID userId, UUID playerId, DeckCardLists deckList) {
|
||||||
GameController gameController = getGameControllerSafe(gameId);
|
GameController gameController = getGameControllerSafe(gameId);
|
||||||
if (gameController != null) {
|
if (gameController != null) {
|
||||||
|
@ -134,6 +153,7 @@ public enum GameManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean cheat(UUID gameId, UUID userId, UUID playerId, String cardName) {
|
public boolean cheat(UUID gameId, UUID userId, UUID playerId, String cardName) {
|
||||||
GameController gameController = getGameControllerSafe(gameId);
|
GameController gameController = getGameControllerSafe(gameId);
|
||||||
if (gameController != null) {
|
if (gameController != null) {
|
||||||
|
@ -142,6 +162,7 @@ public enum GameManager {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void removeGame(UUID gameId) {
|
public void removeGame(UUID gameId) {
|
||||||
GameController gameController = getGameControllerSafe(gameId);
|
GameController gameController = getGameControllerSafe(gameId);
|
||||||
if (gameController != null) {
|
if (gameController != null) {
|
||||||
|
@ -156,6 +177,7 @@ public enum GameManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean saveGame(UUID gameId) {
|
public boolean saveGame(UUID gameId) {
|
||||||
GameController gameController = getGameControllerSafe(gameId);
|
GameController gameController = getGameControllerSafe(gameId);
|
||||||
if (gameController != null) {
|
if (gameController != null) {
|
||||||
|
@ -164,6 +186,7 @@ public enum GameManager {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public GameView getGameView(UUID gameId, UUID playerId) {
|
public GameView getGameView(UUID gameId, UUID playerId) {
|
||||||
GameController gameController = getGameControllerSafe(gameId);
|
GameController gameController = getGameControllerSafe(gameId);
|
||||||
if (gameController != null) {
|
if (gameController != null) {
|
||||||
|
@ -172,10 +195,12 @@ public enum GameManager {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getNumberActiveGames() {
|
public int getNumberActiveGames() {
|
||||||
return getGameController().size();
|
return getGameController().size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Map<UUID, GameController> getGameController() {
|
public Map<UUID, GameController> getGameController() {
|
||||||
Map<UUID, GameController> newControllers = new HashMap<>();
|
Map<UUID, GameController> newControllers = new HashMap<>();
|
||||||
final Lock r = gameControllersLock.readLock();
|
final Lock r = gameControllersLock.readLock();
|
|
@ -11,8 +11,8 @@ import mage.interfaces.callback.ClientCallback;
|
||||||
import mage.interfaces.callback.ClientCallbackMethod;
|
import mage.interfaces.callback.ClientCallbackMethod;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.server.User;
|
import mage.server.User;
|
||||||
import mage.server.UserManager;
|
import mage.server.managers.UserManager;
|
||||||
import mage.server.util.ThreadExecutor;
|
import mage.server.managers.ManagerFactory;
|
||||||
import mage.view.*;
|
import mage.view.*;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
@ -28,12 +28,15 @@ public class GameSessionPlayer extends GameSessionWatcher {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(GameSessionPlayer.class);
|
private static final Logger logger = Logger.getLogger(GameSessionPlayer.class);
|
||||||
|
|
||||||
|
private final UserManager userManager;
|
||||||
private final UUID playerId;
|
private final UUID playerId;
|
||||||
|
|
||||||
private static final ExecutorService callExecutor = ThreadExecutor.instance.getCallExecutor();
|
private final ExecutorService callExecutor;
|
||||||
|
|
||||||
public GameSessionPlayer(Game game, UUID userId, UUID playerId) {
|
public GameSessionPlayer(ManagerFactory managerFactory, Game game, UUID userId, UUID playerId) {
|
||||||
super(userId, game, true);
|
super(managerFactory.userManager(), userId, game, true);
|
||||||
|
this.userManager = managerFactory.userManager();
|
||||||
|
callExecutor = managerFactory.threadExecutor().getCallExecutor();
|
||||||
this.playerId = playerId;
|
this.playerId = playerId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,14 +47,14 @@ public class GameSessionPlayer extends GameSessionWatcher {
|
||||||
|
|
||||||
public void ask(final String question, final Map<String, Serializable> options) {
|
public void ask(final String question, final Map<String, Serializable> options) {
|
||||||
if (!killed) {
|
if (!killed) {
|
||||||
UserManager.instance.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_ASK, game.getId(), new GameClientMessage(getGameView(), question, options)))
|
userManager.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_ASK, game.getId(), new GameClientMessage(getGameView(), question, options)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void target(final String question, final CardsView cardView, final Set<UUID> targets, final boolean required, final Map<String, Serializable> options) {
|
public void target(final String question, final CardsView cardView, final Set<UUID> targets, final boolean required, final Map<String, Serializable> options) {
|
||||||
if (!killed) {
|
if (!killed) {
|
||||||
UserManager.instance.getUser(userId).ifPresent(user -> {
|
userManager.getUser(userId).ifPresent(user -> {
|
||||||
user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_TARGET, game.getId(), new GameClientMessage(getGameView(), question, cardView, targets, required, options)));
|
user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_TARGET, game.getId(), new GameClientMessage(getGameView(), question, cardView, targets, required, options)));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -60,13 +63,13 @@ public class GameSessionPlayer extends GameSessionWatcher {
|
||||||
|
|
||||||
public void select(final String message, final Map<String, Serializable> options) {
|
public void select(final String message, final Map<String, Serializable> options) {
|
||||||
if (!killed) {
|
if (!killed) {
|
||||||
UserManager.instance.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_SELECT, game.getId(), new GameClientMessage(getGameView(), message, options))));
|
userManager.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_SELECT, game.getId(), new GameClientMessage(getGameView(), message, options))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void chooseAbility(final AbilityPickerView abilities) {
|
public void chooseAbility(final AbilityPickerView abilities) {
|
||||||
if (!killed) {
|
if (!killed) {
|
||||||
UserManager.instance.getUser(userId).ifPresent(user
|
userManager.getUser(userId).ifPresent(user
|
||||||
-> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_CHOOSE_ABILITY, game.getId(), abilities)));
|
-> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_CHOOSE_ABILITY, game.getId(), abilities)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +77,7 @@ public class GameSessionPlayer extends GameSessionWatcher {
|
||||||
|
|
||||||
public void choosePile(final String message, final CardsView pile1, final CardsView pile2) {
|
public void choosePile(final String message, final CardsView pile1, final CardsView pile2) {
|
||||||
if (!killed) {
|
if (!killed) {
|
||||||
UserManager.instance.getUser(userId).ifPresent(user
|
userManager.getUser(userId).ifPresent(user
|
||||||
-> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_CHOOSE_PILE, game.getId(), new GameClientMessage(message, pile1, pile2))));
|
-> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_CHOOSE_PILE, game.getId(), new GameClientMessage(message, pile1, pile2))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +85,7 @@ public class GameSessionPlayer extends GameSessionWatcher {
|
||||||
|
|
||||||
public void chooseChoice(final Choice choice) {
|
public void chooseChoice(final Choice choice) {
|
||||||
if (!killed) {
|
if (!killed) {
|
||||||
UserManager.instance.getUser(userId).ifPresent(user
|
userManager.getUser(userId).ifPresent(user
|
||||||
-> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_CHOOSE_CHOICE, game.getId(), new GameClientMessage(choice))));
|
-> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_CHOOSE_CHOICE, game.getId(), new GameClientMessage(choice))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,14 +93,14 @@ public class GameSessionPlayer extends GameSessionWatcher {
|
||||||
|
|
||||||
public void playMana(final String message, final Map<String, Serializable> options) {
|
public void playMana(final String message, final Map<String, Serializable> options) {
|
||||||
if (!killed) {
|
if (!killed) {
|
||||||
UserManager.instance.getUser(userId).ifPresent(user
|
userManager.getUser(userId).ifPresent(user
|
||||||
-> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_PLAY_MANA, game.getId(), new GameClientMessage(getGameView(), message, options))));
|
-> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_PLAY_MANA, game.getId(), new GameClientMessage(getGameView(), message, options))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void playXMana(final String message) {
|
public void playXMana(final String message) {
|
||||||
if (!killed) {
|
if (!killed) {
|
||||||
UserManager.instance.getUser(userId).ifPresent(user
|
userManager.getUser(userId).ifPresent(user
|
||||||
-> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_PLAY_XMANA, game.getId(), new GameClientMessage(getGameView(), message))));
|
-> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_PLAY_XMANA, game.getId(), new GameClientMessage(getGameView(), message))));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -105,7 +108,7 @@ public class GameSessionPlayer extends GameSessionWatcher {
|
||||||
|
|
||||||
public void getAmount(final String message, final int min, final int max) {
|
public void getAmount(final String message, final int min, final int max) {
|
||||||
if (!killed) {
|
if (!killed) {
|
||||||
UserManager.instance.getUser(userId).ifPresent(user -> {
|
userManager.getUser(userId).ifPresent(user -> {
|
||||||
user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_GET_AMOUNT, game.getId(), new GameClientMessage(message, min, max)));
|
user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_GET_AMOUNT, game.getId(), new GameClientMessage(message, min, max)));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -113,15 +116,15 @@ public class GameSessionPlayer extends GameSessionWatcher {
|
||||||
|
|
||||||
public void endGameInfo(Table table) {
|
public void endGameInfo(Table table) {
|
||||||
if (!killed) {
|
if (!killed) {
|
||||||
UserManager.instance.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.END_GAME_INFO, game.getId(), getGameEndView(playerId, table))));
|
userManager.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.END_GAME_INFO, game.getId(), getGameEndView(playerId, table))));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void requestPermissionToRollbackTurn(UUID requestingUserId, int numberTurns) {
|
public void requestPermissionToRollbackTurn(UUID requestingUserId, int numberTurns) {
|
||||||
if (!killed) {
|
if (!killed) {
|
||||||
Optional<User> requestingUser = UserManager.instance.getUser(requestingUserId);
|
Optional<User> requestingUser = userManager.getUser(requestingUserId);
|
||||||
Optional<User> requestedUser = UserManager.instance.getUser(userId);
|
Optional<User> requestedUser = userManager.getUser(userId);
|
||||||
if (requestedUser.isPresent() && requestingUser.isPresent()) {
|
if (requestedUser.isPresent() && requestingUser.isPresent()) {
|
||||||
String message;
|
String message;
|
||||||
switch (numberTurns) {
|
switch (numberTurns) {
|
||||||
|
@ -147,8 +150,8 @@ public class GameSessionPlayer extends GameSessionWatcher {
|
||||||
|
|
||||||
public void requestPermissionToSeeHandCards(UUID watcherId) {
|
public void requestPermissionToSeeHandCards(UUID watcherId) {
|
||||||
if (!killed) {
|
if (!killed) {
|
||||||
Optional<User> watcher = UserManager.instance.getUser(watcherId);
|
Optional<User> watcher = userManager.getUser(watcherId);
|
||||||
Optional<User> user = UserManager.instance.getUser(userId);
|
Optional<User> user = userManager.getUser(userId);
|
||||||
if (user.isPresent() && watcher.isPresent()) {
|
if (user.isPresent() && watcher.isPresent()) {
|
||||||
UserRequestMessage userRequestMessage = new UserRequestMessage(
|
UserRequestMessage userRequestMessage = new UserRequestMessage(
|
||||||
"User request",
|
"User request",
|
||||||
|
@ -217,7 +220,7 @@ public class GameSessionPlayer extends GameSessionWatcher {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeGame() {
|
public void removeGame() {
|
||||||
UserManager.instance.getUser(userId).ifPresent(user -> user.removeGame(playerId));
|
userManager.getUser(userId).ifPresent(user -> user.removeGame(playerId));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import mage.interfaces.callback.ClientCallback;
|
||||||
import mage.interfaces.callback.ClientCallbackMethod;
|
import mage.interfaces.callback.ClientCallbackMethod;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.server.User;
|
import mage.server.User;
|
||||||
import mage.server.UserManager;
|
import mage.server.managers.UserManager;
|
||||||
import mage.view.GameClientMessage;
|
import mage.view.GameClientMessage;
|
||||||
import mage.view.GameEndView;
|
import mage.view.GameEndView;
|
||||||
import mage.view.GameView;
|
import mage.view.GameView;
|
||||||
|
@ -25,12 +25,14 @@ public class GameSessionWatcher {
|
||||||
|
|
||||||
protected static final Logger logger = Logger.getLogger(GameSessionWatcher.class);
|
protected static final Logger logger = Logger.getLogger(GameSessionWatcher.class);
|
||||||
|
|
||||||
|
private final UserManager userManager;
|
||||||
protected final UUID userId;
|
protected final UUID userId;
|
||||||
protected final Game game;
|
protected final Game game;
|
||||||
protected boolean killed = false;
|
protected boolean killed = false;
|
||||||
protected final boolean isPlayer;
|
protected final boolean isPlayer;
|
||||||
|
|
||||||
public GameSessionWatcher(UUID userId, Game game, boolean isPlayer) {
|
public GameSessionWatcher(UserManager userManager, UUID userId, Game game, boolean isPlayer) {
|
||||||
|
this.userManager = userManager;
|
||||||
this.userId = userId;
|
this.userId = userId;
|
||||||
this.game = game;
|
this.game = game;
|
||||||
this.isPlayer = isPlayer;
|
this.isPlayer = isPlayer;
|
||||||
|
@ -38,7 +40,7 @@ public class GameSessionWatcher {
|
||||||
|
|
||||||
public boolean init() {
|
public boolean init() {
|
||||||
if (!killed) {
|
if (!killed) {
|
||||||
Optional<User> user = UserManager.instance.getUser(userId);
|
Optional<User> user = userManager.getUser(userId);
|
||||||
if (user.isPresent()) {
|
if (user.isPresent()) {
|
||||||
user.get().fireCallback(new ClientCallback(ClientCallbackMethod.GAME_INIT, game.getId(), getGameView()));
|
user.get().fireCallback(new ClientCallback(ClientCallbackMethod.GAME_INIT, game.getId(), getGameView()));
|
||||||
return true;
|
return true;
|
||||||
|
@ -49,28 +51,28 @@ public class GameSessionWatcher {
|
||||||
|
|
||||||
public void update() {
|
public void update() {
|
||||||
if (!killed) {
|
if (!killed) {
|
||||||
UserManager.instance.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_UPDATE, game.getId(), getGameView())));
|
userManager.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_UPDATE, game.getId(), getGameView())));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void inform(final String message) {
|
public void inform(final String message) {
|
||||||
if (!killed) {
|
if (!killed) {
|
||||||
UserManager.instance.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_INFORM, game.getId(), new GameClientMessage(getGameView(), message))));
|
userManager.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_INFORM, game.getId(), new GameClientMessage(getGameView(), message))));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void informPersonal(final String message) {
|
public void informPersonal(final String message) {
|
||||||
if (!killed) {
|
if (!killed) {
|
||||||
UserManager.instance.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_INFORM_PERSONAL, game.getId(), new GameClientMessage(getGameView(), message))));
|
userManager.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_INFORM_PERSONAL, game.getId(), new GameClientMessage(getGameView(), message))));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void gameOver(final String message) {
|
public void gameOver(final String message) {
|
||||||
if (!killed) {
|
if (!killed) {
|
||||||
UserManager.instance.getUser(userId).ifPresent(user -> {
|
userManager.getUser(userId).ifPresent(user -> {
|
||||||
user.removeGameWatchInfo(game.getId());
|
user.removeGameWatchInfo(game.getId());
|
||||||
user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_OVER, game.getId(), message));
|
user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_OVER, game.getId(), message));
|
||||||
});
|
});
|
||||||
|
@ -86,7 +88,7 @@ public class GameSessionWatcher {
|
||||||
|
|
||||||
public void gameError(final String message) {
|
public void gameError(final String message) {
|
||||||
if (!killed) {
|
if (!killed) {
|
||||||
UserManager.instance.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_ERROR, game.getId(), message)));
|
userManager.getUser(userId).ifPresent(user -> user.fireCallback(new ClientCallback(ClientCallbackMethod.GAME_ERROR, game.getId(), message)));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,5 @@
|
||||||
|
|
||||||
package mage.server.game;
|
package mage.server.game;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import mage.MageException;
|
import mage.MageException;
|
||||||
import mage.cards.decks.DeckCardLists;
|
import mage.cards.decks.DeckCardLists;
|
||||||
import mage.constants.TableState;
|
import mage.constants.TableState;
|
||||||
|
@ -16,18 +9,21 @@ import mage.game.match.MatchOptions;
|
||||||
import mage.game.tournament.TournamentOptions;
|
import mage.game.tournament.TournamentOptions;
|
||||||
import mage.players.PlayerType;
|
import mage.players.PlayerType;
|
||||||
import mage.server.RoomImpl;
|
import mage.server.RoomImpl;
|
||||||
import mage.server.TableManager;
|
|
||||||
import mage.server.User;
|
import mage.server.User;
|
||||||
import mage.server.UserManager;
|
import mage.server.managers.ManagerFactory;
|
||||||
import mage.server.tournament.TournamentManager;
|
|
||||||
import mage.server.util.ConfigSettings;
|
|
||||||
import mage.server.util.ThreadExecutor;
|
|
||||||
import mage.view.MatchView;
|
import mage.view.MatchView;
|
||||||
import mage.view.RoomUsersView;
|
import mage.view.RoomUsersView;
|
||||||
import mage.view.TableView;
|
import mage.view.TableView;
|
||||||
import mage.view.UsersView;
|
import mage.view.UsersView;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
*/
|
*/
|
||||||
|
@ -40,9 +36,12 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable {
|
||||||
private static List<MatchView> matchView = new ArrayList<>();
|
private static List<MatchView> matchView = new ArrayList<>();
|
||||||
private static List<RoomUsersView> roomUsersView = new ArrayList<>();
|
private static List<RoomUsersView> roomUsersView = new ArrayList<>();
|
||||||
|
|
||||||
|
private final ManagerFactory managerFactory;
|
||||||
private final ConcurrentHashMap<UUID, Table> tables = new ConcurrentHashMap<>();
|
private final ConcurrentHashMap<UUID, Table> tables = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public GamesRoomImpl() {
|
public GamesRoomImpl(ManagerFactory managerFactory) {
|
||||||
|
super(managerFactory.chatManager());
|
||||||
|
this.managerFactory = managerFactory;
|
||||||
UPDATE_EXECUTOR.scheduleAtFixedRate(() -> {
|
UPDATE_EXECUTOR.scheduleAtFixedRate(() -> {
|
||||||
try {
|
try {
|
||||||
update();
|
update();
|
||||||
|
@ -71,7 +70,7 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable {
|
||||||
} else {
|
} else {
|
||||||
// more since 50 matches finished since this match so removeUserFromAllTablesAndChat it
|
// more since 50 matches finished since this match so removeUserFromAllTablesAndChat it
|
||||||
if (table.isTournament()) {
|
if (table.isTournament()) {
|
||||||
TournamentManager.instance.removeTournament(table.getTournament().getId());
|
managerFactory.tournamentManager().removeTournament(table.getTournament().getId());
|
||||||
}
|
}
|
||||||
this.removeTable(table.getId());
|
this.removeTable(table.getId());
|
||||||
}
|
}
|
||||||
|
@ -79,7 +78,7 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable {
|
||||||
tableView = tableList;
|
tableView = tableList;
|
||||||
matchView = matchList;
|
matchView = matchList;
|
||||||
List<UsersView> users = new ArrayList<>();
|
List<UsersView> users = new ArrayList<>();
|
||||||
for (User user : UserManager.instance.getUsers()) {
|
for (User user : managerFactory.userManager().getUsers()) {
|
||||||
if (user.getUserState() != User.UserState.Offline && !user.getName().equals("Admin")) {
|
if (user.getUserState() != User.UserState.Offline && !user.getName().equals("Admin")) {
|
||||||
try {
|
try {
|
||||||
users.add(new UsersView(user.getUserData().getFlagName(), user.getName(),
|
users.add(new UsersView(user.getUserData().getFlagName(), user.getName(),
|
||||||
|
@ -108,9 +107,9 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable {
|
||||||
users.sort((one, two) -> one.getUserName().compareToIgnoreCase(two.getUserName()));
|
users.sort((one, two) -> one.getUserName().compareToIgnoreCase(two.getUserName()));
|
||||||
List<RoomUsersView> roomUserInfo = new ArrayList<>();
|
List<RoomUsersView> roomUserInfo = new ArrayList<>();
|
||||||
roomUserInfo.add(new RoomUsersView(users,
|
roomUserInfo.add(new RoomUsersView(users,
|
||||||
GameManager.instance.getNumberActiveGames(),
|
managerFactory.gameManager().getNumberActiveGames(),
|
||||||
ThreadExecutor.instance.getActiveThreads(ThreadExecutor.instance.getGameExecutor()),
|
managerFactory.threadExecutor().getActiveThreads(managerFactory.threadExecutor().getGameExecutor()),
|
||||||
ConfigSettings.instance.getMaxGameThreads()
|
managerFactory.configSettings().getMaxGameThreads()
|
||||||
));
|
));
|
||||||
roomUsersView = roomUserInfo;
|
roomUsersView = roomUserInfo;
|
||||||
}
|
}
|
||||||
|
@ -123,7 +122,7 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable {
|
||||||
@Override
|
@Override
|
||||||
public boolean joinTable(UUID userId, UUID tableId, String name, PlayerType playerType, int skill, DeckCardLists deckList, String password) throws MageException {
|
public boolean joinTable(UUID userId, UUID tableId, String name, PlayerType playerType, int skill, DeckCardLists deckList, String password) throws MageException {
|
||||||
if (tables.containsKey(tableId)) {
|
if (tables.containsKey(tableId)) {
|
||||||
return TableManager.instance.joinTable(userId, tableId, name, playerType, skill, deckList, password);
|
return managerFactory.tableManager().joinTable(userId, tableId, name, playerType, skill, deckList, password);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -131,7 +130,7 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TableView createTable(UUID userId, MatchOptions options) {
|
public TableView createTable(UUID userId, MatchOptions options) {
|
||||||
Table table = TableManager.instance.createTable(this.getRoomId(), userId, options);
|
Table table = managerFactory.tableManager().createTable(this.getRoomId(), userId, options);
|
||||||
tables.put(table.getId(), table);
|
tables.put(table.getId(), table);
|
||||||
return new TableView(table);
|
return new TableView(table);
|
||||||
}
|
}
|
||||||
|
@ -139,7 +138,7 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable {
|
||||||
@Override
|
@Override
|
||||||
public boolean joinTournamentTable(UUID userId, UUID tableId, String name, PlayerType playerType, int skill, DeckCardLists deckList, String password) throws GameException {
|
public boolean joinTournamentTable(UUID userId, UUID tableId, String name, PlayerType playerType, int skill, DeckCardLists deckList, String password) throws GameException {
|
||||||
if (tables.containsKey(tableId)) {
|
if (tables.containsKey(tableId)) {
|
||||||
return TableManager.instance.joinTournament(userId, tableId, name, playerType, skill, deckList, password);
|
return managerFactory.tableManager().joinTournament(userId, tableId, name, playerType, skill, deckList, password);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -147,7 +146,7 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TableView createTournamentTable(UUID userId, TournamentOptions options) {
|
public TableView createTournamentTable(UUID userId, TournamentOptions options) {
|
||||||
Table table = TableManager.instance.createTournamentTable(this.getRoomId(), userId, options);
|
Table table = managerFactory.tableManager().createTournamentTable(this.getRoomId(), userId, options);
|
||||||
tables.put(table.getId(), table);
|
tables.put(table.getId(), table);
|
||||||
return new TableView(table);
|
return new TableView(table);
|
||||||
}
|
}
|
||||||
|
@ -179,12 +178,12 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void leaveTable(UUID userId, UUID tableId) {
|
public void leaveTable(UUID userId, UUID tableId) {
|
||||||
TableManager.instance.leaveTable(userId, tableId);
|
managerFactory.tableManager().leaveTable(userId, tableId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean watchTable(UUID userId, UUID tableId) throws MageException {
|
public boolean watchTable(UUID userId, UUID tableId) throws MageException {
|
||||||
return TableManager.instance.watchTable(userId, tableId);
|
return managerFactory.tableManager().watchTable(userId, tableId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package mage.server.game;
|
package mage.server.game;
|
||||||
|
|
||||||
|
import mage.server.managers.GamesRoomManager;
|
||||||
|
import mage.server.managers.ManagerFactory;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
@ -9,36 +11,44 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||||
/**
|
/**
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
*/
|
*/
|
||||||
public enum GamesRoomManager {
|
public class GamesRoomManagerImpl implements GamesRoomManager {
|
||||||
instance;
|
|
||||||
|
|
||||||
|
private final ManagerFactory managerFactory;
|
||||||
private final ConcurrentHashMap<UUID, GamesRoom> rooms = new ConcurrentHashMap<>();
|
private final ConcurrentHashMap<UUID, GamesRoom> rooms = new ConcurrentHashMap<>();
|
||||||
private final UUID mainRoomId;
|
private UUID mainRoomId;
|
||||||
private final UUID mainChatId;
|
private UUID mainChatId;
|
||||||
private static final Logger logger = Logger.getLogger(GamesRoomManager.class);
|
private static final Logger logger = Logger.getLogger(GamesRoomManagerImpl.class);
|
||||||
|
|
||||||
|
|
||||||
GamesRoomManager() {
|
public GamesRoomManagerImpl(ManagerFactory managerFactory) {
|
||||||
GamesRoom mainRoom = new GamesRoomImpl();
|
this.managerFactory = managerFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init() {
|
||||||
|
GamesRoom mainRoom = new GamesRoomImpl(managerFactory);
|
||||||
mainRoomId = mainRoom.getRoomId();
|
mainRoomId = mainRoom.getRoomId();
|
||||||
mainChatId = mainRoom.getChatId();
|
mainChatId = mainRoom.getChatId();
|
||||||
rooms.put(mainRoomId, mainRoom);
|
rooms.put(mainRoomId, mainRoom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public UUID createRoom() {
|
public UUID createRoom() {
|
||||||
GamesRoom room = new GamesRoomImpl();
|
GamesRoom room = new GamesRoomImpl(managerFactory);
|
||||||
rooms.put(room.getRoomId(), room);
|
rooms.put(room.getRoomId(), room);
|
||||||
return room.getRoomId();
|
return room.getRoomId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public UUID getMainRoomId() {
|
public UUID getMainRoomId() {
|
||||||
return mainRoomId;
|
return mainRoomId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public UUID getMainChatId() {
|
public UUID getMainChatId() {
|
||||||
return mainChatId;
|
return mainChatId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Optional<GamesRoom> getRoom(UUID roomId) {
|
public Optional<GamesRoom> getRoom(UUID roomId) {
|
||||||
if (rooms.containsKey(roomId)) {
|
if (rooms.containsKey(roomId)) {
|
||||||
return Optional.of(rooms.get(roomId));
|
return Optional.of(rooms.get(roomId));
|
||||||
|
@ -48,6 +58,7 @@ public enum GamesRoomManager {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void removeTable(UUID tableId) {
|
public void removeTable(UUID tableId) {
|
||||||
for (GamesRoom room : rooms.values()) {
|
for (GamesRoom room : rooms.values()) {
|
||||||
room.removeTable(tableId);
|
room.removeTable(tableId);
|
|
@ -1,46 +1,56 @@
|
||||||
|
|
||||||
|
|
||||||
package mage.server.game;
|
package mage.server.game;
|
||||||
|
|
||||||
|
import mage.server.managers.ReplayManager;
|
||||||
|
import mage.server.managers.ManagerFactory;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import mage.server.UserManager;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
*/
|
*/
|
||||||
public enum ReplayManager {
|
public class ReplayManagerImpl implements ReplayManager {
|
||||||
instance;
|
|
||||||
|
|
||||||
private final ConcurrentHashMap<String, ReplaySession> replaySessions = new ConcurrentHashMap<>();
|
private final ConcurrentHashMap<String, ReplaySession> replaySessions = new ConcurrentHashMap<>();
|
||||||
|
private final ManagerFactory managerFactory;
|
||||||
|
|
||||||
public void replayGame(UUID gameId, UUID userId) {
|
public ReplayManagerImpl(ManagerFactory managerFactory) {
|
||||||
ReplaySession replaySession = new ReplaySession(gameId, userId);
|
this.managerFactory = managerFactory;
|
||||||
replaySessions.put(gameId.toString() + userId.toString(), replaySession);
|
|
||||||
UserManager.instance.getUser(userId).ifPresent(user->user.ccReplayGame(gameId));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void replayGame(UUID gameId, UUID userId) {
|
||||||
|
ReplaySession replaySession = new ReplaySession(managerFactory, gameId, userId);
|
||||||
|
replaySessions.put(gameId.toString() + userId.toString(), replaySession);
|
||||||
|
managerFactory.userManager().getUser(userId).ifPresent(user -> user.ccReplayGame(gameId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void startReplay(UUID gameId, UUID userId) {
|
public void startReplay(UUID gameId, UUID userId) {
|
||||||
replaySessions.get(gameId.toString() + userId.toString()).replay();
|
replaySessions.get(gameId.toString() + userId.toString()).replay();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void stopReplay(UUID gameId, UUID userId) {
|
public void stopReplay(UUID gameId, UUID userId) {
|
||||||
replaySessions.get(gameId.toString() + userId.toString()).stop();
|
replaySessions.get(gameId.toString() + userId.toString()).stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void nextPlay(UUID gameId, UUID userId) {
|
public void nextPlay(UUID gameId, UUID userId) {
|
||||||
replaySessions.get(gameId.toString() + userId.toString()).next();
|
replaySessions.get(gameId.toString() + userId.toString()).next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void previousPlay(UUID gameId, UUID userId) {
|
public void previousPlay(UUID gameId, UUID userId) {
|
||||||
replaySessions.get(gameId.toString() + userId.toString()).previous();
|
replaySessions.get(gameId.toString() + userId.toString()).previous();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void skipForward(UUID gameId, UUID userId, int moves) {
|
public void skipForward(UUID gameId, UUID userId, int moves) {
|
||||||
replaySessions.get(gameId.toString() + userId.toString()).next(moves);
|
replaySessions.get(gameId.toString() + userId.toString()).next(moves);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void endReplay(UUID gameId, UUID userId) {
|
public void endReplay(UUID gameId, UUID userId) {
|
||||||
replaySessions.remove(gameId.toString() + userId.toString());
|
replaySessions.remove(gameId.toString() + userId.toString());
|
||||||
}
|
}
|
|
@ -1,32 +1,32 @@
|
||||||
|
|
||||||
|
|
||||||
package mage.server.game;
|
package mage.server.game;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.GameState;
|
import mage.game.GameState;
|
||||||
import mage.interfaces.callback.ClientCallback;
|
import mage.interfaces.callback.ClientCallback;
|
||||||
import mage.interfaces.callback.ClientCallbackMethod;
|
import mage.interfaces.callback.ClientCallbackMethod;
|
||||||
import mage.server.UserManager;
|
import mage.server.managers.ManagerFactory;
|
||||||
import mage.view.GameView;
|
import mage.view.GameView;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
*/
|
*/
|
||||||
public class ReplaySession implements GameCallback {
|
public class ReplaySession implements GameCallback {
|
||||||
|
|
||||||
|
private final ManagerFactory managerFactory;
|
||||||
private final GameReplay replay;
|
private final GameReplay replay;
|
||||||
protected final UUID userId;
|
protected final UUID userId;
|
||||||
|
|
||||||
ReplaySession(UUID gameId, UUID userId) {
|
ReplaySession(ManagerFactory managerFactory, UUID gameId, UUID userId) {
|
||||||
|
this.managerFactory = managerFactory;
|
||||||
this.replay = new GameReplay(gameId);
|
this.replay = new GameReplay(gameId);
|
||||||
this.userId = userId;
|
this.userId = userId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void replay() {
|
public void replay() {
|
||||||
replay.start();
|
replay.start();
|
||||||
UserManager.instance.getUser(userId).ifPresent(user ->
|
managerFactory.userManager().getUser(userId).ifPresent(user ->
|
||||||
user.fireCallback(new ClientCallback(ClientCallbackMethod.REPLAY_INIT, replay.getGame().getId(), new GameView(replay.next(), replay.getGame(), null, null))));
|
user.fireCallback(new ClientCallback(ClientCallbackMethod.REPLAY_INIT, replay.getGame().getId(), new GameView(replay.next(), replay.getGame(), null, null))));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -52,17 +52,17 @@ public class ReplaySession implements GameCallback {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void gameResult(final String result) {
|
public void gameResult(final String result) {
|
||||||
UserManager.instance.getUser(userId).ifPresent(user ->
|
managerFactory.userManager().getUser(userId).ifPresent(user ->
|
||||||
user.fireCallback(new ClientCallback(ClientCallbackMethod.REPLAY_DONE, replay.getGame().getId(), result)));
|
user.fireCallback(new ClientCallback(ClientCallbackMethod.REPLAY_DONE, replay.getGame().getId(), result)));
|
||||||
|
|
||||||
ReplayManager.instance.endReplay(replay.getGame().getId(), userId);
|
managerFactory.replayManager().endReplay(replay.getGame().getId(), userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateGame(final GameState state, Game game) {
|
private void updateGame(final GameState state, Game game) {
|
||||||
if (state == null) {
|
if (state == null) {
|
||||||
gameResult("game ended");
|
gameResult("game ended");
|
||||||
} else {
|
} else {
|
||||||
UserManager.instance.getUser(userId).ifPresent(user ->
|
managerFactory.userManager().getUser(userId).ifPresent(user ->
|
||||||
user.fireCallback(new ClientCallback(ClientCallbackMethod.REPLAY_UPDATE, replay.getGame().getId(), new GameView(state, game, null, null))));
|
user.fireCallback(new ClientCallback(ClientCallbackMethod.REPLAY_UPDATE, replay.getGame().getId(), new GameView(state, game, null, null))));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
package mage.server.managers;
|
||||||
|
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.server.ChatSession;
|
||||||
|
import mage.server.DisconnectReason;
|
||||||
|
import mage.server.exceptions.UserNotFoundException;
|
||||||
|
import mage.view.ChatMessage;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public interface ChatManager {
|
||||||
|
UUID createChatSession(String info);
|
||||||
|
|
||||||
|
void joinChat(UUID chatId, UUID userId);
|
||||||
|
|
||||||
|
void clearUserMessageStorage();
|
||||||
|
|
||||||
|
void leaveChat(UUID chatId, UUID userId);
|
||||||
|
|
||||||
|
void destroyChatSession(UUID chatId);
|
||||||
|
|
||||||
|
void broadcast(UUID chatId, String userName, String message, ChatMessage.MessageColor color, boolean withTime, Game game, ChatMessage.MessageType messageType, ChatMessage.SoundToPlay soundToPlay);
|
||||||
|
|
||||||
|
void broadcast(UUID userId, String message, ChatMessage.MessageColor color) throws UserNotFoundException;
|
||||||
|
|
||||||
|
void sendReconnectMessage(UUID userId);
|
||||||
|
|
||||||
|
void sendLostConnectionMessage(UUID userId, DisconnectReason reason);
|
||||||
|
|
||||||
|
void sendMessageToUserChats(UUID userId, String message);
|
||||||
|
|
||||||
|
void removeUser(UUID userId, DisconnectReason reason);
|
||||||
|
|
||||||
|
List<ChatSession> getChatSessions();
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
package mage.server.managers;
|
||||||
|
|
||||||
|
import mage.server.util.config.GamePlugin;
|
||||||
|
import mage.server.util.config.Plugin;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface ConfigSettings {
|
||||||
|
String getServerAddress();
|
||||||
|
|
||||||
|
String getServerName();
|
||||||
|
|
||||||
|
int getPort();
|
||||||
|
|
||||||
|
int getSecondaryBindPort();
|
||||||
|
|
||||||
|
int getLeasePeriod();
|
||||||
|
|
||||||
|
int getSocketWriteTimeout();
|
||||||
|
|
||||||
|
int getMaxPoolSize();
|
||||||
|
|
||||||
|
int getNumAcceptThreads();
|
||||||
|
|
||||||
|
int getBacklogSize();
|
||||||
|
|
||||||
|
int getMaxGameThreads();
|
||||||
|
|
||||||
|
int getMaxSecondsIdle();
|
||||||
|
|
||||||
|
int getMinUserNameLength();
|
||||||
|
|
||||||
|
int getMaxUserNameLength();
|
||||||
|
|
||||||
|
String getInvalidUserNamePattern();
|
||||||
|
|
||||||
|
int getMinPasswordLength();
|
||||||
|
|
||||||
|
int getMaxPasswordLength();
|
||||||
|
|
||||||
|
String getMaxAiOpponents();
|
||||||
|
|
||||||
|
Boolean isSaveGameActivated();
|
||||||
|
|
||||||
|
Boolean isAuthenticationActivated();
|
||||||
|
|
||||||
|
String getGoogleAccount();
|
||||||
|
|
||||||
|
String getMailgunApiKey();
|
||||||
|
|
||||||
|
String getMailgunDomain();
|
||||||
|
|
||||||
|
String getMailSmtpHost();
|
||||||
|
|
||||||
|
String getMailSmtpPort();
|
||||||
|
|
||||||
|
String getMailUser();
|
||||||
|
|
||||||
|
String getMailPassword();
|
||||||
|
|
||||||
|
String getMailFromAddress();
|
||||||
|
|
||||||
|
List<Plugin> getPlayerTypes();
|
||||||
|
|
||||||
|
List<GamePlugin> getGameTypes();
|
||||||
|
|
||||||
|
List<GamePlugin> getTournamentTypes();
|
||||||
|
|
||||||
|
List<Plugin> getDraftCubes();
|
||||||
|
|
||||||
|
List<Plugin> getDeckTypes();
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package mage.server.managers;
|
||||||
|
|
||||||
|
import mage.game.draft.Draft;
|
||||||
|
import mage.server.draft.DraftController;
|
||||||
|
import mage.view.DraftPickView;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
public interface DraftManager {
|
||||||
|
UUID createDraftSession(Draft draft, ConcurrentHashMap<UUID, UUID> userPlayerMap, UUID tableId);
|
||||||
|
|
||||||
|
void joinDraft(UUID draftId, UUID userId);
|
||||||
|
|
||||||
|
void destroyChatSession(UUID gameId);
|
||||||
|
|
||||||
|
DraftPickView sendCardPick(UUID draftId, UUID userId, UUID cardId, Set<UUID> hiddenCards);
|
||||||
|
|
||||||
|
void sendCardMark(UUID draftId, UUID userId, UUID cardId);
|
||||||
|
|
||||||
|
void removeSession(UUID userId);
|
||||||
|
|
||||||
|
void kill(UUID draftId, UUID userId);
|
||||||
|
|
||||||
|
void timeout(UUID gameId, UUID userId);
|
||||||
|
|
||||||
|
void removeDraft(UUID draftId);
|
||||||
|
|
||||||
|
DraftController getControllerByDraftId(UUID draftId);
|
||||||
|
|
||||||
|
Optional<DraftController> getController(UUID tableId);
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
package mage.server.managers;
|
||||||
|
|
||||||
|
import mage.cards.decks.DeckCardLists;
|
||||||
|
import mage.constants.ManaType;
|
||||||
|
import mage.constants.PlayerAction;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.GameOptions;
|
||||||
|
import mage.server.game.GameController;
|
||||||
|
import mage.view.GameView;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
public interface GameManager {
|
||||||
|
UUID createGameSession(Game game, ConcurrentHashMap<UUID, UUID> userPlayerMap, UUID tableId, UUID choosingPlayerId, GameOptions gameOptions);
|
||||||
|
|
||||||
|
void joinGame(UUID gameId, UUID userId);
|
||||||
|
|
||||||
|
Optional<UUID> getChatId(UUID gameId);
|
||||||
|
|
||||||
|
void sendPlayerUUID(UUID gameId, UUID userId, UUID data);
|
||||||
|
|
||||||
|
void sendPlayerString(UUID gameId, UUID userId, String data);
|
||||||
|
|
||||||
|
void sendPlayerManaType(UUID gameId, UUID playerId, UUID userId, ManaType data);
|
||||||
|
|
||||||
|
void sendPlayerBoolean(UUID gameId, UUID userId, Boolean data);
|
||||||
|
|
||||||
|
void sendPlayerInteger(UUID gameId, UUID userId, Integer data);
|
||||||
|
|
||||||
|
void quitMatch(UUID gameId, UUID userId);
|
||||||
|
|
||||||
|
void sendPlayerAction(PlayerAction playerAction, UUID gameId, UUID userId, Object data);
|
||||||
|
|
||||||
|
boolean watchGame(UUID gameId, UUID userId);
|
||||||
|
|
||||||
|
void stopWatching(UUID gameId, UUID userId);
|
||||||
|
|
||||||
|
void cheat(UUID gameId, UUID userId, UUID playerId, DeckCardLists deckList);
|
||||||
|
|
||||||
|
boolean cheat(UUID gameId, UUID userId, UUID playerId, String cardName);
|
||||||
|
|
||||||
|
void removeGame(UUID gameId);
|
||||||
|
|
||||||
|
boolean saveGame(UUID gameId);
|
||||||
|
|
||||||
|
GameView getGameView(UUID gameId, UUID playerId);
|
||||||
|
|
||||||
|
int getNumberActiveGames();
|
||||||
|
|
||||||
|
Map<UUID, GameController> getGameController();
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package mage.server.managers;
|
||||||
|
|
||||||
|
import mage.server.game.GamesRoom;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public interface GamesRoomManager {
|
||||||
|
UUID createRoom();
|
||||||
|
|
||||||
|
UUID getMainRoomId();
|
||||||
|
|
||||||
|
UUID getMainChatId();
|
||||||
|
|
||||||
|
Optional<GamesRoom> getRoom(UUID roomId);
|
||||||
|
|
||||||
|
void removeTable(UUID tableId);
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package mage.server.managers;
|
||||||
|
|
||||||
|
public interface MailClient {
|
||||||
|
|
||||||
|
boolean sendMessage(String email, String subject, String text);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package mage.server.managers;
|
||||||
|
|
||||||
|
public interface ManagerFactory {
|
||||||
|
ChatManager chatManager();
|
||||||
|
|
||||||
|
DraftManager draftManager();
|
||||||
|
|
||||||
|
GameManager gameManager();
|
||||||
|
|
||||||
|
GamesRoomManager gamesRoomManager();
|
||||||
|
|
||||||
|
MailClient mailClient();
|
||||||
|
|
||||||
|
MailClient mailgunClient();
|
||||||
|
|
||||||
|
ReplayManager replayManager();
|
||||||
|
|
||||||
|
SessionManager sessionManager();
|
||||||
|
|
||||||
|
TableManager tableManager();
|
||||||
|
|
||||||
|
UserManager userManager();
|
||||||
|
|
||||||
|
ConfigSettings configSettings();
|
||||||
|
|
||||||
|
ThreadExecutor threadExecutor();
|
||||||
|
|
||||||
|
TournamentManager tournamentManager();
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package mage.server.managers;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public interface ReplayManager {
|
||||||
|
void replayGame(UUID gameId, UUID userId);
|
||||||
|
|
||||||
|
void startReplay(UUID gameId, UUID userId);
|
||||||
|
|
||||||
|
void stopReplay(UUID gameId, UUID userId);
|
||||||
|
|
||||||
|
void nextPlay(UUID gameId, UUID userId);
|
||||||
|
|
||||||
|
void previousPlay(UUID gameId, UUID userId);
|
||||||
|
|
||||||
|
void skipForward(UUID gameId, UUID userId, int moves);
|
||||||
|
|
||||||
|
void endReplay(UUID gameId, UUID userId);
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package mage.server.managers;
|
||||||
|
|
||||||
|
import mage.MageException;
|
||||||
|
import mage.players.net.UserData;
|
||||||
|
import mage.server.DisconnectReason;
|
||||||
|
import mage.server.Session;
|
||||||
|
import mage.server.User;
|
||||||
|
import org.jboss.remoting.callback.InvokerCallbackHandler;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public interface SessionManager {
|
||||||
|
Optional<Session> getSession(@Nonnull String sessionId);
|
||||||
|
|
||||||
|
void createSession(String sessionId, InvokerCallbackHandler callbackHandler);
|
||||||
|
|
||||||
|
boolean registerUser(String sessionId, String userName, String password, String email) throws MageException;
|
||||||
|
|
||||||
|
boolean connectUser(String sessionId, String userName, String password, String userIdStr) throws MageException;
|
||||||
|
|
||||||
|
boolean connectAdmin(String sessionId);
|
||||||
|
|
||||||
|
boolean setUserData(String userName, String sessionId, UserData userData, String clientVersion, String userIdStr) throws MageException;
|
||||||
|
|
||||||
|
void disconnect(String sessionId, DisconnectReason reason);
|
||||||
|
|
||||||
|
void disconnect(String sessionId, DisconnectReason reason, Session directSession);
|
||||||
|
|
||||||
|
void disconnectUser(String sessionId, String userSessionId);
|
||||||
|
|
||||||
|
void endUserSession(String sessionId, String userSessionId);
|
||||||
|
|
||||||
|
boolean isAdmin(String sessionId);
|
||||||
|
|
||||||
|
boolean isValidSession(@Nonnull String sessionId);
|
||||||
|
|
||||||
|
Optional<User> getUser(@Nonnull String sessionId);
|
||||||
|
|
||||||
|
boolean extendUserSession(String sessionId, String pingInfo);
|
||||||
|
|
||||||
|
void sendErrorMessageToClient(String sessionId, String message);
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
package mage.server.managers;
|
||||||
|
|
||||||
|
import mage.MageException;
|
||||||
|
import mage.cards.decks.DeckCardLists;
|
||||||
|
import mage.game.GameException;
|
||||||
|
import mage.game.Table;
|
||||||
|
import mage.game.draft.Draft;
|
||||||
|
import mage.game.match.Match;
|
||||||
|
import mage.game.match.MatchOptions;
|
||||||
|
import mage.game.tournament.Tournament;
|
||||||
|
import mage.game.tournament.TournamentOptions;
|
||||||
|
import mage.game.tournament.TournamentPlayer;
|
||||||
|
import mage.players.PlayerType;
|
||||||
|
import mage.server.TableController;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public interface TableManager {
|
||||||
|
Table createTable(UUID roomId, UUID userId, MatchOptions options);
|
||||||
|
|
||||||
|
Table createTable(UUID roomId, MatchOptions options);
|
||||||
|
|
||||||
|
Table createTournamentTable(UUID roomId, UUID userId, TournamentOptions options);
|
||||||
|
|
||||||
|
Table getTable(UUID tableId);
|
||||||
|
|
||||||
|
Optional<Match> getMatch(UUID tableId);
|
||||||
|
|
||||||
|
Collection<Table> getTables();
|
||||||
|
|
||||||
|
Collection<TableController> getControllers();
|
||||||
|
|
||||||
|
Optional<TableController> getController(UUID tableId);
|
||||||
|
|
||||||
|
boolean joinTable(UUID userId, UUID tableId, String name, PlayerType playerType, int skill, DeckCardLists deckList, String password) throws MageException;
|
||||||
|
|
||||||
|
boolean joinTournament(UUID userId, UUID tableId, String name, PlayerType playerType, int skill, DeckCardLists deckList, String password) throws GameException;
|
||||||
|
|
||||||
|
boolean submitDeck(UUID userId, UUID tableId, DeckCardLists deckList) throws MageException;
|
||||||
|
|
||||||
|
void updateDeck(UUID userId, UUID tableId, DeckCardLists deckList) throws MageException;
|
||||||
|
|
||||||
|
// removeUserFromAllTablesAndChat user from all tournament sub tables
|
||||||
|
void userQuitTournamentSubTables(UUID userId);
|
||||||
|
|
||||||
|
// removeUserFromAllTablesAndChat user from all sub tables of a tournament
|
||||||
|
void userQuitTournamentSubTables(UUID tournamentId, UUID userId);
|
||||||
|
|
||||||
|
boolean isTableOwner(UUID tableId, UUID userId);
|
||||||
|
|
||||||
|
boolean removeTable(UUID userId, UUID tableId);
|
||||||
|
|
||||||
|
void leaveTable(UUID userId, UUID tableId);
|
||||||
|
|
||||||
|
Optional<UUID> getChatId(UUID tableId);
|
||||||
|
|
||||||
|
void startMatch(UUID userId, UUID roomId, UUID tableId);
|
||||||
|
|
||||||
|
void startTournamentSubMatch(UUID roomId, UUID tableId);
|
||||||
|
|
||||||
|
void startTournament(UUID userId, UUID roomId, UUID tableId);
|
||||||
|
|
||||||
|
void startDraft(UUID tableId, Draft draft);
|
||||||
|
|
||||||
|
boolean watchTable(UUID userId, UUID tableId);
|
||||||
|
|
||||||
|
void endGame(UUID tableId);
|
||||||
|
|
||||||
|
void endDraft(UUID tableId, Draft draft);
|
||||||
|
|
||||||
|
void endTournament(UUID tableId, Tournament tournament);
|
||||||
|
|
||||||
|
void swapSeats(UUID tableId, UUID userId, int seatNum1, int seatNum2);
|
||||||
|
|
||||||
|
void construct(UUID tableId);
|
||||||
|
|
||||||
|
void initTournament(UUID tableId);
|
||||||
|
|
||||||
|
void addPlayer(UUID userId, UUID tableId, TournamentPlayer player) throws GameException;
|
||||||
|
|
||||||
|
void removeTable(UUID tableId);
|
||||||
|
|
||||||
|
void debugServerState();
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package mage.server.managers;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
|
||||||
|
public interface ThreadExecutor {
|
||||||
|
int getActiveThreads(ExecutorService executerService);
|
||||||
|
|
||||||
|
ExecutorService getCallExecutor();
|
||||||
|
|
||||||
|
ExecutorService getGameExecutor();
|
||||||
|
|
||||||
|
ScheduledExecutorService getTimeoutExecutor();
|
||||||
|
|
||||||
|
ScheduledExecutorService getTimeoutIdleExecutor();
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package mage.server.managers;
|
||||||
|
|
||||||
|
import mage.cards.decks.Deck;
|
||||||
|
import mage.game.tournament.Tournament;
|
||||||
|
import mage.server.tournament.TournamentController;
|
||||||
|
import mage.view.TournamentView;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
public interface TournamentManager {
|
||||||
|
Optional<TournamentController> getTournamentController(UUID tournamentId);
|
||||||
|
|
||||||
|
void createTournamentSession(Tournament tournament, ConcurrentHashMap<UUID, UUID> userPlayerMap, UUID tableId);
|
||||||
|
|
||||||
|
void joinTournament(UUID tournamentId, UUID userId);
|
||||||
|
|
||||||
|
void quit(UUID tournamentId, UUID userId);
|
||||||
|
|
||||||
|
void timeout(UUID tournamentId, UUID userId);
|
||||||
|
|
||||||
|
void submitDeck(UUID tournamentId, UUID playerId, Deck deck);
|
||||||
|
|
||||||
|
boolean updateDeck(UUID tournamentId, UUID playerId, Deck deck);
|
||||||
|
|
||||||
|
TournamentView getTournamentView(UUID tournamentId);
|
||||||
|
|
||||||
|
Optional<UUID> getChatId(UUID tournamentId);
|
||||||
|
|
||||||
|
void removeTournament(UUID tournamentId);
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
package mage.server.managers;
|
||||||
|
|
||||||
|
import mage.server.AuthorizedUser;
|
||||||
|
import mage.server.DisconnectReason;
|
||||||
|
import mage.server.User;
|
||||||
|
import mage.view.UserView;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public interface UserManager {
|
||||||
|
Optional<User> createUser(String userName, String host, AuthorizedUser authorizedUser);
|
||||||
|
|
||||||
|
Optional<User> getUser(UUID userId);
|
||||||
|
|
||||||
|
Optional<User> getUserByName(String userName);
|
||||||
|
|
||||||
|
Collection<User> getUsers();
|
||||||
|
|
||||||
|
boolean connectToSession(String sessionId, UUID userId);
|
||||||
|
|
||||||
|
void disconnect(UUID userId, DisconnectReason reason);
|
||||||
|
|
||||||
|
boolean isAdmin(UUID userId);
|
||||||
|
|
||||||
|
void removeUserFromAllTablesAndChat(UUID userId, DisconnectReason reason);
|
||||||
|
|
||||||
|
void informUserOpponents(UUID userId, String message);
|
||||||
|
|
||||||
|
boolean extendUserSession(UUID userId, String pingInfo);
|
||||||
|
|
||||||
|
List<UserView> getUserInfoList();
|
||||||
|
|
||||||
|
void handleException(Exception ex);
|
||||||
|
|
||||||
|
String getUserHistory(String userName);
|
||||||
|
|
||||||
|
void updateUserHistory();
|
||||||
|
}
|
|
@ -3,16 +3,20 @@ package mage.server.record;
|
||||||
import mage.game.Table;
|
import mage.game.Table;
|
||||||
import mage.game.Table.TableRecorder;
|
import mage.game.Table.TableRecorder;
|
||||||
import mage.game.result.ResultProtos.TableProto;
|
import mage.game.result.ResultProtos.TableProto;
|
||||||
import mage.server.UserManager;
|
import mage.server.managers.UserManager;
|
||||||
|
|
||||||
public enum TableRecorderImpl implements TableRecorder {
|
public class TableRecorderImpl implements TableRecorder {
|
||||||
|
|
||||||
instance;
|
private final UserManager userManager;
|
||||||
|
|
||||||
|
public TableRecorderImpl(UserManager userManager) {
|
||||||
|
this.userManager = userManager;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void record(Table table) {
|
public void record(Table table) {
|
||||||
TableProto proto = table.toProto();
|
TableProto proto = table.toProto();
|
||||||
TableRecordRepository.instance.add(new TableRecord(proto, proto.getEndTimeMs()));
|
TableRecordRepository.instance.add(new TableRecord(proto, proto.getEndTimeMs()));
|
||||||
UserManager.instance.updateUserHistory();
|
userManager.updateUserHistory();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,14 +17,10 @@ import mage.game.tournament.Tournament;
|
||||||
import mage.game.tournament.TournamentPairing;
|
import mage.game.tournament.TournamentPairing;
|
||||||
import mage.game.tournament.TournamentPlayer;
|
import mage.game.tournament.TournamentPlayer;
|
||||||
import mage.players.PlayerType;
|
import mage.players.PlayerType;
|
||||||
import mage.server.ChatManager;
|
|
||||||
import mage.server.TableManager;
|
|
||||||
import mage.server.User;
|
import mage.server.User;
|
||||||
import mage.server.UserManager;
|
|
||||||
import mage.server.draft.DraftController;
|
import mage.server.draft.DraftController;
|
||||||
import mage.server.draft.DraftManager;
|
import mage.server.managers.TableManager;
|
||||||
import mage.server.game.GamesRoomManager;
|
import mage.server.managers.ManagerFactory;
|
||||||
import mage.server.util.ThreadExecutor;
|
|
||||||
import mage.view.ChatMessage.MessageColor;
|
import mage.view.ChatMessage.MessageColor;
|
||||||
import mage.view.ChatMessage.MessageType;
|
import mage.view.ChatMessage.MessageType;
|
||||||
import mage.view.ChatMessage.SoundToPlay;
|
import mage.view.ChatMessage.SoundToPlay;
|
||||||
|
@ -44,6 +40,7 @@ public class TournamentController {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(TournamentController.class);
|
private static final Logger logger = Logger.getLogger(TournamentController.class);
|
||||||
|
|
||||||
|
private final ManagerFactory managerFactory;
|
||||||
private final UUID chatId;
|
private final UUID chatId;
|
||||||
private final UUID tableId;
|
private final UUID tableId;
|
||||||
private boolean started = false;
|
private boolean started = false;
|
||||||
|
@ -51,9 +48,10 @@ public class TournamentController {
|
||||||
private ConcurrentMap<UUID, UUID> userPlayerMap = new ConcurrentHashMap<>();
|
private ConcurrentMap<UUID, UUID> userPlayerMap = new ConcurrentHashMap<>();
|
||||||
private final ConcurrentMap<UUID, TournamentSession> tournamentSessions = new ConcurrentHashMap<>();
|
private final ConcurrentMap<UUID, TournamentSession> tournamentSessions = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public TournamentController(Tournament tournament, ConcurrentMap<UUID, UUID> userPlayerMap, UUID tableId) {
|
public TournamentController(ManagerFactory managerFactory, Tournament tournament, ConcurrentMap<UUID, UUID> userPlayerMap, UUID tableId) {
|
||||||
|
this.managerFactory = managerFactory;
|
||||||
this.userPlayerMap = userPlayerMap;
|
this.userPlayerMap = userPlayerMap;
|
||||||
chatId = ChatManager.instance.createChatSession("Tournament " + tournament.getId());
|
chatId = managerFactory.chatManager().createChatSession("Tournament " + tournament.getId());
|
||||||
this.tournament = tournament;
|
this.tournament = tournament;
|
||||||
this.tableId = tableId;
|
this.tableId = tableId;
|
||||||
init();
|
init();
|
||||||
|
@ -67,7 +65,7 @@ public class TournamentController {
|
||||||
checkPlayersState();
|
checkPlayersState();
|
||||||
break;
|
break;
|
||||||
case INFO:
|
case INFO:
|
||||||
ChatManager.instance.broadcast(chatId, "", event.getMessage(), MessageColor.BLACK, true, null, MessageType.STATUS, null);
|
managerFactory.chatManager().broadcast(chatId, "", event.getMessage(), MessageColor.BLACK, true, null, MessageType.STATUS, null);
|
||||||
logger.debug(tournament.getId() + " " + event.getMessage());
|
logger.debug(tournament.getId() + " " + event.getMessage());
|
||||||
break;
|
break;
|
||||||
case START_DRAFT:
|
case START_DRAFT:
|
||||||
|
@ -122,7 +120,7 @@ public class TournamentController {
|
||||||
if (!player.getPlayer().isHuman()) {
|
if (!player.getPlayer().isHuman()) {
|
||||||
player.setJoined();
|
player.setJoined();
|
||||||
logger.debug("player " + player.getPlayer().getId() + " has joined tournament " + tournament.getId());
|
logger.debug("player " + player.getPlayer().getId() + " has joined tournament " + tournament.getId());
|
||||||
ChatManager.instance.broadcast(chatId, "", player.getPlayer().getLogName() + " has joined the tournament", MessageColor.BLACK, true, null, MessageType.STATUS, null);
|
managerFactory.chatManager().broadcast(chatId, "", player.getPlayer().getLogName() + " has joined the tournament", MessageColor.BLACK, true, null, MessageType.STATUS, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
checkStart();
|
checkStart();
|
||||||
|
@ -132,7 +130,7 @@ public class TournamentController {
|
||||||
UUID playerId = userPlayerMap.get(userId);
|
UUID playerId = userPlayerMap.get(userId);
|
||||||
if (playerId == null) {
|
if (playerId == null) {
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
UserManager.instance.getUser(userId).ifPresent(user
|
managerFactory.userManager().getUser(userId).ifPresent(user
|
||||||
-> logger.debug(user.getName() + " shows tournament panel tournamentId: " + tournament.getId()));
|
-> logger.debug(user.getName() + " shows tournament panel tournamentId: " + tournament.getId()));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -143,16 +141,16 @@ public class TournamentController {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// first join of player
|
// first join of player
|
||||||
TournamentSession tournamentSession = new TournamentSession(tournament, userId, tableId, playerId);
|
TournamentSession tournamentSession = new TournamentSession(managerFactory, tournament, userId, tableId, playerId);
|
||||||
tournamentSessions.put(playerId, tournamentSession);
|
tournamentSessions.put(playerId, tournamentSession);
|
||||||
Optional<User> _user = UserManager.instance.getUser(userId);
|
Optional<User> _user = managerFactory.userManager().getUser(userId);
|
||||||
if (_user.isPresent()) {
|
if (_user.isPresent()) {
|
||||||
User user = _user.get();
|
User user = _user.get();
|
||||||
user.addTournament(playerId, tournament.getId());
|
user.addTournament(playerId, tournament.getId());
|
||||||
TournamentPlayer player = tournament.getPlayer(playerId);
|
TournamentPlayer player = tournament.getPlayer(playerId);
|
||||||
player.setJoined();
|
player.setJoined();
|
||||||
logger.debug("player " + player.getPlayer().getName() + " - client has joined tournament " + tournament.getId());
|
logger.debug("player " + player.getPlayer().getName() + " - client has joined tournament " + tournament.getId());
|
||||||
ChatManager.instance.broadcast(chatId, "", player.getPlayer().getLogName() + " has joined the tournament", MessageColor.BLACK, true, null, MessageType.STATUS, null);
|
managerFactory.chatManager().broadcast(chatId, "", player.getPlayer().getLogName() + " has joined the tournament", MessageColor.BLACK, true, null, MessageType.STATUS, null);
|
||||||
checkStart();
|
checkStart();
|
||||||
} else {
|
} else {
|
||||||
logger.error("User not found userId: " + userId + " tournamentId: " + tournament.getId());
|
logger.error("User not found userId: " + userId + " tournamentId: " + tournament.getId());
|
||||||
|
@ -174,7 +172,7 @@ public class TournamentController {
|
||||||
|
|
||||||
private void checkStart() {
|
private void checkStart() {
|
||||||
if (!started && allJoined()) {
|
if (!started && allJoined()) {
|
||||||
ThreadExecutor.instance.getCallExecutor().execute(this::startTournament);
|
managerFactory.threadExecutor().getCallExecutor().execute(this::startTournament);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,15 +209,15 @@ public class TournamentController {
|
||||||
tournamentSession.tournamentOver();
|
tournamentSession.tournamentOver();
|
||||||
}
|
}
|
||||||
this.tournamentSessions.clear();
|
this.tournamentSessions.clear();
|
||||||
TableManager.instance.endTournament(tableId, tournament);
|
managerFactory.tableManager().endTournament(tableId, tournament);
|
||||||
tournament.cleanUpOnTournamentEnd();
|
tournament.cleanUpOnTournamentEnd();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startMatch(TournamentPairing pair, MatchOptions matchOptions) {
|
private void startMatch(TournamentPairing pair, MatchOptions matchOptions) {
|
||||||
try {
|
try {
|
||||||
TableManager tableManager = TableManager.instance;
|
TableManager tableManager = managerFactory.tableManager();
|
||||||
Table table = tableManager.createTable(GamesRoomManager.instance.getMainRoomId(), matchOptions);
|
Table table = tableManager.createTable(managerFactory.gamesRoomManager().getMainRoomId(), matchOptions);
|
||||||
table.setTournamentSubTable(true);
|
table.setTournamentSubTable(true);
|
||||||
table.setTournament(tournament);
|
table.setTournament(tournament);
|
||||||
table.setState(TableState.WAITING);
|
table.setState(TableState.WAITING);
|
||||||
|
@ -261,8 +259,8 @@ public class TournamentController {
|
||||||
|
|
||||||
private void startMultiplayerMatch(MultiplayerRound round, MatchOptions matchOptions) {
|
private void startMultiplayerMatch(MultiplayerRound round, MatchOptions matchOptions) {
|
||||||
try {
|
try {
|
||||||
TableManager tableManager = TableManager.instance;
|
TableManager tableManager = managerFactory.tableManager();
|
||||||
Table table = tableManager.createTable(GamesRoomManager.instance.getMainRoomId(), matchOptions);
|
Table table = tableManager.createTable(managerFactory.gamesRoomManager().getMainRoomId(), matchOptions);
|
||||||
table.setTournamentSubTable(true);
|
table.setTournamentSubTable(true);
|
||||||
table.setTournament(tournament);
|
table.setTournament(tournament);
|
||||||
table.setState(TableState.WAITING);
|
table.setState(TableState.WAITING);
|
||||||
|
@ -287,16 +285,16 @@ public class TournamentController {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startDraft(Draft draft) {
|
private void startDraft(Draft draft) {
|
||||||
TableManager.instance.startDraft(tableId, draft);
|
managerFactory.tableManager().startDraft(tableId, draft);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void construct() {
|
private void construct() {
|
||||||
TableManager.instance.construct(tableId);
|
managerFactory.tableManager().construct(tableId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initTournament() {
|
private void initTournament() {
|
||||||
if (TableManager.instance.getTable(tableId).getState() != TableState.DUELING) {
|
if (managerFactory.tableManager().getTable(tableId).getState() != TableState.DUELING) {
|
||||||
TableManager.instance.initTournament(tableId);
|
managerFactory.tableManager().initTournament(tableId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,7 +303,7 @@ public class TournamentController {
|
||||||
TournamentSession tournamentSession = tournamentSessions.get(playerId);
|
TournamentSession tournamentSession = tournamentSessions.get(playerId);
|
||||||
tournamentSession.construct(timeout);
|
tournamentSession.construct(timeout);
|
||||||
getPlayerUserId(playerId).ifPresent(userId -> {
|
getPlayerUserId(playerId).ifPresent(userId -> {
|
||||||
UserManager.instance.getUser(userId).ifPresent(user -> {
|
managerFactory.userManager().getUser(userId).ifPresent(user -> {
|
||||||
user.addConstructing(playerId, tournamentSession);
|
user.addConstructing(playerId, tournamentSession);
|
||||||
TournamentPlayer player = tournament.getPlayer(playerId);
|
TournamentPlayer player = tournament.getPlayer(playerId);
|
||||||
player.setState(TournamentPlayerState.CONSTRUCTING);
|
player.setState(TournamentPlayerState.CONSTRUCTING);
|
||||||
|
@ -319,7 +317,7 @@ public class TournamentController {
|
||||||
TournamentPlayer player = tournament.getPlayer(playerId);
|
TournamentPlayer player = tournament.getPlayer(playerId);
|
||||||
if (player != null && !player.hasQuit()) {
|
if (player != null && !player.hasQuit()) {
|
||||||
tournamentSessions.get(playerId).submitDeck(deck);
|
tournamentSessions.get(playerId).submitDeck(deck);
|
||||||
ChatManager.instance.broadcast(chatId, "", player.getPlayer().getLogName() + " has submitted their tournament deck", MessageColor.BLACK, true, null, MessageType.STATUS, SoundToPlay.PlayerSubmittedDeck);
|
managerFactory.chatManager().broadcast(chatId, "", player.getPlayer().getLogName() + " has submitted their tournament deck", MessageColor.BLACK, true, null, MessageType.STATUS, SoundToPlay.PlayerSubmittedDeck);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -338,7 +336,7 @@ public class TournamentController {
|
||||||
tournament.autoSubmit(userPlayerMap.get(userId), tournamentPlayer.generateDeck());
|
tournament.autoSubmit(userPlayerMap.get(userId), tournamentPlayer.generateDeck());
|
||||||
} else {
|
} else {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
UserManager.instance.getUser(userId).ifPresent(user
|
managerFactory.userManager().getUser(userId).ifPresent(user
|
||||||
-> sb.append(user.getName()));
|
-> sb.append(user.getName()));
|
||||||
|
|
||||||
sb.append(" - no deck found for auto submit");
|
sb.append(" - no deck found for auto submit");
|
||||||
|
@ -380,16 +378,16 @@ public class TournamentController {
|
||||||
if (tournament.isDoneConstructing()) {
|
if (tournament.isDoneConstructing()) {
|
||||||
info = new StringBuilder("during round ").append(tournament.getRounds().size()).toString();
|
info = new StringBuilder("during round ").append(tournament.getRounds().size()).toString();
|
||||||
// quit active matches of that tournament
|
// quit active matches of that tournament
|
||||||
TableManager.instance.userQuitTournamentSubTables(tournament.getId(), userId);
|
managerFactory.tableManager().userQuitTournamentSubTables(tournament.getId(), userId);
|
||||||
status = TourneyQuitStatus.DURING_ROUND;
|
status = TourneyQuitStatus.DURING_ROUND;
|
||||||
} else if (tournamentPlayer.getState() == TournamentPlayerState.DRAFTING) {
|
} else if (tournamentPlayer.getState() == TournamentPlayerState.DRAFTING) {
|
||||||
info = "during Draft phase";
|
info = "during Draft phase";
|
||||||
if (!checkToReplaceDraftPlayerByAi(userId, tournamentPlayer)) {
|
if (!checkToReplaceDraftPlayerByAi(userId, tournamentPlayer)) {
|
||||||
this.abortDraftTournament();
|
this.abortDraftTournament();
|
||||||
} else {
|
} else {
|
||||||
DraftManager.instance.getController(tableId).ifPresent(draftController -> {
|
managerFactory.draftManager().getController(tableId).ifPresent(draftController -> {
|
||||||
draftController.getDraftSession(playerId).ifPresent(draftSession
|
draftController.getDraftSession(playerId).ifPresent(draftSession
|
||||||
-> DraftManager.instance.kill(draftSession.getDraftId(), userId));
|
-> managerFactory.draftManager().kill(draftSession.getDraftId(), userId));
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -404,7 +402,7 @@ public class TournamentController {
|
||||||
tournamentPlayer.setQuit(info, status);
|
tournamentPlayer.setQuit(info, status);
|
||||||
tournament.quit(playerId);
|
tournament.quit(playerId);
|
||||||
tournamentSession.quit();
|
tournamentSession.quit();
|
||||||
ChatManager.instance.broadcast(chatId, "", tournamentPlayer.getPlayer().getLogName() + " has quit the tournament", MessageColor.BLACK, true, null, MessageType.STATUS, SoundToPlay.PlayerQuitTournament);
|
managerFactory.chatManager().broadcast(chatId, "", tournamentPlayer.getPlayer().getLogName() + " has quit the tournament", MessageColor.BLACK, true, null, MessageType.STATUS, SoundToPlay.PlayerQuitTournament);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -417,8 +415,8 @@ public class TournamentController {
|
||||||
}
|
}
|
||||||
// replace player that quits with draft bot
|
// replace player that quits with draft bot
|
||||||
if (humans > 1) {
|
if (humans > 1) {
|
||||||
Optional<User> user = UserManager.instance.getUser(userId);
|
Optional<User> user = managerFactory.userManager().getUser(userId);
|
||||||
TableManager.instance.getController(tableId).ifPresent(tableController -> {
|
managerFactory.tableManager().getController(tableId).ifPresent(tableController -> {
|
||||||
|
|
||||||
String replacePlayerName = "Draftbot";
|
String replacePlayerName = "Draftbot";
|
||||||
if (user.isPresent()) {
|
if (user.isPresent()) {
|
||||||
|
@ -430,7 +428,7 @@ public class TournamentController {
|
||||||
user.get().removeTable(leavingPlayer.getPlayer().getId());
|
user.get().removeTable(leavingPlayer.getPlayer().getId());
|
||||||
user.get().removeTournament(leavingPlayer.getPlayer().getId());
|
user.get().removeTournament(leavingPlayer.getPlayer().getId());
|
||||||
}
|
}
|
||||||
ChatManager.instance.broadcast(chatId, "", leavingPlayer.getPlayer().getLogName() + " was replaced by draftbot", MessageColor.BLACK, true, null, MessageType.STATUS, null);
|
managerFactory.chatManager().broadcast(chatId, "", leavingPlayer.getPlayer().getLogName() + " was replaced by draftbot", MessageColor.BLACK, true, null, MessageType.STATUS, null);
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -447,7 +445,7 @@ public class TournamentController {
|
||||||
|
|
||||||
private void abortDraftTournament() {
|
private void abortDraftTournament() {
|
||||||
tournament.setAbort(true);
|
tournament.setAbort(true);
|
||||||
DraftManager.instance.getController(tableId).ifPresent(DraftController::abortDraft);
|
managerFactory.draftManager().getController(tableId).ifPresent(DraftController::abortDraft);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAbort() {
|
public boolean isAbort() {
|
||||||
|
@ -472,7 +470,7 @@ public class TournamentController {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cleanUpOnRemoveTournament() {
|
public void cleanUpOnRemoveTournament() {
|
||||||
ChatManager.instance.destroyChatSession(chatId);
|
managerFactory.chatManager().destroyChatSession(chatId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -490,7 +488,7 @@ public class TournamentController {
|
||||||
if (tournamentPlayer != null) {
|
if (tournamentPlayer != null) {
|
||||||
if (!tournamentPlayer.hasQuit()) {
|
if (!tournamentPlayer.hasQuit()) {
|
||||||
if (tournamentPlayer.getPlayer().isHuman()) {
|
if (tournamentPlayer.getPlayer().isHuman()) {
|
||||||
Optional<User> user = UserManager.instance.getUser(entry.getKey());
|
Optional<User> user = managerFactory.userManager().getUser(entry.getKey());
|
||||||
if (!user.isPresent()) {
|
if (!user.isPresent()) {
|
||||||
logger.debug("Tournament user is missing but player active -> start quit - tournamentId: " + tournament.getId() + " state: " + tableState.toString());
|
logger.debug("Tournament user is missing but player active -> start quit - tournamentId: " + tournament.getId() + " state: " + tableState.toString());
|
||||||
// active tournament player but the user is no longer online
|
// active tournament player but the user is no longer online
|
||||||
|
|
|
@ -1,57 +1,71 @@
|
||||||
|
|
||||||
package mage.server.tournament;
|
package mage.server.tournament;
|
||||||
|
|
||||||
|
import mage.cards.decks.Deck;
|
||||||
|
import mage.game.tournament.Tournament;
|
||||||
|
import mage.server.managers.TournamentManager;
|
||||||
|
import mage.server.managers.ManagerFactory;
|
||||||
|
import mage.view.TournamentView;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
import mage.cards.decks.Deck;
|
|
||||||
import mage.game.tournament.Tournament;
|
|
||||||
import mage.view.TournamentView;
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
*/
|
*/
|
||||||
public enum TournamentManager {
|
public class TournamentManagerImpl implements TournamentManager {
|
||||||
instance;
|
|
||||||
|
private final ManagerFactory managerFactory;
|
||||||
private final ConcurrentMap<UUID, TournamentController> controllers = new ConcurrentHashMap<>();
|
private final ConcurrentMap<UUID, TournamentController> controllers = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
public TournamentManagerImpl(ManagerFactory managerFactory) {
|
||||||
|
this.managerFactory = managerFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Optional<TournamentController> getTournamentController(UUID tournamentId) {
|
public Optional<TournamentController> getTournamentController(UUID tournamentId) {
|
||||||
return Optional.ofNullable(controllers.get(tournamentId));
|
return Optional.ofNullable(controllers.get(tournamentId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void createTournamentSession(Tournament tournament, ConcurrentHashMap<UUID, UUID> userPlayerMap, UUID tableId) {
|
public void createTournamentSession(Tournament tournament, ConcurrentHashMap<UUID, UUID> userPlayerMap, UUID tableId) {
|
||||||
TournamentController tournamentController = new TournamentController(tournament, userPlayerMap, tableId);
|
TournamentController tournamentController = new TournamentController(managerFactory, tournament, userPlayerMap, tableId);
|
||||||
controllers.put(tournament.getId(), tournamentController);
|
controllers.put(tournament.getId(), tournamentController);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void joinTournament(UUID tournamentId, UUID userId) {
|
public void joinTournament(UUID tournamentId, UUID userId) {
|
||||||
controllers.get(tournamentId).join(userId);
|
controllers.get(tournamentId).join(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void quit(UUID tournamentId, UUID userId) {
|
public void quit(UUID tournamentId, UUID userId) {
|
||||||
TournamentController tournamentController = controllers.get(tournamentId);
|
TournamentController tournamentController = controllers.get(tournamentId);
|
||||||
if (tournamentController != null) {
|
if (tournamentController != null) {
|
||||||
tournamentController.quit(userId);
|
tournamentController.quit(userId);
|
||||||
} else {
|
} else {
|
||||||
Logger.getLogger(TournamentManager.class).error("Tournament controller missing tournamentid: " + tournamentId + " userId: " + userId);
|
Logger.getLogger(TournamentManagerImpl.class).error("Tournament controller missing tournamentid: " + tournamentId + " userId: " + userId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void timeout(UUID tournamentId, UUID userId) {
|
public void timeout(UUID tournamentId, UUID userId) {
|
||||||
controllers.get(tournamentId).timeout(userId);
|
controllers.get(tournamentId).timeout(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void submitDeck(UUID tournamentId, UUID playerId, Deck deck) {
|
public void submitDeck(UUID tournamentId, UUID playerId, Deck deck) {
|
||||||
controllers.get(tournamentId).submitDeck(playerId, deck);
|
controllers.get(tournamentId).submitDeck(playerId, deck);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean updateDeck(UUID tournamentId, UUID playerId, Deck deck) {
|
public boolean updateDeck(UUID tournamentId, UUID playerId, Deck deck) {
|
||||||
return controllers.get(tournamentId).updateDeck(playerId, deck);
|
return controllers.get(tournamentId).updateDeck(playerId, deck);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public TournamentView getTournamentView(UUID tournamentId) {
|
public TournamentView getTournamentView(UUID tournamentId) {
|
||||||
TournamentController tournamentController = controllers.get(tournamentId);
|
TournamentController tournamentController = controllers.get(tournamentId);
|
||||||
if (tournamentController != null) {
|
if (tournamentController != null) {
|
||||||
|
@ -60,6 +74,7 @@ public enum TournamentManager {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Optional<UUID> getChatId(UUID tournamentId) {
|
public Optional<UUID> getChatId(UUID tournamentId) {
|
||||||
if (controllers.containsKey(tournamentId)) {
|
if (controllers.containsKey(tournamentId)) {
|
||||||
return Optional.of(controllers.get(tournamentId).getChatId());
|
return Optional.of(controllers.get(tournamentId).getChatId());
|
||||||
|
@ -67,6 +82,7 @@ public enum TournamentManager {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void removeTournament(UUID tournamentId) {
|
public void removeTournament(UUID tournamentId) {
|
||||||
TournamentController tournamentController = controllers.get(tournamentId);
|
TournamentController tournamentController = controllers.get(tournamentId);
|
||||||
if (tournamentController != null) {
|
if (tournamentController != null) {
|
|
@ -1,20 +1,19 @@
|
||||||
|
|
||||||
package mage.server.tournament;
|
package mage.server.tournament;
|
||||||
|
|
||||||
|
import mage.cards.decks.Deck;
|
||||||
|
import mage.game.tournament.Tournament;
|
||||||
|
import mage.interfaces.callback.ClientCallback;
|
||||||
|
import mage.interfaces.callback.ClientCallbackMethod;
|
||||||
|
import mage.server.User;
|
||||||
|
import mage.server.managers.ManagerFactory;
|
||||||
|
import mage.view.TournamentView;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.ScheduledFuture;
|
import java.util.concurrent.ScheduledFuture;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import mage.cards.decks.Deck;
|
|
||||||
import mage.game.tournament.Tournament;
|
|
||||||
import mage.interfaces.callback.ClientCallback;
|
|
||||||
import mage.interfaces.callback.ClientCallbackMethod;
|
|
||||||
import mage.server.User;
|
|
||||||
import mage.server.UserManager;
|
|
||||||
import mage.server.util.ThreadExecutor;
|
|
||||||
import mage.view.TournamentView;
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
|
@ -23,6 +22,7 @@ public class TournamentSession {
|
||||||
|
|
||||||
protected static final Logger logger = Logger.getLogger(TournamentSession.class);
|
protected static final Logger logger = Logger.getLogger(TournamentSession.class);
|
||||||
|
|
||||||
|
private final ManagerFactory managerFactory;
|
||||||
protected final UUID userId;
|
protected final UUID userId;
|
||||||
protected final UUID playerId;
|
protected final UUID playerId;
|
||||||
protected final UUID tableId;
|
protected final UUID tableId;
|
||||||
|
@ -30,9 +30,11 @@ public class TournamentSession {
|
||||||
protected boolean killed = false;
|
protected boolean killed = false;
|
||||||
|
|
||||||
private ScheduledFuture<?> futureTimeout;
|
private ScheduledFuture<?> futureTimeout;
|
||||||
protected static final ScheduledExecutorService timeoutExecutor = ThreadExecutor.instance.getTimeoutExecutor();
|
protected final ScheduledExecutorService timeoutExecutor;
|
||||||
|
|
||||||
public TournamentSession(Tournament tournament, UUID userId, UUID tableId, UUID playerId) {
|
public TournamentSession(ManagerFactory managerFactory, Tournament tournament, UUID userId, UUID tableId, UUID playerId) {
|
||||||
|
this.managerFactory = managerFactory;
|
||||||
|
this.timeoutExecutor = managerFactory.threadExecutor().getTimeoutExecutor();
|
||||||
this.userId = userId;
|
this.userId = userId;
|
||||||
this.tournament = tournament;
|
this.tournament = tournament;
|
||||||
this.playerId = playerId;
|
this.playerId = playerId;
|
||||||
|
@ -41,7 +43,7 @@ public class TournamentSession {
|
||||||
|
|
||||||
public boolean init() {
|
public boolean init() {
|
||||||
if (!killed) {
|
if (!killed) {
|
||||||
Optional<User> user = UserManager.instance.getUser(userId);
|
Optional<User> user = managerFactory.userManager().getUser(userId);
|
||||||
if (user.isPresent()) {
|
if (user.isPresent()) {
|
||||||
user.get().fireCallback(new ClientCallback(ClientCallbackMethod.TOURNAMENT_INIT, tournament.getId(), getTournamentView()));
|
user.get().fireCallback(new ClientCallback(ClientCallbackMethod.TOURNAMENT_INIT, tournament.getId(), getTournamentView()));
|
||||||
return true;
|
return true;
|
||||||
|
@ -52,7 +54,7 @@ public class TournamentSession {
|
||||||
|
|
||||||
public void update() {
|
public void update() {
|
||||||
if (!killed) {
|
if (!killed) {
|
||||||
UserManager.instance.getUser(userId).ifPresent(user
|
managerFactory.userManager().getUser(userId).ifPresent(user
|
||||||
-> user.fireCallback(new ClientCallback(ClientCallbackMethod.TOURNAMENT_UPDATE, tournament.getId(), getTournamentView())));
|
-> user.fireCallback(new ClientCallback(ClientCallbackMethod.TOURNAMENT_UPDATE, tournament.getId(), getTournamentView())));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -60,7 +62,7 @@ public class TournamentSession {
|
||||||
|
|
||||||
public void gameOver(final String message) {
|
public void gameOver(final String message) {
|
||||||
if (!killed) {
|
if (!killed) {
|
||||||
UserManager.instance.getUser(userId).ifPresent(user
|
managerFactory.userManager().getUser(userId).ifPresent(user
|
||||||
-> user.fireCallback(new ClientCallback(ClientCallbackMethod.TOURNAMENT_OVER, tournament.getId(), message)));
|
-> user.fireCallback(new ClientCallback(ClientCallbackMethod.TOURNAMENT_OVER, tournament.getId(), message)));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -69,7 +71,7 @@ public class TournamentSession {
|
||||||
public void construct(int timeout) {
|
public void construct(int timeout) {
|
||||||
if (!killed) {
|
if (!killed) {
|
||||||
setupTimeout(timeout);
|
setupTimeout(timeout);
|
||||||
UserManager.instance.getUser(userId).ifPresent(user -> {
|
managerFactory.userManager().getUser(userId).ifPresent(user -> {
|
||||||
int remaining = (int) futureTimeout.getDelay(TimeUnit.SECONDS);
|
int remaining = (int) futureTimeout.getDelay(TimeUnit.SECONDS);
|
||||||
user.ccConstruct(tournament.getPlayer(playerId).getDeck(), tableId, remaining);
|
user.ccConstruct(tournament.getPlayer(playerId).getDeck(), tableId, remaining);
|
||||||
});
|
});
|
||||||
|
@ -102,7 +104,7 @@ public class TournamentSession {
|
||||||
futureTimeout = timeoutExecutor.schedule(
|
futureTimeout = timeoutExecutor.schedule(
|
||||||
() -> {
|
() -> {
|
||||||
try {
|
try {
|
||||||
TournamentManager.instance.timeout(tournament.getId(), userId);
|
managerFactory.tournamentManager().timeout(tournament.getId(), userId);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.fatal("TournamentSession error - userId " + userId + " tId " + tournament.getId(), e);
|
logger.fatal("TournamentSession error - userId " + userId + " tId " + tournament.getId(), e);
|
||||||
}
|
}
|
||||||
|
@ -144,7 +146,7 @@ public class TournamentSession {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeTournamentForUser() {
|
private void removeTournamentForUser() {
|
||||||
Optional<User> user = UserManager.instance.getUser(userId);
|
Optional<User> user = managerFactory.userManager().getUser(userId);
|
||||||
if (user.isPresent()) {
|
if (user.isPresent()) {
|
||||||
user.get().removeTable(playerId);
|
user.get().removeTable(playerId);
|
||||||
user.get().removeTournament(playerId);
|
user.get().removeTournament(playerId);
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
package mage.server.util;
|
||||||
|
|
||||||
|
import mage.server.util.config.Config;
|
||||||
|
|
||||||
|
import javax.xml.bind.JAXBContext;
|
||||||
|
import javax.xml.bind.Unmarshaller;
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
public class ConfigFactory {
|
||||||
|
|
||||||
|
public static Config loadFromFile(final String filePath) {
|
||||||
|
try {
|
||||||
|
final JAXBContext jaxbContext = JAXBContext.newInstance("mage.server.util.config");
|
||||||
|
final Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
|
||||||
|
return (Config) unmarshaller.unmarshal(new File(filePath));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new ConfigurationException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,33 +1,18 @@
|
||||||
|
|
||||||
package mage.server.util;
|
package mage.server.util;
|
||||||
|
|
||||||
import java.io.File;
|
import mage.server.managers.ConfigSettings;
|
||||||
import java.util.List;
|
|
||||||
import javax.xml.bind.JAXBContext;
|
|
||||||
import javax.xml.bind.JAXBException;
|
|
||||||
import javax.xml.bind.Unmarshaller;
|
|
||||||
import mage.server.util.config.Config;
|
import mage.server.util.config.Config;
|
||||||
import mage.server.util.config.GamePlugin;
|
import mage.server.util.config.GamePlugin;
|
||||||
import mage.server.util.config.Plugin;
|
import mage.server.util.config.Plugin;
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
|
|
||||||
/**
|
import java.util.List;
|
||||||
* @author BetaSteward_at_googlemail.com
|
|
||||||
*/
|
|
||||||
public enum ConfigSettings {
|
|
||||||
instance;
|
|
||||||
private final Logger logger = Logger.getLogger(ConfigSettings.class);
|
|
||||||
|
|
||||||
private Config config;
|
public class ConfigWrapper implements ConfigSettings {
|
||||||
|
|
||||||
ConfigSettings() {
|
private final Config config;
|
||||||
try {
|
|
||||||
JAXBContext jaxbContext = JAXBContext.newInstance("mage.server.util.config");
|
public ConfigWrapper(final Config config) {
|
||||||
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
|
this.config = config;
|
||||||
config = (Config) unmarshaller.unmarshal(new File("config/config.xml"));
|
|
||||||
} catch (JAXBException ex) {
|
|
||||||
logger.fatal("ConfigSettings error", ex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getServerAddress() {
|
public String getServerAddress() {
|
|
@ -0,0 +1,7 @@
|
||||||
|
package mage.server.util;
|
||||||
|
|
||||||
|
public class ConfigurationException extends RuntimeException {
|
||||||
|
public ConfigurationException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,24 +1,18 @@
|
||||||
|
|
||||||
package mage.server.util;
|
package mage.server.util;
|
||||||
|
|
||||||
import java.util.concurrent.ExecutorService;
|
import mage.server.managers.ConfigSettings;
|
||||||
import java.util.concurrent.Executors;
|
import mage.server.managers.ThreadExecutor;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
|
||||||
import java.util.concurrent.ThreadFactory;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
*/
|
*/
|
||||||
public enum ThreadExecutor {
|
public class ThreadExecutorImpl implements ThreadExecutor {
|
||||||
instance;
|
private final ExecutorService callExecutor;
|
||||||
private static final ExecutorService callExecutor = Executors.newCachedThreadPool();
|
private final ExecutorService gameExecutor;
|
||||||
private static final ExecutorService userExecutor = Executors.newCachedThreadPool();
|
private final ScheduledExecutorService timeoutExecutor;
|
||||||
private static final ExecutorService gameExecutor = Executors.newFixedThreadPool(ConfigSettings.instance.getMaxGameThreads());
|
private final ScheduledExecutorService timeoutIdleExecutor;
|
||||||
private static final ScheduledExecutorService timeoutExecutor = Executors.newScheduledThreadPool(4);
|
|
||||||
private static final ScheduledExecutorService timeoutIdleExecutor = Executors.newScheduledThreadPool(4);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* noxx: what the settings below do is setting the ability to keep OS
|
* noxx: what the settings below do is setting the ability to keep OS
|
||||||
|
@ -26,17 +20,20 @@ instance;
|
||||||
* within this time period, the thread may be discarded. But anyway if new
|
* within this time period, the thread may be discarded. But anyway if new
|
||||||
* game is created later, new OS/java thread will be created for it taking
|
* game is created later, new OS/java thread will be created for it taking
|
||||||
* MaxGameThreads limit into account.
|
* MaxGameThreads limit into account.
|
||||||
*
|
* <p>
|
||||||
* This all is done for performance reasons as creating new OS threads is
|
* This all is done for performance reasons as creating new OS threads is
|
||||||
* resource consuming process.
|
* resource consuming process.
|
||||||
*/
|
*/
|
||||||
static {
|
|
||||||
|
public ThreadExecutorImpl(ConfigSettings config) {
|
||||||
|
callExecutor = Executors.newCachedThreadPool();
|
||||||
|
gameExecutor = Executors.newFixedThreadPool(config.getMaxGameThreads());
|
||||||
|
timeoutExecutor = Executors.newScheduledThreadPool(4);
|
||||||
|
timeoutIdleExecutor = Executors.newScheduledThreadPool(4);
|
||||||
|
|
||||||
((ThreadPoolExecutor) callExecutor).setKeepAliveTime(60, TimeUnit.SECONDS);
|
((ThreadPoolExecutor) callExecutor).setKeepAliveTime(60, TimeUnit.SECONDS);
|
||||||
((ThreadPoolExecutor) callExecutor).allowCoreThreadTimeOut(true);
|
((ThreadPoolExecutor) callExecutor).allowCoreThreadTimeOut(true);
|
||||||
((ThreadPoolExecutor) callExecutor).setThreadFactory(new XMageThreadFactory("CALL"));
|
((ThreadPoolExecutor) callExecutor).setThreadFactory(new XMageThreadFactory("CALL"));
|
||||||
((ThreadPoolExecutor) userExecutor).setKeepAliveTime(60, TimeUnit.SECONDS);
|
|
||||||
((ThreadPoolExecutor) userExecutor).allowCoreThreadTimeOut(true);
|
|
||||||
((ThreadPoolExecutor) userExecutor).setThreadFactory(new XMageThreadFactory("USER"));
|
|
||||||
((ThreadPoolExecutor) gameExecutor).setKeepAliveTime(60, TimeUnit.SECONDS);
|
((ThreadPoolExecutor) gameExecutor).setKeepAliveTime(60, TimeUnit.SECONDS);
|
||||||
((ThreadPoolExecutor) gameExecutor).allowCoreThreadTimeOut(true);
|
((ThreadPoolExecutor) gameExecutor).allowCoreThreadTimeOut(true);
|
||||||
((ThreadPoolExecutor) gameExecutor).setThreadFactory(new XMageThreadFactory("GAME"));
|
((ThreadPoolExecutor) gameExecutor).setThreadFactory(new XMageThreadFactory("GAME"));
|
||||||
|
@ -49,6 +46,7 @@ instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getActiveThreads(ExecutorService executerService) {
|
public int getActiveThreads(ExecutorService executerService) {
|
||||||
if (executerService instanceof ThreadPoolExecutor) {
|
if (executerService instanceof ThreadPoolExecutor) {
|
||||||
return ((ThreadPoolExecutor) executerService).getActiveCount();
|
return ((ThreadPoolExecutor) executerService).getActiveCount();
|
||||||
|
@ -56,18 +54,22 @@ instance;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public ExecutorService getCallExecutor() {
|
public ExecutorService getCallExecutor() {
|
||||||
return callExecutor;
|
return callExecutor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public ExecutorService getGameExecutor() {
|
public ExecutorService getGameExecutor() {
|
||||||
return gameExecutor;
|
return gameExecutor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public ScheduledExecutorService getTimeoutExecutor() {
|
public ScheduledExecutorService getTimeoutExecutor() {
|
||||||
return timeoutExecutor;
|
return timeoutExecutor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public ScheduledExecutorService getTimeoutIdleExecutor() {
|
public ScheduledExecutorService getTimeoutIdleExecutor() {
|
||||||
return timeoutIdleExecutor;
|
return timeoutIdleExecutor;
|
||||||
}
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package mage.server.util;
|
||||||
|
|
||||||
|
import mage.server.util.config.Config;
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||||
|
|
||||||
|
public class ConfigFactoryTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("should unmarshal configuration from file")
|
||||||
|
void loadConfig() {
|
||||||
|
final Config config = ConfigFactory.loadFromFile("config/config.xml");
|
||||||
|
|
||||||
|
assertThat(config.getServer().getServerName()).isEqualTo("mage-server");
|
||||||
|
assertThat(config.getServer().getPort()).isEqualTo(17171);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("should fail if config is malformed")
|
||||||
|
void failOnMalformed() {
|
||||||
|
assertThatExceptionOfType(ConfigurationException.class)
|
||||||
|
.isThrownBy(() -> ConfigFactory.loadFromFile(Paths.get("src", "test", "resources", "config_error.xml").toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("should fail if file does not exist")
|
||||||
|
void failOnNotFound() {
|
||||||
|
assertThatExceptionOfType(ConfigurationException.class)
|
||||||
|
.isThrownBy(() -> ConfigFactory.loadFromFile("does not exist"));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,294 @@
|
||||||
|
package mage.server.util;
|
||||||
|
|
||||||
|
import mage.server.util.config.*;
|
||||||
|
import mage.utils.FluentBuilder;
|
||||||
|
import org.apache.commons.lang3.RandomStringUtils;
|
||||||
|
import org.apache.commons.lang3.RandomUtils;
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.DynamicTest;
|
||||||
|
import org.junit.jupiter.api.TestFactory;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
public class ConfigWrapperTest {
|
||||||
|
|
||||||
|
static class ConfigBuilder extends FluentBuilder<Config, ConfigBuilder> {
|
||||||
|
|
||||||
|
public String serverAddress;
|
||||||
|
public String serverName;
|
||||||
|
public int port;
|
||||||
|
public int secondaryBindPort;
|
||||||
|
public int leasePeriod;
|
||||||
|
public int socketWriteTimeout;
|
||||||
|
public int maxPoolSize;
|
||||||
|
public int numAcceptThreads;
|
||||||
|
public int backlogSize;
|
||||||
|
public int maxGameThreads;
|
||||||
|
public int maxSecondsIdle;
|
||||||
|
public int minUsernameLength;
|
||||||
|
public int maxUsernameLength;
|
||||||
|
public String invalidUsernamePattern;
|
||||||
|
public int minPasswordLength;
|
||||||
|
public int maxPasswordLength;
|
||||||
|
public String maxAiOpponents;
|
||||||
|
public boolean saveGameActivated;
|
||||||
|
public boolean authenticationActivated;
|
||||||
|
public String googleAccount;
|
||||||
|
public String mailgunApiKey;
|
||||||
|
public String mailgunDomain;
|
||||||
|
public String mailSmtpHost;
|
||||||
|
public String mailSmtpPort;
|
||||||
|
public String mailUser;
|
||||||
|
public String mailPassword;
|
||||||
|
public String mailFromAddress;
|
||||||
|
public List<Plugin> playerTypes = Collections.emptyList();
|
||||||
|
public List<GamePlugin> gameTypes = Collections.emptyList();
|
||||||
|
public List<GamePlugin> tournamentTypes = Collections.emptyList();
|
||||||
|
public List<Plugin> draftCubes = Collections.emptyList();
|
||||||
|
public List<Plugin> deckTypes = Collections.emptyList();
|
||||||
|
|
||||||
|
private ConfigBuilder() {
|
||||||
|
super(ConfigBuilder::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Config makeValue() {
|
||||||
|
final Config result = new Config();
|
||||||
|
result.setServer(makeServer());
|
||||||
|
result.setPlayerTypes(makePlayerTypes());
|
||||||
|
result.setGameTypes(makeGameTypes());
|
||||||
|
result.setTournamentTypes(makeTournamentTypes());
|
||||||
|
result.setDraftCubes(makeDraftCubes());
|
||||||
|
result.setDeckTypes(makeDeckTypes());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Server makeServer() {
|
||||||
|
final Server server = new Server();
|
||||||
|
server.setServerAddress(serverAddress);
|
||||||
|
server.setServerName(serverName);
|
||||||
|
server.setPort(BigInteger.valueOf(port));
|
||||||
|
server.setSecondaryBindPort(bi(secondaryBindPort));
|
||||||
|
server.setLeasePeriod(bi(leasePeriod));
|
||||||
|
server.setSocketWriteTimeout(bi(socketWriteTimeout));
|
||||||
|
server.setMaxPoolSize(bi(maxPoolSize));
|
||||||
|
server.setNumAcceptThreads(bi(numAcceptThreads));
|
||||||
|
server.setBacklogSize(bi(backlogSize));
|
||||||
|
server.setMaxGameThreads(bi(maxGameThreads));
|
||||||
|
server.setMaxSecondsIdle(bi(maxSecondsIdle));
|
||||||
|
server.setMinUserNameLength(bi(minUsernameLength));
|
||||||
|
server.setMaxUserNameLength(bi(maxUsernameLength));
|
||||||
|
server.setInvalidUserNamePattern(invalidUsernamePattern);
|
||||||
|
server.setMinPasswordLength(bi(minPasswordLength));
|
||||||
|
server.setMaxPasswordLength(bi(maxPasswordLength));
|
||||||
|
server.setMaxAiOpponents(maxAiOpponents);
|
||||||
|
server.setSaveGameActivated(saveGameActivated);
|
||||||
|
server.setAuthenticationActivated(authenticationActivated);
|
||||||
|
server.setGoogleAccount(googleAccount);
|
||||||
|
server.setMailgunApiKey(mailgunApiKey);
|
||||||
|
server.setMailgunDomain(mailgunDomain);
|
||||||
|
server.setMailSmtpHost(mailSmtpHost);
|
||||||
|
server.setMailSmtpPort(mailSmtpPort);
|
||||||
|
server.setMailUser(mailUser);
|
||||||
|
server.setMailPassword(mailPassword);
|
||||||
|
server.setMailFromAddress(mailFromAddress);
|
||||||
|
return server;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PlayerTypes makePlayerTypes() {
|
||||||
|
final PlayerTypes playerTypes = new PlayerTypes();
|
||||||
|
this.playerTypes.forEach(p -> playerTypes.getPlayerType().add(p));
|
||||||
|
return playerTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private GameTypes makeGameTypes() {
|
||||||
|
final GameTypes gameTypes = new GameTypes();
|
||||||
|
this.gameTypes.forEach(g -> gameTypes.getGameType().add(g));
|
||||||
|
return gameTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TournamentTypes makeTournamentTypes() {
|
||||||
|
final TournamentTypes tournamentTypes = new TournamentTypes();
|
||||||
|
this.tournamentTypes.forEach(t -> tournamentTypes.getTournamentType().add(t));
|
||||||
|
return tournamentTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DraftCubes makeDraftCubes() {
|
||||||
|
final DraftCubes draftCubes = new DraftCubes();
|
||||||
|
this.draftCubes.forEach(d -> draftCubes.getDraftCube().add(d));
|
||||||
|
return draftCubes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DeckTypes makeDeckTypes() {
|
||||||
|
final DeckTypes deckTypes = new DeckTypes();
|
||||||
|
this.deckTypes.forEach(d -> deckTypes.getDeckType().add(d));
|
||||||
|
return deckTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BigInteger bi(int value) {
|
||||||
|
return BigInteger.valueOf(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ConfigBuilder baseConfigBuilder() {
|
||||||
|
return new ConfigBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String expectedString = RandomStringUtils.randomAlphanumeric(15);
|
||||||
|
private final int expectedPositiveInt = RandomUtils.nextInt(0, Integer.MAX_VALUE);
|
||||||
|
|
||||||
|
|
||||||
|
@TestFactory
|
||||||
|
@DisplayName("should return from server")
|
||||||
|
Stream<DynamicTest> assignmentFromServer() {
|
||||||
|
return Stream.of(
|
||||||
|
testString("server address", c -> c.serverAddress = expectedString, ConfigWrapper::getServerAddress),
|
||||||
|
testString("server name", c -> c.serverName = expectedString, ConfigWrapper::getServerName),
|
||||||
|
testInt("port", c -> c.port = expectedPositiveInt, ConfigWrapper::getPort),
|
||||||
|
testInt("secondary bind port", c -> c.secondaryBindPort = expectedPositiveInt, ConfigWrapper::getSecondaryBindPort),
|
||||||
|
testInt("lease period", c -> c.leasePeriod = expectedPositiveInt, ConfigWrapper::getLeasePeriod),
|
||||||
|
testInt("socket write timeout", c -> c.socketWriteTimeout = expectedPositiveInt, ConfigWrapper::getSocketWriteTimeout),
|
||||||
|
testInt("max pool size", c -> c.maxPoolSize = expectedPositiveInt, ConfigWrapper::getMaxPoolSize),
|
||||||
|
testInt("number of accept threads", c -> c.numAcceptThreads = expectedPositiveInt, ConfigWrapper::getNumAcceptThreads),
|
||||||
|
testInt("backlog size", c -> c.backlogSize = expectedPositiveInt, ConfigWrapper::getBacklogSize),
|
||||||
|
testInt("max game threads", c -> c.maxGameThreads = expectedPositiveInt, ConfigWrapper::getMaxGameThreads),
|
||||||
|
testInt("max seconds idle", c -> c.maxSecondsIdle = expectedPositiveInt, ConfigWrapper::getMaxSecondsIdle),
|
||||||
|
testInt("min username length", c -> c.minUsernameLength = expectedPositiveInt, ConfigWrapper::getMinUserNameLength),
|
||||||
|
testInt("max username length", c -> c.maxUsernameLength = expectedPositiveInt, ConfigWrapper::getMaxUserNameLength),
|
||||||
|
testString("invalid username pattern", c -> c.invalidUsernamePattern = expectedString, ConfigWrapper::getInvalidUserNamePattern),
|
||||||
|
testInt("min password length", c -> c.minPasswordLength = expectedPositiveInt, ConfigWrapper::getMinPasswordLength),
|
||||||
|
testInt("max password length", c -> c.maxPasswordLength = expectedPositiveInt, ConfigWrapper::getMaxPasswordLength),
|
||||||
|
testString("max AI opponents", c -> c.maxAiOpponents = expectedString, ConfigWrapper::getMaxAiOpponents),
|
||||||
|
testTrue("save game activated", c -> c.saveGameActivated = true, ConfigWrapper::isSaveGameActivated),
|
||||||
|
testTrue("authentication activated", c -> c.authenticationActivated = true, ConfigWrapper::isAuthenticationActivated),
|
||||||
|
testString("google account", c -> c.googleAccount = expectedString, ConfigWrapper::getGoogleAccount),
|
||||||
|
testString("mailgun api key", c -> c.mailgunApiKey = expectedString, ConfigWrapper::getMailgunApiKey),
|
||||||
|
testString("mailgun domain", c -> c.mailgunDomain = expectedString, ConfigWrapper::getMailgunDomain),
|
||||||
|
testString("mail smtp host", c -> c.mailSmtpHost = expectedString, ConfigWrapper::getMailSmtpHost),
|
||||||
|
testString("mail smtp port", c -> c.mailSmtpPort = expectedString, ConfigWrapper::getMailSmtpPort),
|
||||||
|
testString("mail from address", c -> c.mailFromAddress = expectedString, ConfigWrapper::getMailFromAddress),
|
||||||
|
testString("mail user", c -> c.mailUser = expectedString, ConfigWrapper::getMailUser),
|
||||||
|
testString("mail password", c -> c.mailPassword = expectedString, ConfigWrapper::getMailPassword)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private DynamicTest testString(String description, Consumer<ConfigBuilder> builderSetter, Function<ConfigWrapper, Object> valueExtractor) {
|
||||||
|
return testTemplate(description, builderSetter, valueExtractor, expectedString);
|
||||||
|
}
|
||||||
|
|
||||||
|
private DynamicTest testTemplate(String description, Consumer<ConfigBuilder> builderSetter, Function<ConfigWrapper, Object> valueExtractor, Object expectedValue) {
|
||||||
|
return DynamicTest.dynamicTest(description, () -> assertThat(valueExtractor.apply(makeTestee(baseConfigBuilder().with(builderSetter)))).isEqualTo(expectedValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
private ConfigWrapper makeTestee(ConfigBuilder builder) {
|
||||||
|
return new ConfigWrapper(builder.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
private DynamicTest testInt(String description, Consumer<ConfigBuilder> builderSetter, Function<ConfigWrapper, Object> valueExtractor) {
|
||||||
|
return testTemplate(description, builderSetter, valueExtractor, expectedPositiveInt);
|
||||||
|
}
|
||||||
|
|
||||||
|
private DynamicTest testTrue(String description, Consumer<ConfigBuilder> builderSetter, Function<ConfigWrapper, Object> valueExtractor) {
|
||||||
|
return testTemplate(description, builderSetter, valueExtractor, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private final Comparator<Plugin> pluginComparator = (p1, p2) -> {
|
||||||
|
if (Objects.equals(p1.getName(), p2.getName()) &&
|
||||||
|
Objects.equals(p1.getJar(), p2.getJar()) &&
|
||||||
|
Objects.equals(p1.getClassName(), p2.getClassName())) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final Comparator<GamePlugin> gamePluginComparator = (p1, p2) -> {
|
||||||
|
if (Objects.equals(p1.getName(), p2.getName()) &&
|
||||||
|
Objects.equals(p1.getJar(), p2.getJar()) &&
|
||||||
|
Objects.equals(p1.getClassName(), p2.getClassName()) &&
|
||||||
|
Objects.equals(p1.getTypeName(), p2.getTypeName())) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final List<Plugin> randomPlugins = IntStream.range(0, RandomUtils.nextInt(1, 10))
|
||||||
|
.mapToObj(i -> makePlugin(
|
||||||
|
RandomStringUtils.randomAlphanumeric(15),
|
||||||
|
RandomStringUtils.randomAlphanumeric(16),
|
||||||
|
RandomStringUtils.randomAlphanumeric(17))
|
||||||
|
).collect(Collectors.toList());
|
||||||
|
private final List<GamePlugin> randomGamePlugins = IntStream.range(0, RandomUtils.nextInt(1, 10))
|
||||||
|
.mapToObj(i -> makeGamePlugin(
|
||||||
|
RandomStringUtils.randomAlphanumeric(15),
|
||||||
|
RandomStringUtils.randomAlphanumeric(16),
|
||||||
|
RandomStringUtils.randomAlphanumeric(17),
|
||||||
|
RandomStringUtils.randomAlphanumeric(18))
|
||||||
|
).collect(Collectors.toList());
|
||||||
|
|
||||||
|
private Plugin makePlugin(String name, String jar, String className) {
|
||||||
|
final Plugin plugin = new Plugin();
|
||||||
|
plugin.setName(name);
|
||||||
|
plugin.setJar(jar);
|
||||||
|
plugin.setClassName(className);
|
||||||
|
return plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
private GamePlugin makeGamePlugin(String name, String jar, String className, String typeName) {
|
||||||
|
final GamePlugin plugin = new GamePlugin();
|
||||||
|
plugin.setName(name);
|
||||||
|
plugin.setJar(jar);
|
||||||
|
plugin.setClassName(className);
|
||||||
|
plugin.setTypeName(typeName);
|
||||||
|
return plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestFactory
|
||||||
|
@DisplayName("should extract")
|
||||||
|
Stream<DynamicTest> pluginsExtraction() {
|
||||||
|
return Stream.of(
|
||||||
|
pluginTest("playerTypes from playerTypes", c -> c.playerTypes = randomPlugins, ConfigWrapper::getPlayerTypes),
|
||||||
|
gamePluginTest("gameTypes from gameTypes", c -> c.gameTypes = randomGamePlugins, ConfigWrapper::getGameTypes),
|
||||||
|
gamePluginTest("tournamentTypes from tournamentTypes", c -> c.tournamentTypes = randomGamePlugins, ConfigWrapper::getTournamentTypes),
|
||||||
|
pluginTest("draftCubes from draftCubes", c -> c.draftCubes = randomPlugins, ConfigWrapper::getDraftCubes),
|
||||||
|
pluginTest("deckTypes from deckTypes", c -> c.deckTypes = randomPlugins, ConfigWrapper::getDeckTypes)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private DynamicTest pluginTest(String description,
|
||||||
|
Consumer<ConfigBuilder> builderSetter,
|
||||||
|
Function<ConfigWrapper, List<Plugin>> listExtractor) {
|
||||||
|
return testTemplateForLists(description, builderSetter, listExtractor, randomPlugins, pluginComparator);
|
||||||
|
}
|
||||||
|
|
||||||
|
private DynamicTest gamePluginTest(String description,
|
||||||
|
Consumer<ConfigBuilder> builderSetter,
|
||||||
|
Function<ConfigWrapper, List<GamePlugin>> listExtractor) {
|
||||||
|
return testTemplateForLists(description, builderSetter, listExtractor, randomGamePlugins, gamePluginComparator);
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> DynamicTest testTemplateForLists(String description,
|
||||||
|
Consumer<ConfigBuilder> builderSetter,
|
||||||
|
Function<ConfigWrapper, List<T>> listExtractor,
|
||||||
|
List<T> expectedValue,
|
||||||
|
Comparator<T> comparator) {
|
||||||
|
return DynamicTest.dynamicTest(description, () ->
|
||||||
|
assertThat(listExtractor.apply(makeTestee(baseConfigBuilder().with(builderSetter))))
|
||||||
|
.usingElementComparator(comparator)
|
||||||
|
.containsExactlyElementsOf(expectedValue)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
173
Mage.Server/src/test/resources/config_error.xml
Normal file
173
Mage.Server/src/test/resources/config_error.xml
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<!-- Configuration file with integers set as strings to cause unmarshalling errors -->
|
||||||
|
<config>
|
||||||
|
<server serverAddress="0.0.0.0"
|
||||||
|
serverName="mage-server"
|
||||||
|
port="NOT AN INTEGER"
|
||||||
|
secondaryBindPort="NOT AN INTEGER"
|
||||||
|
backlogSize="NOT AN INTEGER"
|
||||||
|
numAcceptThreads="NOT AN INTEGER"
|
||||||
|
maxPoolSize="NOT AN INTEGER"
|
||||||
|
leasePeriod="NOT AN INTEGER"
|
||||||
|
socketWriteTimeout="NOT AN INTEGER"
|
||||||
|
maxGameThreads="NOT AN INTEGER"
|
||||||
|
maxSecondsIdle="NOT AN INTEGER"
|
||||||
|
minUserNameLength="NOT AN INTEGER"
|
||||||
|
maxUserNameLength="NOT AN INTEGER"
|
||||||
|
invalidUserNamePattern="[^a-z0-9_]"
|
||||||
|
minPasswordLength="NOT AN INTEGER"
|
||||||
|
maxPasswordLength="NOT AN INTEGER"
|
||||||
|
maxAiOpponents="NOT AN INTEGER"
|
||||||
|
saveGameActivated="false"
|
||||||
|
authenticationActivated="false"
|
||||||
|
googleAccount=""
|
||||||
|
mailgunApiKey=""
|
||||||
|
mailgunDomain=""
|
||||||
|
mailSmtpHost=""
|
||||||
|
mailSmtpPort=""
|
||||||
|
mailUser=""
|
||||||
|
mailPassword=""
|
||||||
|
mailFromAddress=""
|
||||||
|
/>
|
||||||
|
<playerTypes>
|
||||||
|
<playerType name="Human" jar="mage-player-human.jar" className="mage.player.human.HumanPlayer"/>
|
||||||
|
<!--<playerType name="Computer - minimax" jar="mage-player-aiminimax.jar" className="mage.player.ai.ComputerPlayer3"/>-->
|
||||||
|
<playerType name="Computer - mad" jar="mage-player-ai-ma.jar" className="mage.player.ai.ComputerPlayer7"/>
|
||||||
|
<playerType name="Computer - monte carlo" jar="mage-player-aimcts.jar" className="mage.player.ai.ComputerPlayerMCTS"/>
|
||||||
|
<playerType name="Computer - draftbot" jar="mage-player-ai-draft-bot.jar" className="mage.player.ai.ComputerDraftPlayer"/>
|
||||||
|
</playerTypes>
|
||||||
|
<gameTypes>
|
||||||
|
<gameType name="Two Player Duel" jar="mage-game-twoplayerduel.jar" className="mage.game.TwoPlayerMatch" typeName="mage.game.TwoPlayerDuelType"/>
|
||||||
|
<gameType name="Free For All" jar="mage-game-freeforall.jar" className="mage.game.FreeForAllMatch" typeName="mage.game.FreeForAllType"/>
|
||||||
|
<gameType name="Commander Two Player Duel" jar="mage-game-commanderduel.jar" className="mage.game.CommanderDuelMatch" typeName="mage.game.CommanderDuelType"/>
|
||||||
|
<gameType name="Commander Free For All" jar="mage-game-commanderfreeforall.jar" className="mage.game.CommanderFreeForAllMatch" typeName="mage.game.CommanderFreeForAllType"/>
|
||||||
|
<gameType name="Tiny Leaders Two Player Duel" jar="mage-game-tinyleadersduel.jar" className="mage.game.TinyLeadersDuelMatch" typeName="mage.game.TinyLeadersDuelType"/>
|
||||||
|
<gameType name="Canadian Highlander Two Player Duel" jar="mage-game-canadianhighlanderduel.jar" className="mage.game.CanadianHighlanderDuelMatch" typeName="mage.game.CanadianHighlanderDuelType"/>
|
||||||
|
<gameType name="Penny Dreadful Commander Free For All" jar="mage-game-pennydreadfulcommanderfreeforall.jar" className="mage.game.PennyDreadfulCommanderFreeForAllMatch" typeName="mage.game.PennyDreadfulCommanderFreeForAllType"/>
|
||||||
|
<gameType name="Freeform Commander Two Player Duel" jar="mage-game-freeformcommanderduel.jar" className="mage.game.FreeformCommanderDuelMatch" typeName="mage.game.FreeformCommanderDuelType"/>
|
||||||
|
<gameType name="Freeform Commander Free For All" jar="mage-game-freeformcommanderfreeforall.jar" className="mage.game.FreeformCommanderFreeForAllMatch" typeName="mage.game.FreeformCommanderFreeForAllType"/>
|
||||||
|
<gameType name="Freeform Unlimited Commander" jar="mage-game-freeformunlimitedcommander.jar" className="mage.game.FreeformUnlimitedCommanderMatch" typeName="mage.game.FreeformUnlimitedCommanderType"/>
|
||||||
|
<gameType name="Oathbreaker Two Player Duel" jar="mage-game-oathbreakerduel.jar" className="mage.game.OathbreakerDuelMatch" typeName="mage.game.OathbreakerDuelType"/>
|
||||||
|
<gameType name="Oathbreaker Free For All" jar="mage-game-oathbreakerfreeforall.jar" className="mage.game.OathbreakerFreeForAllMatch" typeName="mage.game.OathbreakerFreeForAllType"/>
|
||||||
|
<gameType name="Brawl Two Player Duel" jar="mage-game-brawlduel.jar" className="mage.game.BrawlDuelMatch" typeName="mage.game.BrawlDuelType"/>
|
||||||
|
<gameType name="Brawl Free For All" jar="mage-game-brawlfreeforall.jar" className="mage.game.BrawlFreeForAllMatch" typeName="mage.game.BrawlFreeForAllType"/>
|
||||||
|
<gameType name="Momir Basic Two Player Duel" jar="mage-game-momirduel.jar" className="mage.game.MomirDuelMatch" typeName="mage.game.MomirDuelType"/>
|
||||||
|
<gameType name="Momir Basic Free For All" jar="mage-game-momir.jar" className="mage.game.MomirFreeForAllMatch" typeName="mage.game.MomirFreeForAllType"/>
|
||||||
|
</gameTypes>
|
||||||
|
<tournamentTypes>
|
||||||
|
<tournamentType name="Constructed Elimination" jar="mage-tournament-constructed.jar" className="mage.tournament.ConstructedEliminationTournament" typeName="mage.tournament.ConstructedEliminationTournamentType"/>
|
||||||
|
<tournamentType name="Constructed Swiss" jar="mage-tournament-constructed.jar" className="mage.tournament.ConstructedSwissTournament" typeName="mage.tournament.ConstructedSwissTournamentType"/>
|
||||||
|
<tournamentType name="Booster Draft Elimination" jar="mage-tournament-booster-draft.jar" className="mage.tournament.BoosterDraftEliminationTournament" typeName="mage.tournament.BoosterDraftEliminationTournamentType"/>
|
||||||
|
<tournamentType name="Booster Draft Elimination (Cube)" jar="mage-tournament-booster-draft.jar" className="mage.tournament.BoosterDraftEliminationTournament" typeName="mage.tournament.BoosterDraftEliminationCubeTournamentType"/>
|
||||||
|
<tournamentType name="Booster Draft Elimination (Random)" jar="mage-tournament-booster-draft.jar" className="mage.tournament.RandomBoosterDraftEliminationTournament" typeName="mage.tournament.RandomBoosterDraftEliminationTournamentType"/>
|
||||||
|
<tournamentType name="Booster Draft Elimination (Rich Man)" jar="mage-tournament-booster-draft.jar" className="mage.tournament.RichManDraftEliminationTournament" typeName="mage.tournament.RichManDraftEliminationTournamentType"/>
|
||||||
|
<tournamentType name="Booster Draft Elimination (Rich Man Cube)" jar="mage-tournament-booster-draft.jar" className="mage.tournament.RichManCubeDraftEliminationTournament" typeName="mage.tournament.RichManCubeDraftEliminationTournamentType"/>
|
||||||
|
<tournamentType name="Booster Draft Swiss" jar="mage-tournament-booster-draft.jar" className="mage.tournament.BoosterDraftSwissTournament" typeName="mage.tournament.BoosterDraftSwissTournamentType"/>
|
||||||
|
<tournamentType name="Booster Draft Swiss (Cube)" jar="mage-tournament-booster-draft.jar" className="mage.tournament.BoosterDraftSwissTournament" typeName="mage.tournament.BoosterDraftSwissCubeTournamentType"/>
|
||||||
|
<tournamentType name="Booster Draft Swiss (Random)" jar="mage-tournament-booster-draft.jar" className="mage.tournament.RandomBoosterDraftSwissTournament" typeName="mage.tournament.RandomBoosterDraftSwissTournamentType"/>
|
||||||
|
<tournamentType name="Sealed Elimination" jar="mage-tournament-sealed.jar" className="mage.tournament.SealedEliminationTournament" typeName="mage.tournament.SealedEliminationTournamentType"/>
|
||||||
|
<tournamentType name="Sealed Elimination (Cube)" jar="mage-tournament-sealed.jar" className="mage.tournament.SealedEliminationTournament" typeName="mage.tournament.SealedEliminationCubeTournamentType"/>
|
||||||
|
<tournamentType name="Sealed Swiss" jar="mage-tournament-sealed.jar" className="mage.tournament.SealedSwissTournament" typeName="mage.tournament.SealedSwissTournamentType"/>
|
||||||
|
<tournamentType name="Sealed Swiss (Cube)" jar="mage-tournament-sealed.jar" className="mage.tournament.SealedSwissTournament" typeName="mage.tournament.SealedSwissCubeTournamentType"/>
|
||||||
|
<tournamentType name="Jumpstart Elimination" jar="mage-tournament-sealed.jar" className="mage.tournament.JumpstartEliminationTournament" typeName="mage.tournament.JumpstartEliminationTournamentType"/>
|
||||||
|
<tournamentType name="Jumpstart Swiss" jar="mage-tournament-sealed.jar" className="mage.tournament.JumpstartSwissTournament" typeName="mage.tournament.JumpstartSwissTournamentType"/>
|
||||||
|
</tournamentTypes>
|
||||||
|
<draftCubes>
|
||||||
|
<draftCube name="Adam Styborski's Pauper Cube" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.AdamStyborskisPauperCube"/>
|
||||||
|
<draftCube name="Ben's Cube" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.BensCube"/>
|
||||||
|
<draftCube name="Cube Tutor 360 Pauper" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.CubeTutor360Pauper"/>
|
||||||
|
<draftCube name="Cube Tutor 720" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.CubeTutor720"/>
|
||||||
|
<draftCube name="Eric Klug's Pro Tour Cube" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.EricKlugsProTourCube"/>
|
||||||
|
<draftCube name="Guillaume Matignon's Jenny's/Johnny's Cube" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.GuillaumeMatignonsJennysJohnnysCube"/>
|
||||||
|
<draftCube name="Jim Davis's Cube" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.JimDavisCube"/>
|
||||||
|
<draftCube name="Joseph Vasoli's Peasant Cube" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.JosephVasolisPeasantCube"/>
|
||||||
|
<draftCube name="Mono Blue Cube" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.MonoBlueCube"/>
|
||||||
|
<draftCube name="Sam Black's No Search Cube" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.SamBlacksCube"/>
|
||||||
|
<draftCube name="Timothee Simonot's Twisted Color Pie Cube" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.TimotheeSimonotsTwistedColorPieCube"/>
|
||||||
|
<draftCube name="MTGA Cube 2020 April" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.MTGACube2020April"/>
|
||||||
|
<draftCube name="MTGO Cube March 2014" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.MTGOMarchCube2014"/>
|
||||||
|
<draftCube name="MTGO Legacy Cube" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegacyCube"/>
|
||||||
|
<draftCube name="MTGO Legacy Cube 2015 March" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegacyCubeMarch2015"/>
|
||||||
|
<draftCube name="MTGO Legacy Cube 2015 September" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegacyCubeSeptember2015"/>
|
||||||
|
<draftCube name="MTGO Legacy Cube 2016 January" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegacyCubeJanuary2016"/>
|
||||||
|
<draftCube name="MTGO Legacy Cube 2016 September" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegacyCubeSeptember2016"/>
|
||||||
|
<draftCube name="MTGO Legacy Cube 2017 January" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegacyCubeJanuary2017"/>
|
||||||
|
<draftCube name="MTGO Legacy Cube 2017 April" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegacyCubeApril2017"/>
|
||||||
|
<draftCube name="MTGO Legacy Cube 2018 February" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegacyCube2018February"/>
|
||||||
|
<draftCube name="MTGO Legacy Cube 2019 July" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegacyCubeJuly2019"/>
|
||||||
|
<draftCube name="MTGO Legendary Cube" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegendaryCube"/>
|
||||||
|
<draftCube name="MTGO Legendary Cube April 2016" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegendaryCubeApril2016"/>
|
||||||
|
<draftCube name="MTGO Modern Cube 2017" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.ModernCube2017"/>
|
||||||
|
<draftCube name="MTGO Vintage Cube 2013" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.VintageCube2013"/>
|
||||||
|
<draftCube name="MTGO Vintage Cube 2014" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.VintageCube2014"/>
|
||||||
|
<draftCube name="MTGO Vintage Cube 2015" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.VintageCube2015"/>
|
||||||
|
<draftCube name="MTGO Vintage Cube 2016" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.VintageCube2016"/>
|
||||||
|
<draftCube name="MTGO Vintage Cube June 2016" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.VintageCubeJune2016"/>
|
||||||
|
<draftCube name="MTGO Vintage Cube November 2016" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.VintageCubeNovember2016"/>
|
||||||
|
<draftCube name="MTGO Vintage Cube June 2017" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.VintageCubeJune2017"/>
|
||||||
|
<draftCube name="MTGO Vintage Cube December 2017" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.VintageCubeDecember2017"/>
|
||||||
|
<draftCube name="MTGO Vintage Cube June 2018" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.VintageCubeJune2018"/>
|
||||||
|
<draftCube name="MTGO Vintage Cube December 2018" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.VintageCubeDecember2018"/>
|
||||||
|
<draftCube name="MTGO Vintage Cube June 2019" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.VintageCubeJune2019"/>
|
||||||
|
<draftCube name="MTGO Vintage Cube December 2019" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.VintageCubeDecember2019"/>
|
||||||
|
<draftCube name="MTGO Vintage Cube April 2020" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.VintageCubeApril2020"/>
|
||||||
|
<draftCube name="MTGO Vintage Cube July 2020" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.VintageCubeJuly2020"/>
|
||||||
|
<draftCube name="SCG Con Cube 2018 December" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.ScgConCube2018December"/>
|
||||||
|
<draftCube name="The Peasant's Toolbox" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.PeasantsToolboxCube"/>
|
||||||
|
<draftCube name="www.MTGCube.com" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.MTGCube"/>
|
||||||
|
<draftCube name="Cube From Deck" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.CubeFromDeck"/>
|
||||||
|
</draftCubes>
|
||||||
|
<deckTypes>
|
||||||
|
<deckType name="Constructed - Standard" jar="mage-deck-constructed.jar" className="mage.deck.Standard"/>
|
||||||
|
<deckType name="Constructed - Extended" jar="mage-deck-constructed.jar" className="mage.deck.Extended"/>
|
||||||
|
<deckType name="Constructed - Frontier" jar="mage-deck-constructed.jar" className="mage.deck.Frontier"/>
|
||||||
|
<deckType name="Constructed - Pioneer" jar="mage-deck-constructed.jar" className="mage.deck.Pioneer"/>
|
||||||
|
<deckType name="Constructed - Modern" jar="mage-deck-constructed.jar" className="mage.deck.Modern"/>
|
||||||
|
<deckType name="Constructed - Modern - No Banned List" jar="mage-deck-constructed.jar" className="mage.deck.ModernNoBannedList"/>
|
||||||
|
<deckType name="Constructed - Eternal" jar="mage-deck-constructed.jar" className="mage.deck.Eternal"/>
|
||||||
|
<deckType name="Constructed - Legacy" jar="mage-deck-constructed.jar" className="mage.deck.Legacy"/>
|
||||||
|
<deckType name="Constructed - Vintage" jar="mage-deck-constructed.jar" className="mage.deck.Vintage"/>
|
||||||
|
<deckType name="Constructed - Pauper" jar="mage-deck-constructed.jar" className="mage.deck.Pauper"/>
|
||||||
|
<deckType name="Constructed - Historic" jar="mage-deck-constructed.jar" className="mage.deck.Historic"/>
|
||||||
|
<deckType name="Constructed - Historical Type 2" jar="mage-deck-constructed.jar" className="mage.deck.HistoricalType2"/>
|
||||||
|
<deckType name="Constructed - Super Type 2" jar="mage-deck-constructed.jar" className="mage.deck.SuperType2"/>
|
||||||
|
<deckType name="Constructed - Australian Highlander" jar="mage-deck-constructed.jar" className="mage.deck.AusHighlander"/>
|
||||||
|
<deckType name="Constructed - Canadian Highlander" jar="mage-deck-constructed.jar" className="mage.deck.CanadianHighlander"/>
|
||||||
|
<deckType name="Constructed - Old School 93/94" jar="mage-deck-constructed.jar" className="mage.deck.OldSchool9394"/>
|
||||||
|
<deckType name="Constructed - Old School 93/94 - Italian Rules" jar="mage-deck-constructed.jar" className="mage.deck.OldSchool9394Italian"/>
|
||||||
|
<deckType name="Constructed - Old School 93/94 - Channel Fireball Rules" jar="mage-deck-constructed.jar" className="mage.deck.OldSchool9394CFB"/>
|
||||||
|
<deckType name="Constructed - Old School 93/94 - EudoGames Rules" jar="mage-deck-constructed.jar" className="mage.deck.OldSchool9394EG"/>
|
||||||
|
<deckType name="Constructed - Old School 93/94 - EC Rules" jar="mage-deck-constructed.jar" className="mage.deck.OldSchool9394EC"/>
|
||||||
|
<deckType name="Constructed - Premodern" jar="mage-deck-constructed.jar" className="mage.deck.Premodern"/>
|
||||||
|
<deckType name="Constructed - Freeform" jar="mage-deck-constructed.jar" className="mage.deck.Freeform"/>
|
||||||
|
<deckType name="Variant Magic - Commander" jar="mage-deck-constructed.jar" className="mage.deck.Commander"/>
|
||||||
|
<deckType name="Variant Magic - Duel Commander" jar="mage-deck-constructed.jar" className="mage.deck.DuelCommander"/>
|
||||||
|
<deckType name="Variant Magic - MTGO 1v1 Commander" jar="mage-deck-constructed.jar" className="mage.deck.MTGO1v1Commander"/>
|
||||||
|
<deckType name="Variant Magic - Centurion Commander" jar="mage-deck-constructed.jar" className="mage.deck.CenturionCommander"/>
|
||||||
|
<deckType name="Variant Magic - Tiny Leaders" jar="mage-deck-constructed.jar" className="mage.deck.TinyLeaders"/>
|
||||||
|
<deckType name="Variant Magic - Momir Basic" jar="mage-deck-constructed.jar" className="mage.deck.Momir"/>
|
||||||
|
<deckType name="Variant Magic - Penny Dreadful Commander" jar="mage-deck-constructed.jar" className="mage.deck.PennyDreadfulCommander"/>
|
||||||
|
<deckType name="Variant Magic - Freeform Commander" jar="mage-deck-constructed.jar" className="mage.deck.FreeformCommander"/>
|
||||||
|
<deckType name="Variant Magic - Freeform Unlimited Commander" jar="mage-deck-constructed.jar" className="mage.deck.FreeformUnlimitedCommander"/>
|
||||||
|
<deckType name="Variant Magic - Brawl" jar="mage-deck-constructed.jar" className="mage.deck.Brawl"/>
|
||||||
|
<deckType name="Variant Magic - Oathbreaker" jar="mage-deck-constructed.jar" className="mage.deck.Oathbreaker"/>
|
||||||
|
<deckType name="Block Constructed - Amonkhet" jar="mage-deck-constructed.jar" className="mage.deck.AmonkhetBlock"/>
|
||||||
|
<deckType name="Block Constructed - Battle for Zendikar" jar="mage-deck-constructed.jar" className="mage.deck.BattleForZendikarBlock"/>
|
||||||
|
<deckType name="Block Constructed - Innistrad" jar="mage-deck-constructed.jar" className="mage.deck.InnistradBlock"/>
|
||||||
|
<deckType name="Block Constructed - Ixalan" jar="mage-deck-constructed.jar" className="mage.deck.IxalanBlock"/>
|
||||||
|
<deckType name="Block Constructed - Kaladesh" jar="mage-deck-constructed.jar" className="mage.deck.KaladeshBlock"/>
|
||||||
|
<deckType name="Block Constructed - Kamigawa" jar="mage-deck-constructed.jar" className="mage.deck.KamigawaBlock"/>
|
||||||
|
<deckType name="Block Constructed - Khans of Tarkir" jar="mage-deck-constructed.jar" className="mage.deck.KhansOfTarkirBlock"/>
|
||||||
|
<deckType name="Block Constructed - Lorwyn" jar="mage-deck-constructed.jar" className="mage.deck.LorwynBlock"/>
|
||||||
|
<deckType name="Block Constructed - Return to Ravnica" jar="mage-deck-constructed.jar" className="mage.deck.ReturnToRavnicaBlock"/>
|
||||||
|
<deckType name="Block Constructed - Scars of Mirrodin" jar="mage-deck-constructed.jar" className="mage.deck.ScarsOfMirrodinBlock"/>
|
||||||
|
<deckType name="Block Constructed - Shadowmoor" jar="mage-deck-constructed.jar" className="mage.deck.ShadowmoorBlock"/>
|
||||||
|
<deckType name="Block Constructed - Shadows over Innistrad" jar="mage-deck-constructed.jar" className="mage.deck.ShadowsOverInnistradBlock"/>
|
||||||
|
<deckType name="Block Constructed - Shards of Alara" jar="mage-deck-constructed.jar" className="mage.deck.ShardsOfAlaraBlock"/>
|
||||||
|
<deckType name="Block Constructed - Theros" jar="mage-deck-constructed.jar" className="mage.deck.TherosBlock"/>
|
||||||
|
<deckType name="Block Constructed - Zendikar" jar="mage-deck-constructed.jar" className="mage.deck.ZendikarBlock"/>
|
||||||
|
<deckType name="Block Constructed Custom - Star Wars" jar="mage-deck-constructed.jar" className="mage.deck.StarWarsBlock"/>
|
||||||
|
<deckType name="Limited" jar="mage-deck-limited.jar" className="mage.deck.Limited"/>
|
||||||
|
</deckTypes>
|
||||||
|
</config>
|
|
@ -32,7 +32,7 @@ public final class AgonyWarp extends CardImpl {
|
||||||
|
|
||||||
// Target creature gets -0/-3 until end of turn.
|
// Target creature gets -0/-3 until end of turn.
|
||||||
Effect effect2 = new BoostTargetEffect(-0,-3, Duration.EndOfTurn);
|
Effect effect2 = new BoostTargetEffect(-0,-3, Duration.EndOfTurn);
|
||||||
effect2.setText("<br></br>Target creature gets -0/-3 until end of turn");
|
effect2.setText("<br><br>Target creature gets -0/-3 until end of turn");
|
||||||
effect2.setTargetPointer(SecondTargetPointer.getInstance());
|
effect2.setTargetPointer(SecondTargetPointer.getInstance());
|
||||||
this.getSpellAbility().addEffect(effect2);
|
this.getSpellAbility().addEffect(effect2);
|
||||||
target = new TargetCreaturePermanent(new FilterCreaturePermanent("second creature (can be the same as the first)"));
|
target = new TargetCreaturePermanent(new FilterCreaturePermanent("second creature (can be the same as the first)"));
|
||||||
|
|
|
@ -78,7 +78,18 @@ class ArchelosLagoonMysticEffect extends ReplacementEffectImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||||
return !source.getSourceId().equals(((EntersTheBattlefieldEvent) event).getTarget().getId());
|
Permanent sourceObject = game.getPermanent(source.getSourceId());
|
||||||
|
if (sourceObject == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Permanent targetObject = ((EntersTheBattlefieldEvent) event).getTarget();
|
||||||
|
if (targetObject == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !sourceObject.getId().equals(targetObject.getId())
|
||||||
|
&& sourceObject.isTapped() == this.tapped;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -68,6 +68,6 @@ enum ArcticFoxesCondition implements Condition {
|
||||||
if (defenderId == null) {
|
if (defenderId == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return game.getBattlefield().contains(filter, defenderId, 1, game);
|
return game.getBattlefield().contains(filter, source.getSourceId(), defenderId, game, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -33,7 +33,7 @@ public final class AzoriusPloy extends CardImpl {
|
||||||
|
|
||||||
// Prevent all combat damage that would be dealt to target creature this turn.
|
// Prevent all combat damage that would be dealt to target creature this turn.
|
||||||
Effect effect2 = new PreventDamageToTargetEffect(Duration.EndOfTurn, true);
|
Effect effect2 = new PreventDamageToTargetEffect(Duration.EndOfTurn, true);
|
||||||
effect2.setText("<br></br>Prevent all combat damage that would be dealt to target creature this turn.");
|
effect2.setText("<br><br>Prevent all combat damage that would be dealt to target creature this turn.");
|
||||||
effect2.setTargetPointer(SecondTargetPointer.getInstance());
|
effect2.setTargetPointer(SecondTargetPointer.getInstance());
|
||||||
this.getSpellAbility().addEffect(effect2);
|
this.getSpellAbility().addEffect(effect2);
|
||||||
target = new TargetCreaturePermanent(new FilterCreaturePermanent("second creature (can be the same as the first)"));
|
target = new TargetCreaturePermanent(new FilterCreaturePermanent("second creature (can be the same as the first)"));
|
||||||
|
|
|
@ -63,16 +63,15 @@ class BacklashEffect extends OneShotEffect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
boolean applied = false;
|
|
||||||
Permanent targetCreature = game.getPermanent(targetPointer.getFirst(game, source));
|
Permanent targetCreature = game.getPermanent(targetPointer.getFirst(game, source));
|
||||||
if (targetCreature != null) {
|
if (targetCreature != null) {
|
||||||
applied = targetCreature.tap(source, game);
|
targetCreature.tap(source, game);
|
||||||
Player controller = game.getPlayer(targetCreature.getControllerId());
|
Player controller = game.getPlayer(targetCreature.getControllerId());
|
||||||
if (controller != null) {
|
if (controller != null) {
|
||||||
controller.damage(targetCreature.getPower().getValue(), source.getSourceId(), source, game);
|
controller.damage(targetCreature.getPower().getValue(), targetCreature.getId(), source, game);
|
||||||
applied = true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return applied;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
|
|
||||||
package mage.cards.b;
|
package mage.cards.b;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
import mage.abilities.effects.common.counter.DistributeCountersEffect;
|
import mage.abilities.effects.common.counter.DistributeCountersEffect;
|
||||||
import mage.abilities.keyword.MiracleAbility;
|
import mage.abilities.keyword.MiracleAbility;
|
||||||
|
@ -11,15 +9,15 @@ import mage.constants.CardType;
|
||||||
import mage.counters.CounterType;
|
import mage.counters.CounterType;
|
||||||
import mage.target.common.TargetCreaturePermanentAmount;
|
import mage.target.common.TargetCreaturePermanentAmount;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author North
|
* @author North
|
||||||
*/
|
*/
|
||||||
public final class BlessingsOfNature extends CardImpl {
|
public final class BlessingsOfNature extends CardImpl {
|
||||||
|
|
||||||
public BlessingsOfNature(UUID ownerId, CardSetInfo setInfo) {
|
public BlessingsOfNature(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{4}{G}");
|
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{G}");
|
||||||
|
|
||||||
|
|
||||||
// Distribute four +1/+1 counters among any number of target creatures.
|
// Distribute four +1/+1 counters among any number of target creatures.
|
||||||
this.getSpellAbility().addEffect(new DistributeCountersEffect(CounterType.P1P1, 4, false, "any number of target creatures"));
|
this.getSpellAbility().addEffect(new DistributeCountersEffect(CounterType.P1P1, 4, false, "any number of target creatures"));
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
package mage.cards.c;
|
package mage.cards.c;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.StateTriggeredAbility;
|
import mage.abilities.StateTriggeredAbility;
|
||||||
import mage.abilities.common.SimpleStaticAbility;
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
|
@ -11,7 +8,6 @@ import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.cards.Card;
|
import mage.cards.Card;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import static mage.cards.c.CityInABottle.getArabianNightsNamePredicates;
|
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
|
@ -23,11 +19,15 @@ import mage.filter.predicate.mageobject.NamePredicate;
|
||||||
import mage.filter.predicate.permanent.TokenPredicate;
|
import mage.filter.predicate.permanent.TokenPredicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
import mage.game.events.GameEvent.EventType;
|
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import static mage.cards.c.CityInABottle.getArabianNightsNamePredicates;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author emerald000
|
* @author emerald000
|
||||||
*/
|
*/
|
||||||
public final class CityInABottle extends CardImpl {
|
public final class CityInABottle extends CardImpl {
|
||||||
|
@ -158,7 +158,7 @@ class CityInABottleStateTriggeredAbility extends StateTriggeredAbility {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
public boolean checkTrigger(GameEvent event, Game game) {
|
||||||
return game.getBattlefield().contains(filter, this.getControllerId(), game, 1);
|
return game.getBattlefield().contains(filter, this.getSourceId(), this.getControllerId(), game, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
|
|
||||||
package mage.cards.c;
|
package mage.cards.c;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
|
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
|
@ -18,14 +16,15 @@ import mage.filter.predicate.mageobject.AbilityPredicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author emerald000
|
* @author emerald000
|
||||||
*/
|
*/
|
||||||
public final class ConcertedEffort extends CardImpl {
|
public final class ConcertedEffort extends CardImpl {
|
||||||
|
|
||||||
public ConcertedEffort(UUID ownerId, CardSetInfo setInfo) {
|
public ConcertedEffort(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{W}{W}");
|
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}");
|
||||||
|
|
||||||
// At the beginning of each upkeep, creatures you control gain flying until end of turn if a creature you control has flying. The same is true for fear, first strike, double strike, landwalk, protection, trample, and vigilance.
|
// At the beginning of each upkeep, creatures you control gain flying until end of turn if a creature you control has flying. The same is true for fear, first strike, double strike, landwalk, protection, trample, and vigilance.
|
||||||
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new ConcertedEffortEffect(), TargetController.ANY, false));
|
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new ConcertedEffortEffect(), TargetController.ANY, false));
|
||||||
|
@ -81,22 +80,22 @@ class ConcertedEffortEffect extends OneShotEffect {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
// Flying
|
// Flying
|
||||||
if (game.getBattlefield().contains(filterFlying, source.getControllerId(), 1, game)) {
|
if (game.getBattlefield().contains(filterFlying, source, game, 1)) {
|
||||||
game.addEffect(new GainAbilityControlledEffect(FlyingAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source);
|
game.addEffect(new GainAbilityControlledEffect(FlyingAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fear
|
// Fear
|
||||||
if (game.getBattlefield().contains(filterFear, source.getControllerId(), 1, game)) {
|
if (game.getBattlefield().contains(filterFear, source, game, 1)) {
|
||||||
game.addEffect(new GainAbilityControlledEffect(FearAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source);
|
game.addEffect(new GainAbilityControlledEffect(FearAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
// First strike
|
// First strike
|
||||||
if (game.getBattlefield().contains(filterFirstStrike, source.getControllerId(), 1, game)) {
|
if (game.getBattlefield().contains(filterFirstStrike, source, game, 1)) {
|
||||||
game.addEffect(new GainAbilityControlledEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source);
|
game.addEffect(new GainAbilityControlledEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Double strike
|
// Double strike
|
||||||
if (game.getBattlefield().contains(filterDoubleStrike, source.getControllerId(), 1, game)) {
|
if (game.getBattlefield().contains(filterDoubleStrike, source, game, 1)) {
|
||||||
game.addEffect(new GainAbilityControlledEffect(DoubleStrikeAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source);
|
game.addEffect(new GainAbilityControlledEffect(DoubleStrikeAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,12 +118,12 @@ class ConcertedEffortEffect extends OneShotEffect {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trample
|
// Trample
|
||||||
if (game.getBattlefield().contains(filterTrample, source.getControllerId(), 1, game)) {
|
if (game.getBattlefield().contains(filterTrample, source, game, 1)) {
|
||||||
game.addEffect(new GainAbilityControlledEffect(TrampleAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source);
|
game.addEffect(new GainAbilityControlledEffect(TrampleAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vigilance
|
// Vigilance
|
||||||
if (game.getBattlefield().contains(filterVigilance, source.getControllerId(), 1, game)) {
|
if (game.getBattlefield().contains(filterVigilance, source, game, 1)) {
|
||||||
game.addEffect(new GainAbilityControlledEffect(VigilanceAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source);
|
game.addEffect(new GainAbilityControlledEffect(VigilanceAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -70,18 +70,19 @@ class CourtOfAmbitionEffect extends OneShotEffect {
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
int discardCount = source.isControlledBy(game.getMonarchId()) ? 2 : 1;
|
int discardCount = source.isControlledBy(game.getMonarchId()) ? 2 : 1;
|
||||||
String message = "Discard " + CardUtil.numberToText(discardCount, "a")
|
String message = "Discard " + CardUtil.numberToText(discardCount, "a")
|
||||||
+ "card" + (discardCount > 1 ? 's' : "") + "? If not you lose " + (discardCount * 3) + " life";
|
+ " card" + (discardCount > 1 ? 's' : "") + "? If not you lose " + (discardCount * 3) + " life";
|
||||||
Map<UUID, Cards> discardMap = new HashMap<>();
|
Map<UUID, Cards> discardMap = new HashMap<>();
|
||||||
for (UUID playerId : game.getOpponents(source.getControllerId())) {
|
for (UUID playerId : game.getOpponents(source.getControllerId())) {
|
||||||
Player player = game.getPlayer(playerId);
|
Player player = game.getPlayer(playerId);
|
||||||
if (player == null) {
|
if (player == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (player.getHand().size() < discardCount || !player.chooseUse(outcome, message, source, game)) {
|
if (player.getHand().size() < discardCount || !player.chooseUse(Outcome.LoseLife, message, source, game)) {
|
||||||
player.loseLife(discardCount * 3, game, source, false);
|
player.loseLife(discardCount * 3, game, source, false);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
TargetDiscard target = new TargetDiscard(discardCount, StaticFilters.FILTER_CARD, playerId);
|
TargetDiscard target = new TargetDiscard(discardCount, StaticFilters.FILTER_CARD, playerId);
|
||||||
player.choose(outcome, target, source.getSourceId(), game);
|
player.choose(Outcome.Discard, target, source.getSourceId(), game);
|
||||||
discardMap.put(playerId, new CardsImpl(target.getTargets()));
|
discardMap.put(playerId, new CardsImpl(target.getTargets()));
|
||||||
}
|
}
|
||||||
for (Map.Entry<UUID, Cards> entry : discardMap.entrySet()) {
|
for (Map.Entry<UUID, Cards> entry : discardMap.entrySet()) {
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
|
|
||||||
package mage.cards.c;
|
package mage.cards.c;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
|
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
|
||||||
import mage.abilities.effects.common.DestroyTargetEffect;
|
import mage.abilities.effects.common.DestroyTargetEffect;
|
||||||
|
@ -12,27 +10,30 @@ import mage.constants.ComparisonType;
|
||||||
import mage.constants.TargetController;
|
import mage.constants.TargetController;
|
||||||
import mage.filter.FilterPermanent;
|
import mage.filter.FilterPermanent;
|
||||||
import mage.filter.common.FilterNonlandPermanent;
|
import mage.filter.common.FilterNonlandPermanent;
|
||||||
import mage.filter.predicate.Predicate;
|
import mage.filter.predicate.ObjectSourcePlayer;
|
||||||
|
import mage.filter.predicate.ObjectSourcePlayerPredicate;
|
||||||
import mage.filter.predicate.mageobject.ConvertedManaCostPredicate;
|
import mage.filter.predicate.mageobject.ConvertedManaCostPredicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.target.TargetPermanent;
|
import mage.target.TargetPermanent;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author cg5
|
* @author cg5
|
||||||
*/
|
*/
|
||||||
public final class CullingScales extends CardImpl {
|
public final class CullingScales extends CardImpl {
|
||||||
|
|
||||||
private static final FilterPermanent filterNonlandPermanentWithLowestCmc = new FilterNonlandPermanent(
|
private static final FilterPermanent filterNonlandPermanentWithLowestCmc = new FilterNonlandPermanent(
|
||||||
"nonland permanent with the lowest converted mana cost (<i>If two or more permanents are tied for lowest cost, target any one of them.</i>)"
|
"nonland permanent with the lowest converted mana cost (<i>If two or more permanents are tied for lowest cost, target any one of them.</i>)"
|
||||||
);
|
);
|
||||||
|
|
||||||
static {
|
static {
|
||||||
filterNonlandPermanentWithLowestCmc.add(new HasLowestCMCAmongstNonlandPermanentsPredicate());
|
filterNonlandPermanentWithLowestCmc.add(new HasLowestCMCAmongstNonlandPermanentsPredicate());
|
||||||
}
|
}
|
||||||
|
|
||||||
public CullingScales(UUID ownerId, CardSetInfo setInfo) {
|
public CullingScales(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}");
|
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
|
||||||
|
|
||||||
// At the beginning of your upkeep, destroy target nonland permanent with the lowest converted mana cost.
|
// At the beginning of your upkeep, destroy target nonland permanent with the lowest converted mana cost.
|
||||||
Ability ability = new BeginningOfUpkeepTriggeredAbility(new DestroyTargetEffect(), TargetController.YOU, false);
|
Ability ability = new BeginningOfUpkeepTriggeredAbility(new DestroyTargetEffect(), TargetController.YOU, false);
|
||||||
|
@ -48,16 +49,16 @@ public final class CullingScales extends CardImpl {
|
||||||
public CullingScales copy() {
|
public CullingScales copy() {
|
||||||
return new CullingScales(this);
|
return new CullingScales(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class HasLowestCMCAmongstNonlandPermanentsPredicate implements Predicate<Permanent> {
|
class HasLowestCMCAmongstNonlandPermanentsPredicate implements ObjectSourcePlayerPredicate<ObjectSourcePlayer<Permanent>> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Permanent input, Game game) {
|
public boolean apply(ObjectSourcePlayer<Permanent> input, Game game) {
|
||||||
FilterPermanent filter = new FilterNonlandPermanent();
|
FilterPermanent filter = new FilterNonlandPermanent();
|
||||||
filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, input.getConvertedManaCost()));
|
filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, input.getObject().getConvertedManaCost()));
|
||||||
return !game.getBattlefield().contains(filter, 1, game);
|
return !game.getBattlefield().contains(filter, input.getSourceId(), input.getPlayerId(), game, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -84,7 +84,7 @@ class DoomForetoldEffect extends OneShotEffect {
|
||||||
}
|
}
|
||||||
FilterPermanent filter2 = filter.copy();
|
FilterPermanent filter2 = filter.copy();
|
||||||
filter2.add(new ControllerIdPredicate(player.getId()));
|
filter2.add(new ControllerIdPredicate(player.getId()));
|
||||||
if (game.getBattlefield().contains(filter2, 1, game)) {
|
if (game.getBattlefield().contains(filter2, source, game, 1)) {
|
||||||
TargetPermanent target = new TargetPermanent(filter2);
|
TargetPermanent target = new TargetPermanent(filter2);
|
||||||
target.setNotTarget(true);
|
target.setNotTarget(true);
|
||||||
if (player.choose(Outcome.Sacrifice, target, source.getSourceId(), game)) {
|
if (player.choose(Outcome.Sacrifice, target, source.getSourceId(), game)) {
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
|
|
||||||
package mage.cards.h;
|
package mage.cards.h;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.MageObject;
|
import mage.MageObject;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
|
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
|
||||||
|
@ -24,14 +22,15 @@ import mage.filter.predicate.mageobject.NamePredicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author LevelX2
|
* @author LevelX2
|
||||||
*/
|
*/
|
||||||
public final class HedronAlignment extends CardImpl {
|
public final class HedronAlignment extends CardImpl {
|
||||||
|
|
||||||
public HedronAlignment(UUID ownerId, CardSetInfo setInfo) {
|
public HedronAlignment(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{U}");
|
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}");
|
||||||
|
|
||||||
// Hexproof
|
// Hexproof
|
||||||
this.addAbility(HexproofAbility.getInstance());
|
this.addAbility(HexproofAbility.getInstance());
|
||||||
|
@ -85,7 +84,7 @@ class HedronAlignmentEffect extends OneShotEffect {
|
||||||
Cards cardsToReveal = new CardsImpl();
|
Cards cardsToReveal = new CardsImpl();
|
||||||
controller.revealCards(sourceObject.getIdName(), cardsToReveal, game);
|
controller.revealCards(sourceObject.getIdName(), cardsToReveal, game);
|
||||||
// Check battlefield
|
// Check battlefield
|
||||||
if (!game.getBattlefield().contains(filterPermanent, source.getControllerId(), game, 1)) {
|
if (!game.getBattlefield().contains(filterPermanent, source, game, 1)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (controller.getHand().getCards(filterCard, source.getSourceId(), controller.getId(), game).isEmpty()) {
|
if (controller.getHand().getCards(filterCard, source.getSourceId(), controller.getId(), game).isEmpty()) {
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
|
|
||||||
package mage.cards.h;
|
package mage.cards.h;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.LeavesBattlefieldTriggeredAbility;
|
import mage.abilities.common.LeavesBattlefieldTriggeredAbility;
|
||||||
|
@ -17,12 +15,7 @@ import mage.abilities.keyword.CumulativeUpkeepAbility;
|
||||||
import mage.abilities.keyword.FlyingAbility;
|
import mage.abilities.keyword.FlyingAbility;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.*;
|
||||||
import mage.constants.SubType;
|
|
||||||
import mage.constants.Duration;
|
|
||||||
import mage.constants.Outcome;
|
|
||||||
import mage.constants.TargetController;
|
|
||||||
import mage.constants.Zone;
|
|
||||||
import mage.filter.FilterPermanent;
|
import mage.filter.FilterPermanent;
|
||||||
import mage.filter.common.FilterControlledLandPermanent;
|
import mage.filter.common.FilterControlledLandPermanent;
|
||||||
import mage.filter.common.FilterLandPermanent;
|
import mage.filter.common.FilterLandPermanent;
|
||||||
|
@ -34,13 +27,15 @@ import mage.target.Target;
|
||||||
import mage.target.TargetPermanent;
|
import mage.target.TargetPermanent;
|
||||||
import mage.target.targetpointer.FixedTarget;
|
import mage.target.targetpointer.FixedTarget;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author emerald000
|
* @author emerald000
|
||||||
*/
|
*/
|
||||||
public final class HeraldOfLeshrac extends CardImpl {
|
public final class HeraldOfLeshrac extends CardImpl {
|
||||||
|
|
||||||
private static final FilterPermanent filter = new FilterControlledLandPermanent("land you control but don't own");
|
private static final FilterPermanent filter = new FilterControlledLandPermanent("land you control but don't own");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
filter.add(TargetController.NOT_YOU.getOwnerPredicate());
|
filter.add(TargetController.NOT_YOU.getOwnerPredicate());
|
||||||
}
|
}
|
||||||
|
@ -78,6 +73,7 @@ public final class HeraldOfLeshrac extends CardImpl {
|
||||||
class HeraldOfLeshracCumulativeCost extends CostImpl {
|
class HeraldOfLeshracCumulativeCost extends CostImpl {
|
||||||
|
|
||||||
private static final FilterPermanent filter = new FilterLandPermanent("land you don't control");
|
private static final FilterPermanent filter = new FilterLandPermanent("land you don't control");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
filter.add(TargetController.NOT_YOU.getControllerPredicate());
|
filter.add(TargetController.NOT_YOU.getControllerPredicate());
|
||||||
}
|
}
|
||||||
|
@ -105,7 +101,7 @@ class HeraldOfLeshracCumulativeCost extends CostImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) {
|
public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) {
|
||||||
return game.getBattlefield().contains(filter, controllerId, game, 1);
|
return game.getBattlefield().contains(filter, source.getSourceId(), controllerId, game, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,24 +1,18 @@
|
||||||
|
|
||||||
package mage.cards.i;
|
package mage.cards.i;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.abilities.common.SimpleStaticAbility;
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
import mage.abilities.effects.common.AttachEffect;
|
import mage.abilities.effects.common.AttachEffect;
|
||||||
import mage.abilities.effects.common.PreventDamageToAttachedEffect;
|
import mage.abilities.effects.common.PreventDamageToAttachedEffect;
|
||||||
import mage.abilities.keyword.EnchantAbility;
|
import mage.abilities.keyword.EnchantAbility;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.AttachmentType;
|
import mage.constants.*;
|
||||||
import mage.constants.CardType;
|
|
||||||
import mage.constants.Duration;
|
|
||||||
import mage.constants.Outcome;
|
|
||||||
import mage.constants.SubType;
|
|
||||||
import mage.constants.Zone;
|
|
||||||
import mage.target.TargetPermanent;
|
import mage.target.TargetPermanent;
|
||||||
import mage.target.common.TargetCreaturePermanent;
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author L_J
|
* @author L_J
|
||||||
*/
|
*/
|
||||||
public final class Inviolability extends CardImpl {
|
public final class Inviolability extends CardImpl {
|
||||||
|
@ -34,7 +28,9 @@ public final class Inviolability extends CardImpl {
|
||||||
this.addAbility(new EnchantAbility(auraTarget.getTargetName()));
|
this.addAbility(new EnchantAbility(auraTarget.getTargetName()));
|
||||||
|
|
||||||
// Prevent all damage that would be dealt to enchanted creature.
|
// Prevent all damage that would be dealt to enchanted creature.
|
||||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new PreventDamageToAttachedEffect(Duration.WhileOnBattlefield, AttachmentType.EQUIPMENT, false)));
|
this.addAbility(new SimpleStaticAbility(new PreventDamageToAttachedEffect(
|
||||||
|
Duration.WhileOnBattlefield, AttachmentType.AURA, false
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Inviolability(final Inviolability card) {
|
public Inviolability(final Inviolability card) {
|
||||||
|
|
|
@ -103,62 +103,62 @@ class MajesticMyriarchEffect extends OneShotEffect {
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
|
|
||||||
// Flying
|
// Flying
|
||||||
if (game.getBattlefield().contains(filterFlying, source.getControllerId(), 1, game)) {
|
if (game.getBattlefield().containsControlled(filterFlying, source, game, 1)) {
|
||||||
game.addEffect(new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.EndOfTurn), source);
|
game.addEffect(new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.EndOfTurn), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
// First strike
|
// First strike
|
||||||
if (game.getBattlefield().contains(filterFirstStrike, source.getControllerId(), 1, game)) {
|
if (game.getBattlefield().containsControlled(filterFirstStrike, source, game, 1)) {
|
||||||
game.addEffect(new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn), source);
|
game.addEffect(new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Double strike
|
// Double strike
|
||||||
if (game.getBattlefield().contains(filterDoubleStrike, source.getControllerId(), 1, game)) {
|
if (game.getBattlefield().containsControlled(filterDoubleStrike, source, game, 1)) {
|
||||||
game.addEffect(new GainAbilitySourceEffect(DoubleStrikeAbility.getInstance(), Duration.EndOfTurn), source);
|
game.addEffect(new GainAbilitySourceEffect(DoubleStrikeAbility.getInstance(), Duration.EndOfTurn), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deathtouch
|
// Deathtouch
|
||||||
if (game.getBattlefield().contains(filterDeathtouch, source.getControllerId(), 1, game)) {
|
if (game.getBattlefield().containsControlled(filterDeathtouch, source, game, 1)) {
|
||||||
game.addEffect(new GainAbilitySourceEffect(DeathtouchAbility.getInstance(), Duration.EndOfTurn), source);
|
game.addEffect(new GainAbilitySourceEffect(DeathtouchAbility.getInstance(), Duration.EndOfTurn), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Haste
|
// Haste
|
||||||
if (game.getBattlefield().contains(filterHaste, source.getControllerId(), 1, game)) {
|
if (game.getBattlefield().containsControlled(filterHaste, source, game, 1)) {
|
||||||
game.addEffect(new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.EndOfTurn), source);
|
game.addEffect(new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.EndOfTurn), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hexproof
|
// Hexproof
|
||||||
if (game.getBattlefield().contains(filterHexproof, source.getControllerId(), 1, game)) {
|
if (game.getBattlefield().containsControlled(filterHexproof, source, game, 1)) {
|
||||||
game.addEffect(new GainAbilitySourceEffect(HexproofAbility.getInstance(), Duration.EndOfTurn), source);
|
game.addEffect(new GainAbilitySourceEffect(HexproofAbility.getInstance(), Duration.EndOfTurn), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Indestructible
|
// Indestructible
|
||||||
if (game.getBattlefield().contains(filterIndestructible, source.getControllerId(), 1, game)) {
|
if (game.getBattlefield().containsControlled(filterIndestructible, source, game, 1)) {
|
||||||
game.addEffect(new GainAbilitySourceEffect(IndestructibleAbility.getInstance(), Duration.EndOfTurn), source);
|
game.addEffect(new GainAbilitySourceEffect(IndestructibleAbility.getInstance(), Duration.EndOfTurn), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lifelink
|
// Lifelink
|
||||||
if (game.getBattlefield().contains(filterLifelink, source.getControllerId(), 1, game)) {
|
if (game.getBattlefield().containsControlled(filterLifelink, source, game, 1)) {
|
||||||
game.addEffect(new GainAbilitySourceEffect(LifelinkAbility.getInstance(), Duration.EndOfTurn), source);
|
game.addEffect(new GainAbilitySourceEffect(LifelinkAbility.getInstance(), Duration.EndOfTurn), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Menace
|
// Menace
|
||||||
if (game.getBattlefield().contains(filterMenace, source.getControllerId(), 1, game)) {
|
if (game.getBattlefield().containsControlled(filterMenace, source, game, 1)) {
|
||||||
game.addEffect(new GainAbilitySourceEffect(new MenaceAbility(), Duration.EndOfTurn), source);
|
game.addEffect(new GainAbilitySourceEffect(new MenaceAbility(), Duration.EndOfTurn), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reach
|
// Reach
|
||||||
if (game.getBattlefield().contains(filterReach, source.getControllerId(), 1, game)) {
|
if (game.getBattlefield().containsControlled(filterReach, source, game, 1)) {
|
||||||
game.addEffect(new GainAbilitySourceEffect(ReachAbility.getInstance(), Duration.EndOfTurn), source);
|
game.addEffect(new GainAbilitySourceEffect(ReachAbility.getInstance(), Duration.EndOfTurn), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trample
|
// Trample
|
||||||
if (game.getBattlefield().contains(filterTrample, source.getControllerId(), 1, game)) {
|
if (game.getBattlefield().containsControlled(filterTrample, source, game, 1)) {
|
||||||
game.addEffect(new GainAbilitySourceEffect(TrampleAbility.getInstance(), Duration.EndOfTurn), source);
|
game.addEffect(new GainAbilitySourceEffect(TrampleAbility.getInstance(), Duration.EndOfTurn), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vigilance
|
// Vigilance
|
||||||
if (game.getBattlefield().contains(filterVigilance, source.getControllerId(), 1, game)) {
|
if (game.getBattlefield().containsControlled(filterVigilance, source, game, 1)) {
|
||||||
game.addEffect(new GainAbilitySourceEffect(VigilanceAbility.getInstance(), Duration.EndOfTurn), source);
|
game.addEffect(new GainAbilitySourceEffect(VigilanceAbility.getInstance(), Duration.EndOfTurn), source);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -32,7 +32,7 @@ public final class MartialGlory extends CardImpl {
|
||||||
|
|
||||||
// Target creature gets +0/+3 until end of turn.
|
// Target creature gets +0/+3 until end of turn.
|
||||||
Effect effect2 = new BoostTargetEffect(0,3, Duration.EndOfTurn);
|
Effect effect2 = new BoostTargetEffect(0,3, Duration.EndOfTurn);
|
||||||
effect2.setText("<br></br>Target creature gets +0/+3 until end of turn");
|
effect2.setText("<br><br>Target creature gets +0/+3 until end of turn");
|
||||||
effect2.setTargetPointer(SecondTargetPointer.getInstance());
|
effect2.setTargetPointer(SecondTargetPointer.getInstance());
|
||||||
target = new TargetCreaturePermanent(new FilterCreaturePermanent("second creature (can be the same as the first)"));
|
target = new TargetCreaturePermanent(new FilterCreaturePermanent("second creature (can be the same as the first)"));
|
||||||
this.getSpellAbility().addEffect(effect2);
|
this.getSpellAbility().addEffect(effect2);
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
package mage.cards.o;
|
package mage.cards.o;
|
||||||
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
|
@ -94,67 +93,67 @@ class OdricLunarchMarshalEffect extends OneShotEffect {
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
|
|
||||||
// First strike
|
// First strike
|
||||||
if (game.getBattlefield().contains(filterFirstStrike, source.getControllerId(), 1, game)) {
|
if (game.getBattlefield().containsControlled(filterFirstStrike, source, game, 1)) {
|
||||||
game.addEffect(new GainAbilityControlledEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source);
|
game.addEffect(new GainAbilityControlledEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flying
|
// Flying
|
||||||
if (game.getBattlefield().contains(filterFlying, source.getControllerId(), 1, game)) {
|
if (game.getBattlefield().containsControlled(filterFlying, source, game, 1)) {
|
||||||
game.addEffect(new GainAbilityControlledEffect(FlyingAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source);
|
game.addEffect(new GainAbilityControlledEffect(FlyingAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deathtouch
|
// Deathtouch
|
||||||
if (game.getBattlefield().contains(filterDeathtouch, source.getControllerId(), 1, game)) {
|
if (game.getBattlefield().containsControlled(filterDeathtouch, source, game, 1)) {
|
||||||
game.addEffect(new GainAbilityControlledEffect(DeathtouchAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source);
|
game.addEffect(new GainAbilityControlledEffect(DeathtouchAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Double strike
|
// Double strike
|
||||||
if (game.getBattlefield().contains(filterDoubleStrike, source.getControllerId(), 1, game)) {
|
if (game.getBattlefield().containsControlled(filterDoubleStrike, source, game, 1)) {
|
||||||
game.addEffect(new GainAbilityControlledEffect(DoubleStrikeAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source);
|
game.addEffect(new GainAbilityControlledEffect(DoubleStrikeAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Haste
|
// Haste
|
||||||
if (game.getBattlefield().contains(filterHaste, source.getControllerId(), 1, game)) {
|
if (game.getBattlefield().containsControlled(filterHaste, source, game, 1)) {
|
||||||
game.addEffect(new GainAbilityControlledEffect(HasteAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source);
|
game.addEffect(new GainAbilityControlledEffect(HasteAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hexproof
|
// Hexproof
|
||||||
if (game.getBattlefield().contains(filterHexproof, source.getControllerId(), 1, game)) {
|
if (game.getBattlefield().containsControlled(filterHexproof, source, game, 1)) {
|
||||||
game.addEffect(new GainAbilityControlledEffect(HexproofAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source);
|
game.addEffect(new GainAbilityControlledEffect(HexproofAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Indestructible
|
// Indestructible
|
||||||
if (game.getBattlefield().contains(filterIndestructible, source.getControllerId(), 1, game)) {
|
if (game.getBattlefield().containsControlled(filterIndestructible, source, game, 1)) {
|
||||||
game.addEffect(new GainAbilityControlledEffect(IndestructibleAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source);
|
game.addEffect(new GainAbilityControlledEffect(IndestructibleAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lifelink
|
// Lifelink
|
||||||
if (game.getBattlefield().contains(filterLifelink, source.getControllerId(), 1, game)) {
|
if (game.getBattlefield().containsControlled(filterLifelink, source, game, 1)) {
|
||||||
game.addEffect(new GainAbilityControlledEffect(LifelinkAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source);
|
game.addEffect(new GainAbilityControlledEffect(LifelinkAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Menace
|
// Menace
|
||||||
if (game.getBattlefield().contains(filterMenace, source.getControllerId(), 1, game)) {
|
if (game.getBattlefield().containsControlled(filterMenace, source, game, 1)) {
|
||||||
game.addEffect(new GainAbilityControlledEffect(new MenaceAbility(), Duration.EndOfTurn, filterCreatures), source);
|
game.addEffect(new GainAbilityControlledEffect(new MenaceAbility(), Duration.EndOfTurn, filterCreatures), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reach
|
// Reach
|
||||||
if (game.getBattlefield().contains(filterReach, source.getControllerId(), 1, game)) {
|
if (game.getBattlefield().containsControlled(filterReach, source, game, 1)) {
|
||||||
game.addEffect(new GainAbilityControlledEffect(ReachAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source);
|
game.addEffect(new GainAbilityControlledEffect(ReachAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skulk
|
// Skulk
|
||||||
if (game.getBattlefield().contains(filterSkulk, source.getControllerId(), 1, game)) {
|
if (game.getBattlefield().containsControlled(filterSkulk, source, game, 1)) {
|
||||||
game.addEffect(new GainAbilityControlledEffect(new SkulkAbility(), Duration.EndOfTurn, filterCreatures), source);
|
game.addEffect(new GainAbilityControlledEffect(new SkulkAbility(), Duration.EndOfTurn, filterCreatures), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trample
|
// Trample
|
||||||
if (game.getBattlefield().contains(filterTrample, source.getControllerId(), 1, game)) {
|
if (game.getBattlefield().containsControlled(filterTrample, source, game, 1)) {
|
||||||
game.addEffect(new GainAbilityControlledEffect(TrampleAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source);
|
game.addEffect(new GainAbilityControlledEffect(TrampleAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vigilance
|
// Vigilance
|
||||||
if (game.getBattlefield().contains(filterVigilance, source.getControllerId(), 1, game)) {
|
if (game.getBattlefield().containsControlled(filterVigilance, source, game, 1)) {
|
||||||
game.addEffect(new GainAbilityControlledEffect(VigilanceAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source);
|
game.addEffect(new GainAbilityControlledEffect(VigilanceAbility.getInstance(), Duration.EndOfTurn, filterCreatures), source);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
59
Mage.Sets/src/mage/cards/r/Realmwalker.java
Normal file
59
Mage.Sets/src/mage/cards/r/Realmwalker.java
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
package mage.cards.r;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.common.AsEntersBattlefieldAbility;
|
||||||
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
|
import mage.abilities.effects.common.ChooseCreatureTypeEffect;
|
||||||
|
import mage.abilities.effects.common.continuous.LookAtTopCardOfLibraryAnyTimeEffect;
|
||||||
|
import mage.abilities.effects.common.continuous.PlayTheTopCardEffect;
|
||||||
|
import mage.abilities.keyword.ChangelingAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Outcome;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.filter.common.FilterCreatureCard;
|
||||||
|
import mage.filter.predicate.mageobject.ChosenSubtypePredicate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author weirddan455
|
||||||
|
*/
|
||||||
|
public final class Realmwalker extends CardImpl {
|
||||||
|
|
||||||
|
private static final FilterCreatureCard filter = new FilterCreatureCard("cast creature spells of the chosen type");
|
||||||
|
static {
|
||||||
|
filter.add(ChosenSubtypePredicate.instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Realmwalker(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}");
|
||||||
|
|
||||||
|
this.subtype.add(SubType.SHAPESHIFTER);
|
||||||
|
this.power = new MageInt(2);
|
||||||
|
this.toughness = new MageInt(3);
|
||||||
|
|
||||||
|
// Changeling
|
||||||
|
this.setIsAllCreatureTypes(true);
|
||||||
|
this.addAbility(ChangelingAbility.getInstance());
|
||||||
|
|
||||||
|
// As Realmwalker enters the battlefield, choose a creature type.
|
||||||
|
this.addAbility(new AsEntersBattlefieldAbility(new ChooseCreatureTypeEffect(Outcome.Benefit)));
|
||||||
|
|
||||||
|
// You may look at the top card of your library any time.
|
||||||
|
this.addAbility(new SimpleStaticAbility(new LookAtTopCardOfLibraryAnyTimeEffect()));
|
||||||
|
|
||||||
|
// You may cast creature spells of the chosen type from the top of your library.
|
||||||
|
this.addAbility(new SimpleStaticAbility(new PlayTheTopCardEffect(filter)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Realmwalker(final Realmwalker card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Realmwalker copy() {
|
||||||
|
return new Realmwalker(this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,5 @@
|
||||||
|
|
||||||
package mage.cards.r;
|
package mage.cards.r;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
|
@ -16,14 +14,15 @@ import mage.players.Player;
|
||||||
import mage.target.TargetPermanent;
|
import mage.target.TargetPermanent;
|
||||||
import mage.target.common.TargetOpponent;
|
import mage.target.common.TargetOpponent;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author LevelX2
|
* @author LevelX2
|
||||||
*/
|
*/
|
||||||
public final class RemorselessPunishment extends CardImpl {
|
public final class RemorselessPunishment extends CardImpl {
|
||||||
|
|
||||||
public RemorselessPunishment(UUID ownerId, CardSetInfo setInfo) {
|
public RemorselessPunishment(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{B}{B}");
|
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{B}{B}");
|
||||||
|
|
||||||
// Target opponent loses 5 life unless that player discards two cards or sacrifices a creature or planeswalker. Repeat this process once.
|
// Target opponent loses 5 life unless that player discards two cards or sacrifices a creature or planeswalker. Repeat this process once.
|
||||||
getSpellAbility().addEffect(new RemorselessPunishmentEffect());
|
getSpellAbility().addEffect(new RemorselessPunishmentEffect());
|
||||||
|
@ -80,7 +79,7 @@ class RemorselessPunishmentEffect extends OneShotEffect {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (game.getBattlefield().contains(filter, opponent.getId(), 1, game)) {
|
if (game.getBattlefield().containsControlled(filter, source.getSourceId(), opponent.getId(), game, 1)) {
|
||||||
if (opponent.chooseUse(outcome, "Choose your " + iteration + " punishment.", null, "Sacrifice a creature or planeswalker", "Lose 5 life", source, game)) {
|
if (opponent.chooseUse(outcome, "Choose your " + iteration + " punishment.", null, "Sacrifice a creature or planeswalker", "Lose 5 life", source, game)) {
|
||||||
TargetPermanent target = new TargetPermanent(1, 1, filter, true);
|
TargetPermanent target = new TargetPermanent(1, 1, filter, true);
|
||||||
if (target.choose(Outcome.Sacrifice, opponent.getId(), source.getId(), game)) {
|
if (target.choose(Outcome.Sacrifice, opponent.getId(), source.getId(), game)) {
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
|
|
||||||
package mage.cards.s;
|
package mage.cards.s;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.Cost;
|
||||||
|
@ -11,8 +9,8 @@ import mage.abilities.keyword.TrampleAbility;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.SubType;
|
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
|
import mage.constants.SubType;
|
||||||
import mage.constants.TargetController;
|
import mage.constants.TargetController;
|
||||||
import mage.counters.CounterType;
|
import mage.counters.CounterType;
|
||||||
import mage.filter.common.FilterCreaturePermanent;
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
|
@ -22,8 +20,9 @@ import mage.players.Player;
|
||||||
import mage.target.Target;
|
import mage.target.Target;
|
||||||
import mage.target.common.TargetCreaturePermanent;
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author emerald000
|
* @author emerald000
|
||||||
*/
|
*/
|
||||||
public final class ShelteringAncient extends CardImpl {
|
public final class ShelteringAncient extends CardImpl {
|
||||||
|
@ -82,7 +81,7 @@ class ShelteringAncientCost extends CostImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) {
|
public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) {
|
||||||
return game.getBattlefield().contains(filter, source.getSourceId(), game, 1);
|
return game.getBattlefield().contains(filter, source, game, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
98
Mage.Sets/src/mage/cards/s/SurtlandElementalist.java
Normal file
98
Mage.Sets/src/mage/cards/s/SurtlandElementalist.java
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
package mage.cards.s;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import mage.ApprovingObject;
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.AttacksTriggeredAbility;
|
||||||
|
import mage.abilities.costs.OrCost;
|
||||||
|
import mage.abilities.costs.common.RevealTargetFromHandCost;
|
||||||
|
import mage.abilities.costs.mana.GenericManaCost;
|
||||||
|
import mage.abilities.effects.OneShotEffect;
|
||||||
|
import mage.cards.Card;
|
||||||
|
import mage.constants.Outcome;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.filter.FilterCard;
|
||||||
|
import mage.filter.StaticFilters;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.players.Player;
|
||||||
|
import mage.target.common.TargetCardInHand;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author weirddan455
|
||||||
|
*/
|
||||||
|
public final class SurtlandElementalist extends CardImpl {
|
||||||
|
|
||||||
|
private static final FilterCard filter = new FilterCard("a Giant card from your hand");
|
||||||
|
static {
|
||||||
|
filter.add(SubType.GIANT.getPredicate());
|
||||||
|
}
|
||||||
|
|
||||||
|
public SurtlandElementalist(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{U}{U}");
|
||||||
|
|
||||||
|
this.subtype.add(SubType.GIANT);
|
||||||
|
this.subtype.add(SubType.WIZARD);
|
||||||
|
this.power = new MageInt(8);
|
||||||
|
this.toughness = new MageInt(8);
|
||||||
|
|
||||||
|
// As an additional cost to cast this spell, reveal a Giant card from your hand or pay {2}.
|
||||||
|
this.getSpellAbility().addCost(new OrCost(
|
||||||
|
new RevealTargetFromHandCost(new TargetCardInHand(filter)),
|
||||||
|
new GenericManaCost(2),
|
||||||
|
"reveal a Giant card from your hand or pay {2}"));
|
||||||
|
|
||||||
|
// Whenever Surtland Elementalist attacks, you may cast an instant or sorcery spell from your hand without paying its mana cost.
|
||||||
|
this.addAbility(new AttacksTriggeredAbility(new SurtlandElementalistEffect(), true));
|
||||||
|
}
|
||||||
|
|
||||||
|
private SurtlandElementalist(final SurtlandElementalist card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SurtlandElementalist copy() {
|
||||||
|
return new SurtlandElementalist(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SurtlandElementalistEffect extends OneShotEffect {
|
||||||
|
|
||||||
|
public SurtlandElementalistEffect () {
|
||||||
|
super(Outcome.PlayForFree);
|
||||||
|
this.staticText = "cast an instant or sorcery spell from your hand without paying its mana cost";
|
||||||
|
}
|
||||||
|
|
||||||
|
private SurtlandElementalistEffect(final SurtlandElementalistEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SurtlandElementalistEffect copy() {
|
||||||
|
return new SurtlandElementalistEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
Player player = game.getPlayer(source.getControllerId());
|
||||||
|
if (player != null) {
|
||||||
|
TargetCardInHand target = new TargetCardInHand(0, 1, StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY);
|
||||||
|
if (player.chooseTarget(Outcome.PlayForFree, target, source, game)) {
|
||||||
|
Card card = game.getCard(target.getFirstTarget());
|
||||||
|
if (card != null) {
|
||||||
|
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
|
||||||
|
boolean cardWasCast = player.cast(player.chooseAbilityForCast(card, game, true),
|
||||||
|
game, true, new ApprovingObject(source, game));
|
||||||
|
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
|
||||||
|
return cardWasCast;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,5 @@
|
||||||
|
|
||||||
package mage.cards.t;
|
package mage.cards.t;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.SimpleStaticAbility;
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
|
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
|
||||||
|
@ -18,8 +16,9 @@ import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author spjspj
|
* @author spjspj
|
||||||
*/
|
*/
|
||||||
public final class TheCheeseStandsAlone extends CardImpl {
|
public final class TheCheeseStandsAlone extends CardImpl {
|
||||||
|
@ -47,6 +46,7 @@ class CheeseStandsAloneContinuousEffect extends ContinuousRuleModifyingEffectImp
|
||||||
private static final FilterControlledPermanent filter = new FilterControlledPermanent();
|
private static final FilterControlledPermanent filter = new FilterControlledPermanent();
|
||||||
|
|
||||||
private boolean wonAlready = false;
|
private boolean wonAlready = false;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
filter.add(new NamePredicate("The Cheese Stands Alone"));
|
filter.add(new NamePredicate("The Cheese Stands Alone"));
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ class CheeseStandsAloneContinuousEffect extends ContinuousRuleModifyingEffectImp
|
||||||
}
|
}
|
||||||
|
|
||||||
public CheeseStandsAloneContinuousEffect(final CheeseStandsAloneContinuousEffect effect) {
|
public CheeseStandsAloneContinuousEffect(final CheeseStandsAloneContinuousEffect effect) {
|
||||||
super(effect);
|
super(effect);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -72,7 +72,7 @@ class CheeseStandsAloneContinuousEffect extends ContinuousRuleModifyingEffectImp
|
||||||
if (controller.getHand().isEmpty()) {
|
if (controller.getHand().isEmpty()) {
|
||||||
int numberPerms = new PermanentsOnBattlefieldCount(new FilterControlledPermanent()).calculate(game, source, this);
|
int numberPerms = new PermanentsOnBattlefieldCount(new FilterControlledPermanent()).calculate(game, source, this);
|
||||||
if (numberPerms == 1) {
|
if (numberPerms == 1) {
|
||||||
if (game.getBattlefield().contains(filter, source.getControllerId(), 1, game)) {
|
if (game.getBattlefield().containsControlled(filter, source, game, 1)) {
|
||||||
if (!wonAlready) {
|
if (!wonAlready) {
|
||||||
wonAlready = true;
|
wonAlready = true;
|
||||||
controller.won(game);
|
controller.won(game);
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
|
|
||||||
package mage.cards.t;
|
package mage.cards.t;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.ObjectColor;
|
import mage.ObjectColor;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.StateTriggeredAbility;
|
import mage.abilities.StateTriggeredAbility;
|
||||||
|
@ -31,8 +29,9 @@ import mage.filter.predicate.mageobject.NamePredicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author LoneFox
|
* @author LoneFox
|
||||||
*/
|
*/
|
||||||
public final class TidalInfluence extends CardImpl {
|
public final class TidalInfluence extends CardImpl {
|
||||||
|
@ -44,26 +43,26 @@ public final class TidalInfluence extends CardImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
public TidalInfluence(UUID ownerId, CardSetInfo setInfo) {
|
public TidalInfluence(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{U}");
|
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}");
|
||||||
|
|
||||||
// Cast Tidal Influence only if no permanents named Tidal Influence are on the battlefield.
|
// Cast Tidal Influence only if no permanents named Tidal Influence are on the battlefield.
|
||||||
this.getSpellAbility().addCost(new TidalInfluenceCost());
|
this.getSpellAbility().addCost(new TidalInfluenceCost());
|
||||||
// Tidal Influence enters the battlefield with a tide counter on it.
|
// Tidal Influence enters the battlefield with a tide counter on it.
|
||||||
this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.TIDE.createInstance()),
|
this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.TIDE.createInstance()),
|
||||||
"with a tide counter on it."));
|
"with a tide counter on it."));
|
||||||
// At the beginning of your upkeep, put a tide counter on Tidal Influence.
|
// At the beginning of your upkeep, put a tide counter on Tidal Influence.
|
||||||
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.TIDE.createInstance()),
|
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.TIDE.createInstance()),
|
||||||
TargetController.YOU, false));
|
TargetController.YOU, false));
|
||||||
// As long as there is exactly one tide counter on Tidal Influence, all blue creatures get -2/-0.
|
// As long as there is exactly one tide counter on Tidal Influence, all blue creatures get -2/-0.
|
||||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(
|
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(
|
||||||
new BoostAllEffect(-2, -0, Duration.WhileOnBattlefield, filter, false),
|
new BoostAllEffect(-2, -0, Duration.WhileOnBattlefield, filter, false),
|
||||||
new SourceHasCounterCondition(CounterType.TIDE, 1, 1),
|
new SourceHasCounterCondition(CounterType.TIDE, 1, 1),
|
||||||
"As long as there is exactly one tide counter on {this}, all blue creatures get -2/-0.")));
|
"As long as there is exactly one tide counter on {this}, all blue creatures get -2/-0.")));
|
||||||
// As long as there are exactly three tide counters on Tidal Influence, all blue creatures get +2/+0.
|
// As long as there are exactly three tide counters on Tidal Influence, all blue creatures get +2/+0.
|
||||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(
|
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(
|
||||||
new BoostAllEffect(2, -0, Duration.WhileOnBattlefield, filter, false),
|
new BoostAllEffect(2, -0, Duration.WhileOnBattlefield, filter, false),
|
||||||
new SourceHasCounterCondition(CounterType.TIDE, 3, 3),
|
new SourceHasCounterCondition(CounterType.TIDE, 3, 3),
|
||||||
"As long as there are exactly three tide counter on {this}, all blue creatures get +2/-0.")));
|
"As long as there are exactly three tide counter on {this}, all blue creatures get +2/-0.")));
|
||||||
// Whenever there are four tide counters on Tidal Influence, remove all tide counters from it.
|
// Whenever there are four tide counters on Tidal Influence, remove all tide counters from it.
|
||||||
this.addAbility(new TidalInfluenceTriggeredAbility(new RemoveAllCountersSourceEffect(CounterType.TIDE)));
|
this.addAbility(new TidalInfluenceTriggeredAbility(new RemoveAllCountersSourceEffect(CounterType.TIDE)));
|
||||||
}
|
}
|
||||||
|
@ -97,7 +96,7 @@ class TidalInfluenceCost extends CostImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) {
|
public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) {
|
||||||
return !game.getBattlefield().contains(filter, 1, game);
|
return !game.getBattlefield().contains(filter, source, game, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
|
|
||||||
package mage.cards.t;
|
package mage.cards.t;
|
||||||
|
|
||||||
import java.util.UUID;
|
import mage.MageObject;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.AsEntersBattlefieldAbility;
|
import mage.abilities.common.AsEntersBattlefieldAbility;
|
||||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||||
import mage.abilities.common.SimpleStaticAbility;
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
import mage.abilities.effects.Effect;
|
import mage.abilities.effects.Effect;
|
||||||
import mage.abilities.effects.common.AttachEffect;
|
import mage.abilities.effects.common.AttachEffect;
|
||||||
|
import mage.abilities.effects.common.ChooseCreatureTypeEffect;
|
||||||
import mage.abilities.effects.common.ChooseLandTypeEffect;
|
import mage.abilities.effects.common.ChooseLandTypeEffect;
|
||||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||||
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
|
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
|
||||||
|
@ -15,24 +15,24 @@ import mage.abilities.keyword.EnchantAbility;
|
||||||
import mage.abilities.keyword.LandwalkAbility;
|
import mage.abilities.keyword.LandwalkAbility;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.AttachmentType;
|
import mage.constants.*;
|
||||||
import mage.constants.CardType;
|
|
||||||
import mage.constants.SubType;
|
|
||||||
import mage.constants.Outcome;
|
|
||||||
import mage.constants.Zone;
|
|
||||||
import mage.filter.common.FilterLandPermanent;
|
import mage.filter.common.FilterLandPermanent;
|
||||||
import mage.filter.predicate.mageobject.ChosenSubtypePredicate;
|
import mage.filter.predicate.ObjectSourcePlayer;
|
||||||
|
import mage.filter.predicate.ObjectSourcePlayerPredicate;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
import mage.target.TargetPermanent;
|
import mage.target.TargetPermanent;
|
||||||
import mage.target.common.TargetCreaturePermanent;
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author emerald000
|
* @author emerald000
|
||||||
*/
|
*/
|
||||||
public final class TravelersCloak extends CardImpl {
|
public final class TravelersCloak extends CardImpl {
|
||||||
|
|
||||||
public TravelersCloak(UUID ownerId, CardSetInfo setInfo) {
|
public TravelersCloak(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{U}");
|
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}");
|
||||||
this.subtype.add(SubType.AURA);
|
this.subtype.add(SubType.AURA);
|
||||||
|
|
||||||
// Enchant creature
|
// Enchant creature
|
||||||
|
@ -41,18 +41,17 @@ public final class TravelersCloak extends CardImpl {
|
||||||
this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility));
|
this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility));
|
||||||
Ability ability = new EnchantAbility(auraTarget.getTargetName());
|
Ability ability = new EnchantAbility(auraTarget.getTargetName());
|
||||||
this.addAbility(ability);
|
this.addAbility(ability);
|
||||||
|
|
||||||
// As Traveler's Cloak enters the battlefield, choose a land type.
|
// As Traveler's Cloak enters the battlefield, choose a land type.
|
||||||
this.addAbility(new AsEntersBattlefieldAbility(new ChooseLandTypeEffect(Outcome.AddAbility)));
|
this.addAbility(new AsEntersBattlefieldAbility(new ChooseLandTypeEffect(Outcome.AddAbility)));
|
||||||
|
|
||||||
// When Traveler's Cloak enters the battlefield, draw a card.
|
// When Traveler's Cloak enters the battlefield, draw a card.
|
||||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1), false));
|
this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1), false));
|
||||||
|
|
||||||
// Enchanted creature has landwalk of the chosen type.
|
// Enchanted creature has landwalk of the chosen type.
|
||||||
FilterLandPermanent filter = new FilterLandPermanent("Landwalk of the chosen type");
|
FilterLandPermanent filter = new FilterLandPermanent("Landwalk of the chosen type");
|
||||||
filter.add(ChosenSubtypePredicate.instance);
|
filter.add(TravelersCloakChosenSubtypePredicate.instance);
|
||||||
Ability landwalkAbility = new LandwalkAbility(filter);
|
Effect effect = new TravelersCloakGainAbilityAttachedEffect(filter);
|
||||||
Effect effect = new GainAbilityAttachedEffect(landwalkAbility, AttachmentType.AURA);
|
|
||||||
effect.setText("Enchanted creature has landwalk of the chosen type");
|
effect.setText("Enchanted creature has landwalk of the chosen type");
|
||||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
|
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
|
||||||
}
|
}
|
||||||
|
@ -66,3 +65,35 @@ public final class TravelersCloak extends CardImpl {
|
||||||
return new TravelersCloak(this);
|
return new TravelersCloak(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TravelersCloakGainAbilityAttachedEffect extends GainAbilityAttachedEffect {
|
||||||
|
|
||||||
|
public TravelersCloakGainAbilityAttachedEffect(FilterLandPermanent filter) {
|
||||||
|
super(new LandwalkAbility(filter), AttachmentType.AURA);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterGain(Game game, Ability source, Permanent permanent, Ability addedAbility) {
|
||||||
|
super.afterGain(game, source, permanent, addedAbility);
|
||||||
|
|
||||||
|
// ChooseLandTypeEffect keep settings in original source, but we must transfer it to real permanent
|
||||||
|
Object val = game.getState().getValue(source.getSourceId() + "_type");
|
||||||
|
game.getState().setValue(permanent.getId() + "_landwalk_type", val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum TravelersCloakChosenSubtypePredicate implements ObjectSourcePlayerPredicate<ObjectSourcePlayer<MageObject>> {
|
||||||
|
instance;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(ObjectSourcePlayer<MageObject> input, Game game) {
|
||||||
|
SubType subType = ChooseCreatureTypeEffect.getChosenCreatureType(input.getSourceId(), game, "_landwalk_type");
|
||||||
|
return input.getObject().hasSubtype(subType, game);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Chosen subtype";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -107,7 +107,8 @@ class VivienMonstersAdvocateTokenEffect extends OneShotEffect {
|
||||||
if (permanent == null) {
|
if (permanent == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Choice choice = new ChoiceImpl();
|
Choice choice = new ChoiceImpl(true);
|
||||||
|
choice.setMessage("Choose vigilance, reach, or trample counter");
|
||||||
choice.setChoices(choices);
|
choice.setChoices(choices);
|
||||||
player.choose(outcome, choice, game);
|
player.choose(outcome, choice, game);
|
||||||
String chosen = choice.getChoice();
|
String chosen = choice.getChoice();
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
package mage.cards.w;
|
package mage.cards.w;
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
import mage.abilities.common.SimpleStaticAbility;
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
|
@ -25,8 +21,12 @@ import mage.target.TargetPermanent;
|
||||||
import mage.target.common.TargetControlledCreaturePermanent;
|
import mage.target.common.TargetControlledCreaturePermanent;
|
||||||
import mage.target.common.TargetCreaturePermanent;
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author emerald000
|
* @author emerald000
|
||||||
*/
|
*/
|
||||||
public final class WeightOfConscience extends CardImpl {
|
public final class WeightOfConscience extends CardImpl {
|
||||||
|
@ -84,8 +84,8 @@ class WeightOfConscienceEffect extends OneShotEffect {
|
||||||
// It was not blinked, use the standard method
|
// It was not blinked, use the standard method
|
||||||
enchantment = game.getPermanentOrLKIBattlefield(source.getSourceId());
|
enchantment = game.getPermanentOrLKIBattlefield(source.getSourceId());
|
||||||
}
|
}
|
||||||
if (controller != null
|
if (controller != null
|
||||||
&& enchantment != null
|
&& enchantment != null
|
||||||
&& enchantment.getAttachedTo() != null) {
|
&& enchantment.getAttachedTo() != null) {
|
||||||
Permanent creature = game.getPermanent(enchantment.getAttachedTo());
|
Permanent creature = game.getPermanent(enchantment.getAttachedTo());
|
||||||
if (creature != null) {
|
if (creature != null) {
|
||||||
|
@ -119,10 +119,10 @@ class WeightOfConscienceTarget extends TargetControlledCreaturePermanent {
|
||||||
if (player != null) {
|
if (player != null) {
|
||||||
// Choosing first target
|
// Choosing first target
|
||||||
if (this.getTargets().isEmpty()) {
|
if (this.getTargets().isEmpty()) {
|
||||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, game)) {
|
for (Permanent permanent : game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, sourceId, game)) {
|
||||||
for (SubType subtype : permanent.getSubtype(game)) {
|
for (SubType subtype : permanent.getSubtype(game)) {
|
||||||
if (subtype.getSubTypeSet() == SubTypeSet.CreatureType) {
|
if (subtype.getSubTypeSet() == SubTypeSet.CreatureType) {
|
||||||
if (game.getBattlefield().contains(new FilterControlledCreaturePermanent(subtype, subtype.toString()), sourceControllerId, game, 2)) {
|
if (game.getBattlefield().contains(new FilterControlledCreaturePermanent(subtype, subtype.toString()), sourceId, sourceControllerId, game, 2)) {
|
||||||
possibleTargets.add(permanent.getId());
|
possibleTargets.add(permanent.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,7 +133,7 @@ class WeightOfConscienceTarget extends TargetControlledCreaturePermanent {
|
||||||
UUID firstTargetId = this.getTargets().get(0);
|
UUID firstTargetId = this.getTargets().get(0);
|
||||||
Permanent firstTargetCreature = game.getPermanent(firstTargetId);
|
Permanent firstTargetCreature = game.getPermanent(firstTargetId);
|
||||||
if (firstTargetCreature != null) {
|
if (firstTargetCreature != null) {
|
||||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, game)) {
|
for (Permanent permanent : game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, sourceId, game)) {
|
||||||
if (!permanent.getId().equals(firstTargetId) && firstTargetCreature.shareCreatureTypes(permanent, game)) {
|
if (!permanent.getId().equals(firstTargetId) && firstTargetCreature.shareCreatureTypes(permanent, game)) {
|
||||||
possibleTargets.add(permanent.getId());
|
possibleTargets.add(permanent.getId());
|
||||||
}
|
}
|
||||||
|
@ -146,8 +146,8 @@ class WeightOfConscienceTarget extends TargetControlledCreaturePermanent {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) {
|
public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) {
|
||||||
for (Permanent permanent1 : game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, game)) {
|
for (Permanent permanent1 : game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, sourceId, game)) {
|
||||||
for (Permanent permanent2 : game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, game)) {
|
for (Permanent permanent2 : game.getBattlefield().getActivePermanents(filterUntapped, sourceControllerId, sourceId, game)) {
|
||||||
if (!Objects.equals(permanent1, permanent2) && permanent1.shareCreatureTypes(permanent2, game)) {
|
if (!Objects.equals(permanent1, permanent2) && permanent1.shareCreatureTypes(permanent2, game)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -162,10 +162,10 @@ class WeightOfConscienceTarget extends TargetControlledCreaturePermanent {
|
||||||
Permanent targetPermanent = game.getPermanent(id);
|
Permanent targetPermanent = game.getPermanent(id);
|
||||||
if (targetPermanent != null) {
|
if (targetPermanent != null) {
|
||||||
if (this.getTargets().isEmpty()) {
|
if (this.getTargets().isEmpty()) {
|
||||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(filterUntapped, source.getControllerId(), game)) {
|
for (Permanent permanent : game.getBattlefield().getActivePermanents(filterUntapped, source.getControllerId(), source.getSourceId(), game)) {
|
||||||
for (SubType subtype : permanent.getSubtype(game)) {
|
for (SubType subtype : permanent.getSubtype(game)) {
|
||||||
if (subtype.getSubTypeSet() == SubTypeSet.CreatureType) {
|
if (subtype.getSubTypeSet() == SubTypeSet.CreatureType) {
|
||||||
if (game.getBattlefield().contains(new FilterControlledCreaturePermanent(subtype, subtype.toString()), source.getControllerId(), game, 2)) {
|
if (game.getBattlefield().contains(new FilterControlledCreaturePermanent(subtype, subtype.toString()), source, game, 2)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -173,9 +173,7 @@ class WeightOfConscienceTarget extends TargetControlledCreaturePermanent {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Permanent firstTarget = game.getPermanent(this.getTargets().get(0));
|
Permanent firstTarget = game.getPermanent(this.getTargets().get(0));
|
||||||
if (firstTarget != null && firstTarget.shareCreatureTypes(targetPermanent, game)) {
|
return firstTarget != null && firstTarget.shareCreatureTypes(targetPermanent, game);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,7 @@ public final class Wirecat extends CardImpl {
|
||||||
@Override
|
@Override
|
||||||
public boolean applies(Permanent permanent, Ability source, Game game) {
|
public boolean applies(Permanent permanent, Ability source, Game game) {
|
||||||
if (permanent.getId().equals(source.getSourceId())) {
|
if (permanent.getId().equals(source.getSourceId())) {
|
||||||
return game.getBattlefield().contains(StaticFilters.FILTER_ENCHANTMENT_PERMANENT, 1, game);
|
return game.getBattlefield().contains(StaticFilters.FILTER_ENCHANTMENT_PERMANENT, source, game, 1);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,9 +44,11 @@ public final class Kaldheim extends ExpansionSet {
|
||||||
cards.add(new SetCardInfo("Gladewalker Ritualist", 392, Rarity.UNCOMMON, mage.cards.g.GladewalkerRitualist.class));
|
cards.add(new SetCardInfo("Gladewalker Ritualist", 392, Rarity.UNCOMMON, mage.cards.g.GladewalkerRitualist.class));
|
||||||
cards.add(new SetCardInfo("Hengegate Pathway", 260, Rarity.RARE, mage.cards.h.HengegatePathway.class));
|
cards.add(new SetCardInfo("Hengegate Pathway", 260, Rarity.RARE, mage.cards.h.HengegatePathway.class));
|
||||||
cards.add(new SetCardInfo("Rampage of the Valkyries", 393, Rarity.UNCOMMON, mage.cards.r.RampageOfTheValkyries.class));
|
cards.add(new SetCardInfo("Rampage of the Valkyries", 393, Rarity.UNCOMMON, mage.cards.r.RampageOfTheValkyries.class));
|
||||||
|
cards.add(new SetCardInfo("Realmwalker", 188, Rarity.RARE, mage.cards.r.Realmwalker.class));
|
||||||
cards.add(new SetCardInfo("Renegade Reaper", 386, Rarity.UNCOMMON, mage.cards.r.RenegadeReaper.class));
|
cards.add(new SetCardInfo("Renegade Reaper", 386, Rarity.UNCOMMON, mage.cards.r.RenegadeReaper.class));
|
||||||
cards.add(new SetCardInfo("Showdown of the Skalds", 229, Rarity.RARE, mage.cards.s.ShowdownOfTheSkalds.class));
|
cards.add(new SetCardInfo("Showdown of the Skalds", 229, Rarity.RARE, mage.cards.s.ShowdownOfTheSkalds.class));
|
||||||
cards.add(new SetCardInfo("Starnheim Aspirant", 380, Rarity.UNCOMMON, mage.cards.s.StarnheimAspirant.class));
|
cards.add(new SetCardInfo("Starnheim Aspirant", 380, Rarity.UNCOMMON, mage.cards.s.StarnheimAspirant.class));
|
||||||
|
cards.add(new SetCardInfo("Surtland Elementalist", 375, Rarity.RARE, mage.cards.s.SurtlandElementalist.class));
|
||||||
cards.add(new SetCardInfo("Surtland Flinger", 377, Rarity.RARE, mage.cards.s.SurtlandFlinger.class));
|
cards.add(new SetCardInfo("Surtland Flinger", 377, Rarity.RARE, mage.cards.s.SurtlandFlinger.class));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
package org.mage.test.AI.basic;
|
||||||
|
|
||||||
|
import mage.constants.PhaseStep;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mage.test.serverside.base.CardTestPlayerBaseWithAIHelps;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author JayDi85
|
||||||
|
*/
|
||||||
|
public class TargetAmountAITest extends CardTestPlayerBaseWithAIHelps {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_AI_ChooseTargets() {
|
||||||
|
// Distribute four +1/+1 counters among any number of target creatures.
|
||||||
|
addCard(Zone.HAND, playerA, "Blessings of Nature", 1); // {4}{G}
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Forest", 5);
|
||||||
|
//
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 4); // 2/2
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Balduvian Bears", 4); // 2/2
|
||||||
|
|
||||||
|
// ai must choose by special dialog, not full simulation
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Blessings of Nature");
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
//setStrictChooseMode(true); // ai must choose
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
|
||||||
|
assertPowerToughness(playerA, "Balduvian Bears", 2 + 4, 2 + 4); // boost one creature (it's just a choose code, so can be different from simulation results)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_AI_SimulateTargets() {
|
||||||
|
// Distribute four +1/+1 counters among any number of target creatures.
|
||||||
|
addCard(Zone.HAND, playerA, "Blessings of Nature", 1); // {4}{G}
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Forest", 5);
|
||||||
|
//
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 4); // 2/2
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Balduvian Bears", 4); // 2/2
|
||||||
|
|
||||||
|
// AI must put creatures on own permanents (all in one creature to boost it)
|
||||||
|
aiPlayPriority(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
|
||||||
|
assertPowerToughness(playerA, "Balduvian Bears", 2 + 1, 2 + 1); // boost each possible creatures
|
||||||
|
assertPowerToughness(playerB, "Balduvian Bears", 2, 2); // no boost for enemy
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
package org.mage.test.cards.conditional;
|
package org.mage.test.cards.conditional;
|
||||||
|
|
||||||
import mage.constants.PhaseStep;
|
import mage.constants.PhaseStep;
|
||||||
|
@ -7,7 +6,6 @@ import org.junit.Test;
|
||||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author LevelX2
|
* @author LevelX2
|
||||||
*/
|
*/
|
||||||
public class LegendarySorceryTest extends CardTestPlayerBase {
|
public class LegendarySorceryTest extends CardTestPlayerBase {
|
||||||
|
@ -55,10 +53,13 @@ public class LegendarySorceryTest extends CardTestPlayerBase {
|
||||||
// Flying, first strike, vigilance, trample, haste, protection from black and from red
|
// Flying, first strike, vigilance, trample, haste, protection from black and from red
|
||||||
addCard(Zone.BATTLEFIELD, playerB, "Akroma, Angel of Wrath", 1); // Legendary
|
addCard(Zone.BATTLEFIELD, playerB, "Akroma, Angel of Wrath", 1); // Legendary
|
||||||
|
|
||||||
|
// can't cast cause you don't have a legendary creature (only opponent have)
|
||||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Urza's Ruinous Blast");
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Urza's Ruinous Blast");
|
||||||
|
|
||||||
|
//setStrictChooseMode(true);
|
||||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||||
execute();
|
execute();
|
||||||
|
//assertAllCommandsUsed();
|
||||||
|
|
||||||
assertGraveyardCount(playerA, "Urza's Ruinous Blast", 0);
|
assertGraveyardCount(playerA, "Urza's Ruinous Blast", 0);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
package org.mage.test.cards.single.cmr;
|
||||||
|
|
||||||
|
import mage.constants.PhaseStep;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author JayDi85
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class ArchelosLagoonMysticTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_Playable() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2 + 2); // add lands before Archelos, Lagoon Mystic to ignore ETB effects
|
||||||
|
|
||||||
|
// As long as Archelos, Lagoon Mystic is tapped, other permanents enter the battlefield tapped.
|
||||||
|
// As long as Archelos, Lagoon Mystic is untapped, other permanents enter the battlefield untapped.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Archelos, Lagoon Mystic", 1);
|
||||||
|
//
|
||||||
|
addCard(Zone.HAND, playerA, "Grizzly Bears", 1); // {1}{G}
|
||||||
|
addCard(Zone.HAND, playerA, "Deranged Outcast", 1); // {1}{G}
|
||||||
|
|
||||||
|
// first - untapped
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Grizzly Bears");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkPermanentTapped("untapped", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Archelos, Lagoon Mystic", false, 1);
|
||||||
|
checkPermanentTapped("untapped", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Grizzly Bears", false, 1);
|
||||||
|
|
||||||
|
// prepare tapped mystic
|
||||||
|
attack(1, playerA, "Archelos, Lagoon Mystic", playerB);
|
||||||
|
checkPermanentTapped("tapped", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Archelos, Lagoon Mystic", true, 1);
|
||||||
|
|
||||||
|
// second - tapped
|
||||||
|
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Deranged Outcast");
|
||||||
|
waitStackResolved(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
|
checkPermanentTapped("tapped", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Archelos, Lagoon Mystic", true, 1);
|
||||||
|
checkPermanentTapped("tapped", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Deranged Outcast", true, 1);
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
package org.mage.test.cards.single.inv;
|
||||||
|
|
||||||
|
import mage.abilities.keyword.LandwalkAbility;
|
||||||
|
import mage.constants.PhaseStep;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author JayDi85
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class TravelersCloakTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_MustHaveLandWalkOfTheChosenType() {
|
||||||
|
// Enchant creature
|
||||||
|
// As Traveler's Cloak enters the battlefield, choose a land type.
|
||||||
|
// When Traveler's Cloak enters the battlefield, draw a card.
|
||||||
|
// Enchanted creature has landwalk of the chosen type.
|
||||||
|
addCard(Zone.HAND, playerA, "Traveler's Cloak"); // {2}{U}
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Island", 3);
|
||||||
|
//
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears", 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Kitesail Corsair", 1);
|
||||||
|
|
||||||
|
// cast and assign landwalk ability to creature
|
||||||
|
checkAbility("before", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Grizzly Bears", LandwalkAbility.class, false);
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Traveler's Cloak", "Grizzly Bears");
|
||||||
|
setChoice(playerA, "Swamp"); // land type for landwalk
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkAbility("after", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Grizzly Bears", LandwalkAbility.class, true);
|
||||||
|
|
||||||
|
// check that it can't be blocked
|
||||||
|
attack(1, playerA, "Grizzly Bears");
|
||||||
|
runCode("check blocking", 1, PhaseStep.DECLARE_BLOCKERS, playerB, (info, player, game) -> {
|
||||||
|
Permanent blocker = game.getBattlefield().getAllActivePermanents()
|
||||||
|
.stream()
|
||||||
|
.filter(p -> p.getName().equals("Kitesail Corsair"))
|
||||||
|
.findFirst()
|
||||||
|
.get();
|
||||||
|
Assert.assertFalse("Grizzly Bears must be protected from blocking by Kitesail Corsair",
|
||||||
|
game.getCombat().getGroups().get(0).canBlock(blocker, game));
|
||||||
|
});
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,7 +9,7 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
public class ConspicuousSnoopTest extends CardTestPlayerBase {
|
public class ConspicuousSnoopTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTopCardLibraryRevealed(){
|
public void test_TopCardLibraryRevealed() {
|
||||||
// Play with the top card of your library revealed.
|
// Play with the top card of your library revealed.
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Conspicuous Snoop");
|
addCard(Zone.BATTLEFIELD, playerA, "Conspicuous Snoop");
|
||||||
addCard(Zone.LIBRARY, playerA, "Swamp");
|
addCard(Zone.LIBRARY, playerA, "Swamp");
|
||||||
|
@ -23,43 +23,49 @@ public class ConspicuousSnoopTest extends CardTestPlayerBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void castGoblinSpellsFromLibrary(){
|
public void test_castGoblinSpellsFromLibrary() {
|
||||||
|
skipInitShuffling();
|
||||||
|
removeAllCardsFromLibrary(playerA);
|
||||||
|
|
||||||
// You may cast Goblin spells from the top of your library.
|
// You may cast Goblin spells from the top of your library.
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Conspicuous Snoop");
|
addCard(Zone.BATTLEFIELD, playerA, "Conspicuous Snoop");
|
||||||
|
|
||||||
addCard(Zone.LIBRARY, playerA, "Goblin Lackey");
|
|
||||||
skipInitShuffling();
|
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
|
|
||||||
|
|
||||||
// Whenever Goblin Lackey deals damage to a player, you may put a Goblin permanent card from your hand onto the battlefield.
|
addCard(Zone.LIBRARY, playerA, "Atog", 1); // second from top
|
||||||
|
addCard(Zone.LIBRARY, playerA, "Goblin Lackey", 1); // first from top
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2 * 2);
|
||||||
|
|
||||||
|
// Whenever Goblin Lackey deals damage to a player, you may put a Goblin permanent card from your hand onto the battlefield.
|
||||||
|
checkPlayableAbility("can play goblin", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Goblin Lackey", true);
|
||||||
|
checkPlayableAbility("can't play non goblin before", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Atog", false);
|
||||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Goblin Lackey");
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Goblin Lackey");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkPlayableAbility("can't play non goblin after", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Atog", false);
|
||||||
|
|
||||||
setStopAt(1, PhaseStep.PRECOMBAT_MAIN);
|
setStopAt(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
setStrictChooseMode(true);
|
setStrictChooseMode(true);
|
||||||
execute();
|
execute();
|
||||||
assertAllCommandsUsed();
|
assertAllCommandsUsed();
|
||||||
assertPermanentCount(playerA, "Goblin Lackey", 1);
|
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, "Goblin Lackey", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void hasActivatedAbilities(){
|
public void test_hasActivatedAbilities() {
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
|
||||||
// Play with the top card of your library revealed.
|
// Play with the top card of your library revealed.
|
||||||
// You may cast Goblin spells from the top of your library.
|
// You may cast Goblin spells from the top of your library.
|
||||||
// As long as the top card of your library is a Goblin card, Conspicuous Snoop has all activated abilities of that card.
|
// As long as the top card of your library is a Goblin card, Conspicuous Snoop has all activated abilities of that card.
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Conspicuous Snoop");
|
addCard(Zone.BATTLEFIELD, playerA, "Conspicuous Snoop");
|
||||||
// {R}: Goblin Balloon Brigade gains flying until end of turn.
|
// {R}: Goblin Balloon Brigade gains flying until end of turn.
|
||||||
addCard(Zone.LIBRARY, playerA, "Goblin Balloon Brigade");
|
addCard(Zone.LIBRARY, playerA, "Goblin Balloon Brigade");
|
||||||
skipInitShuffling();
|
skipInitShuffling();
|
||||||
|
|
||||||
setStopAt(1, PhaseStep.PRECOMBAT_MAIN);
|
setStopAt(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
|
||||||
setStrictChooseMode(true);
|
setStrictChooseMode(true);
|
||||||
execute();
|
execute();
|
||||||
|
|
||||||
assertAllCommandsUsed();
|
assertAllCommandsUsed();
|
||||||
assertAbilityCount(playerA, "Conspicuous Snoop", ActivatedAbility.class, 3); // (2 X casts + gains flying )
|
assertAbilityCount(playerA, "Conspicuous Snoop", ActivatedAbility.class, 3); // (2 X casts + gains flying )
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,8 +79,6 @@ public class CastSplitCardsWithSpliceTest extends CardTestPlayerBase {
|
||||||
addTarget(playerA, "Bow of Nylea"); // target right
|
addTarget(playerA, "Bow of Nylea"); // target right
|
||||||
|
|
||||||
// must used all mana
|
// must used all mana
|
||||||
//showAvaileableMana("after", 1, PhaseStep.POSTCOMBAT_MAIN, playerA);
|
|
||||||
|
|
||||||
setStrictChooseMode(true);
|
setStrictChooseMode(true);
|
||||||
setStopAt(1, PhaseStep.END_TURN);
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
execute();
|
execute();
|
||||||
|
|
|
@ -1956,7 +1956,7 @@ public class TestPlayer implements Player {
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (Map.Entry<String, String> entry : rEffects.entrySet()) {
|
for (Map.Entry<String, String> entry : rEffects.entrySet()) {
|
||||||
if (entry.getValue().startsWith(choice)) {
|
if (entry.getValue().startsWith(choice)) {
|
||||||
choices.remove(choice);
|
choices.remove(0);
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
index++;
|
index++;
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue