Added chat mute and user (de)activation actions to the Mage server console.

This commit is contained in:
LevelX2 2016-10-05 00:59:51 +02:00
parent 7c4b40073c
commit c46f75ac28
18 changed files with 511 additions and 213 deletions

View file

@ -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;

View file

@ -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

View file

@ -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();
}

View file

@ -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;
}
}

View file

@ -52,8 +52,9 @@
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<Component id="jPanel3" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jPanel4" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
<Component id="jPanel4" min="-2" pref="57" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -69,7 +70,7 @@
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane1" alignment="0" pref="347" max="32767" attributes="0"/>
<Component id="jScrollPane1" alignment="0" pref="339" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
@ -104,26 +105,51 @@
<EmptySpace max="-2" attributes="0"/>
<Component id="btnDisconnect" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnEndSession" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="sliderMuteDurationMinutes" pref="0" max="32767" attributes="0"/>
<Component id="btnMuteUser" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<Component id="btnEndSession" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnMuteUser" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<Component id="btnDeActivate" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnLockUser" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace pref="50" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="lblMinutes" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="spinnerMuteDurationMinutes" min="-2" pref="64" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Group type="103" groupAlignment="3" attributes="0">
<Component id="btnDisconnect" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnEndSession" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnMuteUser" alignment="3" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Group type="103" groupAlignment="3" attributes="0">
<Component id="btnDisconnect" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnEndSession" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnMuteUser" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="btnDeActivate" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnLockUser" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="16" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="lblMinutes" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="spinnerMuteDurationMinutes" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</Group>
<EmptySpace pref="9" max="32767" attributes="0"/>
<Component id="sliderMuteDurationMinutes" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -154,11 +180,30 @@
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnMuteUserActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JSlider" name="sliderMuteDurationMinutes">
<Component class="javax.swing.JButton" name="btnDeActivate">
<Properties>
<Property name="maximum" type="int" value="3600"/>
<Property name="value" type="int" value="60"/>
<Property name="text" type="java.lang.String" value="(de)activate"/>
<Property name="actionCommand" type="java.lang.String" value="Mute 1h"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnDeActivateActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnLockUser">
<Properties>
<Property name="text" type="java.lang.String" value="Lock user"/>
<Property name="actionCommand" type="java.lang.String" value="Mute 1h"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnLockUserActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="lblMinutes">
<Properties>
<Property name="text" type="java.lang.String" value="Minutes"/>
</Properties>
</Component>
<Component class="javax.swing.JSpinner" name="spinnerMuteDurationMinutes">
</Component>
</SubComponents>
</Container>
@ -182,7 +227,7 @@
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<Component id="jPanel5" max="32767" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
<Component id="jPanel6" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
@ -194,15 +239,12 @@
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane2" alignment="0" pref="351" max="32767" attributes="0"/>
<Component id="jScrollPane2" alignment="0" pref="453" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="jScrollPane2" min="-2" pref="343" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
<Component id="jScrollPane2" alignment="0" pref="340" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>

View file

@ -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<UserView> 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 "";
}

View file

@ -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) {

View file

@ -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<AuthorizedUser, Object> 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<AuthorizedUser, Object> 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;
}
}
}

View file

@ -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);
}
}
}

View file

@ -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;

View file

@ -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<String, String> activeAuthTokens = new LinkedHashMap<String, String>() {
@ -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());
}
}

View file

@ -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<ExtensionPackage> 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<String, Class> 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<String, Class> 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();

View file

@ -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");
}

View file

@ -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<UUID> 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);
}
}
}

View file

@ -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;

View file

@ -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);
}
}

View file

@ -89,73 +89,73 @@ public class TournamentController {
private void init() {
tournament.addTableEventListener(
new Listener<TableEvent>() {
@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<PlayerQueryEvent>() {
@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;
}

View file

@ -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.<br/>
* <br/>
* <b>Implementation note:</b><br/>
* 1. Read init.txt line by line<br/>
* 2. Parse line using the following format: line ::= <zone>:<nickname>:<card name>:<amount><br/>
* 2. Parse line using the following format: line ::=
* <zone>:<nickname>:<card name>:<amount><br/>
* 3. If zone equals to 'hand', add card to player's library<br/>
* 3a. Then swap added card with any card in player's hand<br/>
* 3b. Parse next line (go to 2.), If EOF go to 4.<br/>
* 4. Log message to all players that cards were added (to prevent unfair play).<br/>
* 3a. Then swap added card with any card in player's hand<br/>
* 3b. Parse next line (go to 2.), If EOF go to 4.<br/>
* 4. Log message to all players that cards were added (to prevent unfair
* play).<br/>
* 5. Exit<br/>
*
* @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"));