Package games.stendhal.server.core.rp.group

Source Code of games.stendhal.server.core.rp.group.Group

/* $Id: Group.java,v 1.14 2011/02/24 09:44:04 nhnb Exp $ */
/***************************************************************************
*                   (C) Copyright 2003-2011 - 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.server.core.rp.group;

import games.stendhal.common.NotificationType;
import games.stendhal.server.core.engine.GameEvent;
import games.stendhal.server.core.engine.SingletonRepository;
import games.stendhal.server.core.engine.StendhalRPRuleProcessor;
import games.stendhal.server.entity.player.Player;
import games.stendhal.server.events.GroupChangeEvent;
import games.stendhal.server.events.GroupInviteEvent;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import marauroa.common.game.RPEvent;

/**
* A group of players
*
* @author hendrik
*/
public class Group {
  private static long TIMEOUT = 5*60*1000;
  private static int MAX_MEMBERS = 5;

  private final HashMap<String, Long> membersAndLastSeen = new LinkedHashMap<String, Long>();
  private final HashMap<String, Long> openInvites = new HashMap<String, Long>();
  private String leader = null;
  private String lootmode = "shared";

  /**
   * adds a member to the group
   *
   * @param playerName name of player
   */
  public void addMember(String playerName) {
    openInvites.remove(playerName);
    membersAndLastSeen.put(playerName, Long.valueOf(System.currentTimeMillis()));
    if (leader == null) {
      leader = playerName;
    }
    sendGroupChangeEvent();
  }

  /**
   * removes a member from the group
   *
   * @param playerName name of player
   * @return true if the player was a member of this group
   */
  public boolean removeMember(String playerName) {
    boolean res = membersAndLastSeen.remove(playerName) != null;
    if (res) {
      Set<String> toRemove = new HashSet<String>();
      toRemove.add(playerName);

      // destroy the group if there is only one person and no open invites left
      if ((membersAndLastSeen.size() == 1) && openInvites.isEmpty()) {
        toRemove.add(membersAndLastSeen.keySet().iterator().next());
        membersAndLastSeen.clear();
      }
      fixLeader();

      sendLeftGroupEvent(toRemove);
      sendGroupChangeEvent();
    }
    return res;
  }


  /**
   * removes players that are offline longer than the timeout,
   * destroys the group if there is only one player left
   */
  @SuppressWarnings("unchecked")
  public void clean() {
    Set<String> toRemove = new HashSet<String>();
    StendhalRPRuleProcessor ruleProcessor = SingletonRepository.getRuleProcessor();
    Long currentTime = Long.valueOf(System.currentTimeMillis());
    Long timeoutTime = Long.valueOf(System.currentTimeMillis() - TIMEOUT);

    // remove offline members and set keep alive timestamp
    for (Map.Entry<String, Long> entry : ((Map<String, Long>)membersAndLastSeen.clone()).entrySet()) {
      String playerName = entry.getKey();
      if (ruleProcessor.getPlayer(playerName) != null) {
        membersAndLastSeen.put(playerName, currentTime);
      } else {
        if (entry.getValue().compareTo(timeoutTime) < 0) {
          toRemove.add(playerName);
          new GameEvent(playerName, "group", playerName, "timeout").raise();
        }
      }
    }
    membersAndLastSeen.keySet().removeAll(toRemove);

    // expire open invites
    Iterator<Map.Entry<String, Long>> itr = openInvites.entrySet().iterator();
    while (itr.hasNext()) {
      Map.Entry<String, Long> entry = itr.next();
      if (entry.getValue().compareTo(timeoutTime) < 0) {
        // TODO: "leader" needs to be the leader at invite time
        // TODO: alternatively: cancel the old invite and create a new one on leader change
        //       but the new leader may not agree with the invite, so it may not be a good idea
        //       to fake it his name.
        Player invitedPlayer = ruleProcessor.getPlayer(entry.getKey());
        if (invitedPlayer != null) {
          invitedPlayer.addEvent(new GroupInviteEvent(leader, true));
        }

        itr.remove();
      }
    }

    fixLeader();

    // destroy the group if there is only one person and no open invites left
    if ((membersAndLastSeen.size() == 1) && openInvites.isEmpty()) {
      toRemove.add(membersAndLastSeen.keySet().iterator().next());
      membersAndLastSeen.clear();
    }

    // tell the clients about the changes
    if (!toRemove.isEmpty()) {
      sendGroupChangeEvent();
      sendLeftGroupEvent(toRemove);
    }
  }

