From c46f75ac283c198d4902f8a2eae7fb1e23b63765 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Wed, 5 Oct 2016 00:59:51 +0200 Subject: [PATCH] Added chat mute and user (de)activation actions to the Mage server console. --- .../src/mage/interfaces/MageServer.java | 4 + Mage.Common/src/mage/remote/SessionImpl.java | 30 ++++ .../src/mage/remote/interfaces/Connect.java | 4 + Mage.Common/src/mage/view/UserView.java | 8 +- .../mage/server/console/ConsolePanel.form | 88 ++++++++---- .../mage/server/console/ConsolePanel.java | 110 +++++++++++---- .../main/java/mage/server/AuthorizedUser.java | 21 ++- .../mage/server/AuthorizedUserRepository.java | 53 +++++-- .../main/java/mage/server/ChatManager.java | 31 +++-- .../main/java/mage/server/ChatSession.java | 16 +-- .../main/java/mage/server/MageServerImpl.java | 45 ++++-- .../src/main/java/mage/server/Main.java | 59 +++++--- .../src/main/java/mage/server/Session.java | 7 +- .../src/main/java/mage/server/User.java | 54 +++++++- .../main/java/mage/server/UserManager.java | 4 +- .../java/mage/server/game/GameController.java | 14 +- .../tournament/TournamentController.java | 130 +++++++++--------- .../java/mage/server/util/SystemUtil.java | 46 ++++--- 18 files changed, 511 insertions(+), 213 deletions(-) diff --git a/Mage.Common/src/mage/interfaces/MageServer.java b/Mage.Common/src/mage/interfaces/MageServer.java index 5d8c4a9738..762c7323e2 100644 --- a/Mage.Common/src/mage/interfaces/MageServer.java +++ b/Mage.Common/src/mage/interfaces/MageServer.java @@ -215,6 +215,10 @@ public interface MageServer { void muteUser(String sessionId, String userName, long durationMinutes) throws MageException; + void lockUser(String sessionId, String userName, long durationMinutes) throws MageException; + + void toggleActivation(String sessionId, String userName) throws MageException; + void removeTable(String sessionId, UUID tableId) throws MageException; void sendBroadcastMessage(String sessionId, String message) throws MageException; diff --git a/Mage.Common/src/mage/remote/SessionImpl.java b/Mage.Common/src/mage/remote/SessionImpl.java index 9b2b54831f..f73b4f215f 100644 --- a/Mage.Common/src/mage/remote/SessionImpl.java +++ b/Mage.Common/src/mage/remote/SessionImpl.java @@ -1440,6 +1440,36 @@ public class SessionImpl implements Session { return false; } + @Override + public boolean toggleActivation(String userName) { + try { + if (isConnected()) { + server.toggleActivation(sessionId, userName); + return true; + } + } catch (MageException ex) { + handleMageException(ex); + } catch (Throwable t) { + handleThrowable(t); + } + return false; + } + + @Override + public boolean lockUser(String userName, long durationMinute) { + try { + if (isConnected()) { + server.lockUser(sessionId, userName, durationMinute); + return true; + } + } catch (MageException ex) { + handleMageException(ex); + } catch (Throwable t) { + handleThrowable(t); + } + return false; + } + private void handleThrowable(Throwable t) { logger.fatal("Communication error", t); // Probably this can cause hanging the client under certain circumstances as the disconnect method is synchronized diff --git a/Mage.Common/src/mage/remote/interfaces/Connect.java b/Mage.Common/src/mage/remote/interfaces/Connect.java index f14a252ee7..5f8a4a0667 100644 --- a/Mage.Common/src/mage/remote/interfaces/Connect.java +++ b/Mage.Common/src/mage/remote/interfaces/Connect.java @@ -58,5 +58,9 @@ public interface Connect { boolean muteUserChat(String userName, long durationMinute); + boolean toggleActivation(String userName); + + boolean lockUser(String userName, long durationMinute); + String getSessionId(); } diff --git a/Mage.Common/src/mage/view/UserView.java b/Mage.Common/src/mage/view/UserView.java index 29cd831588..1946985789 100644 --- a/Mage.Common/src/mage/view/UserView.java +++ b/Mage.Common/src/mage/view/UserView.java @@ -43,14 +43,16 @@ public class UserView implements Serializable { private final Date timeConnected; private final String gameInfo; private final String userState; + private final Date muteChatUntil; - public UserView(String userName, String host, String sessionId, Date timeConnected, String gameInfo, String userState) { + public UserView(String userName, String host, String sessionId, Date timeConnected, String gameInfo, String userState, Date muteChatUntil) { this.userName = userName; this.host = host; this.sessionId = sessionId; this.timeConnected = timeConnected; this.gameInfo = gameInfo; this.userState = userState; + this.muteChatUntil = muteChatUntil; } public String getUserName() { @@ -77,4 +79,8 @@ public class UserView implements Serializable { return userState; } + public Date getMuteChatUntil() { + return muteChatUntil; + } + } diff --git a/Mage.Server.Console/src/main/java/mage/server/console/ConsolePanel.form b/Mage.Server.Console/src/main/java/mage/server/console/ConsolePanel.form index 68a4f4baf6..bb261f9c30 100644 --- a/Mage.Server.Console/src/main/java/mage/server/console/ConsolePanel.form +++ b/Mage.Server.Console/src/main/java/mage/server/console/ConsolePanel.form @@ -52,8 +52,9 @@ - - + + + @@ -69,7 +70,7 @@ - + @@ -104,26 +105,51 @@ - - - - + + + + + + + + + + - + + + + + - - - - + + + + + + + + + + + + + + + + + + + + - - + @@ -154,11 +180,30 @@ - + - - + + + + + + + + + + + + + + + + + + + + + @@ -182,7 +227,7 @@ - + @@ -194,15 +239,12 @@ - + - - - - + diff --git a/Mage.Server.Console/src/main/java/mage/server/console/ConsolePanel.java b/Mage.Server.Console/src/main/java/mage/server/console/ConsolePanel.java index 6806072d1f..460d19a7f3 100644 --- a/Mage.Server.Console/src/main/java/mage/server/console/ConsolePanel.java +++ b/Mage.Server.Console/src/main/java/mage/server/console/ConsolePanel.java @@ -70,6 +70,7 @@ public class ConsolePanel extends javax.swing.JPanel { this.tableUserModel = new TableUserModel(); this.tableTableModel = new TableTableModel(); initComponents(); + spinnerMuteDurationMinutes.setValue(60); this.tblUsers.createDefaultColumnsFromModel(); this.tblUsers.setRowSorter(new TableRowSorter(tableUserModel)); this.tblUsers.setAutoResizeMode(AUTO_RESIZE_OFF); @@ -127,7 +128,10 @@ public class ConsolePanel extends javax.swing.JPanel { btnDisconnect = new javax.swing.JButton(); btnEndSession = new javax.swing.JButton(); btnMuteUser = new javax.swing.JButton(); - sliderMuteDurationMinutes = new javax.swing.JSlider(); + btnDeActivate = new javax.swing.JButton(); + btnLockUser = new javax.swing.JButton(); + lblMinutes = new javax.swing.JLabel(); + spinnerMuteDurationMinutes = new javax.swing.JSpinner(); jPanel2 = new javax.swing.JPanel(); jPanel5 = new javax.swing.JPanel(); jScrollPane2 = new javax.swing.JScrollPane(); @@ -149,7 +153,7 @@ public class ConsolePanel extends javax.swing.JPanel { ); jPanel3Layout.setVerticalGroup( jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 347, Short.MAX_VALUE) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 339, Short.MAX_VALUE) ); jPanel4.setVerifyInputWhenFocusTarget(false); @@ -176,8 +180,23 @@ public class ConsolePanel extends javax.swing.JPanel { } }); - sliderMuteDurationMinutes.setMaximum(3600); - sliderMuteDurationMinutes.setValue(60); + btnDeActivate.setText("(de)activate"); + btnDeActivate.setActionCommand("Mute 1h"); + btnDeActivate.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnDeActivateActionPerformed(evt); + } + }); + + btnLockUser.setText("Lock user"); + btnLockUser.setActionCommand("Mute 1h"); + btnLockUser.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnLockUserActionPerformed(evt); + } + }); + + lblMinutes.setText("Minutes"); javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4); jPanel4.setLayout(jPanel4Layout); @@ -187,22 +206,40 @@ public class ConsolePanel extends javax.swing.JPanel { .addContainerGap() .addComponent(btnDisconnect) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnEndSession) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(sliderMuteDurationMinutes, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) - .addComponent(btnMuteUser, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addContainerGap(50, Short.MAX_VALUE)) + .addGroup(jPanel4Layout.createSequentialGroup() + .addComponent(btnEndSession) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnMuteUser)) + .addGroup(jPanel4Layout.createSequentialGroup() + .addComponent(btnDeActivate) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnLockUser, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(lblMinutes) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(spinnerMuteDurationMinutes, javax.swing.GroupLayout.PREFERRED_SIZE, 64, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); jPanel4Layout.setVerticalGroup( jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel4Layout.createSequentialGroup() - .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(btnDisconnect) - .addComponent(btnEndSession) - .addComponent(btnMuteUser)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 9, Short.MAX_VALUE) - .addComponent(sliderMuteDurationMinutes, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel4Layout.createSequentialGroup() + .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(btnDisconnect) + .addComponent(btnEndSession) + .addComponent(btnMuteUser)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(btnDeActivate) + .addComponent(btnLockUser))) + .addGroup(jPanel4Layout.createSequentialGroup() + .addGap(16, 16, 16) + .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(lblMinutes) + .addComponent(spinnerMuteDurationMinutes, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))) + .addContainerGap()) ); javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); @@ -216,8 +253,9 @@ public class ConsolePanel extends javax.swing.JPanel { jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jPanel4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(0, 0, 0) + .addComponent(jPanel4, javax.swing.GroupLayout.PREFERRED_SIZE, 57, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0)) ); jSplitPane1.setLeftComponent(jPanel1); @@ -229,13 +267,11 @@ public class ConsolePanel extends javax.swing.JPanel { jPanel5.setLayout(jPanel5Layout); jPanel5Layout.setHorizontalGroup( jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 351, Short.MAX_VALUE) + .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 453, Short.MAX_VALUE) ); jPanel5Layout.setVerticalGroup( jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel5Layout.createSequentialGroup() - .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 343, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(0, 0, Short.MAX_VALUE)) + .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 340, Short.MAX_VALUE) ); btnRemoveTable.setLabel("Remove Table"); @@ -272,7 +308,7 @@ public class ConsolePanel extends javax.swing.JPanel { jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup() .addComponent(jPanel5, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGap(0, 0, 0) .addComponent(jPanel6, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) ); @@ -307,12 +343,24 @@ public class ConsolePanel extends javax.swing.JPanel { private void btnMuteUserActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnMuteUserActionPerformed int row = this.tblUsers.convertRowIndexToModel(tblUsers.getSelectedRow()); - ConsoleFrame.getSession().muteUserChat((String) tableUserModel.getValueAt(row, TableUserModel.POS_USER_NAME), sliderMuteDurationMinutes.getValue()); + ConsoleFrame.getSession().muteUserChat((String) tableUserModel.getValueAt(row, TableUserModel.POS_USER_NAME), ((Number) spinnerMuteDurationMinutes.getValue()).longValue()); }//GEN-LAST:event_btnMuteUserActionPerformed + private void btnDeActivateActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDeActivateActionPerformed + int row = this.tblUsers.convertRowIndexToModel(tblUsers.getSelectedRow()); + ConsoleFrame.getSession().toggleActivation((String) tableUserModel.getValueAt(row, TableUserModel.POS_USER_NAME)); + }//GEN-LAST:event_btnDeActivateActionPerformed + + private void btnLockUserActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnLockUserActionPerformed + int row = this.tblUsers.convertRowIndexToModel(tblUsers.getSelectedRow()); + ConsoleFrame.getSession().lockUser((String) tableUserModel.getValueAt(row, TableUserModel.POS_USER_NAME), ((Number) spinnerMuteDurationMinutes.getValue()).longValue()); + }//GEN-LAST:event_btnLockUserActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton btnDeActivate; private javax.swing.JButton btnDisconnect; private javax.swing.JButton btnEndSession; + private javax.swing.JButton btnLockUser; private javax.swing.JButton btnMuteUser; private javax.swing.JButton btnRemoveTable; private javax.swing.JPanel jPanel1; @@ -324,7 +372,8 @@ public class ConsolePanel extends javax.swing.JPanel { private javax.swing.JScrollPane jScrollPane1; private javax.swing.JScrollPane jScrollPane2; private javax.swing.JSplitPane jSplitPane1; - private javax.swing.JSlider sliderMuteDurationMinutes; + private javax.swing.JLabel lblMinutes; + private javax.swing.JSpinner spinnerMuteDurationMinutes; private javax.swing.JTable tblTables; private javax.swing.JTable tblUsers; // End of variables declaration//GEN-END:variables @@ -338,10 +387,12 @@ class TableUserModel extends AbstractTableModel { public static final int POS_SESSION_ID = 3; public static final int POS_GAME_INFO = 4; public static final int POS_USER_STATE = 5; + public static final int POS_CHAT_MUTE = 6; - private final String[] columnNames = new String[]{"User Name", "Host", "Time Connected", "SessionId", "Gameinfo", "User State"}; + private final String[] columnNames = new String[]{"User Name", "Host", "Time Connected", "SessionId", "Gameinfo", "User state", "Chat mute"}; private UserView[] users = new UserView[0]; - private static final DateFormat formatter = new SimpleDateFormat("HH:mm:ss"); + private static final DateFormat formatterTime = new SimpleDateFormat("HH:mm:ss"); + private static final DateFormat formatterTimeStamp = new SimpleDateFormat("yy-M-dd HH:mm:ss"); public void loadData(List users) { this.users = users.toArray(new UserView[0]); @@ -366,13 +417,18 @@ class TableUserModel extends AbstractTableModel { case POS_HOST: return users[arg0].getHost(); case POS_TIME_CONNECTED: - return formatter.format(users[arg0].getConnectionTime()); + return formatterTime.format(users[arg0].getConnectionTime()); case POS_SESSION_ID: return users[arg0].getSessionId(); case POS_GAME_INFO: return users[arg0].getGameInfo(); case POS_USER_STATE: return users[arg0].getUserState(); + case POS_CHAT_MUTE: + if (users[arg0].getMuteChatUntil() == null) { + return ""; + } + return formatterTimeStamp.format(users[arg0].getMuteChatUntil()); } return ""; } diff --git a/Mage.Server/src/main/java/mage/server/AuthorizedUser.java b/Mage.Server/src/main/java/mage/server/AuthorizedUser.java index f02b615e8c..43e0573b5b 100644 --- a/Mage.Server/src/main/java/mage/server/AuthorizedUser.java +++ b/Mage.Server/src/main/java/mage/server/AuthorizedUser.java @@ -1,20 +1,22 @@ package mage.server; +import com.j256.ormlite.field.DataType; import com.j256.ormlite.field.DatabaseField; import com.j256.ormlite.table.DatabaseTable; +import java.util.Date; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.SimpleAuthenticationInfo; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.authc.credential.HashedCredentialsMatcher; -import org.apache.shiro.util.ByteSource; import org.apache.shiro.codec.Base64; import org.apache.shiro.crypto.hash.Hash; +import org.apache.shiro.util.ByteSource; @DatabaseTable(tableName = "authorized_user") public class AuthorizedUser { - @DatabaseField(indexName = "name_index", unique = true) + @DatabaseField(id = true, indexName = "name_index", unique = true) protected String name; @DatabaseField @@ -32,6 +34,18 @@ public class AuthorizedUser { @DatabaseField(indexName = "email_index", unique = true) protected String email; + @DatabaseField + protected boolean active; // the user can't sign in + + @DatabaseField(dataType = DataType.DATE_STRING, format = "yyyy-MM-dd HH:mm:ss") + protected Date lockedUntil; // the user can't sign in until timestamp + + @DatabaseField(dataType = DataType.DATE_STRING, format = "yyyy-MM-dd HH:mm:ss") + protected Date chatLockedUntil; // the user can't use the chat until timestamp + + @DatabaseField(dataType = DataType.DATE_STRING, format = "yyyy-MM-dd HH:mm:ss") + protected Date lastConnection; // time of the last user connect + public AuthorizedUser() { } @@ -42,6 +56,9 @@ public class AuthorizedUser { this.hashAlgorithm = hash.getAlgorithmName(); this.hashIterations = hash.getIterations(); this.email = email; + this.chatLockedUntil = null; + this.active = true; + this.lockedUntil = null; } public boolean doCredentialsMatch(String name, String password) { diff --git a/Mage.Server/src/main/java/mage/server/AuthorizedUserRepository.java b/Mage.Server/src/main/java/mage/server/AuthorizedUserRepository.java index 9507ce9a12..4829a2fbdf 100644 --- a/Mage.Server/src/main/java/mage/server/AuthorizedUserRepository.java +++ b/Mage.Server/src/main/java/mage/server/AuthorizedUserRepository.java @@ -12,6 +12,7 @@ import com.j256.ormlite.table.TableUtils; import java.io.File; import java.sql.SQLException; import java.util.List; +import mage.cards.repository.CardRepository; import mage.cards.repository.RepositoryUtil; import org.apache.log4j.Logger; import org.apache.shiro.crypto.RandomNumberGenerator; @@ -27,7 +28,7 @@ public enum AuthorizedUserRepository { private static final String JDBC_URL = "jdbc:h2:file:./db/authorized_user.h2;AUTO_SERVER=TRUE"; private static final String VERSION_ENTITY_NAME = "authorized_user"; // raise this if db structure was changed - private static final long DB_VERSION = 1; + private static final long DB_VERSION = 2; private static final RandomNumberGenerator rng = new SecureRandomNumberGenerator(); private Dao dao; @@ -39,16 +40,10 @@ public enum AuthorizedUserRepository { } try { ConnectionSource connectionSource = new JdbcConnectionSource(JDBC_URL); - boolean obsolete = RepositoryUtil.isDatabaseObsolete(connectionSource, VERSION_ENTITY_NAME, DB_VERSION); - - if (obsolete) { - TableUtils.dropTable(connectionSource, AuthorizedUser.class, true); - } - TableUtils.createTableIfNotExists(connectionSource, AuthorizedUser.class); dao = DaoManager.createDao(connectionSource, AuthorizedUser.class); } catch (SQLException ex) { - Logger.getLogger(AuthorizedUserRepository.class).error("Error creating authorized_user repository - ", ex); + Logger.getLogger(AuthorizedUserRepository.class).error("Error creating / assigning authorized_user repository - ", ex); } } @@ -87,6 +82,14 @@ public enum AuthorizedUserRepository { return null; } + public void update(AuthorizedUser authorizedUser) { + try { + dao.update(authorizedUser); + } catch (SQLException ex) { + Logger.getLogger(AuthorizedUserRepository.class).error("Error updating authorized_user", ex); + } + } + public AuthorizedUser getByEmail(String userName) { try { QueryBuilder qb = dao.queryBuilder(); @@ -112,4 +115,38 @@ public enum AuthorizedUserRepository { Logger.getLogger(AuthorizedUserRepository.class).error("Error closing authorized_user repository - ", ex); } } + + public long getDBVersionFromDB() { + try { + ConnectionSource connectionSource = new JdbcConnectionSource(JDBC_URL); + return RepositoryUtil.getDatabaseVersion(connectionSource, VERSION_ENTITY_NAME); + } catch (SQLException ex) { + Logger.getLogger(CardRepository.class).error("Error getting DB version from DB - ", ex); + } + return 0; + } + + public boolean checkAlterAndMigrateAuthorizedUser() { + long currentDBVersion = getDBVersionFromDB(); + if (currentDBVersion == 1 && DB_VERSION == 2) { + return migrateFrom1To2(); + } + return true; + } + + private boolean migrateFrom1To2() { + try { + Logger.getLogger(AuthorizedUserRepository.class).info("Starting " + VERSION_ENTITY_NAME + " DB migration from version 1 to version 2"); + dao.executeRaw("ALTER TABLE authorized_user ADD COLUMN active BOOLEAN DEFAULT true;"); + dao.executeRaw("ALTER TABLE authorized_user ADD COLUMN lockedUntil DATETIME;"); + dao.executeRaw("ALTER TABLE authorized_user ADD COLUMN chatLockedUntil DATETIME;"); + dao.executeRaw("ALTER TABLE authorized_user ADD COLUMN lastConnection DATETIME;"); + RepositoryUtil.updateVersion(dao.getConnectionSource(), VERSION_ENTITY_NAME, DB_VERSION); + Logger.getLogger(AuthorizedUserRepository.class).info("Migration finished."); + return true; + } catch (SQLException ex) { + Logger.getLogger(AuthorizedUserRepository.class).error("Error while migrating from version 1 to version 2 - ", ex); + return false; + } + } } diff --git a/Mage.Server/src/main/java/mage/server/ChatManager.java b/Mage.Server/src/main/java/mage/server/ChatManager.java index 910b1b0ac2..ba2a3fca2b 100644 --- a/Mage.Server/src/main/java/mage/server/ChatManager.java +++ b/Mage.Server/src/main/java/mage/server/ChatManager.java @@ -28,9 +28,11 @@ package mage.server; import java.util.ArrayList; +import java.util.Calendar; import java.util.Locale; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; +import mage.server.util.SystemUtil; import mage.view.ChatMessage.MessageColor; import mage.view.ChatMessage.MessageType; import mage.view.ChatMessage.SoundToPlay; @@ -94,10 +96,6 @@ public class ChatManager { } } - public void broadcast(UUID chatId, String userName, String message, MessageColor color) { - this.broadcast(chatId, userName, message, color, true); - } - public void broadcast(UUID chatId, String userName, String message, MessageColor color, boolean withTime) { this.broadcast(chatId, userName, message, color, withTime, MessageType.TALK); } @@ -121,8 +119,25 @@ public class ChatManager { } } - if (!messageType.equals(MessageType.GAME) && message.equals(lastMessage)) { - return; + if (!messageType.equals(MessageType.GAME)) { + if (message.equals(lastMessage)) { + // prevent identical messages + return; + } + if (messageType.equals(MessageType.TALK)) { + User user = UserManager.getInstance().getUserByName(userName); + if (user != null) { + if (user.getChatLockedUntil() != null) { + if (user.getChatLockedUntil().compareTo(Calendar.getInstance().getTime()) > 0) { + chatSessions.get(chatId).broadcastInfoToUser(user, "Your chat is muted until " + SystemUtil.dateFormat.format(user.getChatLockedUntil())); + return; + } else { + user.setChatLockedUntil(null); + } + } + } + } + } lastMessage = message; chatSession.broadcast(userName, message, color, withTime, messageType, soundToPlay); @@ -195,7 +210,7 @@ public class ChatManager { if (user != null) { for (ChatSession chat : chatSessions.values()) { if (chat.hasUser(userId)) { - chat.broadcast(user.getName(), message, color); + chat.broadcast(user.getName(), message, color, true, MessageType.TALK, null); } } } @@ -206,7 +221,7 @@ public class ChatManager { if (user != null) { for (ChatSession chat : chatSessions.values()) { if (chat.hasUser(userId)) { - chat.broadcast(null, user.getName() + " has reconnected", MessageColor.BLUE, true, MessageType.STATUS); + chat.broadcast(null, user.getName() + " has reconnected", MessageColor.BLUE, true, MessageType.STATUS, null); } } } diff --git a/Mage.Server/src/main/java/mage/server/ChatSession.java b/Mage.Server/src/main/java/mage/server/ChatSession.java index cab740ddce..3f011f7a0f 100644 --- a/Mage.Server/src/main/java/mage/server/ChatSession.java +++ b/Mage.Server/src/main/java/mage/server/ChatSession.java @@ -65,7 +65,7 @@ public class ChatSession { if (user != null && !clients.containsKey(userId)) { String userName = user.getName(); clients.put(userId, userName); - broadcast(null, userName + " has joined", MessageColor.BLUE, true, MessageType.STATUS); + broadcast(null, userName + " has joined", MessageColor.BLUE, true, MessageType.STATUS, null); logger.trace(userName + " joined chat " + chatId); } } @@ -107,7 +107,7 @@ public class ChatSession { message = " left (" + reason.toString() + ")"; } if (message != null) { - broadcast(null, userName + message, MessageColor.BLUE, true, MessageType.STATUS); + broadcast(null, userName + message, MessageColor.BLUE, true, MessageType.STATUS, null); } } } catch (Exception ex) { @@ -136,18 +136,6 @@ public class ChatSession { return false; } - public void broadcast(String userName, String message, MessageColor color) { - this.broadcast(userName, message, color, true); - } - - public void broadcast(String userName, String message, MessageColor color, boolean withTime) { - this.broadcast(userName, message, color, withTime, MessageType.TALK); - } - - public void broadcast(String userName, String message, MessageColor color, boolean withTime, MessageType messageType) { - this.broadcast(userName, message, color, withTime, messageType, null); - } - public void broadcast(String userName, String message, MessageColor color, boolean withTime, MessageType messageType, SoundToPlay soundToPlay) { if (!message.isEmpty()) { boolean remove = false; diff --git a/Mage.Server/src/main/java/mage/server/MageServerImpl.java b/Mage.Server/src/main/java/mage/server/MageServerImpl.java index ef8d8a78e7..bc4c03c985 100644 --- a/Mage.Server/src/main/java/mage/server/MageServerImpl.java +++ b/Mage.Server/src/main/java/mage/server/MageServerImpl.java @@ -28,8 +28,6 @@ package mage.server; import java.security.SecureRandom; -import java.text.DateFormat; -import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; @@ -77,6 +75,7 @@ import mage.server.tournament.TournamentFactory; import mage.server.tournament.TournamentManager; import mage.server.util.ConfigSettings; import mage.server.util.ServerMessagesUtil; +import mage.server.util.SystemUtil; import mage.server.util.ThreadExecutor; import mage.utils.ActionWithBooleanResult; import mage.utils.ActionWithNullNegativeResult; @@ -105,8 +104,6 @@ public class MageServerImpl implements MageServer { private static final ExecutorService callExecutor = ThreadExecutor.getInstance().getCallExecutor(); private static final SecureRandom RANDOM = new SecureRandom(); - private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-M-dd hh:mm:ss"); - private final String adminPassword; private final boolean testMode; private final LinkedHashMap activeAuthTokens = new LinkedHashMap() { @@ -540,7 +537,7 @@ public class MageServerImpl implements MageServer { new Runnable() { @Override public void run() { - ChatManager.getInstance().broadcast(chatId, userName, StringEscapeUtils.escapeHtml4(message), MessageColor.BLUE); + ChatManager.getInstance().broadcast(chatId, userName, StringEscapeUtils.escapeHtml4(message), MessageColor.BLUE, true, ChatMessage.MessageType.TALK, null); } } ); @@ -1075,7 +1072,9 @@ public class MageServerImpl implements MageServer { user.getSessionId(), user.getConnectionTime(), user.getGameInfo(), - user.getUserState().toString())); + user.getUserState().toString(), + user.getChatLockedUntil() + )); } return users; } @@ -1100,8 +1099,38 @@ public class MageServerImpl implements MageServer { User user = UserManager.getInstance().getUserByName(userName); if (user != null) { Date muteUntil = new Date(Calendar.getInstance().getTimeInMillis() + (durationMinutes * Timer.ONE_MINUTE)); - user.showUserMessage("Admin info", "You were muted for chat messages until " + dateFormat.format(muteUntil) + "."); - // user.setChatMuteUntil(new Date() + duationMinutes); + user.showUserMessage("Admin info", "You were muted for chat messages until " + SystemUtil.dateFormat.format(muteUntil) + "."); + user.setChatLockedUntil(muteUntil); + } + + } + }); + } + + @Override + public void lockUser(String sessionId, final String userName, final long durationMinutes) throws MageException { + execute("muteUser", sessionId, new Action() { + @Override + public void execute() { + User user = UserManager.getInstance().getUserByName(userName); + if (user != null) { + 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.setLockedUntil(lockUntil); + } + + } + }); + } + + @Override + public void toggleActivation(String sessionId, final String userName) throws MageException { + execute("muteUser", sessionId, new Action() { + @Override + public void execute() { + User user = UserManager.getInstance().getUserByName(userName); + if (user != null) { + user.setActive(!user.isActive()); } } diff --git a/Mage.Server/src/main/java/mage/server/Main.java b/Mage.Server/src/main/java/mage/server/Main.java index 32486a5846..e849916cef 100644 --- a/Mage.Server/src/main/java/mage/server/Main.java +++ b/Mage.Server/src/main/java/mage/server/Main.java @@ -37,7 +37,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import javax.management.MBeanServer; - import mage.cards.ExpansionSet; import mage.cards.Sets; import mage.cards.repository.CardScanner; @@ -118,25 +117,42 @@ public class Main { } } + if (ConfigSettings.getInstance().isAuthenticationActivated()) { + logger.info("Check authorized user DB version ..."); + if (!AuthorizedUserRepository.instance.checkAlterAndMigrateAuthorizedUser()) { + logger.fatal("Failed to start server."); + return; + } + logger.info("Done."); + } + logger.info("Loading extension packages..."); List extensions = new ArrayList<>(); - if(!extensionFolder.exists()) if(!extensionFolder.mkdirs()) - logger.error("Could not create extensions directory."); - File[] extensionDirectories = extensionFolder.listFiles(); - if(extensionDirectories != null) for(File f : extensionDirectories) if(f.isDirectory()) - try { - logger.info(" - Loading extension from "+f); - extensions.add(ExtensionPackageLoader.loadExtension(f)); - } catch (IOException e) { - logger.error("Could not load extension in "+f+"!", e); + if (!extensionFolder.exists()) { + if (!extensionFolder.mkdirs()) { + logger.error("Could not create extensions directory."); } + } + File[] extensionDirectories = extensionFolder.listFiles(); + if (extensionDirectories != null) { + for (File f : extensionDirectories) { + if (f.isDirectory()) { + try { + logger.info(" - Loading extension from " + f); + extensions.add(ExtensionPackageLoader.loadExtension(f)); + } catch (IOException e) { + logger.error("Could not load extension in " + f + "!", e); + } + } + } + } logger.info("Done."); - if(!extensions.isEmpty()) { + if (!extensions.isEmpty()) { logger.info("Registering custom sets..."); - for(ExtensionPackage pkg : extensions) { - for(ExpansionSet set : pkg.getSets()) { - logger.info("- Loading "+set.getName()+" ("+set.getCode()+")"); + for (ExtensionPackage pkg : extensions) { + for (ExpansionSet set : pkg.getSets()) { + logger.info("- Loading " + set.getName() + " (" + set.getCode() + ")"); Sets.getInstance().addSet(set); } PluginClassloaderRegistery.registerPluginClassloader(pkg.getClassLoader()); @@ -155,7 +171,6 @@ public class Main { logger.info("Updating user stats DB..."); UserStatsRepository.instance.updateUserStats(); logger.info("Done."); - deleteSavedGames(); ConfigSettings config = ConfigSettings.getInstance(); for (GamePlugin plugin : config.getGameTypes()) { @@ -177,12 +192,12 @@ public class Main { for (ExtensionPackage pkg : extensions) { Map draftCubes = pkg.getDraftCubes(); for (String name : draftCubes.keySet()) { - logger.info("Loading extension: ["+name+"] "+draftCubes.get(name).toString()); + logger.info("Loading extension: [" + name + "] " + draftCubes.get(name).toString()); CubeFactory.getInstance().addDraftCube(name, draftCubes.get(name)); } Map deckTypes = pkg.getDeckTypes(); for (String name : deckTypes.keySet()) { - logger.info("Loading extension: ["+name+"] "+deckTypes.get(name)); + logger.info("Loading extension: [" + name + "] " + deckTypes.get(name)); DeckValidatorFactory.getInstance().addDeckType(name, deckTypes.get(name)); } } @@ -408,11 +423,11 @@ public class Main { } File[] files = directory.listFiles( new FilenameFilter() { - @Override - public boolean accept(File dir, String name) { - return name.endsWith(".game"); - } - } + @Override + public boolean accept(File dir, String name) { + return name.endsWith(".game"); + } + } ); for (File file : files) { file.delete(); diff --git a/Mage.Server/src/main/java/mage/server/Session.java b/Mage.Server/src/main/java/mage/server/Session.java index d6aabf7a06..934168c375 100644 --- a/Mage.Server/src/main/java/mage/server/Session.java +++ b/Mage.Server/src/main/java/mage/server/Session.java @@ -180,14 +180,15 @@ public class Session { public String connectUserHandling(String userName, String password) throws MageException { this.isAdmin = false; + AuthorizedUser authorizedUser = null; if (ConfigSettings.getInstance().isAuthenticationActivated()) { - AuthorizedUser authorizedUser = AuthorizedUserRepository.instance.getByName(userName); + authorizedUser = AuthorizedUserRepository.instance.getByName(userName); if (authorizedUser == null || !authorizedUser.doCredentialsMatch(userName, password)) { return "Wrong username or password. In case you haven't, please register your account first."; } } - User user = UserManager.getInstance().createUser(userName, host); + User user = UserManager.getInstance().createUser(userName, host, authorizedUser); boolean reconnect = false; if (user == null) { // user already exists user = UserManager.getInstance().getUserByName(userName); @@ -223,7 +224,7 @@ public class Session { public void connectAdmin() { this.isAdmin = true; - User user = UserManager.getInstance().createUser("Admin", host); + User user = UserManager.getInstance().createUser("Admin", host, null); if (user == null) { user = UserManager.getInstance().getUserByName("Admin"); } diff --git a/Mage.Server/src/main/java/mage/server/User.java b/Mage.Server/src/main/java/mage/server/User.java index 644440b976..c31aa62fb2 100644 --- a/Mage.Server/src/main/java/mage/server/User.java +++ b/Mage.Server/src/main/java/mage/server/User.java @@ -91,15 +91,30 @@ public class User { private UserState userState; private UserData userData; private UserStats userStats; + private Date chatLockedUntil; + private boolean active; + private Date lockedUntil; + private final AuthorizedUser authorizedUser; - public User(String userName, String host) { + public User(String userName, String host, AuthorizedUser authorizedUser) { this.userId = UUID.randomUUID(); this.userName = userName; this.host = host; this.userState = UserState.Created; - this.connectionTime = new Date(); this.lastActivity = new Date(); + if (authorizedUser != null) { + this.active = authorizedUser.active; + this.chatLockedUntil = authorizedUser.chatLockedUntil; + this.lockedUntil = authorizedUser.lockedUntil; + this.authorizedUser = authorizedUser; + updateAuthorizedUser(); + } else { + this.active = true; + this.chatLockedUntil = null; + this.lockedUntil = null; + this.authorizedUser = null; + } this.tables = new ConcurrentHashMap<>(); this.gameSessions = new ConcurrentHashMap<>(); @@ -128,6 +143,18 @@ public class User { return sessionId; } + public Date getChatLockedUntil() { + return chatLockedUntil; + } + + public boolean isActive() { + return active; + } + + public Date getLockedUntil() { + return lockedUntil; + } + public void setSessionId(String sessionId) { this.sessionId = sessionId; if (sessionId.isEmpty()) { @@ -145,6 +172,21 @@ public class User { } } + public void setChatLockedUntil(Date chatLockedUntil) { + this.chatLockedUntil = chatLockedUntil; + updateAuthorizedUser(); + } + + public void setActive(boolean active) { + this.active = active; + updateAuthorizedUser(); + } + + public void setLockedUntil(Date lockedUntil) { + this.lockedUntil = lockedUntil; + updateAuthorizedUser(); + } + public void lostConnection() { // Because watched games don't get restored after reconnection call stop watching for (Iterator iterator = watchedGames.iterator(); iterator.hasNext();) { @@ -731,4 +773,12 @@ public class User { } return number; } + + private void updateAuthorizedUser() { + if (authorizedUser != null) { + authorizedUser.lastConnection = this.connectionTime; + authorizedUser.chatLockedUntil = this.chatLockedUntil; + AuthorizedUserRepository.instance.update(authorizedUser); + } + } } diff --git a/Mage.Server/src/main/java/mage/server/UserManager.java b/Mage.Server/src/main/java/mage/server/UserManager.java index b7aeb5e1b7..a5798e6659 100644 --- a/Mage.Server/src/main/java/mage/server/UserManager.java +++ b/Mage.Server/src/main/java/mage/server/UserManager.java @@ -76,11 +76,11 @@ public class UserManager { }, 60, 60, TimeUnit.SECONDS); } - public User createUser(String userName, String host) { + public User createUser(String userName, String host, AuthorizedUser authorizedUser) { if (getUserByName(userName) != null) { return null; //user already exists } - User user = new User(userName, host); + User user = new User(userName, host, authorizedUser); users.put(user.getId(), user); usersByName.put(userName, user); return user; diff --git a/Mage.Server/src/main/java/mage/server/game/GameController.java b/Mage.Server/src/main/java/mage/server/game/GameController.java index 26ddefecde..87d3904e9e 100644 --- a/Mage.Server/src/main/java/mage/server/game/GameController.java +++ b/Mage.Server/src/main/java/mage/server/game/GameController.java @@ -166,11 +166,11 @@ public class GameController implements GameCallback { updateGame(); break; case INFO: - ChatManager.getInstance().broadcast(chatId, "", event.getMessage(), MessageColor.BLACK, true, ChatMessage.MessageType.GAME); + ChatManager.getInstance().broadcast(chatId, "", event.getMessage(), MessageColor.BLACK, true, ChatMessage.MessageType.GAME, null); logger.trace(game.getId() + " " + event.getMessage()); break; case STATUS: - ChatManager.getInstance().broadcast(chatId, "", event.getMessage(), MessageColor.ORANGE, event.getWithTime(), ChatMessage.MessageType.GAME); + ChatManager.getInstance().broadcast(chatId, "", event.getMessage(), MessageColor.ORANGE, event.getWithTime(), ChatMessage.MessageType.GAME, null); logger.trace(game.getId() + " " + event.getMessage()); break; case ERROR: @@ -346,7 +346,7 @@ public class GameController implements GameCallback { } user.addGame(playerId, gameSession); logger.debug("Player " + player.getName() + " " + playerId + " has " + joinType + " gameId: " + game.getId()); - ChatManager.getInstance().broadcast(chatId, "", game.getPlayer(playerId).getLogName() + " has " + joinType + " the game", MessageColor.ORANGE, true, MessageType.GAME); + ChatManager.getInstance().broadcast(chatId, "", game.getPlayer(playerId).getLogName() + " has " + joinType + " the game", MessageColor.ORANGE, true, MessageType.GAME, null); checkStart(); } @@ -372,7 +372,7 @@ public class GameController implements GameCallback { GameManager.getInstance().joinGame(game.getId(), user.getId()); logger.debug("Player " + player.getName() + " (disconnected) has joined gameId: " + game.getId()); } - ChatManager.getInstance().broadcast(chatId, player.getName(), user.getPingInfo() + " is pending to join the game", MessageColor.BLUE, true, ChatMessage.MessageType.STATUS); + ChatManager.getInstance().broadcast(chatId, player.getName(), user.getPingInfo() + " is pending to join the game", MessageColor.BLUE, true, ChatMessage.MessageType.STATUS, null); if (user.getSecondsDisconnected() > 240) { // Cancel player join possibility lately after 4 minutes logger.debug("Player " + player.getName() + " - canceled game (after 240 seconds) gameId: " + game.getId()); @@ -443,7 +443,7 @@ public class GameController implements GameCallback { watchers.put(userId, gameWatcher); gameWatcher.init(); user.addGameWatchInfo(game.getId()); - ChatManager.getInstance().broadcast(chatId, user.getName(), " has started watching", MessageColor.BLUE, true, ChatMessage.MessageType.STATUS); + ChatManager.getInstance().broadcast(chatId, user.getName(), " has started watching", MessageColor.BLUE, true, ChatMessage.MessageType.STATUS, null); } } @@ -451,7 +451,7 @@ public class GameController implements GameCallback { watchers.remove(userId); User user = UserManager.getInstance().getUser(userId); if (user != null) { - ChatManager.getInstance().broadcast(chatId, user.getName(), " has stopped watching", MessageColor.BLUE, true, ChatMessage.MessageType.STATUS); + ChatManager.getInstance().broadcast(chatId, user.getName(), " has stopped watching", MessageColor.BLUE, true, ChatMessage.MessageType.STATUS, null); } } @@ -678,7 +678,7 @@ public class GameController implements GameCallback { String sb = player.getLogName() + " has timed out (player had priority and was not active for " + ConfigSettings.getInstance().getMaxSecondsIdle() + " seconds ) - Auto concede."; - ChatManager.getInstance().broadcast(chatId, "", sb, MessageColor.BLACK, true, MessageType.STATUS); + ChatManager.getInstance().broadcast(chatId, "", sb, MessageColor.BLACK, true, MessageType.STATUS, null); game.idleTimeout(playerId); } } diff --git a/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java b/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java index c18b777224..aabe8bf37a 100644 --- a/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java +++ b/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java @@ -89,73 +89,73 @@ public class TournamentController { private void init() { tournament.addTableEventListener( new Listener() { - @Override - public void event(TableEvent event) { - switch (event.getEventType()) { - case CHECK_STATE_PLAYERS: - checkPlayersState(); - break; - case INFO: - ChatManager.getInstance().broadcast(chatId, "", event.getMessage(), MessageColor.BLACK, true, MessageType.STATUS); - logger.debug(tournament.getId() + " " + event.getMessage()); - break; - case START_DRAFT: - startDraft(event.getDraft()); - break; - case CONSTRUCT: - if (!isAbort()) { - construct(); - } else { - endTournament(); - } - break; - case START_MATCH: - if (!isAbort()) { - initTournament(); // set state - startMatch(event.getPair(), event.getMatchOptions()); - } - break; - case START_MULTIPLAYER_MATCH: - if (!isAbort()) { - initTournament(); // set state - MatchOptions matchOptions = event.getMatchOptions(); - if (matchOptions != null && event.getMultiplayerRound() != null) { - for (TournamentPlayer player : event.getMultiplayerRound().getAllPlayers()) { - matchOptions.getPlayerTypes().add(player.getPlayerType()); - } - } - - startMultiplayerMatch(event.getMultiplayerRound(), event.getMatchOptions()); - } - break; - case END: - endTournament(); - break; + @Override + public void event(TableEvent event) { + switch (event.getEventType()) { + case CHECK_STATE_PLAYERS: + checkPlayersState(); + break; + case INFO: + ChatManager.getInstance().broadcast(chatId, "", event.getMessage(), MessageColor.BLACK, true, MessageType.STATUS, null); + logger.debug(tournament.getId() + " " + event.getMessage()); + break; + case START_DRAFT: + startDraft(event.getDraft()); + break; + case CONSTRUCT: + if (!isAbort()) { + construct(); + } else { + endTournament(); } - } + break; + case START_MATCH: + if (!isAbort()) { + initTournament(); // set state + startMatch(event.getPair(), event.getMatchOptions()); + } + break; + case START_MULTIPLAYER_MATCH: + if (!isAbort()) { + initTournament(); // set state + MatchOptions matchOptions = event.getMatchOptions(); + if (matchOptions != null && event.getMultiplayerRound() != null) { + for (TournamentPlayer player : event.getMultiplayerRound().getAllPlayers()) { + matchOptions.getPlayerTypes().add(player.getPlayerType()); + } + } + + startMultiplayerMatch(event.getMultiplayerRound(), event.getMatchOptions()); + } + break; + case END: + endTournament(); + break; } + } + } ); tournament.addPlayerQueryEventListener( new Listener() { - @Override - public void event(PlayerQueryEvent event) { - try { - switch (event.getQueryType()) { - case CONSTRUCT: - construct(event.getPlayerId(), event.getMax()); - break; - } - } catch (MageException ex) { - logger.fatal("Player event listener error", ex); - } + @Override + public void event(PlayerQueryEvent event) { + try { + switch (event.getQueryType()) { + case CONSTRUCT: + construct(event.getPlayerId(), event.getMax()); + break; } + } catch (MageException ex) { + logger.fatal("Player event listener error", ex); } + } + } ); for (TournamentPlayer player : tournament.getPlayers()) { if (!player.getPlayer().isHuman()) { player.setJoined(); logger.debug("player " + player.getPlayer().getId() + " has joined tournament " + tournament.getId()); - ChatManager.getInstance().broadcast(chatId, "", player.getPlayer().getLogName() + " has joined the tournament", MessageColor.BLACK, true, MessageType.STATUS); + ChatManager.getInstance().broadcast(chatId, "", player.getPlayer().getLogName() + " has joined the tournament", MessageColor.BLACK, true, MessageType.STATUS, null); } } checkStart(); @@ -185,7 +185,7 @@ public class TournamentController { TournamentPlayer player = tournament.getPlayer(playerId); player.setJoined(); logger.debug("player " + player.getPlayer().getName() + " - client has joined tournament " + tournament.getId()); - ChatManager.getInstance().broadcast(chatId, "", player.getPlayer().getLogName() + " has joined the tournament", MessageColor.BLACK, true, MessageType.STATUS); + ChatManager.getInstance().broadcast(chatId, "", player.getPlayer().getLogName() + " has joined the tournament", MessageColor.BLACK, true, MessageType.STATUS, null); checkStart(); } else { logger.error("User not found userId: " + userId + " tournamentId: " + tournament.getId()); @@ -209,11 +209,11 @@ public class TournamentController { if (!started && allJoined()) { ThreadExecutor.getInstance().getCallExecutor().execute( new Runnable() { - @Override - public void run() { - startTournament(); - } - }); + @Override + public void run() { + startTournament(); + } + }); } } @@ -278,7 +278,7 @@ public class TournamentController { logger.fatal("TournamentController startMatch error", ex); } } - + private void startMultiplayerMatch(MultiplayerRound round, MatchOptions matchOptions) { try { TableManager tableManager = TableManager.getInstance(); @@ -286,7 +286,7 @@ public class TournamentController { table.setTournamentSubTable(true); table.setTournament(tournament); table.setState(TableState.WAITING); - + for (TournamentPlayer player : round.getAllPlayers()) { tableManager.addPlayer(getPlayerUserId(player.getPlayer().getId()), table.getId(), player.getPlayer(), player.getPlayerType(), player.getDeck()); } @@ -302,7 +302,7 @@ public class TournamentController { } catch (GameException ex) { logger.fatal("TournamentController startMatch error", ex); } - } + } private void startDraft(Draft draft) { TableManager.getInstance().startDraft(tableId, draft); @@ -447,7 +447,7 @@ public class TournamentController { user.removeTable(leavingPlayer.getPlayer().getId()); user.removeTournament(leavingPlayer.getPlayer().getId()); } - ChatManager.getInstance().broadcast(chatId, "", leavingPlayer.getPlayer().getLogName() + " was replaced by draftbot", MessageColor.BLACK, true, MessageType.STATUS); + ChatManager.getInstance().broadcast(chatId, "", leavingPlayer.getPlayer().getLogName() + " was replaced by draftbot", MessageColor.BLACK, true, MessageType.STATUS, null); } return true; } diff --git a/Mage.Server/src/main/java/mage/server/util/SystemUtil.java b/Mage.Server/src/main/java/mage/server/util/SystemUtil.java index aee752c060..d7fb2254a6 100644 --- a/Mage.Server/src/main/java/mage/server/util/SystemUtil.java +++ b/Mage.Server/src/main/java/mage/server/util/SystemUtil.java @@ -1,5 +1,16 @@ package mage.server.util; +import java.io.File; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Scanner; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import mage.cards.Card; import mage.cards.repository.CardInfo; import mage.cards.repository.CardRepository; @@ -8,36 +19,30 @@ import mage.game.Game; import mage.players.Player; import mage.util.RandomUtil; -import java.io.File; -import java.util.Date; -import java.util.HashSet; -import java.util.List; -import java.util.Random; -import java.util.Scanner; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - /** * @author nantuko */ public class SystemUtil { + public static final DateFormat dateFormat = new SimpleDateFormat("yy-M-dd HH:mm:ss"); + private static final String INIT_FILE_PATH = "config" + File.separator + "init.txt"; - private static final org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(SystemUtil.class); + private static final org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(SystemUtil.class); /** * Replaces cards in player's hands by specified in config/init.txt.
*
* Implementation note:
* 1. Read init.txt line by line
- * 2. Parse line using the following format: line ::= :::
+ * 2. Parse line using the following format: line ::= + * :::
* 3. If zone equals to 'hand', add card to player's library
- * 3a. Then swap added card with any card in player's hand
- * 3b. Parse next line (go to 2.), If EOF go to 4.
- * 4. Log message to all players that cards were added (to prevent unfair play).
+ * 3a. Then swap added card with any card in player's hand
+ * 3b. Parse next line (go to 2.), If EOF go to 4.
+ * 4. Log message to all players that cards were added (to prevent unfair + * play).
* 5. Exit
+ * * @param game */ public static void addCardsForTesting(Game game) { @@ -109,8 +114,7 @@ public class SystemUtil { swapWithAnyCard(game, player, card, gameZone); } } - } - finally { + } finally { scanner.close(); } } catch (Exception e) { @@ -137,7 +141,7 @@ public class SystemUtil { } else { card.moveToZone(zone, null, game, false); } - logger.info("Added card to player's " + zone.toString() + ": " + card.getName() +", player = " + player.getName()); + logger.info("Added card to player's " + zone.toString() + ": " + card.getName() + ", player = " + player.getName()); } /** @@ -148,7 +152,7 @@ public class SystemUtil { * @return */ private static Player findPlayer(Game game, String name) { - for (Player player: game.getPlayers().values()) { + for (Player player : game.getPlayers().values()) { if (player.getName().equals(name)) { return player; } @@ -162,7 +166,7 @@ public class SystemUtil { //return matcher.replaceAll(""); return input.replaceAll("[^a-zA-Z0-9]", ""); } - + public static void main(String... args) { System.out.println(sanitize("123")); System.out.println(sanitize("AaAaD_123"));