feat: Add AutoFeeder item with automatic food consumption and configurable hunger threshold
This commit is contained in:
parent
fb7ae54875
commit
6bc2fb2be2
|
|
@ -9,6 +9,7 @@ import net.hareworks.hcu.items.registry.ComponentRegistry
|
||||||
import net.hareworks.hcu.items.content.items.TestItem
|
import net.hareworks.hcu.items.content.items.TestItem
|
||||||
import net.hareworks.hcu.items.content.items.GrapplingItem
|
import net.hareworks.hcu.items.content.items.GrapplingItem
|
||||||
import net.hareworks.hcu.items.content.items.MagnetItem
|
import net.hareworks.hcu.items.content.items.MagnetItem
|
||||||
|
import net.hareworks.hcu.items.content.items.AutoFeederItem
|
||||||
import net.hareworks.hcu.items.content.components.GliderComponent
|
import net.hareworks.hcu.items.content.components.GliderComponent
|
||||||
import net.hareworks.hcu.items.content.components.DoubleJumpComponent
|
import net.hareworks.hcu.items.content.components.DoubleJumpComponent
|
||||||
import net.hareworks.hcu.items.content.components.BlinkComponent
|
import net.hareworks.hcu.items.content.components.BlinkComponent
|
||||||
|
|
@ -41,6 +42,7 @@ public class App : JavaPlugin() {
|
||||||
ItemRegistry.register(TestItem())
|
ItemRegistry.register(TestItem())
|
||||||
ItemRegistry.register(GrapplingItem())
|
ItemRegistry.register(GrapplingItem())
|
||||||
ItemRegistry.register(MagnetItem())
|
ItemRegistry.register(MagnetItem())
|
||||||
|
ItemRegistry.register(AutoFeederItem())
|
||||||
|
|
||||||
// Register Components
|
// Register Components
|
||||||
ComponentRegistry.register(GliderComponent(this))
|
ComponentRegistry.register(GliderComponent(this))
|
||||||
|
|
|
||||||
|
|
@ -17,5 +17,6 @@ interface CustomItem {
|
||||||
fun onEntityDamage(event: org.bukkit.event.entity.EntityDamageEvent) {}
|
fun onEntityDamage(event: org.bukkit.event.entity.EntityDamageEvent) {}
|
||||||
fun onPlayerMove(event: org.bukkit.event.player.PlayerMoveEvent) {}
|
fun onPlayerMove(event: org.bukkit.event.player.PlayerMoveEvent) {}
|
||||||
fun onItemHeld(event: org.bukkit.event.player.PlayerItemHeldEvent) {}
|
fun onItemHeld(event: org.bukkit.event.player.PlayerItemHeldEvent) {}
|
||||||
|
fun onFoodLevelChange(event: org.bukkit.event.entity.FoodLevelChangeEvent) {}
|
||||||
fun onTick(player: org.bukkit.entity.Player, item: ItemStack) {}
|
fun onTick(player: org.bukkit.entity.Player, item: ItemStack) {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ object Config {
|
||||||
var doubleJump = DoubleJumpSettings()
|
var doubleJump = DoubleJumpSettings()
|
||||||
var veinMiner = VeinMinerSettings()
|
var veinMiner = VeinMinerSettings()
|
||||||
var magnet = MagnetSettings()
|
var magnet = MagnetSettings()
|
||||||
|
var autoFeeder = AutoFeederSettings()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* グローバル設定
|
* グローバル設定
|
||||||
|
|
@ -54,6 +55,13 @@ object Config {
|
||||||
var allowScrollChange: Boolean = true
|
var allowScrollChange: Boolean = true
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AutoFeederアイテム設定
|
||||||
|
*/
|
||||||
|
data class AutoFeederSettings(
|
||||||
|
var hungerThreshold: Int = 10
|
||||||
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* VeinMinerコンポーネント設定
|
* VeinMinerコンポーネント設定
|
||||||
*/
|
*/
|
||||||
|
|
@ -100,6 +108,7 @@ object Config {
|
||||||
loadDoubleJumpSettings(config)
|
loadDoubleJumpSettings(config)
|
||||||
loadVeinMinerSettings(plugin, config)
|
loadVeinMinerSettings(plugin, config)
|
||||||
loadMagnetSettings(config)
|
loadMagnetSettings(config)
|
||||||
|
loadAutoFeederSettings(config)
|
||||||
|
|
||||||
saveDefaults(plugin, config)
|
saveDefaults(plugin, config)
|
||||||
}
|
}
|
||||||
|
|
@ -169,6 +178,15 @@ object Config {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AutoFeeder設定を読み込む
|
||||||
|
*/
|
||||||
|
private fun loadAutoFeederSettings(config: FileConfiguration) {
|
||||||
|
autoFeeder = AutoFeederSettings(
|
||||||
|
hungerThreshold = config.getInt("items.auto_feeder.hunger_threshold", 10)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* デフォルト設定を保存する
|
* デフォルト設定を保存する
|
||||||
*/
|
*/
|
||||||
|
|
@ -183,6 +201,7 @@ object Config {
|
||||||
config.addDefault("components.magnet.radius_base", 5.0)
|
config.addDefault("components.magnet.radius_base", 5.0)
|
||||||
config.addDefault("components.magnet.radius_per_tier", 5.0)
|
config.addDefault("components.magnet.radius_per_tier", 5.0)
|
||||||
config.addDefault("components.magnet.allow_scroll_change", true)
|
config.addDefault("components.magnet.allow_scroll_change", true)
|
||||||
|
config.addDefault("items.auto_feeder.hunger_threshold", 10)
|
||||||
|
|
||||||
config.options().copyDefaults(true)
|
config.options().copyDefaults(true)
|
||||||
plugin.saveConfig()
|
plugin.saveConfig()
|
||||||
|
|
@ -196,7 +215,7 @@ object Config {
|
||||||
compatibleMaterials: MutableMap<Material, Set<Material>>
|
compatibleMaterials: MutableMap<Material, Set<Material>>
|
||||||
) {
|
) {
|
||||||
compatibleMaterials.clear()
|
compatibleMaterials.clear()
|
||||||
val groups = config.getList("components.vein_miner.compatible_groups") as? List<*> ?: return
|
val groups = config.getList("components.vein_miner.compatible_groups") ?: return
|
||||||
|
|
||||||
for (groupObj in groups) {
|
for (groupObj in groups) {
|
||||||
val group = when (groupObj) {
|
val group = when (groupObj) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,215 @@
|
||||||
|
package net.hareworks.hcu.items.content.items
|
||||||
|
|
||||||
|
import net.hareworks.hcu.items.api.Tier
|
||||||
|
import net.hareworks.hcu.items.api.item.AbstractItem
|
||||||
|
import net.hareworks.hcu.items.config.Config
|
||||||
|
import net.kyori.adventure.text.Component
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor
|
||||||
|
import org.bukkit.Material
|
||||||
|
import org.bukkit.Particle
|
||||||
|
import org.bukkit.Sound
|
||||||
|
import org.bukkit.entity.Player
|
||||||
|
import org.bukkit.event.entity.FoodLevelChangeEvent
|
||||||
|
import org.bukkit.inventory.ItemStack
|
||||||
|
import org.bukkit.inventory.meta.BundleMeta
|
||||||
|
import io.papermc.paper.datacomponent.DataComponentTypes
|
||||||
|
import io.papermc.paper.datacomponent.item.consumable.ConsumeEffect
|
||||||
|
import org.slf4j.Logger
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto Feeder (オートフィーダー)
|
||||||
|
* バンドルベースのアイテムで、満腹度が一定以下になると自動で中の食料を食べる
|
||||||
|
*/
|
||||||
|
class AutoFeederItem : AbstractItem("auto_feeder") {
|
||||||
|
|
||||||
|
override val maxTier: Int = 2
|
||||||
|
|
||||||
|
override fun buildItem(tier: Tier): ItemStack {
|
||||||
|
return ItemStack(Material.BUNDLE).apply {
|
||||||
|
val meta = itemMeta as? BundleMeta ?: return@apply
|
||||||
|
|
||||||
|
val configInfo = Config.autoFeeder
|
||||||
|
val threshold = configInfo.hungerThreshold
|
||||||
|
|
||||||
|
// ティアによる説明の違い
|
||||||
|
val activationDesc = when (tier.level) {
|
||||||
|
1 -> Component.text("左手に持っている時のみ発動", NamedTextColor.YELLOW)
|
||||||
|
2 -> Component.text("インベントリにあるだけで発動", NamedTextColor.GOLD)
|
||||||
|
else -> Component.text("左手に持っている時のみ発動", NamedTextColor.YELLOW)
|
||||||
|
}
|
||||||
|
|
||||||
|
meta.displayName(Component.text("オートフィーダー", tier.color))
|
||||||
|
|
||||||
|
meta.lore(listOf(
|
||||||
|
Component.empty(),
|
||||||
|
Component.text("満腹度が低下すると自動で食事", NamedTextColor.GRAY),
|
||||||
|
Component.text("バンドル内の食料を消費します", NamedTextColor.GRAY),
|
||||||
|
Component.empty(),
|
||||||
|
Component.text("【性能】", NamedTextColor.WHITE),
|
||||||
|
Component.text("ティア: ${tier.name}", tier.color),
|
||||||
|
Component.text("発動閾値: ${threshold}以下", NamedTextColor.GREEN),
|
||||||
|
activationDesc,
|
||||||
|
Component.empty(),
|
||||||
|
Component.text("バンドルに食料を入れて使用", NamedTextColor.AQUA)
|
||||||
|
))
|
||||||
|
|
||||||
|
itemMeta = meta
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTick(player: Player, item: ItemStack) {
|
||||||
|
|
||||||
|
// 満腹度チェック
|
||||||
|
val configInfo = Config.autoFeeder
|
||||||
|
val threshold = configInfo.hungerThreshold
|
||||||
|
|
||||||
|
if (player.foodLevel > threshold) return
|
||||||
|
|
||||||
|
// Tierによる発動条件チェック
|
||||||
|
val tier = getTier(item)
|
||||||
|
if (tier.level == 1) {
|
||||||
|
// Tier 1: 左手(オフハンド)に持っている時のみ
|
||||||
|
// まったく同じアイテムかチェック(参照または内容の一致)
|
||||||
|
if (item != player.inventory.itemInOffHand) return
|
||||||
|
}
|
||||||
|
// Tier 2: インベントリにあればOK(onTickが呼ばれている時点でインベントリ内にあると仮定)
|
||||||
|
|
||||||
|
// 食事処理を実行
|
||||||
|
feed(player, item)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun feed(player: Player, item: ItemStack) {
|
||||||
|
// バンドルから食料を取得して食べる
|
||||||
|
val bundleMeta = item.itemMeta as? BundleMeta ?: return
|
||||||
|
val contents = bundleMeta.items.toMutableList()
|
||||||
|
|
||||||
|
// 食料アイテムを探す
|
||||||
|
val foodItem = contents.firstOrNull { it.type.isEdible } ?: return
|
||||||
|
|
||||||
|
// Food情報を取得
|
||||||
|
var nutrition = 0
|
||||||
|
var saturation = 0.0f
|
||||||
|
|
||||||
|
if (foodItem.hasData(DataComponentTypes.FOOD)) {
|
||||||
|
val food = foodItem.getData(DataComponentTypes.FOOD)
|
||||||
|
if (food != null) {
|
||||||
|
nutrition = food.nutrition()
|
||||||
|
saturation = food.saturation()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 食料を消費
|
||||||
|
if (foodItem.amount > 1) {
|
||||||
|
foodItem.amount -= 1
|
||||||
|
} else {
|
||||||
|
contents.remove(foodItem)
|
||||||
|
}
|
||||||
|
bundleMeta.setItems(contents)
|
||||||
|
item.itemMeta = bundleMeta
|
||||||
|
|
||||||
|
// 満腹度を回復
|
||||||
|
val newFood = (player.foodLevel + nutrition).coerceAtMost(20)
|
||||||
|
val newSaturation = (player.saturation + saturation).coerceAtMost(newFood.toFloat())
|
||||||
|
|
||||||
|
player.foodLevel = newFood
|
||||||
|
player.saturation = newSaturation
|
||||||
|
|
||||||
|
// 特殊効果を適用
|
||||||
|
applyFoodEffects(player, foodItem)
|
||||||
|
|
||||||
|
// フィードバック
|
||||||
|
player.sendActionBar(
|
||||||
|
Component.text("🍖 ", NamedTextColor.GOLD)
|
||||||
|
.append(Component.text(foodItem.type.name.lowercase().replace("_", " "), NamedTextColor.YELLOW))
|
||||||
|
.append(Component.text(" を自動で食べました!", NamedTextColor.GRAY))
|
||||||
|
)
|
||||||
|
|
||||||
|
// パーティクルとサウンド
|
||||||
|
player.world.spawnParticle(
|
||||||
|
Particle.ITEM,
|
||||||
|
player.location.add(0.0, 1.5, 0.0),
|
||||||
|
10,
|
||||||
|
0.3, 0.3, 0.3,
|
||||||
|
0.1,
|
||||||
|
foodItem
|
||||||
|
)
|
||||||
|
|
||||||
|
player.playSound(
|
||||||
|
player.location,
|
||||||
|
Sound.ENTITY_GENERIC_EAT,
|
||||||
|
1.0f,
|
||||||
|
1.0f
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DataComponentTypes.CONSUMABLEを使用して効果を適用する
|
||||||
|
*/
|
||||||
|
private fun applyFoodEffects(player: Player, item: ItemStack) {
|
||||||
|
// DataComponentが存在するかチェック
|
||||||
|
if (!item.hasData(DataComponentTypes.CONSUMABLE)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val consumable = item.getData(DataComponentTypes.CONSUMABLE) ?: return
|
||||||
|
|
||||||
|
// consumeEffects (APIによっては effects などの可能性あり)
|
||||||
|
for (consumeEffect in consumable.consumeEffects()) {
|
||||||
|
if (consumeEffect is ConsumeEffect.ApplyStatusEffects) {
|
||||||
|
if (Math.random() < consumeEffect.probability()) {
|
||||||
|
for (effect in consumeEffect.effects()) {
|
||||||
|
player.addPotionEffect(effect)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class FoodInfo(val nutrition: Int, val saturation: Float)
|
||||||
|
|
||||||
|
private fun getFoodInfo(material: Material): FoodInfo? {
|
||||||
|
return when (material) {
|
||||||
|
Material.APPLE -> FoodInfo(4, 2.4f)
|
||||||
|
Material.BAKED_POTATO -> FoodInfo(5, 6.0f)
|
||||||
|
Material.BREAD -> FoodInfo(5, 6.0f)
|
||||||
|
Material.CARROT -> FoodInfo(3, 3.6f)
|
||||||
|
Material.COOKED_BEEF -> FoodInfo(8, 12.8f)
|
||||||
|
Material.COOKED_CHICKEN -> FoodInfo(6, 7.2f)
|
||||||
|
Material.COOKED_COD -> FoodInfo(5, 6.0f)
|
||||||
|
Material.COOKED_MUTTON -> FoodInfo(6, 9.6f)
|
||||||
|
Material.COOKED_PORKCHOP -> FoodInfo(8, 12.8f)
|
||||||
|
Material.COOKED_RABBIT -> FoodInfo(5, 6.0f)
|
||||||
|
Material.COOKED_SALMON -> FoodInfo(6, 9.6f)
|
||||||
|
Material.COOKIE -> FoodInfo(2, 0.4f)
|
||||||
|
Material.DRIED_KELP -> FoodInfo(1, 0.6f)
|
||||||
|
Material.ENCHANTED_GOLDEN_APPLE -> FoodInfo(4, 9.6f)
|
||||||
|
Material.GOLDEN_APPLE -> FoodInfo(4, 9.6f)
|
||||||
|
Material.GOLDEN_CARROT -> FoodInfo(6, 14.4f)
|
||||||
|
Material.HONEY_BOTTLE -> FoodInfo(6, 1.2f)
|
||||||
|
Material.MELON_SLICE -> FoodInfo(2, 1.2f)
|
||||||
|
Material.MUSHROOM_STEW -> FoodInfo(6, 7.2f)
|
||||||
|
Material.POISONOUS_POTATO -> FoodInfo(2, 1.2f)
|
||||||
|
Material.POTATO -> FoodInfo(1, 0.6f)
|
||||||
|
Material.PUFFERFISH -> FoodInfo(1, 0.2f)
|
||||||
|
Material.PUMPKIN_PIE -> FoodInfo(8, 4.8f)
|
||||||
|
Material.RABBIT_STEW -> FoodInfo(10, 12.0f)
|
||||||
|
Material.BEEF -> FoodInfo(3, 1.8f)
|
||||||
|
Material.CHICKEN -> FoodInfo(2, 1.2f)
|
||||||
|
Material.COD -> FoodInfo(2, 0.4f)
|
||||||
|
Material.MUTTON -> FoodInfo(2, 1.2f)
|
||||||
|
Material.PORKCHOP -> FoodInfo(3, 1.8f)
|
||||||
|
Material.RABBIT -> FoodInfo(3, 1.8f)
|
||||||
|
Material.SALMON -> FoodInfo(2, 0.4f)
|
||||||
|
Material.ROTTEN_FLESH -> FoodInfo(4, 0.8f)
|
||||||
|
Material.SPIDER_EYE -> FoodInfo(2, 3.2f)
|
||||||
|
Material.SUSPICIOUS_STEW -> FoodInfo(6, 7.2f)
|
||||||
|
Material.SWEET_BERRIES -> FoodInfo(2, 0.4f)
|
||||||
|
Material.GLOW_BERRIES -> FoodInfo(2, 0.4f)
|
||||||
|
Material.BEETROOT -> FoodInfo(1, 1.2f)
|
||||||
|
Material.BEETROOT_SOUP -> FoodInfo(6, 7.2f)
|
||||||
|
Material.CHORUS_FRUIT -> FoodInfo(4, 2.4f)
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -146,6 +146,18 @@ class EventListener(private val plugin: Plugin) : Listener {
|
||||||
dispatchToComponents(item) { it.onItemHeld(player, item, event) }
|
dispatchToComponents(item) { it.onItemHeld(player, item, event) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
fun onFoodLevelChange(event: org.bukkit.event.entity.FoodLevelChangeEvent) {
|
||||||
|
val entity = event.entity
|
||||||
|
if (entity is Player) {
|
||||||
|
// インベントリ内の全アイテムをチェック
|
||||||
|
val items = entity.inventory.contents.filterNotNull()
|
||||||
|
for (item in items) {
|
||||||
|
dispatchToItem(item) { it.onFoodLevelChange(event) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun tickComponents() {
|
private fun tickComponents() {
|
||||||
for (player in plugin.server.onlinePlayers) {
|
for (player in plugin.server.onlinePlayers) {
|
||||||
val uuid = player.uniqueId
|
val uuid = player.uniqueId
|
||||||
|
|
@ -175,17 +187,25 @@ class EventListener(private val plugin: Plugin) : Listener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update Cache
|
|
||||||
// Update Cache
|
// Update Cache
|
||||||
lastHeldItems[uuid] = Pair(currentMainHand, currentOffHand)
|
lastHeldItems[uuid] = Pair(currentMainHand, currentOffHand)
|
||||||
|
|
||||||
// --- Regular Tick Processing ---
|
// --- Regular Tick Processing ---
|
||||||
|
|
||||||
// Armor Tick
|
// 1. Dispatch onTick to ALL CustomItems in inventory
|
||||||
val armorItems = player.inventory.armorContents.filterNotNull()
|
// inventory.contents typically covers storage, hotbar, armor, and offhand depending on implementation,
|
||||||
for (item in armorItems) {
|
// but we iterate it to ensure we catch items anywhere in the inventory.
|
||||||
if (item.type.isAir) continue
|
for (item in player.inventory.contents) {
|
||||||
|
if (item == null || item.type.isAir) continue
|
||||||
dispatchToItem(item) { it.onTick(player, item) }
|
dispatchToItem(item) { it.onTick(player, item) }
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Dispatch to Components for specific slots (Armor, MainHand, OffHand)
|
||||||
|
// Note: dispatchToItem is skipped here because it was already done above for all items.
|
||||||
|
|
||||||
|
// Armor Tick
|
||||||
|
for (item in player.inventory.armorContents) {
|
||||||
|
if (item == null || item.type.isAir) continue
|
||||||
dispatchToComponents(item) { component ->
|
dispatchToComponents(item) { component ->
|
||||||
if (component is EquippableComponent) {
|
if (component is EquippableComponent) {
|
||||||
component.onTick(player, item)
|
component.onTick(player, item)
|
||||||
|
|
@ -195,7 +215,6 @@ class EventListener(private val plugin: Plugin) : Listener {
|
||||||
|
|
||||||
// ToolComponents in Main Hand
|
// ToolComponents in Main Hand
|
||||||
if (!currentMainHand.type.isAir) {
|
if (!currentMainHand.type.isAir) {
|
||||||
dispatchToItem(currentMainHand) { it.onTick(player, currentMainHand) }
|
|
||||||
dispatchToComponents(currentMainHand) { component ->
|
dispatchToComponents(currentMainHand) { component ->
|
||||||
if (component is ToolComponent) {
|
if (component is ToolComponent) {
|
||||||
component.onHoldTick(player, currentMainHand)
|
component.onHoldTick(player, currentMainHand)
|
||||||
|
|
@ -208,7 +227,6 @@ class EventListener(private val plugin: Plugin) : Listener {
|
||||||
|
|
||||||
// ToolComponents in Off Hand
|
// ToolComponents in Off Hand
|
||||||
if (!currentOffHand.type.isAir) {
|
if (!currentOffHand.type.isAir) {
|
||||||
dispatchToItem(currentOffHand) { it.onTick(player, currentOffHand) }
|
|
||||||
dispatchToComponents(currentOffHand) { component ->
|
dispatchToComponents(currentOffHand) { component ->
|
||||||
if (component is ToolComponent) {
|
if (component is ToolComponent) {
|
||||||
component.onHoldTick(player, currentOffHand)
|
component.onHoldTick(player, currentOffHand)
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ components:
|
||||||
"#minecraft:gold_ores": "#FCEE4B"
|
"#minecraft:gold_ores": "#FCEE4B"
|
||||||
"#minecraft:copper_ores": "#966756"
|
"#minecraft:copper_ores": "#966756"
|
||||||
"#minecraft:coal_ores": "#363636"
|
"#minecraft:coal_ores": "#363636"
|
||||||
"#minecraft:redstone_ores": "#FF0000"
|
"#minecraft:redstone_ores": "#FF0000"
|
||||||
"#minecraft:lapis_ores": "#1F61AE"
|
"#minecraft:lapis_ores": "#1F61AE"
|
||||||
"#minecraft:emerald_ores": "#00D93A"
|
"#minecraft:emerald_ores": "#00D93A"
|
||||||
"minecraft:ancient_debr ": "#623A32"
|
"minecraft:ancient_debr ": "#623A32"
|
||||||
|
|
@ -71,3 +71,6 @@ components:
|
||||||
- "minecraft:hay_block"
|
- "minecraft:hay_block"
|
||||||
- "#minecraft:wart_blocks"
|
- "#minecraft:wart_blocks"
|
||||||
|
|
||||||
|
items:
|
||||||
|
auto_feeder:
|
||||||
|
hunger_threshold: 10 # 満腹度がこの値以下になると自動で食事
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user