  /**
   * destroys the groups
   */
  public void destory() {
    sendLeftGroupEvent(membersAndLastSeen.keySet());
    membersAndLastSeen.clear();
  }

  /**
   * checks if this group does not have any members
   *
   * @return true, if it is empty; false if there are members in it
   */
  public boolean isEmpty() {
    return membersAndLastSeen.isEmpty();
  }

  /**
   * checks if the group is full.
   *
   * @return true if the group is full; false otherwise
   */
  public boolean isFull() {
    return membersAndLastSeen.size() >= MAX_MEMBERS;
  }

  /**
   * check if the player was invited
   * @param playerName player to check if it was invited
   * @return true, if the player was invited; false otherwise
   */
  public boolean hasBeenInvited(String playerName) {
    return openInvites.get(playerName) != null;
  }

  /**
   * is the specified player the leader of this group?
   *
   * @param playerName name of player
   * @return true if its the leader; false otherwise
   */
  public boolean hasLeader(String playerName) {
    return (leader != null) && leader.equals(playerName);
  }

  /**
   * is the player a member of this group?
   *
   * @param playerName name of player
   * @return true if the player is a member of this group
   */
  public boolean hasMember(String playerName) {
    return membersAndLastSeen.get(playerName) != null;
  }

  /**
   * is the specified player the leader of this group?
   *
   * @param playerName name of player
   * @return true if its the leader; false otherwise
   */
  public boolean setLeader(String playerName) {
    if (!membersAndLastSeen.containsKey(playerName)) {
      return false;
    }
    leader = playerName;
    sendGroupChangeEvent();
    return true;
  }

  /**
   * gets the loot mode
   *
   * @return loot mode
   */
  public String getLootmode() {
    return lootmode;
  }

  /**
   * sets the loot mode
   *
   * @param mode "single" or "shared"
   */
  public void setLootmode(String mode) {
    this.lootmode = mode;
    sendGroupChangeEvent();
  }

  /**
   * invites a player to join this group.
   *
   * @param player  player sending the invited
   * @param targetPlayer invited player
   */
  public void invite(Player player, Player targetPlayer) {
    openInvites.put(targetPlayer.getName(), Long.valueOf(System.currentTimeMillis()));
    targetPlayer.addEvent(new GroupInviteEvent(player.getName(), false));
  }

  /**
   * defines a new leader, if the leader is not part of the group anymore.
   */
  private void fixLeader() {
    if (membersAndLastSeen.isEmpty()) {
      return;
    }
    if ((leader == null) || !membersAndLastSeen.containsKey(leader)) {
      leader = membersAndLastSeen.keySet().iterator().next();
      new GameEvent(leader, "group", leader, "leader fixed").raise();
    }
  }


  /**
   * sends a group chat message to all members
   *
   * @param name   name of sender
   * @param text message to send
   */
  public void sendGroupMessage(String name, String text) {
    StendhalRPRuleProcessor ruleProcessor = SingletonRepository.getRuleProcessor();
    for (String playerName : membersAndLastSeen.keySet()) {
      Player player = ruleProcessor.getPlayer(playerName);
      if (player != null) {
        player.sendPrivateText(NotificationType.GROUP, name + ": " + text);
      }
    }
  }


  /**
   * tell the clients about changes in the group
   */
  private void sendGroupChangeEvent() {
    StendhalRPRuleProcessor ruleProcessor = SingletonRepository.getRuleProcessor();
    List<String> members = new LinkedList<String>(membersAndLastSeen.keySet());
    RPEvent event = new GroupChangeEvent(leader, members, lootmode);
    for (String playerName : membersAndLastSeen.keySet()) {
      Player player = ruleProcessor.getPlayer(playerName);
      if (player != null) {
        player.addEvent(event);
      }
    }
  }

  /**
   * tells the player the current status of the group
   *
   * @param player Player
   */
  public void sendGroupChangeEvent(Player player) {
    List<String> members = new LinkedList<String>(membersAndLastSeen.keySet());
    RPEvent event = new GroupChangeEvent(leader, members, lootmode);
    player.addEvent(event);
  }

  /**
   * tell players about them being removed from the group
   *
   * @param toRemove players to remove.
   */
  private void sendLeftGroupEvent(Set<String> toRemove) {
    StendhalRPRuleProcessor ruleProcessor = SingletonRepository.getRuleProcessor();
    RPEvent event = new GroupChangeEvent();
    for (String playerName : toRemove) {
      Player player = ruleProcessor.getPlayer(playerName);
      if (player != null) {
        player.addEvent(event);
      }
    }
  }
}
TOP

Related Classes of games.stendhal.server.core.rp.group.Group

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.