Package games.stendhal.client.gui.map

Source Code of games.stendhal.client.gui.map.MapPanelController

/* $Id: MapPanelController.java,v 1.6 2011/03/05 16:08:05 kiheru Exp $ */
/***************************************************************************
*                   (C) Copyright 2003-2010 - Stendhal                    *
***************************************************************************
***************************************************************************
*                                                                         *
*   This program is free software; you can redistribute it and/or modify  *
*   it under the terms of the GNU General Public License as published by  *
*   the Free Software Foundation; either version 2 of the License, or     *
*   (at your option) any later version.                                   *
*                                                                         *
***************************************************************************/
package games.stendhal.client.gui.map;

import games.stendhal.client.GameObjects;
import games.stendhal.client.StendhalClient;
import games.stendhal.client.entity.DomesticAnimal;
import games.stendhal.client.entity.EntityChangeListener;
import games.stendhal.client.entity.HousePortal;
import games.stendhal.client.entity.IEntity;
import games.stendhal.client.entity.Player;
import games.stendhal.client.entity.Portal;
import games.stendhal.client.entity.RPEntity;
import games.stendhal.client.entity.User;
import games.stendhal.client.entity.WalkBlocker;
import games.stendhal.common.CollisionDetection;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.swing.JComponent;
import javax.swing.SwingUtilities;

public class MapPanelController implements GameObjects.GameObjectListener {
  private static final boolean supermanMode = (System.getProperty("stendhal.superman") != null);
  private MapPanel panel;
  final Map<IEntity, MapObject> mapObjects = new ConcurrentHashMap<IEntity, MapObject>();
  double x, y;

  /**
   * <code>true</code> if the map should be repainted, <code>false</code>
   * otherwise.
   */
  private volatile boolean needsRefresh;
 
  public MapPanelController(final StendhalClient client) {
    panel = new MapPanel(this, client);
    client.getGameObjects().addGameObjectListener(this);
  }
 
  /**
   * Mark the map contents changed, so that the component should be redrawn.
   *
   * @param needed
   */
  void setNeedsRefresh(boolean needed) {
    needsRefresh = needed;
  }
 
  /**
   * Get the map panel component
   * @return component
   */
  public JComponent getComponent() {
    return panel;
  }
 
  /**
   * Add an entity to the map, if it should be displayed to the user. This
   * method is thread safe.
   *
   * @param entity the added entity
   */
  public void addEntity(final IEntity entity) {
    MapObject object = null;
   
    if (entity instanceof User) {
      entity.addChangeListener(new EntityChangeListener() {
        public void entityChanged(final IEntity entity, final Object property) {
          if (property == IEntity.PROP_POSITION) {
            positionChanged(entity.getX(), entity.getY());
          }
        }
      });
      positionChanged(entity.getX(), entity.getY());
     
      object = new PlayerMapObject(entity);
    } else if (entity instanceof Player) {
      object = new PlayerMapObject(entity);
    } else if (entity instanceof Portal) {
      final Portal portal = (Portal) entity;

      if (!portal.isHidden()) {
        mapObjects.put(entity, new PortalMapObject(entity));
      }
    } else if (entity instanceof HousePortal) {
      object = new PortalMapObject(entity);
    } else if (entity instanceof WalkBlocker) {
      object = new WalkBlockerMapObject(entity);
    } else if (entity instanceof DomesticAnimal) {
      // Only own pets and sheep are drawn but this is checked in the map object so the user status is always up to date
      object = new DomesticAnimalMapObject((DomesticAnimal)entity);
    } else if (supermanMode && User.isAdmin()) {
      if (entity instanceof RPEntity) {
        object = new RPEntityMapObject(entity);
      } else {
        object = new MovingMapObject(entity);
      }
    }
   
    if (object != null) {
      mapObjects.put(entity, object);
     
      // changes to objects that should trigger a refresh
      if (object instanceof MovingMapObject) {
        entity.addChangeListener(new EntityChangeListener() {
          public void entityChanged(final IEntity entity, final Object property) {
            if ((property == IEntity.PROP_POSITION)
                || (property == RPEntity.PROP_GHOSTMODE)
                || (property == RPEntity.PROP_GROUP_MEMBERSHIP)) {
              needsRefresh = true;
            }
          }
        });
      }
      needsRefresh = true;
    }
  }

 
  /**
   * Remove an entity from the map entity list.
   *
   * @param entity the entity to be removed
   */
  public void removeEntity(final IEntity entity) {
    if (mapObjects.containsKey(entity)) {
      mapObjects.remove(entity);
      needsRefresh = true;
    }
  }
 
  /**
   * Request redrawing the map screen if the needed.
   */
  public void refresh() {
    if (needsRefresh) {
      panel.repaint();
    }
  }
 
  /**
   * Update the map with new data.
   *
   * @param cd
   *            The collision map.
   * @param pd 
   *          The protection map.
   * @param zone
   *            The zone name.
   */
  public void update(final CollisionDetection cd, final CollisionDetection pd, final String zone) {
    // Panel will do the relevant part in EDT.
    panel.update(cd, pd, zone);
  }
 
  /**
   * The player's position changed.
   *
   * @param x
   *            The X coordinate (in world units).
   * @param y
   *            The Y coordinate (in world units).
   */
  private void positionChanged(final double x, final double y) {
    /*
     * The client gets occasionally spurious events.
     * Suppress repainting unless the position actually changed
     */
    if ((this.x != x) || (this.y != y)) {
      this.x = x;
      this.y = y;
      SwingUtilities.invokeLater(new Runnable() {
        public void run() {
          panel.positionChanged(x, y);
          /*
           * Set the refresh flag after the map offset has been
           * actually updated. The position listener for moving map
           * objects sets it, but it happens in the game loop thread
           * and may be unset before the map panel has actually got
           * the correct map offset.
           */
          setNeedsRefresh(true);
        }
      });
    }
  }
TOP

Related Classes of games.stendhal.client.gui.map.MapPanelController

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.