Project: packetsamurai
package com.l2j.packetsamurai.gui;
 
import java.awt.BorderLayout; 
import java.awt.Dimension; 
import java.awt.Toolkit; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.InputEvent; 
import java.awt.event.KeyEvent; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 
import java.io.File; 
import java.io.FileNotFoundException; 
import java.io.IOException; 
import java.nio.BufferUnderflowException; 
import java.util.Set; 
 
import javax.swing.JCheckBoxMenuItem; 
import javax.swing.JComponent; 
import javax.swing.JDialog; 
import javax.swing.JFileChooser; 
import javax.swing.JFrame; 
import javax.swing.JList; 
import javax.swing.JMenu; 
import javax.swing.JMenuBar; 
import javax.swing.JMenuItem; 
import javax.swing.JOptionPane; 
import javax.swing.JScrollPane; 
import javax.swing.JTabbedPane; 
import javax.swing.JTable; 
import javax.swing.KeyStroke; 
import javax.swing.ListSelectionModel; 
import javax.swing.filechooser.FileFilter; 
 
import javolution.util.FastList; 
 
import com.l2j.packetsamurai.Captor; 
import com.l2j.packetsamurai.IUserInterface; 
import com.l2j.packetsamurai.PacketSamurai; 
import com.l2j.packetsamurai.gui.logrepo.LogRepoTab; 
import com.l2j.packetsamurai.gui.protocoleditor.ProtocolEditor; 
import com.l2j.packetsamurai.logreaders.AbstractLogReader; 
import com.l2j.packetsamurai.session.DataPacket; 
import com.l2j.packetsamurai.session.GameSessionTable; 
import com.l2j.packetsamurai.session.Session; 
import com.l2j.packetsamurai.utils.NpcGatherExporter; 
import com.l2j.packetsamurai.utils.NpcInfoExporter; 
import com.l2j.packetsamurai.utils.NpcSpawnExporter; 
 
/**
 * @author Ulysses R. Ribeiro 
 */
 
public class Main implements IUserInterface { 
 protected JFrame _frame; 
 
 private JMenuBar _menuBar = new JMenuBar(); 
 
 private JMenu _fileMenu = new JMenu("File"); 
 private JMenu _editMenu = new JMenu("Edit"); 
 private JMenu _utilsMenu = new JMenu("Export"); 
 private JMenu _toolsMenu = new JMenu("Tools"); 
 private JMenu _helpMenu = new JMenu("Help"); 
 
 private JMenuItem _itemClose; 
 private JMenuItem _itemCloseAll; 
 
 private JMenuItem _itemSearch; 
 private JMenuItem _itemSearchNext; 
 private JMenuItem _itemGoto; 
 private JMenuItem _itemFilter; 
 private JCheckBoxMenuItem _itemRecording; 
 
 private ProtocolEditor _pEditor; 
 
 private ActionListener _menuListener = new MenuActionListener(); 
 
 private JTabbedPane _tabPane = new JTabbedPane(); 
 
 private ConsoleTab _consoleTab; 
 
 private ViewTab _viewerTab; 
 
 private JDialog _selectInterfaceWindow; 
 
 private SearchDlg _searchDlg; 
 
 private JList _interfaceList; 
 
 private LogRepoTab _logRepo; 
 
