001/* 002 * Trident - A Multithreaded Server Alternative 003 * Copyright 2014 The TridentSDK Team 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package net.tridentsdk.server.entity.ai.pathfind; 019 020import net.tridentsdk.util.Vector; 021 022import javax.annotation.concurrent.NotThreadSafe; 023import java.util.ArrayList; 024import java.util.Collections; 025import java.util.LinkedList; 026import java.util.List; 027 028@NotThreadSafe 029public class Path { 030 private final List<Node> pathPoints; 031 private int index; 032 private double step; 033 034 public Path(Node end) { 035 LinkedList<Node> trace = new LinkedList<>(); 036 037 while(end != null) { 038 trace.add(end); 039 end = end.parent(); 040 } 041 042 Collections.reverse(trace); // Reverse list so that it isn't backwards 043 this.pathPoints = new ArrayList<>(trace); 044 } 045 046 /** 047 * Get the movement for the enxt tick based on the speed of the entity. 048 * 049 * @param speed of entity (blocks per tick). 050 * @return Movement for entity in current tick 051 */ 052 public Vector pollMovement(double speed) { 053 if(speed > 1.0) { 054 throw new IllegalArgumentException("Cannot move more than 1X/tick!"); 055 } 056 057 Vector movement = new Vector(0, 0, 0); 058 Node current = pathPoints.get(index); 059 Node next = pathPoints.get(index + 1); 060 double dx = next.x() - current.x(); 061 double dz = next.z() - current.z(); 062 063 if(speed + step >= 1.0) { 064 movement.add(1 - step, 0, 1 - step); 065 066 // Find next node 067 index += 1; 068 069 if(!finished()) { 070 movement.setY(next.y() - current.y()); 071 072 // Recalculate values 073 current = next; 074 next = pathPoints.get(index + 1); 075 dx = next.x() - current.x(); 076 dz = next.z() - current.z(); 077 this.step = 0.0; 078 } 079 } 080 081 step += speed; 082 movement.add(dx * speed, 0, dz * speed); 083 return movement; 084 } 085 086 public boolean finished() { 087 return index >= pathPoints.size() - 1; 088 } 089}