com.supaham.commons.bukkit.PlayerTeleportFix.java Source code

Java tutorial

Introduction

Here is the source code for com.supaham.commons.bukkit.PlayerTeleportFix.java

Source

// Released under the BSD License.
// Kristian S. Stangeland 2013.
package com.supaham.commons.bukkit;

import com.google.common.base.Preconditions;

import com.supaham.commons.bukkit.players.Players;
import com.supaham.commons.bukkit.players.Players.PlayersSupplierFor;

import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitRunnable;

import java.util.Collection;

import javax.annotation.Nonnull;

/**
 * This class fixes player entity mispositioning, whether it be a block off, or completely
 * invisible, by hiding the entity from the online players and back again.
 *
 * @see #PlayerTeleportFix(Plugin)
 * @see #PlayerTeleportFix(Plugin, long)
 * @see #PlayerTeleportFix(Plugin, PlayersSupplierFor)
 * @see #PlayerTeleportFix(Plugin, long, PlayersSupplierFor)
 * @since 0.2
 */
public class PlayerTeleportFix implements Listener {

    public static final long DEFAULT_TASK_DELAY = 10;
    private final Plugin plugin;
    private final long taskDelay;
    private final PlayersSupplierFor<Player> supplier;

    private boolean enabled;

    private static PlayersSupplierFor<Player> getPlayerTrackingRange(Plugin plugin) {
        Preconditions.checkNotNull(plugin, "plugin cannot be null.");
        final Server server = plugin.getServer();
        // TODO support spigot
        final double radius = server.getViewDistance() * 16;

        // The following is a playersByRadius wrapper that passes the given player's location
        return new PlayersSupplierFor<Player>() {
            PlayersSupplierFor<Location> delegate = Players.playersByRadius(null, radius);

            @Override
            public Collection<Player> get(Player player) {
                return delegate.get(player.getLocation());
            }
        };
    }

    /**
     * Constructs a new instance with the given {@link Plugin} and {@link #DEFAULT_TASK_DELAY} as the
     * task delay.
     *
     * @param plugin plugin to own this instance
     *
     * @see #PlayerTeleportFix(Plugin, long)
     */
    public PlayerTeleportFix(@Nonnull Plugin plugin) {
        this(plugin, DEFAULT_TASK_DELAY);
    }

    /**
     * Constructs a new instance with the given {@link Plugin} and task delay.
     *
     * @param plugin plugin to own this instance
     * @param taskDelay delay of the fix AFTER a player teleports
     *
     * @see #PlayerTeleportFix(Plugin, long, PlayersSupplierFor)
     */
    public PlayerTeleportFix(@Nonnull Plugin plugin, long taskDelay) {
        this(plugin, taskDelay, getPlayerTrackingRange(plugin));
    }

    /**
     * Constructs a new instance with the given {@link Plugin} and {@link PlayersSupplierFor}, and
     * {@link #DEFAULT_TASK_DELAY} as the task delay.
     *
     * @param plugin plugin to own this instance
     * @param supplier players supplier
     *
     * @see #PlayerTeleportFix(Plugin, long, PlayersSupplierFor)
     */
    public PlayerTeleportFix(@Nonnull Plugin plugin, @Nonnull PlayersSupplierFor<Player> supplier) {
        this(plugin, DEFAULT_TASK_DELAY, supplier);
    }

    /**
     * Constructs a new instance with the given {@link Plugin}, task delay, and
     * {@link PlayersSupplierFor}.
     *
     * @param plugin plugin to own this instance
     * @param taskDelay delay of the fix AFTER a player teleports
     * @param supplier players supplier
     */
    public PlayerTeleportFix(@Nonnull Plugin plugin, long taskDelay, @Nonnull PlayersSupplierFor<Player> supplier) {
        Preconditions.checkNotNull(plugin, "plugin cannot be null.");
        Preconditions.checkNotNull(supplier, "supplier cannot be null.");
        this.plugin = plugin;
        this.taskDelay = taskDelay;
        this.supplier = supplier;
    }

    @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
    protected void onPlayerTeleport(PlayerTeleportEvent event) {
        if (!isEnabled() || event.getFrom().equals(event.getPlayer().getLocation())) {
            return;
        }
        final Player player = event.getPlayer();
        new BukkitRunnable() {
            @Override
            public void run() {
                final Collection<? extends Player> players = supplier.get(player);
                updateEntities(player, players, false); // hide all
                new BukkitRunnable() {
                    @Override
                    public void run() {
                        updateEntities(player, players, true); // show all
                    }
                }.runTaskLater(plugin, 1);
            }
        }.runTaskLater(plugin, taskDelay);
    }

    private void updateEntities(Player observer, Collection<? extends Player> players, boolean visible) {
        // Hide every player
        for (Player player : players) {
            if (observer.getEntityId() != player.getEntityId()) {
                if (visible) {
                    observer.showPlayer(player);
                    player.showPlayer(observer);
                } else {
                    observer.hidePlayer(player);
                    player.hidePlayer(observer);
                }
            }
        }
    }

    public Plugin getPlugin() {
        return plugin;
    }

    public PlayersSupplierFor<Player> getSupplier() {
        return supplier;
    }

    public long getTaskDelay() {
        return taskDelay;
    }

    public boolean isEnabled() {
        return enabled;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }
}