Created
September 26, 2012 15:09
-
-
Save aadnk/3788593 to your computer and use it in GitHub Desktop.
A way of enabling block breaking from far away
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.comphenix.example; | |
import java.util.HashMap; | |
import java.util.Map; | |
import net.minecraft.server.Packet55BlockBreakAnimation; | |
import org.bukkit.Server; | |
import org.bukkit.block.Block; | |
import org.bukkit.craftbukkit.CraftServer; | |
import org.bukkit.craftbukkit.CraftWorld; | |
import org.bukkit.entity.Player; | |
import org.bukkit.event.EventHandler; | |
import org.bukkit.event.EventPriority; | |
import org.bukkit.event.Listener; | |
import org.bukkit.event.block.Action; | |
import org.bukkit.event.player.PlayerInteractEvent; | |
import org.bukkit.plugin.Plugin; | |
import org.bukkit.scheduler.BukkitScheduler; | |
public class ExampleListener implements Listener { | |
private final static int PLAYER_REACH = 60; | |
private final static int MINIMUM_DISTANCE = 4; | |
// Number of ticks it takes to break a block | |
private final static int BREAK_TIME = 40; | |
private Map<String, TaskedRunnable> playerClicking = new HashMap<String, TaskedRunnable>(); | |
private Plugin plugin; | |
private Server server; | |
private BukkitScheduler scheduler; | |
public ExampleListener(Plugin plugin) { | |
this.plugin = plugin; | |
this.server = plugin.getServer(); | |
this.scheduler = server.getScheduler(); | |
} | |
@EventHandler(priority = EventPriority.NORMAL) | |
public void onPlayerInteractEvent(PlayerInteractEvent event) { | |
Player player = event.getPlayer(); | |
int dimension = ((CraftWorld) player.getWorld()).getHandle().dimension; | |
int breakTime = BREAK_TIME; | |
if (event.getAction() == Action.LEFT_CLICK_AIR || event.getAction() == Action.LEFT_CLICK_BLOCK) { | |
// Cancel previous actions | |
TaskedRunnable previous = playerClicking.get(player.getName()); | |
if (previous != null) { | |
previous.cancel(); | |
} | |
Block block = player.getTargetBlock(null, PLAYER_REACH); | |
// No need if we're within the default distance | |
if (block.getLocation().distance(player.getLocation()) >= MINIMUM_DISTANCE) { | |
TaskedRunnable tasked = new TaskedRunnable(player, block, dimension, breakTime); | |
int taskID = scheduler.scheduleSyncRepeatingTask(plugin, tasked, 1L, 1L); | |
// Save the task ID | |
tasked.setTaskID(taskID); | |
playerClicking.put(player.getName(), tasked); | |
} | |
} | |
} | |
private class TaskedRunnable implements Runnable { | |
private static final int BLOCK_BREAK_MAX = 11; | |
private int counter = 0; | |
private int taskID; | |
private Player player; | |
private Block block; | |
private int breakTime; | |
private int dimension; | |
private int lastDamage = -1; | |
public TaskedRunnable(Player player, Block block, int dimension, int breakTime) { | |
this.player = player; | |
this.block = block; | |
this.dimension = dimension; | |
this.breakTime = breakTime; | |
} | |
public void setTaskID(int taskID) { | |
this.taskID = taskID; | |
} | |
@Override | |
public void run() { | |
double progress = counter / (double)breakTime; | |
int damage = (int) (progress * BLOCK_BREAK_MAX); | |
// No need to send the same damage | |
if (damage != lastDamage) { | |
Block newTarget = player.getTargetBlock(null, PLAYER_REACH); | |
// Make sure we're looking at the same block | |
if (newTarget == null || !block.getLocation().equals(newTarget.getLocation())) { | |
cancel(); | |
return; | |
} | |
sendBlockBreak(damage); | |
lastDamage = damage; | |
} | |
counter++; | |
System.out.println(String.format("Counter: %s Damage: %s", counter, damage)); | |
if (counter >= breakTime) { | |
block.breakNaturally(); | |
scheduler.cancelTask(taskID); | |
} | |
} | |
private void sendBlockBreak(int damage) { | |
Packet55BlockBreakAnimation breakBlockPacket = new Packet55BlockBreakAnimation( | |
0, //player.getEntityId() | |
block.getX(), block.getY(), block.getZ(), | |
damage); | |
((CraftServer) server).getHandle().sendPacketNearby( | |
block.getX(), block.getY(), block.getZ(), | |
PLAYER_REACH * 2, dimension, breakBlockPacket); | |
} | |
public void cancel() { | |
playerClicking.remove(player.getName()); | |
scheduler.cancelTask(taskID); | |
// Reset block | |
sendBlockBreak(10); | |
System.out.println("Cancelled"); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment