goes with the commit below VVVV

This commit is contained in:
NewGarbo 2016-01-12 07:02:19 +00:00
parent d3452772ed
commit ed8d9459b2
4 changed files with 727 additions and 0 deletions

View File

@ -0,0 +1,130 @@
package mineplex.game.clans.clans.outpost;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.entity.Skeleton;
import org.bukkit.inventory.ItemStack;
import com.mojang.authlib.GameProfile;
import mineplex.core.common.util.UtilEnt;
import mineplex.core.common.util.UtilMath;
import mineplex.core.common.util.UtilPlayer;
import mineplex.core.disguise.disguises.DisguisePlayer;
import mineplex.game.clans.clans.outpost.pathing.AStar;
import mineplex.game.clans.clans.outpost.pathing.AStar.InvalidPathException;
import mineplex.game.clans.clans.outpost.pathing.PathingResult;
import mineplex.game.clans.clans.outpost.pathing.Tile;
public class OutpostBuilder
{
private Skeleton _entity;
private List<Location> _path;
private int _pathPos;
private List<Location> _moveLocations;
private int _nextLocation;
private long _arrivedTime;
private long _lastMovement;
private Outpost _host;
public OutpostBuilder(Location pos, String name, List<Location> locations, Outpost host)
{
_host = host;
Location spawnLoc = pos;
Skeleton skel = pos.getWorld().spawn(spawnLoc, Skeleton.class);
skel.teleport(spawnLoc);
skel.setHealth(20);
UtilEnt.Vegetate(skel);
UtilEnt.silence(skel, true);
skel.getEquipment().setHelmet(new ItemStack(Material.NETHER_BRICK_ITEM, 1));
skel.getEquipment().setItemInHand(new ItemStack(Material.IRON_PICKAXE, 1));
// Get in range
List<Player> inRange = UtilPlayer.getNearby(spawnLoc, 75d);
// Disguise
DisguisePlayer disguise = new DisguisePlayer(skel, new GameProfile(Bukkit.getOfflinePlayer("Chiss").getUniqueId(), "Chiss"));
host.getClan().Clans.getDisguiseManager().disguise(disguise, inRange.toArray(new Player[inRange.size()]));
_entity = skel;
_moveLocations = locations;
}
public void tick()
{
if (_path == null || _arrivedTime != -1)
{
_nextLocation = UtilMath.random.nextInt(_moveLocations.size());
_path = calculatePath();
_pathPos = 0;
return;
}
if (System.currentTimeMillis() - _lastMovement >= 500)
{
if (_pathPos == _path.size() - 1)
{
_arrivedTime = 1;
}
else
{
_entity.teleport(_path.get(++_pathPos));
_arrivedTime = -1;
}
_lastMovement = System.currentTimeMillis();
}
}
private List<Location> calculatePath()
{
Location start = _entity.getLocation();
Location end = _moveLocations.get(_nextLocation);
int range = _host._type._size * 2;
try
{
AStar pathFinder = new AStar(start, end, range);
ArrayList<Tile> route = pathFinder.iterate();
PathingResult res = pathFinder.getPathingResult();
if (res == PathingResult.NO_PATH)
{
return Arrays.asList(_moveLocations.get(_nextLocation));
}
List<Location> list = new ArrayList<>();
for (Tile tile : route)
{
list.add(tile.getLocation(start));
}
return list;
}
catch (InvalidPathException e)
{
cleanup();
return null;
}
}
private void cleanup()
{
_entity.remove();
_host.queueForRemoval(this);
}
}

View File

@ -0,0 +1,391 @@
/*
* By @Adamki11s
*/
package mineplex.game.clans.clans.outpost.pathing;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.material.Gate;
/**
* Not made by meee (NewGarbo)
* https://bukkit.org/threads/lib-a-pathfinding-algorithm.129786/
*/
public class AStar
{
private final int _sx;
private final int _sy;
private final int _sz;
private final int _ex;
private final int _ey;
private final int _ez;
private final World _world;
private PathingResult _result;
private HashMap<String, Tile> _open = new HashMap<String, Tile>();
private HashMap<String, Tile> _closed = new HashMap<String, Tile>();
private void addToOpenList(Tile t, boolean modify)
{
if (_open.containsKey(t.getUID()))
{
if (modify)
{
_open.put(t.getUID(), t);
}
}
else
{
_open.put(t.getUID(), t);
}
}
private void addToClosedList(Tile t)
{
if (!_closed.containsKey(t.getUID()))
{
_closed.put(t.getUID(), t);
}
}
private final int _range;
private final String _endUID;
public AStar(Location start, Location end, int range) throws InvalidPathException
{
boolean s = true, e = true;
if (!(s = isLocationWalkable(start)) || !(e = isLocationWalkable(end)))
{
throw new InvalidPathException(s, e);
}
_world = start.getWorld();
_sx = start.getBlockX();
_sy = start.getBlockY();
_sz = start.getBlockZ();
_ex = end.getBlockX();
_ey = end.getBlockY();
_ez = end.getBlockZ();
_range = range;
short sh = 0;
Tile t = new Tile(sh, sh, sh, null);
t.calculateBoth(_sx, _sy, _sz, _ex, _ey, _ez, true);
_open.put(t.getUID(), t);
processAdjacentTiles(t);
StringBuilder b = new StringBuilder();
b.append(_ex - _sx).append(_ey - _sy).append(_ez - _sz);
_endUID = b.toString();
}
public Location getEndLocation()
{
return new Location(_world, _ex, _ey, _ez);
}
public PathingResult getPathingResult()
{
return _result;
}
protected boolean _checkOnce = false;
private int abs(int i)
{
return (i < 0 ? -i : i);
}
public ArrayList<Tile> iterate()
{
if (!_checkOnce)
{
// invert the boolean flag
_checkOnce ^= true;
if ((abs(_sx - _ex) > _range) || (abs(_sy - _ey) > _range) || (abs(_sz - _ez) > _range))
{
_result = PathingResult.NO_PATH;
return null;// jump out
}
}
// while not at end
Tile current = null;
while (canContinue())
{
// get lowest F cost square on open list
current = getLowestFTile();
// process tiles
processAdjacentTiles(current);
}
if (_result != PathingResult.SUCCESS)
{
return null;
}
else
{
// path found
LinkedList<Tile> routeTrace = new LinkedList<Tile>();
Tile parent;
routeTrace.add(current);
while ((parent = current.getParent()) != null)
{
routeTrace.add(parent);
current = parent;
}
Collections.reverse(routeTrace);
return new ArrayList<Tile>(routeTrace);
}
}
private boolean canContinue()
{
// check if open list is empty, if it is no path has been found
if (_open.size() == 0)
{
_result = PathingResult.NO_PATH;
return false;
}
else
{
if (_closed.containsKey(_endUID))
{
_result = PathingResult.SUCCESS;
return false;
}
else
{
return true;
}
}
}
private Tile getLowestFTile()
{
double f = 0;
Tile drop = null;
// get lowest F cost square
for (Tile t : _open.values())
{
if (f == 0)
{
t.calculateBoth(_sx, _sy, _sz, _ex, _ey, _ez, true);
f = t.getF();
drop = t;
}
else
{
t.calculateBoth(_sx, _sy, _sz, _ex, _ey, _ez, true);
double posF = t.getF();
if (posF < f)
{
f = posF;
drop = t;
}
}
}
// drop from open list and add to closed
_open.remove(drop.getUID());
addToClosedList(drop);
return drop;
}
private boolean isOnClosedList(Tile t)
{
return _closed.containsKey(t.getUID());
}
// pass in the current tile as the parent
private void processAdjacentTiles(Tile current)
{
// set of possible walk to locations adjacent to current tile
HashSet<Tile> possible = new HashSet<Tile>(26);
for (byte x = -1; x <= 1; x++)
{
for (byte y = -1; y <= 1; y++)
{
for (byte z = -1; z <= 1; z++)
{
if (x == 0 && y == 0 && z == 0)
{
continue;// don't check current square
}
Tile t = new Tile((short) (current.getX() + x), (short) (current.getY() + y), (short) (current.getZ() + z), current);
if (!t.isInRange(_range))
{
// if block is out of bounds continue
continue;
}
if (x != 0 && z != 0 && (y == 0 || y == 1))
{
// check to stop jumping through diagonal blocks
Tile xOff = new Tile((short) (current.getX() + x), (short) (current.getY() + y), (short) (current.getZ()), current), zOff = new Tile((short) (current.getX()), (short) (current.getY() + y), (short) (current.getZ() + z), current);
if (!isTileWalkable(xOff) && !isTileWalkable(zOff))
{
continue;
}
}
if (isOnClosedList(t))
{
// ignore tile
continue;
}
// only process the tile if it can be walked on
if (isTileWalkable(t))
{
t.calculateBoth(_sx, _sy, _sz, _ex, _ey, _ez, true);
possible.add(t);
}
}
}
}
for (Tile t : possible)
{
// get the reference of the object in the array
Tile openRef = null;
if ((openRef = isOnOpenList(t)) == null)
{
// not on open list, so add
addToOpenList(t, false);
}
else
{
// is on open list, check if path to that square is better using
// G cost
if (t.getG() < openRef.getG())
{
// if current path is better, change parent
openRef.setParent(current);
// force updates of F, G and H values.
openRef.calculateBoth(_sx, _sy, _sz, _ex, _ey, _ez, true);
}
}
}
}
private Tile isOnOpenList(Tile t)
{
return (_open.containsKey(t.getUID()) ? _open.get(t.getUID()) : null);
/*
* for (Tile o : open) { if (o.equals(t)) { return o; } } return null;
*/
}
private boolean isTileWalkable(Tile t)
{
Location l = new Location(_world, (_sx + t.getX()), (_sy + t.getY()), (_sz + t.getZ()));
Block b = l.getBlock();
int i = b.getTypeId();
// lava, fire, wheat and ladders cannot be walked on, and of course air
// 85, 107 and 113 stops npcs climbing fences and fence gates
if (i != 10 && i != 11 && i != 51 && i != 59 && i != 65 && i != 0 && i != 85 && i != 107 && i != 113 && !canBlockBeWalkedThrough(i))
{
// make sure the blocks above are air
if (b.getRelative(0, 1, 0).getTypeId() == 107)
{
// fench gate check, if closed continue
Gate g = new Gate(b.getRelative(0, 1, 0).getData());
return (g.isOpen() ? (b.getRelative(0, 2, 0).getTypeId() == 0) : false);
}
return (canBlockBeWalkedThrough(b.getRelative(0, 1, 0).getTypeId()) && b.getRelative(0, 2, 0).getTypeId() == 0);
}
else
{
return false;
}
}
private boolean isLocationWalkable(Location l)
{
Block b = l.getBlock();
int i = b.getTypeId();
if (i != 10 && i != 11 && i != 51 && i != 59 && i != 65 && i != 0 && !canBlockBeWalkedThrough(i))
{
// make sure the blocks above are air or can be walked through
return (canBlockBeWalkedThrough(b.getRelative(0, 1, 0).getTypeId()) && b.getRelative(0, 2, 0).getTypeId() == 0);
}
else
{
return false;
}
}
private boolean canBlockBeWalkedThrough(int id)
{
return (id == 0 || id == 6 || id == 50 || id == 63 || id == 30 || id == 31 || id == 32 || id == 37 || id == 38 || id == 39 || id == 40 || id == 55 || id == 66 || id == 75 || id == 76 || id == 78);
}
@SuppressWarnings("serial")
public class InvalidPathException extends Exception
{
private final boolean _s, _e;
public InvalidPathException(boolean s, boolean e)
{
_s = s;
_e = e;
}
public String getErrorReason()
{
StringBuilder sb = new StringBuilder();
if (!_s)
{
sb.append("Start Location was air. ");
}
if (!_e)
{
sb.append("End Location was air.");
}
return sb.toString();
}
public boolean isStartNotSolid()
{
return (!_s);
}
public boolean isEndNotSolid()
{
return (!_e);
}
}
}

View File

@ -0,0 +1,23 @@
package mineplex.game.clans.clans.outpost.pathing;
/**
* Not made by meee (NewGarbo)
* https://bukkit.org/threads/lib-a-pathfinding-algorithm.129786/
*/
public enum PathingResult
{
SUCCESS(0),
NO_PATH(-1);
private final int _ec;
PathingResult(int ec)
{
_ec = ec;
}
public int getEndCode()
{
return _ec;
}
}

View File

@ -0,0 +1,183 @@
/*
* By @Adamki11s
*/
package mineplex.game.clans.clans.outpost.pathing;
import org.bukkit.Location;
/**
* Not made by meee (NewGarbo)
* https://bukkit.org/threads/lib-a-pathfinding-algorithm.129786/
*/
public class Tile
{
// as offset from starting point
private final short _x;
private final short _y;
private final short _z;
private double _g = -1;
private double _h = -1;
private Tile _parent = null;
private final String _uid;
public Tile(short x, short y, short z, Tile parent)
{
_x = x;
_y = y;
_z = z;
_parent = parent;
StringBuilder b = new StringBuilder();
b.append(x);
b.append(y);
b.append(z);
_uid = b.toString();
}
public boolean isInRange(int range)
{
return ((range - abs(_x) >= 0) && (range - abs(_y) >= 0) && (range - abs(_z) >= 0));
}
public void setParent(Tile parent)
{
_parent = parent;
}
public Location getLocation(Location start)
{
return new Location(start.getWorld(), start.getBlockX() + _x, start.getBlockY() + _y, start.getBlockZ() + _z);
}
public Tile getParent()
{
return _parent;
}
public short getX()
{
return _x;
}
public int getX(Location i)
{
return (i.getBlockX() + _x);
}
public short getY()
{
return _y;
}
public int getY(Location i)
{
return (i.getBlockY() + _y);
}
public short getZ()
{
return _z;
}
public int getZ(Location i)
{
return (i.getBlockZ() + _z);
}
public String getUID()
{
return _uid;
}
public boolean equals(Tile t)
{
return (t.getX() == _x && t.getY() == _y && t.getZ() == _z);
}
public void calculateBoth(int sx, int sy, int sz, int ex, int ey, int ez, boolean update)
{
calculateG(sx, sy, sz, update);
calculateH(sx, sy, sz, ex, ey, ez, update);
}
public void calculateH(int sx, int sy, int sz, int ex, int ey, int ez, boolean update)
{
// only update if h hasn't been calculated or if forced
if ((!update && _h == -1) || update)
{
int hx = sx + _x, hy = sy + _y, hz = sz + _z;
_h = getEuclideanDistance(hx, hy, hz, ex, ey, ez);
}
}
// G = the movement cost to move from the starting point A to a given square
// on the grid, following the path generated to get there.
public void calculateG(int sx, int sy, int sz, boolean update)
{
if ((!update && _g == -1) || update)
{
// only update if g hasn't been calculated or if forced
Tile currentParent = getParent(), currentTile = this;
int gCost = 0;
// follow path back to start
while ((currentParent = currentTile.getParent()) != null)
{
int dx = currentTile.getX() - currentParent.getX(), dy = currentTile.getY() - currentParent.getY(), dz = currentTile.getZ() - currentParent.getZ();
dx = abs(dx);
dy = abs(dy);
dz = abs(dz);
if (dx == 1 && dy == 1 && dz == 1)
{
gCost += 1.7;
} else if (((dx == 1 || dz == 1) && dy == 1) || ((dx == 1 || dz == 1) && dy == 0))
{
gCost += 1.4;
}
else
{
gCost += 1.0;
}
// move backwards a tile
currentTile = currentParent;
}
_g = gCost;
}
}
public double getG()
{
return _g;
}
public double getH()
{
return _h;
}
public double getF()
{
// f = h + g
return (_h + _g);
}
private double getEuclideanDistance(int sx, int sy, int sz, int ex, int ey, int ez)
{
double dx = sx - ex, dy = sy - ey, dz = sz - ez;
return Math.sqrt((dx * dx) + (dy * dy) + (dz * dz));
}
private int abs(int i)
{
return (i < 0 ? -i : i);
}
}