 public Main() { 
 
 
 
 public void init() { 
  _frame = new JFrame("Packet Samurai [aion-lightning edition]"); 
  _frame.setLayout(new BorderLayout()); 
  _frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
 
  // Menu Bar Itens 
  // File Menu 
  JMenuItem itemOpen = new JMenuItem("Open"); 
  itemOpen.setActionCommand("Open"); 
  itemOpen.addActionListener(_menuListener); 
 
  _itemClose = new JMenuItem("Close"); 
  _itemClose.setEnabled(false); 
  _itemClose.setActionCommand("Close"); 
  _itemClose.addActionListener(_menuListener); 
 
  _itemCloseAll = new JMenuItem("Close All"); 
  _itemCloseAll.setEnabled(false); 
  _itemCloseAll.setActionCommand("CloseAll"); 
  _itemCloseAll.addActionListener(_menuListener); 
 
  JMenuItem itemExit = new JMenuItem("Exit"); 
  itemExit.setActionCommand("Exit"); 
  itemExit.addActionListener(_menuListener); 
 
  _fileMenu.add(itemOpen); 
  _fileMenu.add(_itemClose); 
  _fileMenu.add(_itemCloseAll); 
  _fileMenu.add(itemExit); 
 
  // Edit 
  _itemSearch = new JMenuItem("Search"); 
  _itemSearch.setEnabled(false); 
  _itemSearch.setActionCommand("Search"); 
  _itemSearch.setMnemonic(KeyEvent.VK_F); 
  _itemSearch.addActionListener(_menuListener); 
  _editMenu.add(_itemSearch); 
 
  _itemSearchNext = new JMenuItem("Search Next"); 
  _itemSearchNext.setEnabled(false); 
  _itemSearchNext.setActionCommand("SearchNext"); 
  _itemSearchNext.addActionListener(_menuListener); 
  _editMenu.add(_itemSearchNext); 
 
  _itemGoto = new JMenuItem("Go to..."); 
  _itemGoto.setEnabled(false); 
  _itemGoto.setActionCommand("GoTo"); 
  _itemGoto.addActionListener(_menuListener); 
  _editMenu.add(_itemGoto); 
 
  _itemFilter = new JMenuItem("Filter"); 
  _itemFilter.setEnabled(false); 
  _itemFilter.setActionCommand("Filter"); 
  _itemFilter.addActionListener(_menuListener); 
  _editMenu.add(_itemFilter); 
 
  // Utils 
  JMenuItem exportSpawns = new JMenuItem("Export Npc Spawns"); 
  exportSpawns.setActionCommand("ExportNpcSpawns"); 
  exportSpawns.addActionListener(_menuListener); 
  _utilsMenu.add(exportSpawns); 
 
  JMenuItem exportGather = new JMenuItem("Export Gather Spawns"); 
  exportGather.setActionCommand("ExportGatherSpawns"); 
  exportGather.addActionListener(_menuListener); 
  _utilsMenu.add(exportGather); 
 
  JMenuItem exportTitles = new JMenuItem("Export Npc Infos"); 
  exportTitles.setActionCommand("ExportNpcInfo"); 
  exportTitles.addActionListener(_menuListener); 
  _utilsMenu.add(exportTitles); 
 
  // Tools 
  _itemRecording = new JCheckBoxMenuItem("Record Stream"); 
  _itemRecording.setState(true); 
  _toolsMenu.add(_itemRecording); 
 
  JMenuItem itemSelectInterface = new JMenuItem("Select Interface"); 
  itemSelectInterface.setActionCommand("SelectInterface"); 
  itemSelectInterface.addActionListener(_menuListener); 
  _toolsMenu.add(itemSelectInterface); 
 
  JMenuItem itemEditProtocol = new JMenuItem("Edit Protocol"); 
  itemEditProtocol.setActionCommand("EditProtocol"); 
  itemEditProtocol.addActionListener(_menuListener); 
  _toolsMenu.add(itemEditProtocol); 
 
  JMenuItem itemSetActiveProtocols = new JMenuItem("Set Active Protocols"); 
  itemSetActiveProtocols.setActionCommand("SetActiveProtocols"); 
  itemSetActiveProtocols.addActionListener(_menuListener); 
  _toolsMenu.add(itemSetActiveProtocols); 
 
  // Help 
  JMenuItem itemAbout = new JMenuItem("About"); 
  itemAbout.setActionCommand("About"); 
  itemAbout.addActionListener(_menuListener); 
  _helpMenu.add(itemAbout); 
 
  _menuBar.add(_fileMenu); 
  _menuBar.add(_editMenu); 
  _menuBar.add(_utilsMenu); 
  _menuBar.add(_toolsMenu); 
  _menuBar.add(_helpMenu); 
  _frame.setJMenuBar(_menuBar); 
 
  // Console Tab 
  _consoleTab = new ConsoleTab(); 
 
  // Viewer Tab 
  _viewerTab = new ViewTab(); 
 
  _logRepo = new LogRepoTab(); 
 
  // hotkeys 
  _tabPane.registerKeyboardAction(_menuListener, "Search"
    KeyStroke.getKeyStroke(KeyEvent.VK_F, InputEvent.CTRL_MASK), 
    JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); 
  _tabPane.registerKeyboardAction(_menuListener, "SearchNext"
    KeyStroke.getKeyStroke(KeyEvent.VK_G, InputEvent.CTRL_MASK), 
    JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); 
  _tabPane.registerKeyboardAction(_menuListener, "EditProtocol"
    KeyStroke.getKeyStroke(KeyEvent.VK_E, InputEvent.CTRL_MASK), 
    JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); 
  _tabPane.registerKeyboardAction(_menuListener, "Filter"
    KeyStroke.getKeyStroke(KeyEvent.VK_T, InputEvent.CTRL_MASK), 
    JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); 
 
  _tabPane.add("Console", _consoleTab); 
  _tabPane.add("Viewer", _viewerTab); 
  // _tabPane.add("Log Repository", _logRepo); 
 
  // build the frame 
  _frame.add(_tabPane, BorderLayout.CENTER); 
 
  // add the window listeners 
  addListeners(); 
 
  _frame.setMinimumSize(new Dimension(750500)); 
  _frame.setExtendedState(JFrame.MAXIMIZED_BOTH); 
  _frame.setVisible(true); 
 
 
 public JTabbedPane getTabPane() { 
  return _tabPane; 
 
 
 public LogRepoTab getLogRepoTab() { 
  return _logRepo; 
 
 
 public void log(String text) { 
  _consoleTab.addText(text); 
  System.err.println(text); 
 
 
 private void addListeners() { 
  // Window Closing 
  /*
   * _frame.addWindowListener(new WindowAdapter() { public void 
   * windowClosing(WindowEvent event) { close(); } }); 
   */
 
 
 
 public void showInterfaceSelector(String[] interfaceNames) { 
  _selectInterfaceWindow = new JDialog(_frame); 
  _selectInterfaceWindow.setTitle("Double-Click to Select the Interface"); 
  _selectInterfaceWindow.setLocationRelativeTo(_frame); 
  _interfaceList = new JList(interfaceNames); 
  _interfaceList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 
  JScrollPane scrollPane = new JScrollPane(_interfaceList); 
 
  MouseListener mouseListener = new MouseAdapter() { 
   public void mouseClicked(MouseEvent e) { 
    if (e.getClickCount() == 2) { 
     int index = _interfaceList.locationToIndex(e.getPoint()); 
     if (Captor.getInstance().getCurrentDeviceId() == index) { 
      _selectInterfaceWindow.dispose(); 
      return
     
     Captor.getInstance().openDevice(index); 
     PacketSamurai.setConfigProperty("NetworkInterface"
       Integer.toString(index)); 
     _selectInterfaceWindow.dispose(); 
    
   
  }; 
 
  _interfaceList.addMouseListener(mouseListener); 
 
  _selectInterfaceWindow.add(scrollPane); 
  _selectInterfaceWindow.setSize(400350); 
  _selectInterfaceWindow.setVisible(true); 
 
 
 public void showAboutDialog() { 
  JOptionPane 
    .showMessageDialog( 
      this.getMainFrame(), 
      "Packet Samurai Aion-Lightning\n\nGilles Duboscq\nUlysses R. Ribeiro\n\n\nModified by Magenik"
      "About Packet Samurai", JOptionPane.PLAIN_MESSAGE); 
 
 
 public void close() { 
  PacketSamurai.saveConfig(); 
 
 
 public void toggleSearchDialog() { 
  if (getViewerTab().getComponentCount() > 0) { 
   if (_searchDlg == null) { 
    _searchDlg = new SearchDlg(_frame); 
    _searchDlg.setVisible(true); 
   else { 
    // toggle display 
    _searchDlg.setVisible(!_searchDlg.isVisible()); 
   
  
 
 
 public void toggleFilterDialog() { 
  if (getViewerTab().getComponentCount() > 0) { 
   FilterDlg filterDlg = getViewerTab().getCurrentViewPane() 
     .getFilterDialog(); 
 
   // toggle display 
   filterDlg.setVisible(!filterDlg.isVisible()); 
  
 
 
 public void searchNext() { 
  if (getViewerTab().getComponentCount() > 0) { 
   if (_searchDlg != null) { 
    ViewPane pane = ((Main) PacketSamurai.getUserInterface()) 
      .getViewerTab().getCurrentViewPane(); 
    if (pane != null) { 
     int index = _searchDlg 
       .search(pane.getSelectedPacketindex() + 1); 
     if (index >= 0) { 
      JTable pt = ((Main) PacketSamurai.getUserInterface()) 
        .getViewerTab().getCurrentViewPane() 
        .getPacketTable(); 
      pt.setAutoscrolls(true); 
      pt.getSelectionModel().setSelectionInterval(index, 
        index); 
      pt.scrollRectToVisible(pt.getCellRect(index, 0true)); 
      _searchDlg.setCurrentSearchIndex(index + 1); 
     
    
   else { 
    toggleSearchDialog(); 
   
  
 
 
 public void toggleProtocolEditor() { 
  if (_pEditor == null) { 
   ProtocolEditor pe = new ProtocolEditor(_frame); 
   _pEditor = pe; 
   _pEditor.setLocationRelativeTo(_frame); // will make PE spawn 
   // centered relatively to 
   // the main frame 
  
 
  // toggle display 
  _pEditor.setVisible(!_pEditor.isVisible()); 
 
 
 private void exportNpcTitles() { 
  if (getViewerTab().getComponentCount() > 0) { 
 
   ViewPane pane = ((Main) PacketSamurai.getUserInterface()) 
     .getViewerTab().getCurrentViewPane(); 
   if (pane != null) { 
    String sessionName = pane.getGameSessionViewer().getSession() 
      .getSessionName(); 
    FastList<DataPacket> packets = pane.getGameSessionViewer() 
      .getSession().getPackets(); 
    new NpcInfoExporter(packets, sessionName).parse(); 
   
  
 
 
 private void exportNpcSpawns() { 
  if (getViewerTab().getComponentCount() > 0) { 
 
   ViewPane pane = ((Main) PacketSamurai.getUserInterface()) 
     .getViewerTab().getCurrentViewPane(); 
   if (pane != null) { 
    String sessionName = pane.getGameSessionViewer().getSession() 
      .getSessionName(); 
    FastList<DataPacket> packets = pane.getGameSessionViewer() 
      .getSession().getPackets(); 
    new NpcSpawnExporter(packets, sessionName).parse(); 
   
  
 
 
 private void exportGatherSpawns() { 
  if (getViewerTab().getComponentCount() > 0) { 
 
   ViewPane pane = ((Main) PacketSamurai.getUserInterface()) 
     .getViewerTab().getCurrentViewPane(); 
   if (pane != null) { 
    String sessionName = pane.getGameSessionViewer().getSession() 
      .getSessionName(); 
    FastList<DataPacket> packets = pane.getGameSessionViewer() 
      .getSession().getPackets(); 
    new NpcGatherExporter(packets, sessionName).parse(); 
   
  
 
 
 // MenuActions 
 public class MenuActionListener implements ActionListener { 
 
  public void actionPerformed(ActionEvent ev) { 
   String actionCmd = ev.getActionCommand(); 
   if (actionCmd.equals("Open")) { 
    final JFileChooser chooser = new JFileChooser( 
      PacketSamurai.getConfigProperty("lastLogDir""." 
        + File.separator + "logs" + File.separator)); 
    chooser.setFileFilter(new FileFilter() { 
 
     @Override 
     public boolean accept(File f) { 
      return f.isDirectory() 
        || f.isFile() 
        && (f.getName().endsWith(".pcap"
          || f.getName().endsWith(".cap"
          || f.getName().endsWith(".bin") || f 
          .getName().endsWith(".psl")); 
     
 
     @Override 
     public String getDescription() { 
      return "All supported formats (.cap .pcap .bin .psl)"
     
 
    }); 
    final int returnVal = chooser.showOpenDialog(_frame); 
    if (returnVal == JFileChooser.APPROVE_OPTION) { 
     Thread t = new Thread() { 
      public void run() { 
       ((Main) PacketSamurai.getUserInterface()) 
         .openSession(chooser.getSelectedFile()); 
      
     }; 
     t.start(); 
    
   else if (actionCmd.equals("Close")) { 
    Main.this.closeSessionTab(Main.this.getViewerTab() 
      .getCurrentViewPane()); 
   else if (actionCmd.equals("CloseAll")) { 
    getViewerTab().removeAll(); 
    Main.this.toggleSessionItems(false); 
   else if (actionCmd.equals("Search")) { 
    toggleSearchDialog(); 
   else if (actionCmd.equals("SearchNext")) { 
    searchNext(); 
   else if (actionCmd.equals("GoTo")) { 
    String ret = JOptionPane.showInputDialog(null
      "Enter the packet number""Go to packet..."
      JOptionPane.INFORMATION_MESSAGE); 
    if (ret != null) { 
     try { 
      int pn = Integer.parseInt(ret); 
 
      if (pn >= 0 
        && pn < Main.this.getViewerTab() 
          .getCurrentViewPane().getPacketTable() 
          .getRowCount()) { 
       Main.this.getViewerTab().getCurrentViewPane() 
         .setSelectedPacket(pn, pn); 
      else { 
       JOptionPane.showMessageDialog(null
         "Invalid value for packet number."
         "ERROR", JOptionPane.ERROR_MESSAGE); 
      
     catch (NumberFormatException e) { 
      JOptionPane.showMessageDialog(null
        "Invalid value for packet number.""ERROR"
        JOptionPane.ERROR_MESSAGE); 
     
    
   else if (actionCmd.equals("Filter")) { 
    toggleFilterDialog(); 
   else if (actionCmd.equals("SelectInterface")) { 
    // must run asynchronously from Main UI 
    new Thread(new Runnable() { 
 
     public void run() { 
      Captor.getInstance().selectNetWorkInterface(); 
 
     
    }).start(); 
   else if (actionCmd.equals("SetActiveProtocols")) { 
    new Thread(new Runnable() { 
 
     public void run() { 
      Captor.showSetActiveProtocols(); 
     
    }).start(); 
   else if (actionCmd.equals("Exit")) { 
    System.exit(0); 
   else if (actionCmd.equals("About")) { 
    showAboutDialog(); 
   else if (actionCmd.equals("EditProtocol")) { 
    toggleProtocolEditor(); 
   else if (actionCmd.equals("ExportNpcInfo")) { 
    exportNpcTitles(); 
   else if (actionCmd.equals("ExportNpcSpawns")) { 
    exportNpcSpawns(); 
   else if (actionCmd.equals("ExportGatherSpawns")) { 
    exportGatherSpawns(); 
   
 
  
 
 
 public ProtocolEditor getProtocolEditor() { 
  return _pEditor; 
 
 
 public ViewTab getViewerTab() { 
  return _viewerTab; 
 
 
 public void openSession(File file) { 
  Set<Session> sessions = null
  try { 
   sessions = Main.getSessionsFromFile(file); 
  catch (FileNotFoundException fnfe) { 
   PacketSamurai.getUserInterface().log( 
     "ERROR: Opening (" + file.getAbsolutePath() 
       "), file was not found."); 
  catch (IOException ioe) { 
   ioe.printStackTrace(); 
   PacketSamurai.getUserInterface().log( 
     "ERROR: Opening (" + file.getAbsolutePath() 
       "), I/O error."); 
  catch (BufferUnderflowException e) { 
   PacketSamurai.getUserInterface().log( 
     "ERROR: Opening (" + file.getAbsolutePath() 
       "), file format error."); 
   e.printStackTrace(); 
  
 
  if (sessions != null) { 
   PacketSamurai.setConfigProperty("lastLogDir", file.getParent()); 
   for (Session s : sessions) { 
    this.showSession(s, false); 
   
  
 
 
 /**
  *  
  * @param file 
  *            The file to be opened 
  * @return A set containing all session(s) stored on the file, or null if 
  *         there is no support for the file extension. 
  * @throws IOException 
  *             if there was an I/O error. 
  * @throws BufferUnderflowException 
  *             if there was insufficient data or a file format error. 
  */
 
 public static Set<Session> getSessionsFromFile(File file) 
   throws IOException { 
  Set<Session> sessions = null
 
  String filename = file.getAbsolutePath(); 
 
  // for now its hardcoded, maybe registering later 
  AbstractLogReader reader = AbstractLogReader 
    .getLogReaderForFile(filename); 
  if (reader == null
   return null
  reader.parse(); 
  sessions = reader.getSessions(); 
 
  return sessions; 
 
 
 public JFrame getMainFrame() { 
  return _frame; 
 
 
 public void showSessions() { 
  for (Session s : GameSessionTable.getInstance().getSessions()) { 
   if (!s.isShown()) 
    this.showSession(s, true); 
  
 
 
 public void showSession(Session s, boolean notify) { 
  this.getViewerTab().showSession(s, notify); 
  this.toggleSessionItems(true); 
 
 
 public void toggleSessionItems(boolean enabled) { 
  _itemClose.setEnabled(enabled); 
  _itemCloseAll.setEnabled(enabled); 
  _itemSearch.setEnabled(enabled); 
  _itemSearchNext.setEnabled(enabled); 
  _itemGoto.setEnabled(enabled); 
  _itemFilter.setEnabled(enabled); 
 
 
 public void closeSessionTab(ViewPane vp) { 
  Session s = vp.getGameSessionViewer().getSession(); 
  if (s != null) { 
   s.setShown(false); 
  
  getViewerTab().remove(vp); 
  if (getViewerTab().getComponentCount() == 0) { 
   this.toggleSessionItems(false); 
  
 
 
 public boolean isRecording() { 
  return _itemRecording.getState(); 
 
}