/* * Copyright (C) 2004-2015 L2J Server * * This file is part of L2J Server. * * L2J Server 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. * * L2J Server 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 . */ package com.l2jserver.gameserver.pathfinding; import java.util.List; import com.l2jserver.Config; import com.l2jserver.gameserver.model.L2World; import com.l2jserver.gameserver.pathfinding.cellnodes.CellPathFinding; import com.l2jserver.gameserver.pathfinding.geonodes.GeoPathFinding; /** * @author -Nemesiss- */ public abstract class PathFinding { public static PathFinding getInstance() { if (Config.PATHFINDING == 1) { // Higher Memory Usage, Smaller Cpu Usage return GeoPathFinding.getInstance(); } // Cell pathfinding, calculated directly from geodata files return CellPathFinding.getInstance(); } public abstract boolean pathNodesExist(short regionoffset); public abstract List findPath(int x, int y, int z, int tx, int ty, int tz, int instanceId, boolean playable); // @formatter:off /* public List search(AbstractNode start, AbstractNode end, int instanceId) { // The simplest grid-based pathfinding. // Drawback is not having higher cost for diagonal movement (means funny routes) // Could be optimized e.g. not to calculate backwards as far as forwards. // List of Visited Nodes LinkedList visited = new LinkedList(); // List of Nodes to Visit LinkedList to_visit = new LinkedList(); to_visit.add(start); int i = 0; while (i < 800) { AbstractNode node; try { node = to_visit.removeFirst(); } catch (Exception e) { // No Path found return null; } if (node.equals(end)) //path found! return constructPath(node, instanceId); else { i++; visited.add(node); node.attachNeighbors(); Node[] neighbors = node.getNeighbors(); if (neighbors == null) continue; for (Node n : neighbors) { if (!visited.contains(n) && !to_visit.contains(n)) { n.setParent(node); to_visit.add(n); } } } } //No Path found return null; } */ /* public List searchAStar(Node start, Node end, int instanceId) { // Not operational yet? int start_x = start.getLoc().getX(); int start_y = start.getLoc().getY(); int end_x = end.getLoc().getX(); int end_y = end.getLoc().getY(); //List of Visited Nodes FastNodeList visited = new FastNodeList(800);//TODO! Add limit to cfg // List of Nodes to Visit BinaryNodeHeap to_visit = new BinaryNodeHeap(800); to_visit.add(start); int i = 0; while (i < 800)//TODO! Add limit to cfg { AbstractNode node; try { node = to_visit.removeFirst(); } catch (Exception e) { // No Path found return null; } if (node.equals(end)) //path found! return constructPath(node, instanceId); else { visited.add(node); node.attachNeighbors(); for (Node n : node.getNeighbors()) { if (!visited.contains(n) && !to_visit.contains(n)) { i++; n.setParent(node); n.setCost(Math.abs(start_x - n.getLoc().getNodeX()) + Math.abs(start_y - n.getLoc().getNodeY()) + Math.abs(end_x - n.getLoc().getNodeX()) + Math.abs(end_y - n.getLoc().getNodeY())); to_visit.add(n); } } } } //No Path found return null; } */ // @formatter:on /** * Convert geodata position to pathnode position * @param geo_pos * @return pathnode position */ public short getNodePos(int geo_pos) { return (short) (geo_pos >> 3); // OK? } /** * Convert node position to pathnode block position * @param node_pos * @return pathnode block position (0...255) */ public short getNodeBlock(int node_pos) { return (short) (node_pos % 256); } public byte getRegionX(int node_pos) { return (byte) ((node_pos >> 8) + L2World.TILE_X_MIN); } public byte getRegionY(int node_pos) { return (byte) ((node_pos >> 8) + L2World.TILE_Y_MIN); } public short getRegionOffset(byte rx, byte ry) { return (short) ((rx << 5) + ry); } /** * Convert pathnode x to World x position * @param node_x rx * @return */ public int calculateWorldX(short node_x) { return L2World.MAP_MIN_X + (node_x * 128) + 48; } /** * Convert pathnode y to World y position * @param node_y * @return */ public int calculateWorldY(short node_y) { return L2World.MAP_MIN_Y + (node_y * 128) + 48; } public String[] getStat() { return null; } }