/* * Copyright (c) 2012. HappyDroids LLC, All rights reserved. */ package com.happydroids.sparky; import com.happydroids.HappyDroidConsts; import com.happydroids.server.HappyDroidService; import com.happydroids.utils.BackgroundTask; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.File; import java.io.IOException; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; import java.util.logging.Level; import java.util.logging.Logger; public class SparkyMain extends JFrame { private JPanel contentPane; private JLabel happyDroidsLogo; private JProgressBar updateProgress; private JLabel updateStatus; private JPanel innerPane; private JButton startBuildingButton; private JScrollPane scrollPane; private JEditorPane webPane; private JPanel bottomPanel; private BackgroundPanel backgroundPanel; private boolean updateInProgress; private File gameStorage; private File gameJar; public SparkyMain() { setContentPane(contentPane); setSize(contentPane.getWidth(), contentPane.getHeight()); setResizable(false); setTitle("Droid Towers"); getRootPane().setDefaultButton(startBuildingButton); setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); scrollPane.setBorder(null); contentPane.setBorder(null); bottomPanel.setBorder(null); bottomPanel.setOpaque(false); scrollPane.setBackground(new Color(0, 0, 0, 0)); scrollPane.setOpaque(false); startBuildingButton.addActionListener(new StartBuildingButtonClick()); // call onCancel() when cross is clicked addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { onCancel(e); } }); // call onCancel() on ESCAPE contentPane.registerKeyboardAction(new ActionListener() { public void actionPerformed(ActionEvent e) { onCancel(null); } }, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); updateProgressStatus(null); gameStorage = PlatformUtil.getAppRoot(); gameJar = new File(gameStorage, "DroidTowers.jar"); makeRequestForGameUpdates(); } private void createUIComponents() { backgroundPanel = new BackgroundPanel(new ImageIcon("assets/background.png").getImage(), BackgroundPanel.TILED, 1f, 0f); backgroundPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); backgroundPanel.setTransparentAdd(true); } private void makeRequestForGameUpdates() { updateInProgress = true; updateProgress.setMaximum(100); updateProgressStatus("Checking for updates..."); HappyDroidService.instance().withNetworkConnection(new Runnable() { public void run() { GameUpdateCheckWorker updateCheckerWorker = new GameUpdateCheckWorker(gameStorage, gameJar); updateCheckerWorker.addPropertyChangeListener(new GameUpdateCheckListener()); updateCheckerWorker.execute(); try { new BackgroundTask() { @Override protected void execute() throws Exception { try { webPane.setPage(HappyDroidConsts.HAPPYDROIDS_URI + "/game-updates"); } catch (IOException ignored) { } } }.execute(); } catch (Exception e) { e.printStackTrace(); } } }); } private void launchGameFromJar(File mergedJarFile) { try { URLClassLoader classLoader = (URLClassLoader) getClass().getClassLoader(); Method addURL = URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{URL.class}); addURL.setAccessible(true); addURL.invoke(classLoader, mergedJarFile.toURI().toURL()); Class aClass = classLoader.loadClass("com.happydroids.droidtowers.DesktopGame"); Method main = aClass.getDeclaredMethod("main", String[].class); Object instance = aClass.newInstance(); main.invoke(instance, new Object[]{null}); dispose(); } catch (Exception e) { throw new RuntimeException("Unable to start game."); } } private void updateProgressStatus(String message) { if (message != null) { updateStatus.setForeground(Color.WHITE); updateStatus.setText(message); updateProgress.setEnabled(true); } else { updateStatus.setForeground(Color.darkGray); updateProgress.setEnabled(false); } } private void onCancel(WindowEvent e) { if (updateInProgress) { JOptionPane.showMessageDialog(null, "You are in the middle of updating core files, exiting now will be very bad.", "Wait!", JOptionPane.ERROR_MESSAGE); return; } System.exit(0); dispose(); } public static void main(final String[] args) { if (HappyDroidConsts.DEBUG) { Logger.getAnonymousLogger().setLevel(Level.FINEST); } // BackgroundTask.setUncaughtExceptionHandler(new DesktopUncaughtExceptionHandler()); // Thread.setDefaultUncaughtExceptionHandler(new DesktopUncaughtExceptionHandler()); // PlatformProtocolHandlerFactory.newInstance().initialize(args); SwingUtilities.invokeLater(new Runnable() { public void run() { setDefaultLookAndFeelDecorated(true); SparkyMain window = new SparkyMain(); window.pack(); window.setLocationRelativeTo(null); window.setVisible(true); } }); } private class StartBuildingButtonClick implements ActionListener { public void actionPerformed(ActionEvent e) { launchGameFromJar(gameJar); } } private class GameUpdateCheckListener implements PropertyChangeListener { public void propertyChange(PropertyChangeEvent propertyChangeEvent) { String propertyName = propertyChangeEvent.getPropertyName(); if (propertyName.equals("state")) { return; } try { Method declaredMethod = GameUpdateCheckListener.class.getDeclaredMethod(propertyName, new Class[]{PropertyChangeEvent.class}); if (declaredMethod != null) { declaredMethod.invoke(this, propertyChangeEvent); } } catch (Exception e) { e.printStackTrace(); } } private void updateDownloadProgress(PropertyChangeEvent event) { updateProgressStatus("Downloading update..."); updateProgressBarFromEvent(event); } private void updateProcessingProgress(PropertyChangeEvent event) { updateProgressStatus("Extracting update..."); updateProgressBarFromEvent(event); } private void updateProcessComplete(PropertyChangeEvent event) { updateInProgress = false; if (gameJar.exists()) { updateProgress.setValue(100); updateProgressStatus("Update complete!"); startBuildingButton.setEnabled(true); } else { // JOptionPane.showMessageDialog(null, "Sorry, there was a problem contacting the update server\nto download a copy of Droid Towers.\n\nPlease check your internet connection then try again.", "Connection Problem: ETF0NH0M3", JOptionPane.INFORMATION_MESSAGE); updateProgressStatus("Update failed!"); updateProgress.setValue(0); updateProgress.setEnabled(false); } } private void updateCheckComplete(PropertyChangeEvent event) { if (((Boolean) event.getNewValue())) { updateProgressStatus("There is an update available, it will be automatically downloaded for you."); } else { updateProgressStatus("No updates found."); } } private void updateProgressBarFromEvent(PropertyChangeEvent event) { Integer totalBytesToDownload = (Integer) event.getOldValue(); Integer totalBytesDownloaded = (Integer) event.getNewValue(); double progress = ((float) totalBytesDownloaded / (float) totalBytesToDownload) * 100.0; updateProgress.setValue((int) progress); } } }