Package lineage2.gameserver.geodata

Source Code of lineage2.gameserver.geodata.PathFindBuffers$PathFindBuffer

/*
* 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 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package lineage2.gameserver.geodata;

import gnu.trove.iterator.TIntIntIterator;
import gnu.trove.map.hash.TIntIntHashMap;
import gnu.trove.map.hash.TIntObjectHashMap;

import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import lineage2.commons.text.StrTable;
import lineage2.gameserver.Config;
import lineage2.gameserver.utils.Location;

/**
* @author Mobius
* @version $Revision: 1.0 $
*/
public class PathFindBuffers
{
  /**
   * Field MIN_MAP_SIZE.
   */
  public final static int MIN_MAP_SIZE = 1 << 6;
  /**
   * Field STEP_MAP_SIZE.
   */
  public final static int STEP_MAP_SIZE = 1 << 5;
  /**
   * Field MAX_MAP_SIZE.
   */
  public final static int MAX_MAP_SIZE = 1 << 9;
  /**
   * Field buffers.
   */
  private static TIntObjectHashMap<PathFindBuffer[]> buffers = new TIntObjectHashMap<>();
  /**
   * Field sizes.
   */
  private static int[] sizes = new int[0];
  /**
   * Field lock.
   */
  private static Lock lock = new ReentrantLock();
  static
  {
    TIntIntHashMap config = new TIntIntHashMap();
    String[] k;
    for (String e : Config.PATHFIND_BUFFERS.split(";"))
    {
      if (!e.isEmpty() && ((k = e.split("x")).length == 2))
      {
        config.put(Integer.valueOf(k[1]), Integer.valueOf(k[0]));
      }
    }
    TIntIntIterator itr = config.iterator();
    while (itr.hasNext())
    {
      itr.advance();
      int size = itr.key();
      int count = itr.value();
      PathFindBuffer[] buff = new PathFindBuffer[count];
      for (int i = 0; i < count; i++)
      {
        buff[i] = new PathFindBuffer(size);
      }
      buffers.put(size, buff);
    }
    sizes = config.keys();
    Arrays.sort(sizes);
  }
 
  /**
   * Method create.
   * @param mapSize int
   * @return PathFindBuffer
   */
  private static PathFindBuffer create(int mapSize)
  {
    lock.lock();
    try
    {
      PathFindBuffer buffer;
      PathFindBuffer[] buff = buffers.get(mapSize);
      if (buff != null)
      {
        buff = lineage2.commons.lang.ArrayUtils.add(buff, buffer = new PathFindBuffer(mapSize));
      }
      else
      {
        buff = new PathFindBuffer[]
        {
          buffer = new PathFindBuffer(mapSize)
        };
        sizes = org.apache.commons.lang3.ArrayUtils.add(sizes, mapSize);
        Arrays.sort(sizes);
      }
      buffers.put(mapSize, buff);
      buffer.inUse = true;
      return buffer;
    }
    finally
    {
      lock.unlock();
    }
  }
 
  /**
   * Method get.
   * @param mapSize int
   * @return PathFindBuffer
   */
  private static PathFindBuffer get(int mapSize)
  {
    lock.lock();
    try
    {
      PathFindBuffer[] buff = buffers.get(mapSize);
      for (PathFindBuffer buffer : buff)
      {
        if (!buffer.inUse)
        {
          buffer.inUse = true;
          return buffer;
        }
      }
      return null;
    }
    finally
    {
      lock.unlock();
    }
  }
 
  /**
   * Method alloc.
   * @param mapSize int
   * @return PathFindBuffer
   */
  public static PathFindBuffer alloc(int mapSize)
  {
    if (mapSize > MAX_MAP_SIZE)
    {
      return null;
    }
    mapSize += STEP_MAP_SIZE;
    if (mapSize < MIN_MAP_SIZE)
    {
      mapSize = MIN_MAP_SIZE;
    }
    PathFindBuffer buffer = null;
    for (int size : sizes)
    {
      if (size >= mapSize)
      {
        mapSize = size;
        buffer = get(mapSize);
        break;
      }
    }
    if (buffer == null)
    {
      for (int size = MIN_MAP_SIZE; size < MAX_MAP_SIZE; size += STEP_MAP_SIZE)
      {
        if (size >= mapSize)
        {
          mapSize = size;
          buffer = create(mapSize);
          break;
        }
      }
    }
    return buffer;
  }
 
  /**
   * Method recycle.
   * @param buffer PathFindBuffer
   */
  public static void recycle(PathFindBuffer buffer)
  {
    lock.lock();
    try
    {
      buffer.inUse = false;
    }
    finally
    {
      lock.unlock();
    }
  }
 
