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
|
var componentTickInterval: Long = 1L
|
||||||
|
|
||||||
// Vein Miner
|
// 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 veinMinerMaxBlocks: Int = 64
|
||||||
var veinMinerActivationMode: String = "SNEAK" // "SNEAK", "ALWAYS", "STAND"
|
var veinMinerActivationMode: String = "SNEAK" // "SNEAK", "ALWAYS", "STAND"
|
||||||
val veinMinerCompatibleMaterials: MutableMap<org.bukkit.Material, Set<org.bukkit.Material>> = mutableMapOf()
|
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()
|
val veinMinerToolCategories: MutableList<ToolCategory> = mutableListOf()
|
||||||
|
|
||||||
|
|
||||||
fun load(plugin: JavaPlugin) {
|
fun load(plugin: JavaPlugin) {
|
||||||
plugin.reloadConfig()
|
plugin.reloadConfig()
|
||||||
val config = plugin.config
|
val config = plugin.config
|
||||||
|
|
@ -47,6 +49,7 @@ object Config {
|
||||||
|
|
||||||
veinMinerActivationMode = config.getString("components.vein_miner.activation_mode", "SNEAK") ?: "SNEAK"
|
veinMinerActivationMode = config.getString("components.vein_miner.activation_mode", "SNEAK") ?: "SNEAK"
|
||||||
loadCompatibleGroups(config)
|
loadCompatibleGroups(config)
|
||||||
|
loadBlockColors(config)
|
||||||
loadToolCategories(config)
|
loadToolCategories(config)
|
||||||
|
|
||||||
// Save back to ensure defaults are written if missing
|
// 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
|
val groups = config.getList("components.vein_miner.compatible_groups") as? List<*> ?: return
|
||||||
|
|
||||||
for (groupObj in groups) {
|
for (groupObj in groups) {
|
||||||
val group = groupObj as? List<*> ?: continue
|
val group = when (groupObj) {
|
||||||
val materials = group.mapNotNull {
|
is List<*> -> groupObj
|
||||||
val name = (it as? String) ?: return@mapNotNull null
|
is String -> listOf(groupObj)
|
||||||
try {
|
else -> continue
|
||||||
org.bukkit.Material.valueOf(name.uppercase().removePrefix("MINECRAFT:"))
|
}
|
||||||
} catch (e: IllegalArgumentException) {
|
|
||||||
null
|
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) {
|
for (mat in materials) {
|
||||||
val existing = veinMinerCompatibleMaterials.getOrDefault(mat, emptySet())
|
val existing = veinMinerCompatibleMaterials.getOrDefault(mat, emptySet())
|
||||||
|
|
@ -97,9 +117,49 @@ object Config {
|
||||||
val list = config.getMapList("components.vein_miner.tool_categories")
|
val list = config.getMapList("components.vein_miner.tool_categories")
|
||||||
|
|
||||||
for (map in list) {
|
for (map in list) {
|
||||||
val toolPattern = map["tool_pattern"] as? String ?: continue
|
val tool = map["tool"] as? String ?: continue
|
||||||
val allowedBlocks = (map["allowed_blocks"] as? List<*>)?.filterIsInstance<String>() ?: continue
|
val blocks = (map["active_blocks"] as? List<*>)?.filterIsInstance<String>() ?: continue
|
||||||
veinMinerToolCategories.add(ToolCategory(toolPattern, allowedBlocks))
|
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.block.Block
|
||||||
import org.bukkit.entity.Player
|
import org.bukkit.entity.Player
|
||||||
import org.bukkit.event.block.BlockBreakEvent
|
import org.bukkit.event.block.BlockBreakEvent
|
||||||
|
import org.bukkit.event.player.PlayerItemDamageEvent
|
||||||
import org.bukkit.inventory.ItemStack
|
import org.bukkit.inventory.ItemStack
|
||||||
import org.bukkit.persistence.PersistentDataType
|
import org.bukkit.persistence.PersistentDataType
|
||||||
import org.bukkit.plugin.java.JavaPlugin
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
|
@ -17,6 +18,9 @@ import org.bukkit.entity.ExperienceOrb
|
||||||
import org.bukkit.entity.BlockDisplay
|
import org.bukkit.entity.BlockDisplay
|
||||||
import org.bukkit.entity.Display
|
import org.bukkit.entity.Display
|
||||||
import org.bukkit.util.Transformation
|
import org.bukkit.util.Transformation
|
||||||
|
import org.bukkit.map.MapPalette
|
||||||
|
import org.bukkit.GameMode
|
||||||
|
import org.bukkit.Tag
|
||||||
import org.joml.Vector3f
|
import org.joml.Vector3f
|
||||||
import org.bukkit.Color
|
import org.bukkit.Color
|
||||||
import org.bukkit.Bukkit
|
import org.bukkit.Bukkit
|
||||||
|
|
@ -102,7 +106,6 @@ class VeinMinerComponent(private val plugin: JavaPlugin) : ToolComponent {
|
||||||
// クライアントのパフォーマンスを考慮し、最大ハイライト数を制限しても良いが、
|
// クライアントのパフォーマンスを考慮し、最大ハイライト数を制限しても良いが、
|
||||||
// ユーザー要望通り全てハイライトする
|
// ユーザー要望通り全てハイライトする
|
||||||
if (!supportsBlockDisplay) return
|
if (!supportsBlockDisplay) return
|
||||||
|
|
||||||
for (block in blocksToBreak) {
|
for (block in blocksToBreak) {
|
||||||
val loc = block.location.add(0.5, 0.5, 0.5)
|
val loc = block.location.add(0.5, 0.5, 0.5)
|
||||||
try {
|
try {
|
||||||
|
|
@ -111,13 +114,13 @@ class VeinMinerComponent(private val plugin: JavaPlugin) : ToolComponent {
|
||||||
e.block = block.blockData
|
e.block = block.blockData
|
||||||
// 少し大きくして元のブロックを覆う
|
// 少し大きくして元のブロックを覆う
|
||||||
e.transformation = Transformation(
|
e.transformation = Transformation(
|
||||||
Vector3f(0f, 0f, 0f),
|
Vector3f(-0.5005f, -0.5005f, -0.5005f),
|
||||||
org.joml.AxisAngle4f(0f, 0f, 0f, 0f),
|
org.joml.AxisAngle4f(0f, 0f, 0f, 1f),
|
||||||
Vector3f(1.01f, 1.01f, 1.01f),
|
Vector3f(1.001f, 1.001f, 1.001f),
|
||||||
org.joml.AxisAngle4f(0f, 0f, 0f, 0f)
|
org.joml.AxisAngle4f(0f, 0f, 0f, 1f)
|
||||||
)
|
)
|
||||||
e.isGlowing = true
|
e.isGlowing = true
|
||||||
e.glowColorOverride = Color.AQUA // 鮮やかな色
|
e.glowColorOverride = Config.veinMinerBlockColors[block.type] ?: block.blockData.getMapColor()
|
||||||
e.brightness = Display.Brightness(15, 15) // 最大輝度
|
e.brightness = Display.Brightness(15, 15) // 最大輝度
|
||||||
e.isVisibleByDefault = false
|
e.isVisibleByDefault = false
|
||||||
}
|
}
|
||||||
|
|
@ -128,6 +131,7 @@ class VeinMinerComponent(private val plugin: JavaPlugin) : ToolComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
activeHighlights[player.uniqueId] = HighlightSession(targetBlock, entities, System.currentTimeMillis())
|
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 dropLocation = block.location.add(0.5, 0.5, 0.5)
|
||||||
val hasSilkTouch = item.containsEnchantment(Enchantment.SILK_TOUCH)
|
val hasSilkTouch = item.containsEnchantment(Enchantment.SILK_TOUCH)
|
||||||
|
val isDropItems = player.gameMode != GameMode.CREATIVE && player.gameMode != GameMode.SPECTATOR
|
||||||
var soundPlayed = false
|
|
||||||
|
|
||||||
for (target in blocksToBreak) {
|
for (target in blocksToBreak) {
|
||||||
if (target == block) continue // 起点ブロックはイベントフローで破壊される
|
if (target == block) continue // 起点ブロックはイベントフローで破壊される
|
||||||
|
|
||||||
// 保護プラグインチェック (擬似イベント)
|
if (isDropItems){
|
||||||
val checkEvent = BlockBreakEvent(target, player)
|
target.breakNaturally(item, true, true, true)
|
||||||
Bukkit.getPluginManager().callEvent(checkEvent)
|
player.damageItemStack(item, 1)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
else target.type = Material.AIR
|
||||||
// ドロップ処理
|
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -264,46 +240,40 @@ class VeinMinerComponent(private val plugin: JavaPlugin) : ToolComponent {
|
||||||
private fun isValidTarget(block: Block, item: ItemStack): Boolean {
|
private fun isValidTarget(block: Block, item: ItemStack): Boolean {
|
||||||
if (block.getDrops(item).isEmpty()) return false
|
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) {
|
for (category in Config.veinMinerToolCategories) {
|
||||||
if (itemName.contains(category.toolPattern)) {
|
if (matchesTool(item, category.tool)) {
|
||||||
for (pattern in category.allowedBlockPatterns) {
|
for (blockPattern in category.blocks) {
|
||||||
if (blockName.contains(pattern)) {
|
if (matchesBlock(block, blockPattern)) {
|
||||||
isAllowed = true
|
return true
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isAllowed) break
|
|
||||||
}
|
}
|
||||||
return isAllowed
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun damageItem(player: Player, item: ItemStack) {
|
private fun matchesTool(item: ItemStack, criteria: String): Boolean {
|
||||||
val meta = item.itemMeta as? Damageable ?: return
|
// Tag check (#namespace:key)
|
||||||
val unbreakingLevel = item.getEnchantmentLevel(Enchantment.UNBREAKING)
|
if (criteria.startsWith("#")) {
|
||||||
|
val key = NamespacedKey.fromString(criteria.substring(1))
|
||||||
if (unbreakingLevel > 0) {
|
return key != null && Bukkit.getTag(Tag.REGISTRY_ITEMS, key, Material::class.java)?.isTagged(item.type) == true
|
||||||
val random = Random()
|
|
||||||
if (random.nextInt(unbreakingLevel + 1) > 0) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val maxDamage = item.type.maxDurability
|
// Exact Material Match
|
||||||
if (maxDamage > 0) {
|
val targetMat = Material.matchMaterial(criteria)
|
||||||
val newDamage = meta.damage + 1
|
return targetMat == item.type
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Exact Material Match
|
||||||
|
val targetMat = Material.matchMaterial(criteria)
|
||||||
|
return targetMat != null && block.type == targetMat
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getExpFromBlock(type: Material): Int {
|
private fun getExpFromBlock(type: Material): Int {
|
||||||
|
|
|
||||||
|
|
@ -9,42 +9,61 @@ components:
|
||||||
vein_miner:
|
vein_miner:
|
||||||
max_blocks: 64
|
max_blocks: 64
|
||||||
activation_mode: "SNEAK" # SNEAK, ALWAYS, STAND
|
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:
|
compatible_groups:
|
||||||
- [ "minecraft:diamond_ore", "minecraft:deepslate_diamond_ore" ]
|
- [ "#minecraft:diamond_ores" ]
|
||||||
- [ "minecraft:iron_ore", "minecraft:deepslate_iron_ore" ]
|
- [ "#minecraft:iron_ores" ]
|
||||||
- [ "minecraft:gold_ore", "minecraft:deepslate_gold_ore" ]
|
- [ "#minecraft:gold_ores" ]
|
||||||
- [ "minecraft:copper_ore", "minecraft:deepslate_copper_ore" ]
|
- [ "#minecraft:copper_ores" ]
|
||||||
- [ "minecraft:coal_ore", "minecraft:deepslate_coal_ore" ]
|
- [ "#minecraft:coal_ores" ]
|
||||||
- [ "minecraft:redstone_ore", "minecraft:deepslate_redstone_ore" ]
|
- [ "#minecraft:redstone_ores" ]
|
||||||
- [ "minecraft:lapis_ore", "minecraft:deepslate_lapis_ore" ]
|
- [ "#minecraft:lapis_ores" ]
|
||||||
- [ "minecraft:emerald_ore", "minecraft:deepslate_emerald_ore" ]
|
- [ "#minecraft:emerald_ores" ]
|
||||||
tool_categories:
|
tool_categories:
|
||||||
- tool_pattern: "_pickaxe"
|
- tool: "#minecraft:pickaxes"
|
||||||
allowed_blocks:
|
active_blocks:
|
||||||
- "_ore"
|
- "#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:ancient_debris"
|
||||||
- "minecraft:amethyst_block"
|
- "minecraft:amethyst_block"
|
||||||
- "minecraft:budding_amethyst"
|
- "minecraft:budding_amethyst"
|
||||||
- "minecraft:obsidian"
|
- "minecraft:obsidian"
|
||||||
- tool_pattern: "_axe"
|
- tool: "#minecraft:axes"
|
||||||
allowed_blocks:
|
active_blocks:
|
||||||
- "_log"
|
- "#minecraft:logs"
|
||||||
- "_stem"
|
|
||||||
- "_hyphae"
|
|
||||||
- "minecraft:mangrove_roots"
|
- "minecraft:mangrove_roots"
|
||||||
- "minecraft:bamboo_block"
|
- "minecraft:bamboo_block"
|
||||||
- tool_pattern: "_shovel"
|
- tool: "#minecraft:shovels"
|
||||||
allowed_blocks:
|
active_blocks:
|
||||||
- "minecraft:clay"
|
- "minecraft:clay"
|
||||||
- "minecraft:gravel"
|
- "minecraft:gravel"
|
||||||
- "minecraft:soul_sand"
|
- "minecraft:soul_sand"
|
||||||
- "minecraft:soul_soil"
|
- "minecraft:soul_soil"
|
||||||
- "minecraft:mud"
|
- "minecraft:mud"
|
||||||
- "minecraft:snow"
|
- "minecraft:snow"
|
||||||
- tool_pattern: "_hoe"
|
- "minecraft:snow_block"
|
||||||
allowed_blocks:
|
- tool: "#minecraft:hoes"
|
||||||
- "_leaves"
|
active_blocks:
|
||||||
|
- "#minecraft:leaves"
|
||||||
- "minecraft:nether_wart_block"
|
- "minecraft:nether_wart_block"
|
||||||
- "minecraft:shroomlight"
|
- "minecraft:shroomlight"
|
||||||
- "minecraft:hay_block"
|
- "minecraft:hay_block"
|
||||||
|
- "#minecraft:wart_blocks"
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user