refactor: Restructure configuration into nested data classes and update component references.

This commit is contained in:
Kariya 2025-12-17 08:49:33 +00:00
parent a464a8f77f
commit 0e72f24164
6 changed files with 253 additions and 119 deletions

View File

@ -1,80 +1,176 @@
package net.hareworks.hcu.items.config
import org.bukkit.Color
import org.bukkit.Material
import org.bukkit.NamespacedKey
import org.bukkit.Tag
import org.bukkit.Bukkit
import org.bukkit.configuration.file.FileConfiguration
import org.bukkit.plugin.java.JavaPlugin
/**
* プラグインの設定を管理するシングルトンオブジェクト
*/
object Config {
// Component Settings
var blinkCooldown: Long = 1500
var doubleJumpCooldown: Long = 1500
var doubleJumpPowerVertical: Double = 0.5
var doubleJumpPowerForward: Double = 0.3
// グローバル設定
var global = GlobalSettings()
// Global Settings
var componentTickInterval: Long = 1L
// コンポーネント設定
var blink = BlinkSettings()
var doubleJump = DoubleJumpSettings()
var veinMiner = VeinMinerSettings()
// Vein Miner
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()
/**
* グローバル設定
*/
data class GlobalSettings(
var tickInterval: Long = 1L
)
/**
* Blinkコンポーネント設定
*/
data class BlinkSettings(
var cooldown: Long = 1500
)
/**
* DoubleJumpコンポーネント設定
*/
data class DoubleJumpSettings(
var cooldown: Long = 1500,
var powerVertical: Double = 0.5,
var powerForward: Double = 0.3
)
/**
* VeinMinerコンポーネント設定
*/
data class VeinMinerSettings(
var maxBlocks: Int = 64,
var activationMode: ActivationMode = ActivationMode.SNEAK,
val compatibleMaterials: MutableMap<Material, Set<Material>> = mutableMapOf(),
val blockColors: MutableMap<Material, Color> = mutableMapOf(),
val toolCategories: MutableList<ToolCategory> = mutableListOf()
)
/**
* VeinMinerのアクティベーションモード
*/
enum class ActivationMode {
SNEAK, // スニーク時のみ有効
ALWAYS, // 常に有効
STAND; // 立っている時のみ有効
companion object {
fun fromString(value: String): ActivationMode {
return values().find { it.name.equals(value, ignoreCase = true) } ?: SNEAK
}
}
}
/**
* ツールカテゴリ設定
*/
data class ToolCategory(
val tool: String,
val blocks: List<String>
)
/**
* 設定ファイルから設定を読み込む
*/
fun load(plugin: JavaPlugin) {
plugin.reloadConfig()
val config = plugin.config
// Global
componentTickInterval = config.getLong("components.global.tick_interval", 1L).coerceAtLeast(1L)
// Blink
blinkCooldown = config.getLong("components.blink.cooldown", 1500)
loadGlobalSettings(config)
loadBlinkSettings(config)
loadDoubleJumpSettings(config)
loadVeinMinerSettings(plugin, config)
// Double Jump
doubleJumpCooldown = config.getLong("components.double_jump.cooldown", 1500)
doubleJumpPowerVertical = config.getDouble("components.double_jump.power.vertical", 0.5)
doubleJumpPowerForward = config.getDouble("components.double_jump.power.forward", 0.3)
// Vein Miner
val rawMaxBlocks = config.getInt("components.vein_miner.max_blocks", 64)
if (rawMaxBlocks > 2048) {
plugin.logger.warning("Vein miner max blocks set to $rawMaxBlocks, which is very high. Capping at 2048 to prevent crashes.")
veinMinerMaxBlocks = 2048
} else {
veinMinerMaxBlocks = rawMaxBlocks
}
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
saveDefaults(plugin, config)
}
/**
* グローバル設定を読み込む
*/
private fun loadGlobalSettings(config: FileConfiguration) {
global = GlobalSettings(
tickInterval = config.getLong("components.global.tick_interval", 1L).coerceAtLeast(1L)
)
}
/**
* Blink設定を読み込む
*/
private fun loadBlinkSettings(config: FileConfiguration) {
blink = BlinkSettings(
cooldown = config.getLong("components.blink.cooldown", 1500)
)
}
/**
* DoubleJump設定を読み込む
*/
private fun loadDoubleJumpSettings(config: FileConfiguration) {
doubleJump = DoubleJumpSettings(
cooldown = config.getLong("components.double_jump.cooldown", 1500),
powerVertical = config.getDouble("components.double_jump.power.vertical", 0.5),
powerForward = config.getDouble("components.double_jump.power.forward", 0.3)
)
}
/**
* VeinMiner設定を読み込む
*/
private fun loadVeinMinerSettings(plugin: JavaPlugin, config: FileConfiguration) {
val rawMaxBlocks = config.getInt("components.vein_miner.max_blocks", 64)
val maxBlocks = if (rawMaxBlocks > 2048) {
plugin.logger.warning("Vein miner max blocks set to $rawMaxBlocks, which is very high. Capping at 2048 to prevent crashes.")
2048
} else {
rawMaxBlocks
}
val activationModeStr = config.getString("components.vein_miner.activation_mode", "SNEAK") ?: "SNEAK"
val activationMode = ActivationMode.fromString(activationModeStr)
veinMiner = VeinMinerSettings(
maxBlocks = maxBlocks,
activationMode = activationMode
)
loadCompatibleGroups(config, veinMiner.compatibleMaterials)
loadBlockColors(config, veinMiner.blockColors)
loadToolCategories(config, veinMiner.toolCategories)
}
/**
* デフォルト設定を保存する
*/
private fun saveDefaults(plugin: JavaPlugin, config: FileConfiguration) {
config.addDefault("components.global.tick_interval", 1L)
config.addDefault("components.blink.cooldown", 1500)
config.addDefault("components.double_jump.cooldown", 1500)
config.addDefault("components.double_jump.power.vertical", 0.5)
config.addDefault("components.double_jump.power.forward", 0.3)
config.addDefault("components.vein_miner.max_blocks", 64)
// Groups default is complex to add here, relying on config.yml resource or existing file
// Tool categories default is handled by config.yml resource
config.addDefault("components.vein_miner.activation_mode", "SNEAK")
config.options().copyDefaults(true)
plugin.saveConfig()
}
private fun loadCompatibleGroups(config: FileConfiguration) {
veinMinerCompatibleMaterials.clear()
/**
* 互換性のあるブロックグループを読み込む
*/
private fun loadCompatibleGroups(
config: FileConfiguration,
compatibleMaterials: MutableMap<Material, Set<Material>>
) {
compatibleMaterials.clear()
val groups = config.getList("components.vein_miner.compatible_groups") as? List<*> ?: return
for (groupObj in groups) {
@ -84,82 +180,121 @@ object Config {
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
}
}
}
val materials = parseMaterialList(group)
// 各マテリアルに対して、グループ内の全マテリアルを互換性リストに追加
for (mat in materials) {
val existing = veinMinerCompatibleMaterials.getOrDefault(mat, emptySet())
veinMinerCompatibleMaterials[mat] = existing + materials
val existing = compatibleMaterials.getOrDefault(mat, emptySet())
compatibleMaterials[mat] = existing + materials
}
}
}
private fun loadToolCategories(config: FileConfiguration) {
veinMinerToolCategories.clear()
/**
* ツールカテゴリを読み込む
*/
private fun loadToolCategories(
config: FileConfiguration,
toolCategories: MutableList<ToolCategory>
) {
toolCategories.clear()
val list = config.getMapList("components.vein_miner.tool_categories")
for (map in list) {
val tool = map["tool"] as? String ?: continue
val blocks = (map["active_blocks"] as? List<*>)?.filterIsInstance<String>() ?: continue
veinMinerToolCategories.add(ToolCategory(tool, blocks))
toolCategories.add(ToolCategory(tool, blocks))
}
}
private fun loadBlockColors(config: FileConfiguration) {
veinMinerBlockColors.clear()
/**
* ブロックの色設定を読み込む
*/
private fun loadBlockColors(
config: FileConfiguration,
blockColors: MutableMap<Material, Color>
) {
blockColors.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
}
val color = parseColor(hexOrRgb) ?: continue
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
}
val materials = parseMaterialKey(keyStr)
for (mat in materials) {
blockColors[mat] = color
}
}
}
/**
* マテリアルリストを解析する
*/
private fun parseMaterialList(list: List<*>): Set<Material> {
val materials = mutableSetOf<Material>()
for (item in list) {
val name = (item as? String) ?: continue
materials.addAll(parseMaterialKey(name))
}
return materials
}
/**
* マテリアルキーを解析するタグまたは個別マテリアル
*/
private fun parseMaterialKey(key: String): Set<Material> {
return if (key.startsWith("#")) {
// タグとして解析
parseTag(key.substring(1))
} else {
// 個別マテリアルとして解析
parseSingleMaterial(key)?.let { setOf(it) } ?: emptySet()
}
}
/**
* タグからマテリアルセットを取得する
*/
private fun parseTag(tagName: String): Set<Material> {
val key = NamespacedKey.fromString(tagName) ?: return emptySet()
val tag = Bukkit.getTag(Tag.REGISTRY_BLOCKS, key, Material::class.java) ?: return emptySet()
return tag.values.toSet()
}
/**
* 単一のマテリアルを解析する
*/
private fun parseSingleMaterial(name: String): Material? {
return try {
Material.valueOf(name.uppercase().removePrefix("MINECRAFT:"))
} catch (e: IllegalArgumentException) {
null
}
}
/**
* 色文字列を解析するHEXまたはRGB
*/
private fun parseColor(colorStr: String): Color? {
return try {
if (colorStr.contains(",")) {
// RGB形式
val parts = colorStr.split(",").map { it.trim().toInt() }
if (parts.size == 3) {
Color.fromRGB(parts[0], parts[1], parts[2])
} else {
null
}
} else {
// HEX形式
val hex = colorStr.removePrefix("#")
Color.fromRGB(hex.toInt(16))
}
} catch (e: Exception) {
null
}
}
}

View File

@ -35,7 +35,7 @@ class BlinkComponent(private val plugin: App) : AbstractComponent(plugin, "blink
companion object {
// Track players who have used their blink (GLIDER is removed until landing)
private val usedBlink = ConcurrentHashMap.newKeySet<UUID>()
private val cooldown = Cooldown(net.hareworks.hcu.items.config.Config.blinkCooldown)
private val cooldown = Cooldown(net.hareworks.hcu.items.config.Config.blink.cooldown)
// Color scheme - Purple/Magenta for teleport/blink theme
private val PRIMARY_COLOR = TextColor.color(0xDA70D6) // Orchid

View File

@ -34,7 +34,7 @@ class DoubleJumpComponent(private val plugin: App) : AbstractComponent(plugin, "
companion object {
// Track players who have used their double jump (GLIDER is removed)
private val usedDoubleJump = ConcurrentHashMap.newKeySet<UUID>()
private val cooldown = Cooldown(net.hareworks.hcu.items.config.Config.doubleJumpCooldown)
private val cooldown = Cooldown(net.hareworks.hcu.items.config.Config.doubleJump.cooldown)
// Color scheme
private val PRIMARY_COLOR = TextColor.color(0x7DF9FF) // Electric Cyan
@ -127,8 +127,8 @@ class DoubleJumpComponent(private val plugin: App) : AbstractComponent(plugin, "
val currentVelocity = player.velocity
// Base power + Tier bonus
val verticalPower = net.hareworks.hcu.items.config.Config.doubleJumpPowerVertical + (tier.level * 0.15)
val forwardPower = net.hareworks.hcu.items.config.Config.doubleJumpPowerForward + (tier.level * 0.1)
val verticalPower = net.hareworks.hcu.items.config.Config.doubleJump.powerVertical + (tier.level * 0.15)
val forwardPower = net.hareworks.hcu.items.config.Config.doubleJump.powerForward + (tier.level * 0.1)
player.velocity = currentVelocity.add(direction.multiply(forwardPower)).setY(verticalPower)

View File

@ -45,7 +45,7 @@ class GliderComponent(private val plugin: App) : AbstractComponent(plugin, "glid
init {
// Global Ticker for active gliders
val interval = net.hareworks.hcu.items.config.Config.componentTickInterval
val interval = net.hareworks.hcu.items.config.Config.global.tickInterval
plugin.server.scheduler.runTaskTimer(plugin, Runnable {
if (activeGliders.isEmpty()) return@Runnable
@ -120,7 +120,7 @@ class GliderComponent(private val plugin: App) : AbstractComponent(plugin, "glid
// Find the itemStack that has this component in user's equipment
private fun findGliderItem(player: Player): ItemStack? {
val equipment = player.equipment ?: return null
val equipment = player.equipment
val candidates = mutableListOf<ItemStack>()
candidates.addAll(equipment.armorContents.filterNotNull())
candidates.add(equipment.itemInMainHand)

View File

@ -120,7 +120,7 @@ class VeinMinerComponent(private val plugin: JavaPlugin) : ToolComponent {
org.joml.AxisAngle4f(0f, 0f, 0f, 1f)
)
e.isGlowing = true
e.glowColorOverride = Config.veinMinerBlockColors[block.type] ?: block.blockData.getMapColor()
e.glowColorOverride = Config.veinMiner.blockColors[block.type] ?: block.blockData.getMapColor()
e.brightness = Display.Brightness(15, 15) // 最大輝度
e.isVisibleByDefault = false
}
@ -180,11 +180,10 @@ class VeinMinerComponent(private val plugin: JavaPlugin) : ToolComponent {
}
private fun shouldActivate(player: Player): Boolean {
return when (Config.veinMinerActivationMode) {
"SNEAK" -> player.isSneaking
"STAND" -> !player.isSneaking
"ALWAYS" -> true
else -> player.isSneaking
return when (Config.veinMiner.activationMode) {
Config.ActivationMode.SNEAK -> player.isSneaking
Config.ActivationMode.STAND -> !player.isSneaking
Config.ActivationMode.ALWAYS -> true
}
}
@ -196,14 +195,14 @@ class VeinMinerComponent(private val plugin: JavaPlugin) : ToolComponent {
// 互換ブロックタイプ抽出
val startType = startBlock.type
val targetMaterials = Config.veinMinerCompatibleMaterials[startType] ?: setOf()
val targetMaterials = Config.veinMiner.compatibleMaterials[startType] ?: setOf()
val efficientTargets = if (targetMaterials.isNotEmpty()) targetMaterials else setOf(startType)
val queue: Queue<Block> = LinkedList()
visited.add(startBlock)
queue.add(startBlock)
val max = Config.veinMinerMaxBlocks
val max = Config.veinMiner.maxBlocks
// 見つかったブロックの実リスト
val foundBlocks = mutableSetOf<Block>()
foundBlocks.add(startBlock)
@ -240,7 +239,7 @@ class VeinMinerComponent(private val plugin: JavaPlugin) : ToolComponent {
private fun isValidTarget(block: Block, item: ItemStack): Boolean {
if (block.getDrops(item).isEmpty()) return false
for (category in Config.veinMinerToolCategories) {
for (category in Config.veinMiner.toolCategories) {
if (matchesTool(item, category.tool)) {
for (blockPattern in category.blocks) {
if (matchesBlock(block, blockPattern)) {

View File

@ -22,7 +22,7 @@ class EventListener(private val plugin: Plugin) : Listener {
init {
// Use configurable tick interval (defaulting to 1L if something goes wrong, though Config handles defaults)
val interval = net.hareworks.hcu.items.config.Config.componentTickInterval
val interval = net.hareworks.hcu.items.config.Config.global.tickInterval
plugin.server.scheduler.runTaskTimer(plugin, Runnable {
tickComponents()
}, 1L, interval)