  /**
   * Method getStats.
   * @return StrTable
   */
  public static StrTable getStats()
  {
    StrTable table = new StrTable("PathFind Buffers Stats");
    lock.lock();
    try
    {
      long totalUses = 0, totalPlayable = 0, totalTime = 0;
      int index = 0;
      int count;
      long uses;
      long playable;
      long itrs;
      long success;
      long overtime;
      long time;
      for (int size : sizes)
      {
        index++;
        count = 0;
        uses = 0;
        playable = 0;
        itrs = 0;
        success = 0;
        overtime = 0;
        time = 0;
        for (PathFindBuffer buff : buffers.get(size))
        {
          count++;
          uses += buff.totalUses;
          playable += buff.playableUses;
          success += buff.successUses;
          overtime += buff.overtimeUses;
          time += buff.totalTime / 1000000;
          itrs += buff.totalItr;
        }
        totalUses += uses;
        totalPlayable += playable;
        totalTime += time;
        table.set(index, "Size", size);
        table.set(index, "Count", count);
        table.set(index, "Uses (success%)", uses + "(" + String.format("%2.2f", (uses > 0) ? (success * 100.) / uses : 0) + "%)");
        table.set(index, "Uses, playble", playable + "(" + String.format("%2.2f", (uses > 0) ? (playable * 100.) / uses : 0) + "%)");
        table.set(index, "Uses, overtime", overtime + "(" + String.format("%2.2f", (uses > 0) ? (overtime * 100.) / uses : 0) + "%)");
        table.set(index, "Iter., avg", (uses > 0) ? itrs / uses : 0);
        table.set(index, "Time, avg (ms)", String.format("%1.3f", (uses > 0) ? (double) time / uses : 0.));
      }
      table.addTitle("Uses, total / playable  : " + totalUses + " / " + totalPlayable);
      table.addTitle("Uses, total time / avg (ms) : " + totalTime + " / " + String.format("%1.3f", totalUses > 0 ? (double) totalTime / totalUses : 0));
    }
    finally
    {
      lock.unlock();
    }
    return table;
  }
 
  /**
   * @author Mobius
   */
  public static class PathFindBuffer
  {
    /**
     * Field mapSize.
     */
    final int mapSize;
    /**
     * Field nodes.
     */
    final GeoNode[][] nodes;
    /**
     * Field open.
     */
    final Queue<GeoNode> open;
    /**
     * Field offsetY.
     */
    /**
     * Field offsetX.
     */
    int offsetX, offsetY;
    /**
     * Field inUse.
     */
    boolean inUse;
    /**
     * Field totalUses.
     */
    long totalUses;
    /**
     * Field successUses.
     */
    long successUses;
    /**
     * Field overtimeUses.
     */
    long overtimeUses;
    /**
     * Field playableUses.
     */
    long playableUses;
    /**
     * Field totalTime.
     */
    long totalTime;
    /**
     * Field totalItr.
     */
    long totalItr;
   
    /**
     * Constructor for PathFindBuffer.
     * @param mapSize int
     */
    public PathFindBuffer(int mapSize)
    {
      open = new PriorityQueue<>(mapSize);
      this.mapSize = mapSize;
      nodes = new GeoNode[mapSize][mapSize];
      for (int i = 0; i < nodes.length; i++)
      {
        for (int j = 0; j < nodes[i].length; j++)
        {
          nodes[i][j] = new GeoNode();
        }
      }
    }
   
    /**
     * Method free.
     */
    public void free()
    {
      open.clear();
      for (GeoNode[] node : nodes)
      {
        for (GeoNode element : node)
        {
          element.free();
        }
      }
    }
  }
 
  /**
   * @author Mobius
   */
  public static class GeoNode implements Comparable<GeoNode>
  {
    /**
     * Field NONE. (value is 0)
     */
    public final static int NONE = 0;
    /**
     * Field OPENED. (value is 1)
     */
    public final static int OPENED = 1;
    /**
     * Field CLOSED. (value is -1)
     */
    public final static int CLOSED = -1;
    /**
     * Field y.
     */
    /**
     * Field x.
     */
    public int x, y;
    /**
     * Field nswe.
     */
    /**
     * Field z.
     */
    public short z, nswe;
    /**
     * Field costToEnd.
     */
    /**
     * Field costFromStart.
     */
    /**
     * Field totalCost.
     */
    public float totalCost, costFromStart, costToEnd;
    /**
     * Field state.
     */
    public int state;
    /**
     * Field parent.
     */
    public GeoNode parent;
   
    /**
     * Constructor for GeoNode.
     */
    public GeoNode()
    {
      nswe = -1;
    }
   
    /**
     * Method set.
     * @param x int
     * @param y int
     * @param z short
     * @return GeoNode
     */
    public GeoNode set(int x, int y, short z)
    {
      this.x = x;
      this.y = y;
      this.z = z;
      return this;
    }
   
    /**
     * Method isSet.
     * @return boolean
     */
    public boolean isSet()
    {
      return nswe != -1;
    }
   
    /**
     * Method free.
     */
    public void free()
    {
      nswe = -1;
      costFromStart = 0f;
      totalCost = 0f;
      costToEnd = 0f;
      parent = null;
      state = NONE;
    }
   
    /**
     * Method getLoc.
     * @return Location
     */
    public Location getLoc()
    {
      return new Location(x, y, z);
    }
   
    /**
     * Method toString.
     * @return String
     */
    @Override
    public String toString()
    {
      return "[" + x + "," + y + "," + z + "] f: " + totalCost;
    }
   
    /**
     * Method compareTo.
     * @param o GeoNode
     * @return int
     */
    @Override
    public int compareTo(GeoNode o)
    {
      if (totalCost > o.totalCost)
      {
        return 1;
      }
      if (totalCost < o.totalCost)
      {
        return -1;
      }
      return 0;
    }
  }
}
TOP

Related Classes of lineage2.gameserver.geodata.PathFindBuffers$PathFindBuffer

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.