Fixed some bugs in table handling. Fixed that matches were not set to finished yet, if players left match during sideboarding phase.

This commit is contained in:
LevelX2 2014-02-07 02:04:14 +01:00
parent df9c200753
commit 40c25fae34
25 changed files with 274 additions and 140 deletions

View file

@ -189,8 +189,7 @@ public class TablesPanel extends javax.swing.JPanel {
}
} else if (action.equals("Replay")) {
logger.info("Replaying game " + gameId);
// no replay because of memory leaks
// session.replayGame(gameId);
session.replayGame(gameId);
}
}
};
@ -201,8 +200,8 @@ public class TablesPanel extends javax.swing.JPanel {
public void actionPerformed(ActionEvent e)
{
int modelRow = Integer.valueOf( e.getActionCommand() );
if (matchesModel.getValueAt(modelRow, MatchesTableModel.ACTION_COLUMN) instanceof List) {
List<UUID> games = (List<UUID>)matchesModel.getValueAt(modelRow, MatchesTableModel.ACTION_COLUMN);
if (matchesModel.getValueAt(modelRow, MatchesTableModel.GAMES_LIST_COLUMN) instanceof List) {
List<UUID> games = (List<UUID>)matchesModel.getValueAt(modelRow, MatchesTableModel.GAMES_LIST_COLUMN);
if (games.size() == 1) {
session.replayGame(games.get(0));
}
@ -769,19 +768,16 @@ class TableTableModel extends AbstractTableModel {
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
if (columnIndex != ACTION_COLUMN) {
return false;
}
return true;
return columnIndex == ACTION_COLUMN;
}
}
class UpdateTablesTask extends SwingWorker<Void, Collection<TableView>> {
private Session session;
private UUID roomId;
private TablesPanel panel;
private final Session session;
private final UUID roomId;
private final TablesPanel panel;
private static final Logger logger = Logger.getLogger(UpdateTablesTask.class);
@ -830,9 +826,9 @@ class UpdateTablesTask extends SwingWorker<Void, Collection<TableView>> {
class UpdatePlayersTask extends SwingWorker<Void, Collection<UsersView>> {
private Session session;
private UUID roomId;
private ChatPanel chat;
private final Session session;
private final UUID roomId;
private final ChatPanel chat;
private static final Logger logger = Logger.getLogger(UpdatePlayersTask.class);
@ -872,8 +868,8 @@ class UpdatePlayersTask extends SwingWorker<Void, Collection<UsersView>> {
class MatchesTableModel extends AbstractTableModel {
public static final int ACTION_COLUMN = 7; // column the action is located (starting with 0)
private String[] columnNames = new String[]{"Match Name", "Game Type", "Deck Type", "Players", "Result", "Start Time", "End Time","Action"};
public static final int GAMES_LIST_COLUMN = 8;
private final String[] columnNames = new String[]{"Match Name", "Game Type", "Deck Type", "Players", "Result", "Start Time", "End Time","Action"};
private MatchView[] matches = new MatchView[0];
private static final DateFormat timeFormatter = SimpleDateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
@ -914,7 +910,12 @@ class MatchesTableModel extends AbstractTableModel {
return "";
}
case 7:
return "None";
if (matches[arg0].isReplayAvailable()) {
return "Replay";
} else {
return "None";
}
case 8:
return matches[arg0].getGames();
}
@ -939,19 +940,16 @@ class MatchesTableModel extends AbstractTableModel {
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
if (columnIndex != ACTION_COLUMN) {
return false;
}
return true;
return columnIndex == ACTION_COLUMN;
}
}
class UpdateMatchesTask extends SwingWorker<Void, Collection<MatchView>> {
private Session session;
private UUID roomId;
private TablesPanel panel;
private final Session session;
private final UUID roomId;
private final TablesPanel panel;
private static final Logger logger = Logger.getLogger(UpdateTablesTask.class);
@ -1013,7 +1011,7 @@ class GameChooser extends JPopupMenu {
private class GameChooserAction extends AbstractAction {
private UUID id;
private final UUID id;
public GameChooserAction(UUID id, String choice) {
this.id = id;

View file

@ -87,9 +87,10 @@ public class SessionImpl implements Session {
private static final Logger logger = Logger.getLogger(SessionImpl.class);
private final MageClient client;
private String sessionId;
private MageServer server;
private MageClient client;
private Client callbackClient;
private CallbackHandler callbackHandler;
private ServerState serverState;
@ -828,6 +829,7 @@ public class SessionImpl implements Session {
try {
if (isConnected()) {
server.removeTable(sessionId, roomId, tableId);
return true;
}
} catch (MageException ex) {
@ -1275,8 +1277,8 @@ public class SessionImpl implements Session {
}
class MageAuthenticator extends Authenticator {
private String username;
private String password;
private final String username;
private final String password;
public MageAuthenticator(String username, String password) {
this.username = username;

View file

@ -44,17 +44,18 @@ import mage.game.tournament.TournamentPlayer;
*/
public class MatchView implements Serializable {
private UUID matchId;
private String matchName;
private final UUID matchId;
private final String matchName;
private String gameType;
private String deckType;
private final String deckType;
private List<UUID> games = new ArrayList<UUID>();
private String result;
private String players;
private final List<UUID> games = new ArrayList<UUID>();
private final String result;
private final String players;
private Date startTime;
private Date endTime;
private final Date startTime;
private final Date endTime;
private final Boolean replayAvailable;
public MatchView(Match match) {
this.matchId = match.getId();
@ -79,6 +80,7 @@ public class MatchView implements Serializable {
result = sb2.substring(0, sb2.length() - 2);
this.startTime = match.getStartTime();
this.endTime = match.getEndTime();
this.replayAvailable = match.isReplayAvailable();
}
// used for tournaments
@ -107,6 +109,7 @@ public class MatchView implements Serializable {
this.result = sb2.toString();
this.startTime = table.getTournament().getStartTime();
this.endTime = table.getTournament().getEndTime();
this.replayAvailable = false;
}
public UUID getMatchId() {
@ -144,4 +147,13 @@ public class MatchView implements Serializable {
public Date getEndTime() {
return endTime;
}
public String getMatchName() {
return matchName;
}
public Boolean isReplayAvailable() {
return replayAvailable;
}
}

View file

@ -10,6 +10,7 @@
maxUserNameLength="14"
userNamePattern="[^a-z0-9_]"
maxAiOpponents="3"
saveGameActivated="false"
/>
<playerTypes>
<playerType name="Human" jar="mage-player-human.jar" className="mage.player.human.HumanPlayer"/>

View file

@ -1,7 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Config.xsd">
<server serverAddress="0.0.0.0" serverName="mage-server" port="17171" maxGameThreads="10" maxSecondsIdle="600" minUserNameLength="3" maxUserNameLength="14" userNamePattern="[^a-z0-9_]"/>
<server serverAddress="0.0.0.0" serverName="mage-server" port="17171"
maxGameThreads="10"
maxSecondsIdle="600"
minUserNameLength="3"
maxUserNameLength="14"
userNamePattern="[^a-z0-9_]"
maxAiOpponents="15"
saveGameActivated="false"
/>
<playerTypes>
<playerType name="Human" jar="mage-player-human-${project.version}.jar" className="mage.player.human.HumanPlayer"/>
<playerType name="Computer - mad" jar="mage-player-ai-ma-${project.version}.jar" className="mage.player.ai.ComputerPlayer7"/>

View file

@ -89,10 +89,10 @@ import org.apache.log4j.Logger;
public class MageServerImpl implements MageServer {
private static final Logger logger = Logger.getLogger(MageServerImpl.class);
private static ExecutorService callExecutor = ThreadExecutor.getInstance().getCallExecutor();
private static final ExecutorService callExecutor = ThreadExecutor.getInstance().getCallExecutor();
private String password;
private boolean testMode;
private final String password;
private final boolean testMode;
public MageServerImpl(String password, boolean testMode) {
this.password = password;
@ -187,7 +187,9 @@ public class MageServerImpl implements MageServer {
logger.debug("Tournament table " + table.getTableId() + " created");
LogServiceImpl.instance.log(LogKeys.KEY_TOURNAMENT_TABLE_CREATED, sessionId, userId.toString(), table.getTableId().toString());
return table;
} catch (Exception ex) {
} catch (NumberFormatException ex) {
handleException(ex);
} catch (MageException ex) {
handleException(ex);
}
return null;

View file

@ -32,6 +32,7 @@ import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.Map;
import javax.management.MBeanServer;
@ -76,12 +77,13 @@ import org.w3c.dom.Element;
*/
public class Main {
private static Logger logger = Logger.getLogger(Main.class);
private static final Logger logger = Logger.getLogger(Main.class);
private static final MageVersion version = new MageVersion(1, 3, 0, "dev2014-02-03");
private static final String testModeArg = "-testMode=";
private static final String adminPasswordArg = "-adminPassword=";
private static final String pluginFolder = "plugins";
private static MageVersion version = new MageVersion(1, 3, 0, "");
public static PluginClassLoader classLoader = new PluginClassLoader();
public static TransporterServer server;
@ -250,10 +252,9 @@ public class Main {
@Override
public void removeListener(InvokerCallbackHandler callbackHandler) {
logger.fatal("removeListener called");
// ServerInvokerCallbackHandler handler = (ServerInvokerCallbackHandler) callbackHandler;
// String sessionId = handler.getCallbackClient().getSessionId();
// SessionManager.getInstance().disconnect(sessionId);
ServerInvokerCallbackHandler handler = (ServerInvokerCallbackHandler) callbackHandler;
String sessionId = handler.getClientSessionId();
SessionManager.getInstance().disconnect(sessionId, true);
}
}
@ -264,8 +265,8 @@ public class Main {
logger.debug("Loading plugin: " + plugin.getClassName());
return Class.forName(plugin.getClassName(), true, classLoader);
} catch (ClassNotFoundException ex) {
logger.warn(new StringBuilder("Plugin not Found: ").append(plugin.getClassName()).append(" - ").append(plugin.getJar()).append(" - check plugin folder"));
} catch (Exception ex) {
logger.warn(new StringBuilder("Plugin not Found: ").append(plugin.getClassName()).append(" - ").append(plugin.getJar()).append(" - check plugin folder"), ex);
} catch (MalformedURLException ex) {
logger.fatal("Error loading plugin " + plugin.getJar(), ex);
}
return null;
@ -277,8 +278,12 @@ public class Main {
logger.debug("Loading game type: " + plugin.getClassName());
return (MatchType) Class.forName(plugin.getTypeName(), true, classLoader).newInstance();
} catch (ClassNotFoundException ex) {
logger.warn("Game type not found:" + plugin.getJar() + " - check plugin folder");
} catch (Exception ex) {
logger.warn("Game type not found:" + plugin.getJar() + " - check plugin folder", ex);
} catch (IllegalAccessException ex) {
logger.fatal("Error loading game type " + plugin.getJar(), ex);
} catch (InstantiationException ex) {
logger.fatal("Error loading game type " + plugin.getJar(), ex);
} catch (MalformedURLException ex) {
logger.fatal("Error loading game type " + plugin.getJar(), ex);
}
return null;
@ -290,8 +295,12 @@ public class Main {
logger.debug("Loading tournament type: " + plugin.getClassName());
return (TournamentType) Class.forName(plugin.getTypeName(), true, classLoader).newInstance();
} catch (ClassNotFoundException ex) {
logger.warn("Tournament type not found:" + plugin.getName() + " / "+ plugin.getJar() + " - check plugin folder");
} catch (Exception ex) {
logger.warn("Tournament type not found:" + plugin.getName() + " / "+ plugin.getJar() + " - check plugin folder", ex);
} catch (IllegalAccessException ex) {
logger.fatal("Error loading game type " + plugin.getJar(), ex);
} catch (InstantiationException ex) {
logger.fatal("Error loading game type " + plugin.getJar(), ex);
} catch (MalformedURLException ex) {
logger.fatal("Error loading game type " + plugin.getJar(), ex);
}
return null;

View file

@ -67,6 +67,7 @@ import mage.server.services.LogKeys;
import mage.server.services.impl.LogServiceImpl;
import mage.server.tournament.TournamentFactory;
import mage.server.tournament.TournamentManager;
import mage.server.util.ConfigSettings;
import mage.server.util.ServerMessagesUtil;
import mage.server.util.ThreadExecutor;
import org.apache.log4j.Logger;
@ -80,15 +81,16 @@ public class TableController {
private static final Logger logger = Logger.getLogger(TableController.class);
private UUID userId;
private UUID chatId;
private String controllerName;
private Table table;
private final UUID userId;
private final UUID chatId;
private final String controllerName;
private final Table table;
private final ConcurrentHashMap<UUID, UUID> userPlayerMap = new ConcurrentHashMap<UUID, UUID>();
private Match match;
private MatchOptions options;
private Tournament tournament;
private ConcurrentHashMap<UUID, UUID> userPlayerMap = new ConcurrentHashMap<UUID, UUID>();
private ScheduledFuture<?> futureTimeout;
protected static ScheduledExecutorService timeoutExecutor = ThreadExecutor.getInstance().getTimeoutExecutor();
@ -237,10 +239,10 @@ public class TableController {
}
match.addPlayer(player, deck);
table.joinTable(player, seat);
user.addTable(player.getId(), table);
logger.debug("player joined " + player.getId());
logger.debug("player joined " + player.getId() + " " + player.getName());
//only inform human players and add them to sessionPlayerMap
if (seat.getPlayer().isHuman()) {
user.addTable(player.getId(), table);
user.joinedTable(table.getRoomId(), table.getId(), false);
userPlayerMap.put(userId, player.getId());
}
@ -383,6 +385,14 @@ public class TableController {
TableManager.getInstance().userQuitTournamentSubTables(userId);
TournamentManager.getInstance().quit(tournament.getId(), userId);
} else {
MatchPlayer matchPlayer = match.getPlayer(playerId);
if (matchPlayer != null) {
if (table.getState().equals(TableState.SIDEBOARDING)) {
// submit deck to finish sideboarding and trigger match start / end
matchPlayer.submitDeck(matchPlayer.getDeck());
}
matchPlayer.setQuit(true);
}
match.leave(playerId);
}
}
@ -547,30 +557,6 @@ public class TableController {
}
}
private void sendMatchEndInfo(UUID playerId) {
for (Entry<UUID, UUID> entry: userPlayerMap.entrySet()) {
if (entry.getValue().equals(playerId)) {
User user = UserManager.getInstance().getUser(entry.getKey());
if (user != null) {
StringBuilder sb = new StringBuilder();
if (table.isTournamentSubTable()) {
sb.append("Your tournament match of round ");
sb.append(table.getTournament().getRounds().size());
sb.append(" is over. ");
} else {
sb.append("Match [").append(match.getName()).append("] is over. ");
}
if(match.getPlayers().size() > 2) {
sb.append("All your opponents have lost or quit the match.");
} else {
sb.append("Your opponent has quit the match.");
}
user.showUserMessage("Match info", sb.toString());
}
break;
}
}
}
public int getRemainingTime() {
return (int) futureTimeout.getDelay(TimeUnit.SECONDS);
}
@ -596,10 +582,11 @@ public class TableController {
UUID choosingPlayerId = match.getChooser();
match.endGame();
table.endGame();
// Saving of games caused memory leaks - so save is deactivated
// if (!match.getGame().isSimulation()) {
// GameManager.getInstance().saveGame(match.getGame().getId());
// }
if (ConfigSettings.getInstance().isSaveGameActivated() && !match.getGame().isSimulation()) {
if (GameManager.getInstance().saveGame(match.getGame().getId())) {
match.setReplayAvailable(true);
}
}
GameManager.getInstance().removeGame(match.getGame().getId());
try {
if (!match.isMatchOver()) {
@ -610,23 +597,56 @@ public class TableController {
if (!match.isMatchOver()) {
startGame(choosingPlayerId);
} else {
this.matchEnd();
if (!ConfigSettings.getInstance().isSaveGameActivated() || match.getGame().isSimulation()) {
match.getGames().clear();
}
table.endGame();
// opponent(s) left during sideboarding
for (MatchPlayer mPlayer :match.getPlayers()) {
if(!mPlayer.hasQuit()) {
this.sendMatchEndInfo(mPlayer.getPlayer().getId());
}
}
}
}
else {
match.getGames().clear();
// if match has only one game
this.matchEnd();
if (!ConfigSettings.getInstance().isSaveGameActivated() || match.getGame().isSimulation()) {
match.getGames().clear();
}
table.endGame();
}
} catch (GameException ex) {
logger.fatal(null, ex);
}
}
private void matchEnd() {
for (Entry<UUID, UUID> entry: userPlayerMap.entrySet()) {
MatchPlayer matchPlayer = match.getPlayer(entry.getValue());
// opponent(s) left during sideboarding
if(!matchPlayer.hasQuit()) {
User user = UserManager.getInstance().getUser(entry.getKey());
if (user != null) {
if (table.getState().equals(TableState.SIDEBOARDING)) {
StringBuilder sb = new StringBuilder();
if (table.isTournamentSubTable()) {
sb.append("Your tournament match of round ");
sb.append(table.getTournament().getRounds().size());
sb.append(" is over. ");
} else {
sb.append("Match [").append(match.getName()).append("] is over. ");
}
if (match.getPlayers().size() > 2) {
sb.append("All your opponents have lost or quit the match.");
} else {
sb.append("Your opponent has quit the match.");
}
user.showUserMessage("Match info", sb.toString());
}
// remove table from user - table manager holds table for display of finished matches
user.removeTable(entry.getValue());
}
}
}
}
private synchronized void setupTimeout(int seconds) {
cancelTimeout();
if (seconds > 0) {

View file

@ -62,8 +62,8 @@ public class TableManager {
private static final TableManager INSTANCE = new TableManager();
private static final Logger logger = Logger.getLogger(TableManager.class);
private ConcurrentHashMap<UUID, TableController> controllers = new ConcurrentHashMap<UUID, TableController>();
private ConcurrentHashMap<UUID, Table> tables = new ConcurrentHashMap<UUID, Table>();
private final ConcurrentHashMap<UUID, TableController> controllers = new ConcurrentHashMap<UUID, TableController>();
private final ConcurrentHashMap<UUID, Table> tables = new ConcurrentHashMap<UUID, Table>();
/**
* Defines how often checking process should be run on server.
@ -184,6 +184,7 @@ public class TableManager {
public boolean removeTable(UUID userId, UUID tableId) {
if (isTableOwner(tableId, userId) || UserManager.getInstance().isAdmin(userId)) {
leaveTable(userId, tableId);
removeTable(tableId);
return true;
}
@ -192,13 +193,14 @@ public class TableManager {
public void leaveTable(UUID userId, UUID tableId) {
if (controllers.containsKey(tableId)) {
controllers.get(tableId).leaveTable(userId);
// table not started yet and user is the owner, remove the table
if (isTableOwner(tableId, userId)) {
if (getTable(tableId).getState().equals(TableState.WAITING)
|| getTable(tableId).getState().equals(TableState.STARTING)) {
removeTable(tableId);
}
if (isTableOwner(tableId, userId)
&& (getTable(tableId).getState().equals(TableState.WAITING)
|| getTable(tableId).getState().equals(TableState.STARTING))) {
removeTable(tableId);
} else {
controllers.get(tableId).leaveTable(userId);
}
}
}

View file

@ -28,7 +28,6 @@
package mage.server;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@ -36,6 +35,7 @@ import java.util.Map.Entry;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import mage.cards.decks.Deck;
import mage.constants.TableState;
import mage.game.Table;
import mage.interfaces.callback.ClientCallback;
import mage.players.net.UserData;
@ -324,15 +324,47 @@ public class User {
}
public String getGameInfo() {
StringBuilder sb = new StringBuilder();
if (gameSessions.size() > 0) {
sb.append("G: ").append(gameSessions.size());
}
if (tournamentSessions.size() > 0) {
if (sb.length() > 0) {
sb.append(" ");
StringBuilder sb = new StringBuilder();
int draft = 0, match = 0, sideboard = 0, tournament = 0, construct = 0;
for (Table table : tables.values()) {
if (table.isTournament()) {
switch (table.getState()) {
case CONSTRUCTING:
construct++;
break;
case DRAFTING:
draft++;
break;
case DUELING:
tournament++;
break;
}
} else {
switch (table.getState()) {
case SIDEBOARDING:
sideboard++;
break;
case DUELING:
match++;
break;
}
}
sb.append("T: ").append(tournamentSessions.size());
}
if (match > 0) {
sb.append("MP: ").append(match).append(" ");
}
if (sideboard > 0) {
sb.append("MS: ").append(sideboard).append(" ");
}
if (draft > 0) {
sb.append("TD: ").append(draft).append(" ");
}
if (construct > 0) {
sb.append("TC: ").append(construct).append(" ");
}
if (tournament > 0) {
sb.append("TP: ").append(tournament).append(" ");
}
return sb.toString();
}

View file

@ -64,7 +64,7 @@ public class UserManager {
}, 60, 60, TimeUnit.SECONDS);
}
private ConcurrentHashMap<UUID, User> users = new ConcurrentHashMap<UUID, User>();
private final ConcurrentHashMap<UUID, User> users = new ConcurrentHashMap<UUID, User>();
public User createUser(String userName, String host) {
if (findUser(userName) != null) {
@ -95,8 +95,8 @@ public class UserManager {
public boolean connectToSession(String sessionId, UUID userId) {
if (users.containsKey(userId)) {
users.get(userId).setSessionId(sessionId);
return true;
}
return true;
}
return false;
}

View file

@ -694,7 +694,7 @@ public class GameController implements GameCallback {
}
}
public void saveGame() {
public boolean saveGame() {
try {
OutputStream file = new FileOutputStream("saved/" + game.getId().toString() + ".game");
OutputStream buffer = new BufferedOutputStream(file);
@ -707,10 +707,12 @@ public class GameController implements GameCallback {
output.close();
}
logger.debug("Saved game:" + game.getId());
return true;
}
catch(IOException ex) {
logger.fatal("Cannot save game.", ex);
}
return false;
}
/**

View file

@ -180,10 +180,11 @@ public class GameManager {
gameControllers.remove(gameId);
}
public void saveGame(UUID gameId) {
public boolean saveGame(UUID gameId) {
if (gameControllers.containsKey(gameId)) {
gameControllers.get(gameId).saveGame();
return gameControllers.get(gameId).saveGame();
}
return false;
}
public GameView getGameView(UUID gameId, UUID userId, UUID playerId) {

View file

@ -35,11 +35,15 @@ import java.io.InputStream;
import java.io.ObjectInput;
import java.util.UUID;
import java.util.zip.GZIPInputStream;
import mage.game.*;
import mage.game.Game;
import mage.game.GameState;
import mage.game.GameStates;
import mage.server.Main;
import mage.util.CopierObjectInputStream;
import org.apache.log4j.Logger;
/**
*
* @author BetaSteward_at_googlemail.com
@ -48,8 +52,8 @@ public class GameReplay {
private static final Logger logger = Logger.getLogger(GameReplay.class);
private GameStates savedGame;
private Game game;
private final GameStates savedGame;
private final Game game;
private int stateIndex;
public GameReplay(UUID gameId) {

View file

@ -57,8 +57,8 @@ import mage.view.SimpleCardsView;
*/
public class GameSession extends GameWatcher {
private UUID playerId;
private boolean useTimeout;
private final UUID playerId;
private final boolean useTimeout;
private ScheduledFuture<?> futureTimeout;
protected static ScheduledExecutorService timeoutExecutor = ThreadExecutor.getInstance().getTimeoutExecutor();

View file

@ -33,6 +33,7 @@ import org.apache.log4j.Logger;
import java.util.UUID;
import java.util.concurrent.Callable;
import mage.MageException;
/**
*
@ -42,9 +43,9 @@ public class GameWorker implements Callable {
private static final Logger logger = Logger.getLogger(GameWorker.class);
private GameCallback result;
private Game game;
private UUID choosingPlayerId;
private final GameCallback result;
private final Game game;
private final UUID choosingPlayerId;
public GameWorker(Game game, UUID choosingPlayerId, GameCallback result) {
this.game = game;
@ -58,7 +59,7 @@ public class GameWorker implements Callable {
game.start(choosingPlayerId);
game.fireUpdatePlayersEvent();
result.gameResult(game.getWinner());
} catch (Exception ex) {
} catch (MageException ex) {
logger.fatal("GameWorker error ", ex);
}
return null;

View file

@ -45,14 +45,12 @@ public class ReplayManager {
private ReplayManager() {}
private ConcurrentHashMap<String, ReplaySession> replaySessions = new ConcurrentHashMap<String, ReplaySession>();
private final ConcurrentHashMap<String, ReplaySession> replaySessions = new ConcurrentHashMap<String, ReplaySession>();
public void replayGame(UUID gameId, UUID userId) {
if (1 == 2) { // deactivated because replay causes memor leaks
ReplaySession replaySession = new ReplaySession(gameId, userId);
replaySessions.put(gameId.toString() + userId.toString(), replaySession);
UserManager.getInstance().getUser(userId).replayGame(gameId);
}
ReplaySession replaySession = new ReplaySession(gameId, userId);
replaySessions.put(gameId.toString() + userId.toString(), replaySession);
UserManager.getInstance().getUser(userId).replayGame(gameId);
}
public void startReplay(UUID gameId, UUID userId) {

View file

@ -51,11 +51,19 @@ public class Config {
remoteServer = p.getProperty("remote-server");
maxGameThreads = Integer.parseInt(p.getProperty("max-game-threads"));
maxSecondsIdle = Integer.parseInt(p.getProperty("max-seconds-idle"));
minUserNameLength = Integer.parseInt(p.getProperty("minUserNameLength"));
maxUserNameLength = Integer.parseInt(p.getProperty("maxUserNameLength"));
userNamePattern = p.getProperty("userNamePattern");
saveGameActivated = Boolean.parseBoolean(p.getProperty("saveGameActivated"));
}
public static final String remoteServer;
public static final int port;
public static final int maxGameThreads;
public static final int maxSecondsIdle;
public static final int minUserNameLength;
public static final int maxUserNameLength;
public static final String userNamePattern;
public static final boolean saveGameActivated;
}

View file

@ -24,6 +24,8 @@
<xs:attribute name="minUserNameLength" type="xs:positiveInteger" use="required"/>
<xs:attribute name="maxUserNameLength" type="xs:positiveInteger" use="required"/>
<xs:attribute name="userNamePattern" type="xs:string" use="required"/>
<xs:attribute name="maxAiOpponents" type="xs:string" use="optional"/>
<xs:attribute name="saveGameActivated" type="xs:boolean" use="optional"/>
</xs:complexType>
</xs:element>

View file

@ -99,6 +99,10 @@ public class ConfigSettings {
return config.getServer().getMaxAiOpponents();
}
public Boolean isSaveGameActivated() {
return config.getServer().isSaveGameActivated();
}
public List<Plugin> getPlayerTypes() {
return config.getPlayerTypes().getPlayerType();
}

View file

@ -1,7 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Config.xsd">
<server serverAddress="0.0.0.0" serverName="mage-server" port="17171" maxGameThreads="10" maxSecondsIdle="600" minUserNameLength="3" maxUserNameLength="14" userNamePattern="[^a-z0-9_]"/>
<server serverAddress="0.0.0.0" serverName="mage-server" port="17171" maxGameThreads="10"
maxSecondsIdle="600"
minUserNameLength="3"
maxUserNameLength="14"
userNamePattern="[^a-z0-9_]"
saveGameActivated="true"
maxAiOpponents="15"
saveGameActivated="false"
/>
<playerTypes>
<playerType name="Human" jar="Mage.Player.Human.jar" className="mage.player.human.HumanPlayer"/>
<playerType name="Computer - default" jar="Mage.Player.AI.jar" className="mage.player.ai.ComputerPlayer"/>

View file

@ -22,10 +22,11 @@
<xs:attribute name="port" type="xs:positiveInteger" use="required"/>
<xs:attribute name="maxGameThreads" type="xs:positiveInteger" use="required"/>
<xs:attribute name="maxSecondsIdle" type="xs:positiveInteger" use="required"/>
<xs:attribute name="minUserNameLength" type="xs:positiveInteger" use="required"/>
<xs:attribute name="maxUserNameLength" type="xs:positiveInteger" use="required"/>
<xs:attribute name="userNamePattern" type="xs:string" use="required"/>
<xs:attribute name="maxAiOpponents" type="xs:string" use="optional"/>
<xs:attribute name="minUserNameLength" type="xs:positiveInteger" use="required"/>
<xs:attribute name="maxUserNameLength" type="xs:positiveInteger" use="required"/>
<xs:attribute name="userNamePattern" type="xs:string" use="required"/>
<xs:attribute name="maxAiOpponents" type="xs:string" use="optional"/>
<xs:attribute name="saveGameActivated" type="xs:boolean" use="optional"/>
</xs:complexType>
</xs:element>

View file

@ -76,4 +76,11 @@ public interface Match {
// match times
Date getStartTime();
Date getEndTime();
/**
* Can the games of the match be replayed
*
* @return
*/
boolean isReplayAvailable();
void setReplayAvailable(boolean replayAvailable);
}

View file

@ -60,9 +60,12 @@ public abstract class MatchImpl implements Match {
protected Date startTime;
protected Date endTime;
protected boolean replayAvailable;
public MatchImpl(MatchOptions options) {
this.options = options;
startTime = new Date();
replayAvailable = false;
}
@Override
@ -316,4 +319,12 @@ public abstract class MatchImpl implements Match {
return null;
}
@Override
public boolean isReplayAvailable() {
return replayAvailable;
}
public void setReplayAvailable(boolean replayAvailable) {
this.replayAvailable = replayAvailable;
}
}

View file

@ -1,12 +1,13 @@
package mage.util.functions;
import java.io.Serializable;
import mage.game.Game;
import mage.game.permanent.Permanent;
/**
* @author noxx
*/
public abstract class ApplyToPermanent {
public abstract class ApplyToPermanent implements Serializable {
public abstract Boolean apply(Game game, Permanent permanent);
}