/** * Copyright (c) 2005-2017, KoLmafia development team * http://kolmafia.sourceforge.net/ * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * [1] Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * [2] Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * [3] Neither the name "KoLmafia" nor the names of its contributors may * be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ package net.sourceforge.kolmafia.swingui.panel; import java.awt.BorderLayout; import java.awt.CardLayout; import java.awt.Color; import java.awt.Component; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.io.IOException; import java.io.PrintStream; import java.lang.InterruptedException; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import net.java.dev.spellcast.utilities.JComponentUtilities; import net.sourceforge.kolmafia.KoLConstants; import net.sourceforge.kolmafia.RequestThread; import net.sourceforge.kolmafia.StaticEntity; import net.sourceforge.kolmafia.persistence.ItemDatabase; import net.sourceforge.kolmafia.session.MushroomManager; import net.sourceforge.kolmafia.swingui.button.InvocationButton; import net.sourceforge.kolmafia.utilities.InputFieldUtilities; import net.sourceforge.kolmafia.utilities.LogStream; public class MushroomPlotPanel extends JPanel { private boolean doingLayout = false; private String[] currentData; private String[] layoutData; private final MushroomButton[][] currentButtons; private final MushroomButton[][] layoutButtons; private final MushroomButton[][] forecastButtons; public MushroomPlotPanel() { JPanel currentPlot = new JPanel( new GridLayout( 4, 4, 0, 0 ) ); JPanel layoutPlot = new JPanel( new GridLayout( 4, 4, 0, 0 ) ); JPanel forecastPlot = new JPanel( new GridLayout( 4, 4, 0, 0 ) ); this.currentButtons = new MushroomButton[ 4 ][ 4 ]; this.layoutButtons = new MushroomButton[ 4 ][ 4 ]; this.forecastButtons = new MushroomButton[ 4 ][ 4 ]; for ( int i = 0; i < 4; ++i ) { for ( int j = 0; j < 4; ++j ) { this.currentButtons[ i ][ j ] = new MushroomButton( i * 4 + j, false ); this.layoutButtons[ i ][ j ] = new MushroomButton( i * 4 + j, true ); this.forecastButtons[ i ][ j ] = new MushroomButton( i * 4 + j, false ); currentPlot.add( this.currentButtons[ i ][ j ] ); layoutPlot.add( this.layoutButtons[ i ][ j ] ); forecastPlot.add( this.forecastButtons[ i ][ j ] ); } } JPanel centerPanel = new JPanel( new GridLayout( 1, 3, 20, 20 ) ); centerPanel.add( this.constructPanel( "Current Plot", currentPlot ) ); centerPanel.add( this.constructPanel( "Layout Plot", layoutPlot ) ); centerPanel.add( this.constructPanel( "Forecasted Plot", forecastPlot ) ); JPanel completePanel = new JPanel( new BorderLayout( 20, 20 ) ); completePanel.add( centerPanel, BorderLayout.CENTER ); // Dummy buttons for the mushroom plot (just for layout // viewing purposes. To be replaced with real functionality // at a later date. JPanel buttonPanel = new JPanel(); buttonPanel.add( new InvocationButton( "Harvest All", MushroomManager.class, "harvestMushrooms" ) ); buttonPanel.add( new InvocationButton( "Do Layout", this, "executeLayout" ) ); buttonPanel.add( new InvocationButton( "Script Layout", this, "scriptLayout" ) ); completePanel.add( buttonPanel, BorderLayout.SOUTH ); this.setLayout( new CardLayout( 40, 40 ) ); this.add( completePanel, "" ); // Do not try to load the current plot in the Swing thread. // Do it in a separate thread. RequestThread.executeMethod( this, "loadCurrentPlot" ); } public void executeLayout() { // Change any mushrooms which no longer // match the existing plot. this.doingLayout = true; for ( int i = 0; i < 16; ++i ) { if ( !this.currentData[ i ].equals( this.layoutData[ i ] ) ) { MushroomManager.pickMushroom( i + 1, false ); if ( !this.layoutData[ i ].endsWith( "/dirt1.gif" ) && !this.layoutData[ i ].endsWith( "/mushsprout.gif" ) ) { MushroomManager.plantMushroom( i + 1, MushroomManager.getMushroomType( this.layoutData[ i ] ) ); } } } this.doingLayout = false; } private File output; public void scriptLayout() { this.output = null; try { SwingUtilities.invokeAndWait( new Runnable() { public void run() { MushroomPlotPanel.this.output = InputFieldUtilities.chooseOutputFile( KoLConstants.SCRIPT_LOCATION, MushroomPlotPanel.this ); } } ); } catch ( Exception ie ) { } if ( output == null ) { return; } String outputPath = null; try { outputPath = output.getCanonicalPath(); } catch ( IOException e ) { return; } try { PrintStream ostream = LogStream.openStream( output, true ); ostream.println( "field harvest" ); for ( int i = 0; i < 16; ++i ) { int mushroomType = MushroomManager.getMushroomType( this.layoutData[ i ] ); switch ( mushroomType ) { case MushroomManager.SPOOKY: case MushroomManager.KNOB: case MushroomManager.KNOLL: ostream.println( "field pick " + ( i + 1 ) ); ostream.println( "field plant " + ( i + 1 ) + " " + ItemDatabase.getItemName( mushroomType ) ); break; case MushroomManager.EMPTY: ostream.println( "field pick " + ( i + 1 ) ); break; } } ostream.close(); } catch ( Exception e ) { // This should not happen. Therefore, print // a stack trace for debug purposes. StaticEntity.printStackTrace( e, "Error saving file <" + outputPath + ">" ); } } public JPanel constructPanel( final String label, final Component c ) { JPanel panel = new JPanel( new BorderLayout() ); panel.setBorder( BorderFactory.createLineBorder( Color.black, 1 ) ); panel.add( new JLabel( label, SwingConstants.CENTER ), BorderLayout.NORTH ); panel.add( c, BorderLayout.CENTER ); return panel; } public void loadCurrentPlot() { // Get the layout state of the field and update String plot = MushroomManager.getMushroomManager( true ); this.currentData = plot.split( ";" ); // Only update the layout data if you're // not currently doing any layouts. if ( !this.doingLayout ) { this.layoutData = plot.split( ";" ); } // With everything that you need updated, // feel free to refresh the layout. this.refresh(); } public void refresh() { // Do nothing if you don't have a plot if ( this.layoutData[ 0 ].equals( "Your plot is unavailable." ) ) { return; } // Convert each piece of layout data into the appropriate // mushroom plot data. String[][] layoutArray = new String[ 4 ][ 4 ]; for ( int i = 0; i < 4; ++i ) { for ( int j = 0; j < 4; ++j ) { layoutArray[ i ][ j ] = this.layoutData[ i * 4 + j ]; } } String[] forecastData = MushroomManager.getForecastedPlot( true, layoutArray ).split( ";" ); // What you do is you update each mushroom button based on // what is contained in each of the data fields. for ( int i = 0; i < 4; ++i ) { for ( int j = 0; j < 4; ++j ) { this.currentButtons[ i ][ j ].setIcon( JComponentUtilities.getImage( this.currentData[ i * 4 + j ] ) ); this.layoutButtons[ i ][ j ].setIcon( JComponentUtilities.getImage( this.layoutData[ i * 4 + j ] ) ); this.forecastButtons[ i ][ j ].setIcon( JComponentUtilities.getImage( forecastData[ i * 4 + j ] ) ); } } } private class MushroomButton extends JButton implements ActionListener { private final int index; private boolean canModify; public MushroomButton( final int index, final boolean canModify ) { this.index = index; this.canModify = canModify; JComponentUtilities.setComponentSize( this, 30, 30 ); this.setOpaque( true ); this.setBackground( Color.white ); this.addActionListener( this ); } public void actionPerformed( final ActionEvent e ) { if ( !this.canModify ) { return; } // No mushroom plot if ( MushroomPlotPanel.this.layoutData.length == 1 ) { return; } // Sprouts transform into dirt because all you can // do is pick them. if ( MushroomPlotPanel.this.layoutData[ this.index ].endsWith( "/mushsprout.gif" ) ) { MushroomPlotPanel.this.layoutData[ this.index ] = "itemimages/dirt1.gif"; MushroomPlotPanel.this.refresh(); return; } // Second generation mushrooms transform into dirt // because all you can do is pick them. if ( MushroomPlotPanel.this.layoutData[ this.index ].endsWith( "/flatshroom.gif" ) || MushroomPlotPanel.this.layoutData[ this.index ].endsWith( "/plaidroom.gif" ) || MushroomPlotPanel.this.layoutData[ this.index ].endsWith( "/tallshroom.gif" ) ) { MushroomPlotPanel.this.layoutData[ this.index ] = "itemimages/dirt1.gif"; MushroomPlotPanel.this.refresh(); return; } // Third generation mushrooms transform into dirt // because all you can do is pick them. if ( MushroomPlotPanel.this.layoutData[ this.index ].endsWith( "/fireshroom.gif" ) || MushroomPlotPanel.this.layoutData[ this.index ].endsWith( "/iceshroom.gif" ) || MushroomPlotPanel.this.layoutData[ this.index ].endsWith( "/stinkshroo.gif" ) ) { MushroomPlotPanel.this.layoutData[ this.index ] = "itemimages/dirt1.gif"; MushroomPlotPanel.this.refresh(); return; } // Everything else rotates based on what was there // when you clicked on the image. if ( MushroomPlotPanel.this.layoutData[ this.index ].endsWith( "/dirt1.gif" ) ) { MushroomPlotPanel.this.layoutData[ this.index ] = "itemimages/mushroom.gif"; MushroomPlotPanel.this.refresh(); return; } if ( MushroomPlotPanel.this.layoutData[ this.index ].endsWith( "/mushroom.gif" ) ) { MushroomPlotPanel.this.layoutData[ this.index ] = "itemimages/bmushroom.gif"; MushroomPlotPanel.this.refresh(); return; } if ( MushroomPlotPanel.this.layoutData[ this.index ].endsWith( "/bmushroom.gif" ) ) { MushroomPlotPanel.this.layoutData[ this.index ] = "itemimages/spooshroom.gif"; MushroomPlotPanel.this.refresh(); return; } if ( MushroomPlotPanel.this.layoutData[ this.index ].endsWith( "/spooshroom.gif" ) ) { MushroomPlotPanel.this.layoutData[ this.index ] = MushroomPlotPanel.this.currentData[ this.index ]; MushroomPlotPanel.this.refresh(); return; } } } }