Skip to content

Instantly share code, notes, and snippets.

@ucchyocean
Last active September 30, 2015 03:13
Show Gist options
  • Save ucchyocean/03ea7e4af90ce7499bff to your computer and use it in GitHub Desktop.
Save ucchyocean/03ea7e4af90ce7499bff to your computer and use it in GitHub Desktop.
木こりプラグインを作ってみた
/**
* きこりプラグイン
* @author ucchy
*/
public class WoodChopper extends JavaPlugin implements Listener {
private static final int MAX_CHECK_NUM = 100;
/**
* プラグインが有効化されたときに呼び出されるメソッド
* @see org.bukkit.plugin.java.JavaPlugin#onEnable()
*/
@Override
public void onEnable() {
// イベントリスナー登録
getServer().getPluginManager().registerEvents(this, this);
}
/**
* ブロックを壊したときに呼び出されるメソッド
* @param event
*/
@EventHandler
public void onBlockBreak(BlockBreakEvent event) {
// ブロックを壊したのがサバイバルモードのプレイヤーで、
// 壊したブロックが原木なら、イベントをキャンセルして再帰処理に突入する。
Block block = event.getBlock();
if ( event.getPlayer().getGameMode() == GameMode.SURVIVAL
&& (block.getType() == Material.LOG || block.getType() == Material.LOG_2) ) {
event.setCancelled(true);
chop(block, true, event.getPlayer().getItemInHand(),
getSpecies(block), new ArrayList<Location>());
}
}
/**
* 対象のブロックが原木・葉かどうかを調べて、原木・葉なら破壊しつつ、
* 周りのブロックにも同様のことを実行する。
* @param block 対象ブロック
* @param woodCheck 原木をチェック対象にするかどうか
* @param tool この原木ブロックをきこるツール
* @param data きこる木の種類
* @param checkList 再帰処理探索済みのLocationのチェックリスト
*/
private void chop(Block block, boolean woodCheck,
final ItemStack tool, final TreeSpecies data, final List<Location> checkList) {
final Material material = block.getType();
// 対象ではないブロックの種類なら、何もしない。
if ( woodCheck ) {
if ( !isLog(material) && !isLeaves(material) ) {
return;
}
} else {
if ( !isLeaves(material) ) {
return;
}
}
// 既にチェック済みなら、何もしない。
if ( checkList.contains(block.getLocation()) ) {
return;
}
// チェック済みの地点として記録
checkList.add(block.getLocation());
final TreeSpecies species = getSpecies(block);
// 違う種類の木なら、何もしない。
if ( species != data ) {
return;
}
// チェック最大値を超えているなら、何もしない。
if ( checkList.size() > MAX_CHECK_NUM ) {
return;
}
// 対象のブロックを破壊する
block.breakNaturally(tool);
// 1tick遅延させてから、周りのブロックにも実行する(再帰処理)
new BukkitRunnable() {
public void run() {
boolean woodCheck = isLog(material);
chop(block.getRelative(BlockFace.NORTH), woodCheck, tool, data, checkList);
chop(block.getRelative(BlockFace.EAST), woodCheck, tool, data, checkList);
chop(block.getRelative(BlockFace.SOUTH), woodCheck, tool, data, checkList);
chop(block.getRelative(BlockFace.WEST), woodCheck, tool, data, checkList);
chop(block.getRelative(BlockFace.UP), woodCheck, tool, data, checkList);
// アカシア木なら、さらに斜め上も確認する
if ( species == TreeSpecies.ACACIA && isLog(material) ) {
Block up = block.getRelative(BlockFace.UP);
chop(up.getRelative(BlockFace.NORTH), woodCheck, tool, data, checkList);
chop(up.getRelative(BlockFace.NORTH_EAST), woodCheck, tool, data, checkList);
chop(up.getRelative(BlockFace.EAST), woodCheck, tool, data, checkList);
chop(up.getRelative(BlockFace.SOUTH_EAST), woodCheck, tool, data, checkList);
chop(up.getRelative(BlockFace.SOUTH), woodCheck, tool, data, checkList);
chop(up.getRelative(BlockFace.SOUTH_WEST), woodCheck, tool, data, checkList);
chop(up.getRelative(BlockFace.WEST), woodCheck, tool, data, checkList);
chop(up.getRelative(BlockFace.NORTH_WEST), woodCheck, tool, data, checkList);
}
}
}.runTaskLater(this, 1);
}
/**
* 対象のブロックが原木かどうかを調べる
* @param block ブロック
* @return 原木かどうか
*/
private boolean isLog(Material material) {
return material == Material.LOG || material == Material.LOG_2;
}
/**
* 対象のブロックが葉ブロックかどうかを調べる
* @param block ブロック
* @return 葉ブロックかどうか
*/
private boolean isLeaves(Material material) {
return material == Material.LEAVES || material == Material.LEAVES_2;
}
/**
* ブロックの木の種類を返す
* @param block ブロック
* @return 木の種類
*/
@SuppressWarnings("deprecation")
private TreeSpecies getSpecies(Block block) {
if ( block.getType() == Material.LOG_2 || block.getType() == Material.LEAVES_2 ) return TreeSpecies.ACACIA;
return TreeSpecies.getByData((byte) (block.getState().getData().getData() & 3));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment