feat(hamster-chain-break): 连锁破坏插件
This commit is contained in:
2
hamster-chain-break/build.gradle
Normal file
2
hamster-chain-break/build.gradle
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
version = '1.0.0'
|
||||||
|
setArchivesBaseName("HamsterChainBreak")
|
@@ -0,0 +1,26 @@
|
|||||||
|
package cn.hamster3.mc.plugin.chain.breaks;
|
||||||
|
|
||||||
|
import cn.hamster3.mc.plugin.chain.breaks.core.ConfigManager;
|
||||||
|
import cn.hamster3.mc.plugin.chain.breaks.listener.MainListener;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
|
public class ChainBreakPlugin extends JavaPlugin {
|
||||||
|
private static ChainBreakPlugin instance;
|
||||||
|
|
||||||
|
public static ChainBreakPlugin getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoad() {
|
||||||
|
instance = this;
|
||||||
|
ConfigManager.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEnable() {
|
||||||
|
Bukkit.getPluginManager().registerEvents(MainListener.INSTANCE, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,22 @@
|
|||||||
|
package cn.hamster3.mc.plugin.chain.breaks.config;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class ToolGroup {
|
||||||
|
private final String name;
|
||||||
|
private final List<String> toolTypes;
|
||||||
|
private final List<String> blockTypes;
|
||||||
|
private final List<String> skipBlockTypes;
|
||||||
|
|
||||||
|
public ToolGroup(@NotNull ConfigurationSection config) {
|
||||||
|
name = config.getName();
|
||||||
|
toolTypes = config.getStringList("tool-types");
|
||||||
|
blockTypes = config.getStringList("block-types");
|
||||||
|
skipBlockTypes = config.getStringList("skip-block-types");
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,34 @@
|
|||||||
|
package cn.hamster3.mc.plugin.chain.breaks.core;
|
||||||
|
|
||||||
|
import cn.hamster3.mc.plugin.chain.breaks.ChainBreakPlugin;
|
||||||
|
import cn.hamster3.mc.plugin.chain.breaks.config.ToolGroup;
|
||||||
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public final class ConfigManager {
|
||||||
|
private static List<ToolGroup> toolGroups;
|
||||||
|
|
||||||
|
private ConfigManager() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void init() {
|
||||||
|
ChainBreakPlugin plugin = ChainBreakPlugin.getInstance();
|
||||||
|
plugin.saveDefaultConfig();
|
||||||
|
plugin.reloadConfig();
|
||||||
|
FileConfiguration pluginConfig = plugin.getConfig();
|
||||||
|
|
||||||
|
toolGroups = new ArrayList<>();
|
||||||
|
ConfigurationSection toolGroupsConfig = pluginConfig.getConfigurationSection("tool-groups");
|
||||||
|
for (String key : toolGroupsConfig.getKeys(false)) {
|
||||||
|
ToolGroup group = new ToolGroup(toolGroupsConfig.getConfigurationSection(key));
|
||||||
|
toolGroups.add(group);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<ToolGroup> getToolGroups() {
|
||||||
|
return toolGroups;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,106 @@
|
|||||||
|
package cn.hamster3.mc.plugin.chain.breaks.listener;
|
||||||
|
|
||||||
|
import cn.hamster3.mc.plugin.chain.breaks.config.ToolGroup;
|
||||||
|
import cn.hamster3.mc.plugin.chain.breaks.util.ChainBreakUtils;
|
||||||
|
import org.bukkit.GameMode;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.Sound;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.BlockFace;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.block.BlockBreakEvent;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public final class MainListener implements Listener {
|
||||||
|
public static final MainListener INSTANCE = new MainListener();
|
||||||
|
private static final BlockFace[] BLOCK_FACES = new BlockFace[]{
|
||||||
|
BlockFace.NORTH,
|
||||||
|
BlockFace.EAST,
|
||||||
|
BlockFace.SOUTH,
|
||||||
|
BlockFace.WEST,
|
||||||
|
BlockFace.UP,
|
||||||
|
BlockFace.DOWN
|
||||||
|
};
|
||||||
|
|
||||||
|
private MainListener() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(ignoreCancelled = true)
|
||||||
|
public void onBlockBreak(BlockBreakEvent event) {
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
if (player.isSneaking()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ItemStack stack = player.getInventory().getItemInMainHand();
|
||||||
|
ToolGroup group = ChainBreakUtils.getToolGroup(stack);
|
||||||
|
if (group == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!ChainBreakUtils.isToolGroupBlock(group, event.getBlock())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<Block> resultBlocks = new ArrayList<>();
|
||||||
|
bfsSearchBlock(group, resultBlocks, Collections.singletonList(event.getBlock()));
|
||||||
|
resultBlocks.remove(event.getBlock());
|
||||||
|
if (resultBlocks.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (player.getGameMode() == GameMode.CREATIVE) {
|
||||||
|
for (Block block : resultBlocks) {
|
||||||
|
block.breakNaturally(stack);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
short maxDurability = stack.getType().getMaxDurability();
|
||||||
|
short durability = stack.getDurability();
|
||||||
|
for (Block block : resultBlocks) {
|
||||||
|
if (block.breakNaturally(stack)) {
|
||||||
|
durability++;
|
||||||
|
if (durability >= maxDurability) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (durability >= maxDurability) {
|
||||||
|
player.getInventory().setItemInMainHand(null);
|
||||||
|
player.getWorld().playSound(player.getLocation(), Sound.ENTITY_ITEM_BREAK, 1, 1);
|
||||||
|
} else {
|
||||||
|
stack.setDurability(durability);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void bfsSearchBlock(@NotNull ToolGroup group, @NotNull List<Block> result, @NotNull List<Block> searchBlocks) {
|
||||||
|
ArrayList<Block> nextSearchBlocks = new ArrayList<>();
|
||||||
|
for (Block block : searchBlocks) {
|
||||||
|
for (BlockFace face : BLOCK_FACES) {
|
||||||
|
Block relative = block.getRelative(face);
|
||||||
|
if (relative.getType() == Material.AIR) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (result.contains(relative)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!ChainBreakUtils.isToolGroupBlock(group, relative)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
result.add(relative);
|
||||||
|
nextSearchBlocks.add(relative);
|
||||||
|
if (result.size() > 300) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nextSearchBlocks.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bfsSearchBlock(group, result, nextSearchBlocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,38 @@
|
|||||||
|
package cn.hamster3.mc.plugin.chain.breaks.util;
|
||||||
|
|
||||||
|
import cn.hamster3.mc.plugin.chain.breaks.config.ToolGroup;
|
||||||
|
import cn.hamster3.mc.plugin.chain.breaks.core.ConfigManager;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
public class ChainBreakUtils {
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static ToolGroup getToolGroup(@Nullable ItemStack stack) {
|
||||||
|
if (stack == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String name = stack.getType().name().toLowerCase();
|
||||||
|
for (ToolGroup group : ConfigManager.getToolGroups()) {
|
||||||
|
for (String type : group.getToolTypes()) {
|
||||||
|
if (name.matches(type)) {
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||||
|
public static boolean isToolGroupBlock(@NotNull ToolGroup group, @NotNull Block block) {
|
||||||
|
String name = block.getType().name().toLowerCase();
|
||||||
|
for (String type : group.getBlockTypes()) {
|
||||||
|
if (name.matches(type)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
17
hamster-chain-break/src/main/resources/config.yml
Normal file
17
hamster-chain-break/src/main/resources/config.yml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# 方块破坏的间隔时间
|
||||||
|
# 单位: tick
|
||||||
|
break-interval: 5
|
||||||
|
|
||||||
|
tool-groups:
|
||||||
|
axe:
|
||||||
|
tool-types:
|
||||||
|
- ".*_axe"
|
||||||
|
block-types:
|
||||||
|
- ".*_wood"
|
||||||
|
- ".*_log"
|
||||||
|
- ".*_leaves"
|
||||||
|
pickaxe:
|
||||||
|
tool-types:
|
||||||
|
- ".*_pickaxe"
|
||||||
|
block-types:
|
||||||
|
- ".*_ore"
|
8
hamster-chain-break/src/main/resources/plugin.yml
Normal file
8
hamster-chain-break/src/main/resources/plugin.yml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
name: HamsterChainBreak
|
||||||
|
main: cn.hamster3.mc.plugin.chain.breaks.ChainBreakPlugin
|
||||||
|
version: ${version}
|
||||||
|
api-version: 1.13
|
||||||
|
|
||||||
|
author: MiniDay
|
||||||
|
website: https://github.com/MiniDay/hamster-little-plugins
|
||||||
|
description: 仓鼠连锁破坏:一键挖矿 & 砍树
|
Reference in New Issue
Block a user