001    //  edu.isi.gamebots.examples.ExampleBot
002    //  Copyright 2000, University of Southern California,
003    //                  Information Science Institute
004    //
005    //  Personal and Educational use is hereby granted.
006    //  Permission required for commercial use and redistribution.
007    
008    
009    package edu.isi.gamebots.examples;
010    
011    import java.awt.*;
012    import java.awt.geom.*;
013    import java.lang.*;
014    import java.util.*;
015    
016    import javax.swing.*;
017    
018    import us.ca.la.anm.util.io.*;
019    
020    import edu.isi.gamebots.client.*;
021    import edu.isi.gamebots.examples.*;
022    
023    
024    /**
025     *  This example implementation the VizTool class which shows basic message
026     *  handling and uses {@link UTMapUI} for a map in its user interface.
027     *
028     *  @author <a href="mailto:amarshal#gamebots@isi.edu">Andrew n marshall</a>
029     */
030    public class ExampleVizTool implements VizTool {
031      //  Private Constants
032      ////////////////////////////////////////////////////////////////////////////
033      public final static double VISION_DIST   = 400.0d;
034    
035      //  Private Data
036      ////////////////////////////////////////////////////////////////////////////
037      protected DebugLog log;
038    
039      protected boolean isConnected = false;
040    
041      protected final Object classLock = new Object();
042      protected java.util.Map knownClasses = new Hashtable();  // String class name to UTClass
043    
044      protected final Object actorLock = new Object();
045      protected java.util.Map knownObjs = new Hashtable(); // String id to UTActor
046      protected Set navPoints = new HashSet();
047      protected Set players = new HashSet();
048      protected Set pickups = new HashSet();
049    
050      protected VizMap vizMap = new VizMap();
051      protected static final Shape visionArc = new Arc2D.Double( -VISION_DIST, -VISION_DIST, 2*VISION_DIST, 2*VISION_DIST, -45, 90, Arc2D.PIE );
052    
053      private Set nextNavPoints = new HashSet();
054      private Set nextPlayers = new HashSet();
055      private Set nextPickups = new HashSet();
056    
057    
058    
059      //  Public Methods
060      ////////////////////////////////////////////////////////////////////////////
061      public ExampleVizTool() {
062        vizMap.addActorSet( navPoints );
063        vizMap.addActorSet( players );
064        vizMap.addActorSet( pickups );
065      }
066    
067      public void init( DebugLog log ) {
068        this.log = log;
069      }
070    
071      public JComponent getView() {
072        return vizMap;
073    //return new JLabel( getClass().getName() );
074      }
075    
076      public GamebotsClient.Listener getListener() {
077        return listener;
078      }
079    
080      public void destroy() {
081        // do nothing
082      }
083    
084      //  Private Methods
085      ////////////////////////////////////////////////////////////////////////////
086      protected UTActor getActor( Message message ) {
087        String type = message.getType();
088        if( type.equals( END ) )
089          return null;
090        String id  = message.getProperty( ACTOR_ID );
091        UTActor actor;
092        synchronized( actorLock ) {
093          actor = (UTActor) knownObjs.get( id );
094          if( actor != null )
095            return actor;
096    
097          String classname = message.getProperty( ACTOR_CLASS );
098          if( classname == null )
099            classname = UTClass.classNameFromId( id );
100    
101          UTClass utClass = (UTClass) knownClasses.get( classname );
102          if( type.equals( INV ) ) {
103            if( utClass == null )
104              utClass = new UTClass( classname, UTClass.PICKUP );
105            actor = new UTActor( id, utClass, log );
106          } else if( type.equals( PLAYER ) ) {
107    log.logNote( "Player message: "+message );
108            if( utClass == null )
109              utClass = new UTClass( classname, UTClass.PAWN );
110            actor = new UTPawn( id, utClass, log );
111          } else {
112            if( utClass == null ) {
113              utClass = new UTClass( classname, UTClass.ACTOR );
114              knownClasses.put( classname, utClass );
115            }
116            actor = new UTActor( id, utClass, log );
117          }
118          knownObjs.put( id, actor );
119        } // end sync
120    
121        return actor;
122      }
123    
124      // Event Handlers
125      protected GamebotsClient.Listener listener = new GamebotsClient.Listener() {
126        public void connected() {
127          log.logNote( "Connected: "+new Date() );
128          isConnected = true;
129          vizMap.repaint();
130        }
131    
132        public void receivedAsyncMessage( Message message ) {
133          log.logNote( message );
134        }
135    
136        public void receivedSyncMessage( MessageBlock block ) {
137          nextNavPoints.clear();
138          nextPlayers.clear();
139          nextPickups.clear();
140    
141          Iterator i = block.getMessages();
142          Message message;
143          String id;
144          UTActor actor;
145          while( i.hasNext() ) {
146            message = (Message) i.next();
147            actor = getActor( message );
148            if( actor != null ) {
149              actor.update( message );
150              if( actor.utClass.parent == UTClass.PAWN ) {
151                nextPlayers.add( actor );
152              } else if( actor.utClass.parent == UTClass.PICKUP ) {
153                nextPickups.add( actor );
154              } else { // Normal Actor/Nav-Point
155                nextNavPoints.add( actor );
156              }
157            }
158          }
159    
160          Set newNavPoints;
161          Set newPlayers, missingPlayers;
162          Set newPickups, missingPickups;
163          synchronized( actorLock ) {
164            // Diff NavPoints
165            newNavPoints = new HashSet( nextNavPoints );
166            newNavPoints.removeAll( navPoints );
167            navPoints.addAll( newNavPoints );
168    
169            // Diff Players
170            newPlayers = new HashSet( nextPlayers );
171            newPlayers.removeAll( players );
172            missingPlayers = new HashSet( players );
173            missingPlayers.removeAll( nextPlayers );
174            players.removeAll( missingPlayers );
175            players.addAll( newPlayers );
176    
177            // Diff Pickups
178            newPickups = new HashSet( nextPickups );
179            newPickups.removeAll( pickups );
180            missingPickups = new HashSet( pickups );
181            missingPickups.removeAll( nextPickups );
182            pickups.removeAll( missingPickups );
183            pickups.addAll( newPickups );
184          }
185    
186          if( !newNavPoints.isEmpty() ||
187              !missingPlayers.isEmpty() ||
188              !missingPickups.isEmpty() ||
189              !newPlayers.isEmpty() ||
190              !newPickups.isEmpty() ) {
191            StringBuffer sb = new StringBuffer();
192            block.getMessageString( sb, 0 );
193    
194            i = newNavPoints.iterator();
195            while( i.hasNext() ) {
196              actor = (UTActor) i.next();
197              sb.append( "\n  + " );
198              sb.append( actor );
199              sb.append( "\n      " );
200              sb.append( actor.propertiesToString() );
201            }
202    
203            i = missingPlayers.iterator();
204            while( i.hasNext() ) {
205              actor = (UTActor) i.next();
206              sb.append( "\n  - " );
207              sb.append( actor );
208              sb.append( "\n      " );
209              sb.append( actor.propertiesToString() );
210            }
211    
212            i = missingPickups.iterator();
213            while( i.hasNext() ) {
214              actor = (UTActor) i.next();
215              sb.append( "\n  - " );
216              sb.append( actor );
217              sb.append( "\n      " );
218              sb.append( actor.propertiesToString() );
219            }
220    
221            i = newPickups.iterator();
222            while( i.hasNext() ) {
223              actor = (UTActor) i.next();
224              sb.append( "\n  + " );
225              sb.append( actor );
226              sb.append( "\n      " );
227              sb.append( actor.propertiesToString() );
228            }
229    
230            i = newPlayers.iterator();
231            while( i.hasNext() ) {
232              actor = (UTActor) i.next();
233              sb.append( "\n  + " );
234              sb.append( actor );
235              sb.append( "\n      " );
236              sb.append( actor.propertiesToString() );
237            }
238    
239            log.logNote( sb.toString() );
240          }
241    
242          vizMap.repaint();
243        }
244    
245        public void receivedError( Throwable error ) {
246          log.logError( error.toString(), error );
247        }
248    
249        public void disconnected() {
250          log.logNote( "Disconnected: "+new Date() );
251          isConnected = false;
252          vizMap.repaint();
253        }
254      };
255    
256      protected class VizMap extends UTMapUI {
257        protected void paintComponent( Graphics g ) {
258          super.paintComponent( g );
259    
260          Font font = getFont();
261          g.setFont( font );
262          FontMetrics fm = getFontMetrics( font );
263          Dimension size = getSize();
264    
265          if( !isConnected ) {
266            final String message = "Disconnected";
267            int width = fm.stringWidth( message );
268    
269            g.setColor( Color.red );
270            g.drawString( message, size.width-width-2, size.height-fm.getDescent()-2 );
271          }
272        }
273    
274        protected void drawPlayerSymbol( Graphics2D g, double pitch, double yaw ) {
275          double length = symbolSize*Math.cos( pitch );
276          double x = length * Math.cos( yaw );
277          double y = length * Math.sin( yaw );
278    
279          g.draw( playerCircle );
280          g.rotate( yaw );
281          g.draw( visionArc );
282        }
283      }
284    }
285