feat: Vein Miner configuration now supports block tags and block highlight colors.
This commit is contained in:
parent
32dbebb228
commit
a464a8f77f
|
|
@ -15,12 +15,14 @@ object Config {
|
|||
var componentTickInterval: Long = 1L
|
||||
|
||||
// Vein Miner
|
||||
data class ToolCategory(val toolPattern: String, val allowedBlockPatterns: List<String>)
|
||||
data class ToolCategory(val tool: String, val blocks: List<String>)
|
||||
var veinMinerMaxBlocks: Int = 64
|
||||
var veinMinerActivationMode: String = "SNEAK" // "SNEAK", "ALWAYS", "STAND"
|
||||
val veinMinerCompatibleMaterials: MutableMap<org.bukkit.Material, Set<org.bukkit.Material>> = mutableMapOf()
|
||||
val veinMinerBlockColors: MutableMap<org.bukkit.Material, org.bukkit.Color> = mutableMapOf()
|
||||
val veinMinerToolCategories: MutableList<ToolCategory> = mutableListOf()
|
||||
|
||||
|
||||
fun load(plugin: JavaPlugin) {
|
||||
plugin.reloadConfig()
|
||||
val config = plugin.config
|
||||
|
|
@ -47,6 +49,7 @@ object Config {
|
|||
|
||||
veinMinerActivationMode = config.getString("components.vein_miner.activation_mode", "SNEAK") ?: "SNEAK"
|
||||
loadCompatibleGroups(config)
|
||||
loadBlockColors(config)
|
||||
loadToolCategories(config)
|
||||
|
||||
// Save back to ensure defaults are written if missing
|
||||
|
|
@ -75,15 +78,32 @@ object Config {
|
|||
val groups = config.getList("components.vein_miner.compatible_groups") as? List<*> ?: return
|
||||
|
||||
for (groupObj in groups) {
|
||||
val group = groupObj as? List<*> ?: continue
|
||||
val materials = group.mapNotNull {
|
||||
val name = (it as? String) ?: return@mapNotNull null
|
||||
try {
|
||||
org.bukkit.Material.valueOf(name.uppercase().removePrefix("MINECRAFT:"))
|
||||
} catch (e: IllegalArgumentException) {
|
||||
null
|
||||
val group = when (groupObj) {
|
||||
is List<*> -> groupObj
|
||||
is String -> listOf(groupObj)
|
||||
else -> continue
|
||||
}
|
||||
|
||||
val materials = mutableSetOf<org.bukkit.Material>()
|
||||
|
||||
for (it in group) {
|
||||
val name = (it as? String) ?: continue
|
||||
if (name.startsWith("#")) {
|
||||
val key = org.bukkit.NamespacedKey.fromString(name.substring(1))
|
||||
if (key != null) {
|
||||
val tag = org.bukkit.Bukkit.getTag(org.bukkit.Tag.REGISTRY_BLOCKS, key, org.bukkit.Material::class.java)
|
||||
if (tag != null) {
|
||||
materials.addAll(tag.values)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
materials.add(org.bukkit.Material.valueOf(name.uppercase().removePrefix("MINECRAFT:")))
|
||||
} catch (e: IllegalArgumentException) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}.toSet()
|
||||
}
|
||||
|
||||
for (mat in materials) {
|
||||
val existing = veinMinerCompatibleMaterials.getOrDefault(mat, emptySet())
|
||||
|
|
@ -97,9 +117,49 @@ object Config {
|
|||
val list = config.getMapList("components.vein_miner.tool_categories")
|
||||
|
||||
for (map in list) {
|
||||
val toolPattern = map["tool_pattern"] as? String ?: continue
|
||||
val allowedBlocks = (map["allowed_blocks"] as? List<*>)?.filterIsInstance<String>() ?: continue
|
||||
veinMinerToolCategories.add(ToolCategory(toolPattern, allowedBlocks))
|
||||
val tool = map["tool"] as? String ?: continue
|
||||
val blocks = (map["active_blocks"] as? List<*>)?.filterIsInstance<String>() ?: continue
|
||||
veinMinerToolCategories.add(ToolCategory(tool, blocks))
|
||||
}
|
||||
}
|
||||
private fun loadBlockColors(config: FileConfiguration) {
|
||||
veinMinerBlockColors.clear()
|
||||
val section = config.getConfigurationSection("components.vein_miner.block_colors") ?: return
|
||||
|
||||
for (keyStr in section.getKeys(false)) {
|
||||
val hexOrRgb = section.getString(keyStr) ?: continue
|
||||
val color = try {
|
||||
if (hexOrRgb.contains(",")) {
|
||||
val parts = hexOrRgb.split(",").map { it.trim().toInt() }
|
||||
if (parts.size == 3) org.bukkit.Color.fromRGB(parts[0], parts[1], parts[2]) else null
|
||||
} else {
|
||||
val hex = hexOrRgb.removePrefix("#")
|
||||
org.bukkit.Color.fromRGB(hex.toInt(16))
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
|
||||
if (color == null) continue
|
||||
|
||||
if (keyStr.startsWith("#")) {
|
||||
val key = org.bukkit.NamespacedKey.fromString(keyStr.substring(1))
|
||||
if (key != null) {
|
||||
val tag = org.bukkit.Bukkit.getTag(org.bukkit.Tag.REGISTRY_BLOCKS, key, org.bukkit.Material::class.java)
|
||||
if (tag != null) {
|
||||
for (mat in tag.values) {
|
||||
veinMinerBlockColors[mat] = color
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
val mat = org.bukkit.Material.valueOf(keyStr.uppercase().removePrefix("MINECRAFT:"))
|
||||
veinMinerBlockColors[mat] = color
|
||||
} catch (e: IllegalArgumentException) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import org.bukkit.NamespacedKey
|
|||
import org.bukkit.block.Block
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.event.block.BlockBreakEvent
|
||||
import org.bukkit.event.player.PlayerItemDamageEvent
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import org.bukkit.persistence.PersistentDataType
|
||||
import org.bukkit.plugin.java.JavaPlugin
|
||||
|
|
@ -17,6 +18,9 @@ import org.bukkit.entity.ExperienceOrb
|
|||
import org.bukkit.entity.BlockDisplay
|
||||
import org.bukkit.entity.Display
|
||||
import org.bukkit.util.Transformation
|
||||
import org.bukkit.map.MapPalette
|
||||
import org.bukkit.GameMode
|
||||
import org.bukkit.Tag
|
||||
import org.joml.Vector3f
|
||||
import org.bukkit.Color
|
||||
import org.bukkit.Bukkit
|
||||
|
|
@ -102,7 +106,6 @@ class VeinMinerComponent(private val plugin: JavaPlugin) : ToolComponent {
|
|||
// クライアントのパフォーマンスを考慮し、最大ハイライト数を制限しても良いが、
|
||||
// ユーザー要望通り全てハイライトする
|
||||
if (!supportsBlockDisplay) return
|
||||
|
||||
for (block in blocksToBreak) {
|
||||
val loc = block.location.add(0.5, 0.5, 0.5)
|
||||
try {
|
||||
|
|
@ -111,13 +114,13 @@ class VeinMinerComponent(private val plugin: JavaPlugin) : ToolComponent {
|
|||
e.block = block.blockData
|
||||
// 少し大きくして元のブロックを覆う
|
||||
e.transformation = Transformation(
|
||||
Vector3f(0f, 0f, 0f),
|
||||
org.joml.AxisAngle4f(0f, 0f, 0f, 0f),
|
||||
Vector3f(1.01f, 1.01f, 1.01f),
|
||||
org.joml.AxisAngle4f(0f, 0f, 0f, 0f)
|
||||
Vector3f(-0.5005f, -0.5005f, -0.5005f),
|
||||
org.joml.AxisAngle4f(0f, 0f, 0f, 1f),
|
||||
Vector3f(1.001f, 1.001f, 1.001f),
|
||||
org.joml.AxisAngle4f(0f, 0f, 0f, 1f)
|
||||
)
|
||||
e.isGlowing = true
|
||||
e.glowColorOverride = Color.AQUA // 鮮やかな色
|
||||
e.glowColorOverride = Config.veinMinerBlockColors[block.type] ?: block.blockData.getMapColor()
|
||||
e.brightness = Display.Brightness(15, 15) // 最大輝度
|
||||
e.isVisibleByDefault = false
|
||||
}
|
||||
|
|
@ -128,6 +131,7 @@ class VeinMinerComponent(private val plugin: JavaPlugin) : ToolComponent {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
activeHighlights[player.uniqueId] = HighlightSession(targetBlock, entities, System.currentTimeMillis())
|
||||
}
|
||||
|
||||
|
|
@ -162,44 +166,16 @@ class VeinMinerComponent(private val plugin: JavaPlugin) : ToolComponent {
|
|||
|
||||
val dropLocation = block.location.add(0.5, 0.5, 0.5)
|
||||
val hasSilkTouch = item.containsEnchantment(Enchantment.SILK_TOUCH)
|
||||
|
||||
var soundPlayed = false
|
||||
val isDropItems = player.gameMode != GameMode.CREATIVE && player.gameMode != GameMode.SPECTATOR
|
||||
|
||||
for (target in blocksToBreak) {
|
||||
if (target == block) continue // 起点ブロックはイベントフローで破壊される
|
||||
|
||||
// 保護プラグインチェック (擬似イベント)
|
||||
val checkEvent = BlockBreakEvent(target, player)
|
||||
Bukkit.getPluginManager().callEvent(checkEvent)
|
||||
if (checkEvent.isCancelled) continue
|
||||
|
||||
// 演出 (最初の1回だけ、または確率で)
|
||||
if (!soundPlayed) {
|
||||
target.world.playSound(target.location, target.blockSoundGroup.breakSound, 1f, 1f)
|
||||
target.world.spawnParticle(org.bukkit.Particle.BLOCK, target.location.add(0.5,0.5,0.5), 10, 0.3, 0.3, 0.3, target.blockData)
|
||||
soundPlayed = true
|
||||
if (isDropItems){
|
||||
target.breakNaturally(item, true, true, true)
|
||||
player.damageItemStack(item, 1)
|
||||
}
|
||||
|
||||
// ドロップ処理
|
||||
val drops = target.getDrops(item)
|
||||
for (drop in drops) {
|
||||
target.world.dropItem(dropLocation, drop)
|
||||
}
|
||||
|
||||
// 経験値
|
||||
if (!hasSilkTouch) {
|
||||
val xp = getExpFromBlock(target.type)
|
||||
if (xp > 0) {
|
||||
val orb = target.world.spawn(dropLocation, ExperienceOrb::class.java)
|
||||
orb.experience = xp
|
||||
}
|
||||
}
|
||||
|
||||
// ブロック消去
|
||||
target.type = Material.AIR
|
||||
|
||||
// 耐久消費
|
||||
damageItem(player, item)
|
||||
else target.type = Material.AIR
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -264,46 +240,40 @@ class VeinMinerComponent(private val plugin: JavaPlugin) : ToolComponent {
|
|||
private fun isValidTarget(block: Block, item: ItemStack): Boolean {
|
||||
if (block.getDrops(item).isEmpty()) return false
|
||||
|
||||
val itemName = item.type.key.toString()
|
||||
val blockName = block.type.key.toString()
|
||||
|
||||
var isAllowed = false
|
||||
for (category in Config.veinMinerToolCategories) {
|
||||
if (itemName.contains(category.toolPattern)) {
|
||||
for (pattern in category.allowedBlockPatterns) {
|
||||
if (blockName.contains(pattern)) {
|
||||
isAllowed = true
|
||||
break
|
||||
if (matchesTool(item, category.tool)) {
|
||||
for (blockPattern in category.blocks) {
|
||||
if (matchesBlock(block, blockPattern)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isAllowed) break
|
||||
}
|
||||
return isAllowed
|
||||
return false
|
||||
}
|
||||
|
||||
private fun damageItem(player: Player, item: ItemStack) {
|
||||
val meta = item.itemMeta as? Damageable ?: return
|
||||
val unbreakingLevel = item.getEnchantmentLevel(Enchantment.UNBREAKING)
|
||||
|
||||
if (unbreakingLevel > 0) {
|
||||
val random = Random()
|
||||
if (random.nextInt(unbreakingLevel + 1) > 0) {
|
||||
return
|
||||
}
|
||||
private fun matchesTool(item: ItemStack, criteria: String): Boolean {
|
||||
// Tag check (#namespace:key)
|
||||
if (criteria.startsWith("#")) {
|
||||
val key = NamespacedKey.fromString(criteria.substring(1))
|
||||
return key != null && Bukkit.getTag(Tag.REGISTRY_ITEMS, key, Material::class.java)?.isTagged(item.type) == true
|
||||
}
|
||||
|
||||
// Exact Material Match
|
||||
val targetMat = Material.matchMaterial(criteria)
|
||||
return targetMat == item.type
|
||||
}
|
||||
|
||||
private fun matchesBlock(block: Block, criteria: String): Boolean {
|
||||
// Tag check (#namespace:key)
|
||||
if (criteria.startsWith("#")) {
|
||||
val key = NamespacedKey.fromString(criteria.substring(1)) ?: return false
|
||||
return Bukkit.getTag(Tag.REGISTRY_BLOCKS, key, Material::class.java)?.isTagged(block.type) == true
|
||||
}
|
||||
|
||||
val maxDamage = item.type.maxDurability
|
||||
if (maxDamage > 0) {
|
||||
val newDamage = meta.damage + 1
|
||||
if (newDamage >= maxDamage) {
|
||||
item.amount = 0
|
||||
player.world.playSound(player.location, org.bukkit.Sound.ENTITY_ITEM_BREAK, 1f, 1f)
|
||||
} else {
|
||||
meta.damage = newDamage
|
||||
item.itemMeta = meta
|
||||
}
|
||||
}
|
||||
// Exact Material Match
|
||||
val targetMat = Material.matchMaterial(criteria)
|
||||
return targetMat != null && block.type == targetMat
|
||||
}
|
||||
|
||||
private fun getExpFromBlock(type: Material): Int {
|
||||
|
|
|
|||
|
|
@ -9,42 +9,61 @@ components:
|
|||
vein_miner:
|
||||
max_blocks: 64
|
||||
activation_mode: "SNEAK" # SNEAK, ALWAYS, STAND
|
||||
block_colors:
|
||||
"#minecraft:diamond_ores": "#5DECE5"
|
||||
"#minecraft:iron_ores": "#D8AF93"
|
||||
"#minecraft:gold_ores": "#FCEE4B"
|
||||
"#minecraft:copper_ores": "#966756"
|
||||
"#minecraft:coal_ores": "#363636"
|
||||
"#minecraft:redstone_ores": "#FF0000"
|
||||
"#minecraft:lapis_ores": "#1F61AE"
|
||||
"#minecraft:emerald_ores": "#00D93A"
|
||||
"minecraft:ancient_debr ": "#623A32"
|
||||
"minecraft:nether_quartz_ore": "#EADFD4"
|
||||
compatible_groups:
|
||||
- [ "minecraft:diamond_ore", "minecraft:deepslate_diamond_ore" ]
|
||||
- [ "minecraft:iron_ore", "minecraft:deepslate_iron_ore" ]
|
||||
- [ "minecraft:gold_ore", "minecraft:deepslate_gold_ore" ]
|
||||
- [ "minecraft:copper_ore", "minecraft:deepslate_copper_ore" ]
|
||||
- [ "minecraft:coal_ore", "minecraft:deepslate_coal_ore" ]
|
||||
- [ "minecraft:redstone_ore", "minecraft:deepslate_redstone_ore" ]
|
||||
- [ "minecraft:lapis_ore", "minecraft:deepslate_lapis_ore" ]
|
||||
- [ "minecraft:emerald_ore", "minecraft:deepslate_emerald_ore" ]
|
||||
- [ "#minecraft:diamond_ores" ]
|
||||
- [ "#minecraft:iron_ores" ]
|
||||
- [ "#minecraft:gold_ores" ]
|
||||
- [ "#minecraft:copper_ores" ]
|
||||
- [ "#minecraft:coal_ores" ]
|
||||
- [ "#minecraft:redstone_ores" ]
|
||||
- [ "#minecraft:lapis_ores" ]
|
||||
- [ "#minecraft:emerald_ores" ]
|
||||
tool_categories:
|
||||
- tool_pattern: "_pickaxe"
|
||||
allowed_blocks:
|
||||
- "_ore"
|
||||
- tool: "#minecraft:pickaxes"
|
||||
active_blocks:
|
||||
- "#minecraft:coal_ores"
|
||||
- "#minecraft:iron_ores"
|
||||
- "#minecraft:copper_ores"
|
||||
- "#minecraft:gold_ores"
|
||||
- "#minecraft:redstone_ores"
|
||||
- "#minecraft:lapis_ores"
|
||||
- "#minecraft:diamond_ores"
|
||||
- "#minecraft:emerald_ores"
|
||||
- "minecraft:nether_quartz_ore"
|
||||
- "minecraft:ancient_debris"
|
||||
- "minecraft:amethyst_block"
|
||||
- "minecraft:budding_amethyst"
|
||||
- "minecraft:obsidian"
|
||||
- tool_pattern: "_axe"
|
||||
allowed_blocks:
|
||||
- "_log"
|
||||
- "_stem"
|
||||
- "_hyphae"
|
||||
- tool: "#minecraft:axes"
|
||||
active_blocks:
|
||||
- "#minecraft:logs"
|
||||
- "minecraft:mangrove_roots"
|
||||
- "minecraft:bamboo_block"
|
||||
- tool_pattern: "_shovel"
|
||||
allowed_blocks:
|
||||
- tool: "#minecraft:shovels"
|
||||
active_blocks:
|
||||
- "minecraft:clay"
|
||||
- "minecraft:gravel"
|
||||
- "minecraft:soul_sand"
|
||||
- "minecraft:soul_soil"
|
||||
- "minecraft:mud"
|
||||
- "minecraft:snow"
|
||||
- tool_pattern: "_hoe"
|
||||
allowed_blocks:
|
||||
- "_leaves"
|
||||
- "minecraft:snow_block"
|
||||
- tool: "#minecraft:hoes"
|
||||
active_blocks:
|
||||
- "#minecraft:leaves"
|
||||
- "minecraft:nether_wart_block"
|
||||
- "minecraft:shroomlight"
|
||||
- "minecraft:hay_block"
|
||||
- "#minecraft:wart_blocks"
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user