Package org.mctourney.autoreferee.util

Source Code of org.mctourney.autoreferee.util.TeleportationUtil

package org.mctourney.autoreferee.util;

import java.util.Set;
import java.lang.Math;

import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.Material;
import org.bukkit.Location;
import org.bukkit.util.Vector;

import com.google.common.collect.Sets;

import org.mctourney.autoreferee.AutoRefPlayer;

public class TeleportationUtil
{
  private TeleportationUtil()
  {  }

  public static Location locationTeleport(Location loc)
  {
    if (loc == null) return null;

    Location x, c = loc.clone(), best = c;
    double sqd, bsqd = -1.0;

    for (Vector vec : directions)
    {
      x = TeleportationUtil.checkDirection(c, vec);
      sqd = x.distanceSquared(best);
      if (sqd > bsqd) { bsqd = sqd; best = x; }
    }

    // return a location that is looking at the target
    Location dest = locationLookingAt(best, loc);
    return dest.distance(loc) < 1.0 ? null : dest;
  }

  public static Location blockTeleport(Block b)
  { return blockTeleport(b.getLocation()); }

  public static Location blockTeleport(Location loc)
  { return locationTeleport(loc.clone().add(0.5, 0.5, 0.5)); }

  public static Location entityTeleport(Entity e)
  {
    Location loc = e.getLocation().clone();
    if (e instanceof LivingEntity)
    {
      LivingEntity live = (LivingEntity) e;
      loc.add(0, live.getEyeHeight(), 0);
    }
    return locationTeleport(loc);
  }

  public static Location playerTeleport(AutoRefPlayer apl)
  {
    if (apl == null) return null;
    if (apl.isOnline()) return entityTeleport(apl.getPlayer());

    Location loc = apl.getLocation().clone();
    return locationTeleport(loc);
  }

  private static Location locationLookingAt(Location base, Location target)
  {
    if (base == null || target == null) return base;

    double dx = base.getX() - target.getX(),
           dy = base.getY() - target.getY(),
           dz = base.getZ() - target.getZ();

    double dist = Math.sqrt(dx*dx + dz*dz);

    Location res = base.clone();
    res.setPitch((float)(Math.atan2(dy, dist)*180/Math.PI));
    res.setYaw((float)(Math.atan2(dz, dx)*180/Math.PI) + 90.0f);

    return res;
  }

  private static Set<Material> passableBlocks = Sets.newHashSet
  Material.AIR
  ,  Material.DEAD_BUSH
  ,  Material.DIODE_BLOCK_ON
  ,  Material.DIODE_BLOCK_OFF
  ,  Material.LADDER
  ,  Material.LEVER
  ,  Material.LONG_GRASS
  ,  Material.MELON_STEM
  ,  Material.NETHER_STALK
  ,  Material.NETHER_WARTS
  ,  Material.POWERED_RAIL
  ,  Material.PUMPKIN_STEM
  ,  Material.RAILS
  ,  Material.RED_ROSE
  ,  Material.REDSTONE_TORCH_ON
  ,  Material.REDSTONE_TORCH_OFF
  ,  Material.REDSTONE_WIRE
  ,  Material.SAPLING
  ,  Material.SIGN
  ,  Material.SIGN_POST
  ,  Material.SNOW
  ,  Material.STATIONARY_WATER
  ,  Material.STONE_BUTTON
  ,  Material.STONE_PLATE
  ,  Material.TORCH
  ,  Material.TRIPWIRE
  ,  Material.TRIPWIRE_HOOK
  ,  Material.VINE
  ,  Material.WALL_SIGN
  ,  Material.WATER
  ,  Material.WATER_LILY
  ,  Material.WOOD_PLATE
  ,  Material.YELLOW_FLOWER
  );

  public static boolean isBlockPassable(Block b)
  { return passableBlocks.contains(b.getType()); }

  public static boolean safeLocation(Location loc)
  { return isBlockPassable(loc.getBlock()) &&
    isBlockPassable(loc.getBlock().getRelative(0, 1, 0)); }

  private static final int MAX_TELEPORT_DISTANCE = 4;
  private static Location checkDirection(Location loc, Vector v)
  {
    v = v.normalize();
    int d = -1;

    // furthest we can stray in one direction
    // based on the rows preceeding
    int m = MAX_TELEPORT_DISTANCE;

    Location best = loc.clone();
    for (int h = 0; h <= MAX_TELEPORT_DISTANCE && m > h; ++h)
    {
      // attempt up to M blocks away from the center
      Location c = loc.clone().add(0, h, 0);
      int k; for (k = 1; k <= m; ++k)
      {
        // the next location we are checking
        Location nc = c.add(v);

        // if this block is impassable, dec k before quitting
        if (!isBlockPassable(nc.getBlock())) { --k; break; }

        // update c if the block is passable
        else c = nc;
      }

      // we only got to row k, don't exceed this in future passes
      if (k < m) m = k;

      // if this is farther away than any previously, save it
      // only allow locations below a grade of 45deg
      if (h > 0 && k >= h && k + h > d) { d = k + h; best = c; }
    }

    return best;
  }

  private static Set<Vector> directions = Sets.newHashSet
  new Vector( 001)
  new Vector( 00, -1)
  new Vector( 100)
  new Vector(-100)
  );
}
TOP

Related Classes of org.mctourney.autoreferee.util.TeleportationUtil

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.