mirror of
https://github.com/correl/mage.git
synced 2025-03-07 20:53:18 -10:00
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:
parent
df9c200753
commit
40c25fae34
25 changed files with 274 additions and 140 deletions
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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"/>
|
||||
|
|
|
@ -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"/>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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"/>
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue