package games.strategy.engine.lobby.client.ui; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.List; import javax.swing.Action; import javax.swing.BoxLayout; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JSpinner; import javax.swing.JSplitPane; import javax.swing.JTextPane; import javax.swing.SpinnerNumberModel; import com.google.common.collect.ImmutableList; import games.strategy.engine.chat.Chat; import games.strategy.engine.chat.ChatMessagePanel; import games.strategy.engine.chat.ChatPlayerPanel; import games.strategy.engine.framework.GameRunner; import games.strategy.engine.framework.startup.ui.MainFrame; import games.strategy.engine.lobby.client.LobbyClient; import games.strategy.engine.lobby.client.login.LobbyServerProperties; import games.strategy.engine.lobby.server.IModeratorController; import games.strategy.engine.lobby.server.LobbyServer; import games.strategy.engine.lobby.server.ModeratorController; import games.strategy.net.INode; import games.strategy.triplea.ui.menubar.LobbyMenu; import games.strategy.ui.SwingAction; import games.strategy.util.CountDownLatchHandler; import games.strategy.util.EventThreadJOptionPane; public class LobbyFrame extends JFrame { private static final long serialVersionUID = -388371674076362572L; private static final List<String> banOrMuteOptions = ImmutableList.of( "Mac Address Only", "User Name only", "Name and Mac", "Cancel"); private final LobbyClient m_client; private final ChatMessagePanel m_chatMessagePanel; public LobbyFrame(final LobbyClient client, final LobbyServerProperties props) { super("TripleA Lobby"); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); setIconImage(GameRunner.getGameIcon(this)); m_client = client; setJMenuBar(new LobbyMenu(this)); final Chat chat = new Chat(m_client.getMessenger(), LobbyServer.LOBBY_CHAT, m_client.getChannelMessenger(), m_client.getRemoteMessenger(), Chat.CHAT_SOUND_PROFILE.LOBBY_CHATROOM); m_chatMessagePanel = new ChatMessagePanel(chat); showServerMessage(props); m_chatMessagePanel.setShowTime(true); final ChatPlayerPanel chatPlayers = new ChatPlayerPanel(null); chatPlayers.addHiddenPlayerName(LobbyServer.ADMIN_USERNAME); chatPlayers.setChat(chat); chatPlayers.setPreferredSize(new Dimension(200, 600)); chatPlayers.addActionFactory(clickedOn -> createAdminActions(clickedOn)); final LobbyGamePanel gamePanel = new LobbyGamePanel(m_client.getMessengers()); final JSplitPane leftSplit = new JSplitPane(); leftSplit.setOrientation(JSplitPane.VERTICAL_SPLIT); leftSplit.setTopComponent(gamePanel); leftSplit.setBottomComponent(m_chatMessagePanel); leftSplit.setResizeWeight(0.8); gamePanel.setPreferredSize(new Dimension(700, 200)); m_chatMessagePanel.setPreferredSize(new Dimension(700, 400)); final JSplitPane mainSplit = new JSplitPane(); mainSplit.setOrientation(JSplitPane.HORIZONTAL_SPLIT); mainSplit.setLeftComponent(leftSplit); mainSplit.setRightComponent(chatPlayers); add(mainSplit, BorderLayout.CENTER); pack(); m_chatMessagePanel.requestFocusInWindow(); setLocationRelativeTo(null); m_client.getMessenger().addErrorListener((messenger, reason) -> connectionToServerLost()); addWindowListener(new WindowAdapter() { @Override public void windowClosing(final WindowEvent e) { shutdown(); } }); } public ChatMessagePanel getChatMessagePanel() { return m_chatMessagePanel; } private void showServerMessage(final LobbyServerProperties props) { if (props.serverMessage != null && props.serverMessage.length() > 0) { m_chatMessagePanel.addServerMessage(props.serverMessage); } } private List<Action> createAdminActions(final INode clickedOn) { if (!m_client.isAdmin()) { return Collections.emptyList(); } if (clickedOn.equals(m_client.getMessenger().getLocalNode())) { return Collections.emptyList(); } final IModeratorController controller = (IModeratorController) m_client.getRemoteMessenger() .getRemote(ModeratorController.getModeratorControllerName()); final List<Action> rVal = new ArrayList<>(); rVal.add(SwingAction.of("Boot " + clickedOn.getName(), e -> { if (!confirm("Boot " + clickedOn.getName())) { return; } controller.boot(clickedOn); })); rVal.add(SwingAction.of("Ban Player", e -> { final int resultBT = JOptionPane.showOptionDialog(LobbyFrame.this, "<html>Select the type of ban: <br>" + "Please consult other admins before banning longer than 1 day. <br>" + "And please remember to report this ban.</html>", "Select Ban Type", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, banOrMuteOptions.toArray(), banOrMuteOptions.toArray()[banOrMuteOptions.size() - 1]); if (resultBT < 0) { return; } final String selectedBanType = (String) banOrMuteOptions.toArray()[resultBT]; if (selectedBanType.equals("Cancel")) { return; } final List<String> timeUnits = new ArrayList<>(); timeUnits.add("Minute"); timeUnits.add("Hour"); timeUnits.add("Day"); timeUnits.add("Week"); timeUnits.add("Month"); timeUnits.add("Year"); timeUnits.add("Forever"); timeUnits.add("Cancel"); final int resultTU = JOptionPane.showOptionDialog(LobbyFrame.this, "Select the unit of measurement: ", "Select Timespan Unit", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, timeUnits.toArray(), timeUnits.toArray()[timeUnits.size() - 1]); if (resultTU < 0) { return; } final String selectedTimeUnit = (String) timeUnits.toArray()[resultTU]; if (selectedTimeUnit.equalsIgnoreCase("Cancel")) { return; } if (selectedTimeUnit.equals("Forever")) { if (selectedBanType.toLowerCase().contains("name")) { controller.banUsername(clickedOn, null); } if (selectedBanType.toLowerCase().contains("mac")) { controller.banMac(clickedOn, null); } // Should we keep this auto? controller.boot(clickedOn); return; } final String resultLOT = JOptionPane.showInputDialog(LobbyFrame.this, "Now please enter the length of time to ban the player: (In " + selectedTimeUnit + "s) ", 1); if (resultLOT == null) { return; } final long result2 = Long.parseLong(resultLOT); if (result2 < 0) { return; } long ticks = 0; if (selectedTimeUnit.equals("Minute")) { ticks = result2 * 1000 * 60; } else if (selectedTimeUnit.equals("Hour")) { ticks = result2 * 1000 * 60 * 60; } else if (selectedTimeUnit.equals("Day")) { ticks = result2 * 1000 * 60 * 60 * 24; } else if (selectedTimeUnit.equals("Week")) { ticks = result2 * 1000 * 60 * 60 * 24 * 7; } else if (selectedTimeUnit.equals("Month")) { ticks = result2 * 1000 * 60 * 60 * 24 * 30; } else if (selectedTimeUnit.equals("Year")) { ticks = result2 * 1000 * 60 * 60 * 24 * 365; } final long expire = System.currentTimeMillis() + ticks; if (selectedBanType.toLowerCase().contains("name")) { controller.banUsername(clickedOn, new Date(expire)); } if (selectedBanType.toLowerCase().contains("mac")) { controller.banMac(clickedOn, new Date(expire)); } // Should we keep this auto? controller.boot(clickedOn); })); rVal.add(SwingAction.of("Mute Player", e -> { final int resultMT = JOptionPane.showOptionDialog(LobbyFrame.this, "<html>Select the type of mute: <br>Please consult other admins before muting longer than 1 day.</html>", "Select Mute Type", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, banOrMuteOptions.toArray(), banOrMuteOptions.toArray()[banOrMuteOptions.size() - 1]); if (resultMT < 0) { return; } final String selectedMuteType = (String) banOrMuteOptions.toArray()[resultMT]; if (selectedMuteType.equals("Cancel")) { return; } final List<String> timeUnits = new ArrayList<>(); timeUnits.add("Minute"); timeUnits.add("Hour"); timeUnits.add("Day"); timeUnits.add("Week"); timeUnits.add("Month"); timeUnits.add("Year"); timeUnits.add("Forever"); timeUnits.add("Cancel"); final int resultTU = JOptionPane.showOptionDialog(LobbyFrame.this, "Select the unit of measurement: ", "Select Timespan Unit", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, timeUnits.toArray(), timeUnits.toArray()[timeUnits.size() - 1]); if (resultTU < 0) { return; } final String selectedTimeUnit = (String) timeUnits.toArray()[resultTU]; if (selectedTimeUnit.equals("Cancel")) { return; } if (selectedTimeUnit.equals("Forever")) { if (selectedMuteType.toLowerCase().contains("name")) { controller.muteUsername(clickedOn, null); } if (selectedMuteType.toLowerCase().contains("mac")) { controller.muteMac(clickedOn, null); } return; } final String resultLOT = JOptionPane.showInputDialog(LobbyFrame.this, "Now please enter the length of time to mute the player: (In " + selectedTimeUnit + "s) ", 1); if (resultLOT == null) { return; } final long result2 = Long.parseLong(resultLOT); if (result2 < 0) { return; } long ticks = 0; if (selectedTimeUnit.equals("Minute")) { ticks = result2 * 1000 * 60; } else if (selectedTimeUnit.equals("Hour")) { ticks = result2 * 1000 * 60 * 60; } else if (selectedTimeUnit.equals("Day")) { ticks = result2 * 1000 * 60 * 60 * 24; } else if (selectedTimeUnit.equals("Week")) { ticks = result2 * 1000 * 60 * 60 * 24 * 7; } else if (selectedTimeUnit.equals("Month")) { ticks = result2 * 1000 * 60 * 60 * 24 * 30; } else if (selectedTimeUnit.equals("Year")) { ticks = result2 * 1000 * 60 * 60 * 24 * 365; } final long expire = System.currentTimeMillis() + ticks; if (selectedMuteType.toLowerCase().contains("name")) { controller.muteUsername(clickedOn, new Date(expire)); } if (selectedMuteType.toLowerCase().contains("mac")) { controller.muteMac(clickedOn, new Date(expire)); } })); rVal.add(SwingAction.of("Quick Mute", e -> { final JLabel label = new JLabel("How many minutes should this player be muted?"); final JSpinner spinner = new JSpinner(new SpinnerNumberModel(10, 0, 60 * 24 * 2, 1)); final JPanel panel = new JPanel(); panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS)); panel.add(label); panel.add(spinner); if (JOptionPane.showConfirmDialog(LobbyFrame.this, panel, "Mute Player", JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION) { final Object value = spinner.getValue(); if (value == null) { return; } final long resultML = Long.parseLong(value.toString()); if (resultML < 0) { return; } final long ticks = resultML * 1000 * 60; final long expire = System.currentTimeMillis() + ticks; controller.muteUsername(clickedOn, new Date(expire)); controller.muteMac(clickedOn, new Date(expire)); } })); rVal.add(SwingAction.of("Show player information", e -> { final String text = controller.getInformationOn(clickedOn); final JTextPane textPane = new JTextPane(); textPane.setEditable(false); textPane.setText(text); JOptionPane.showMessageDialog(null, textPane, "Player Info", JOptionPane.INFORMATION_MESSAGE); })); return rVal; } private boolean confirm(final String question) { final int rVal = JOptionPane.showConfirmDialog(JOptionPane.getFrameForComponent(this), question, "Question", JOptionPane.OK_CANCEL_OPTION); return rVal == JOptionPane.OK_OPTION; } public LobbyClient getLobbyClient() { return m_client; } public void setShowChatTime(final boolean showTime) { if (m_chatMessagePanel != null) { m_chatMessagePanel.setShowTime(showTime); } } public void shutdown() { setVisible(false); dispose(); MainFrame.getInstance().setVisible(true); m_client.getMessenger().shutDown(); GameRunner.exitGameIfFinished(); } private void connectionToServerLost() { EventThreadJOptionPane.showMessageDialog(LobbyFrame.this, "Connection to Server Lost. Please close this instance and reconnect to the lobby.", "Connection Lost", JOptionPane.ERROR_MESSAGE, new CountDownLatchHandler(true)); } }