mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-10-20 14:16:26 -04:00
Migrated the pickup items for foxes and stuff to the config struct
This commit is contained in:
+1
-1
@@ -29,6 +29,6 @@ class EatHeldItemTaskConfig : SingleTaskConfig {
|
||||
behaviourConfigurationContext.addMemories(
|
||||
CobblemonMemories.IS_CONSUMING_ITEM,
|
||||
)
|
||||
return EatHeldItemTask().wrapped<PokemonEntity>()
|
||||
return EatHeldItemTask(entity).wrapped<PokemonEntity>()
|
||||
}
|
||||
}
|
||||
@@ -38,7 +38,9 @@ interface MoLangScriptingEntity {
|
||||
var behavioursAreCustom: Boolean
|
||||
val behaviours: MutableList<ResourceLocation>
|
||||
val registeredVariables: MutableList<MoLangConfigVariable>
|
||||
/** Configuration properties that are managed and reset prior to entity behaviour initialization. */
|
||||
var config: VariableStruct
|
||||
/** Data that is persisted. */
|
||||
var data: VariableStruct
|
||||
var callbacks: EntityCallbacks
|
||||
|
||||
|
||||
@@ -76,6 +76,7 @@ import com.cobblemon.mod.common.entity.generic.GenericBedrockEntity
|
||||
import com.cobblemon.mod.common.entity.npc.NPCEntity
|
||||
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.PokemonMoveControl
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.sensors.PokemonItemSensor
|
||||
import com.cobblemon.mod.common.entity.pokemon.effects.EffectTracker
|
||||
import com.cobblemon.mod.common.entity.pokemon.effects.IllusionEffect
|
||||
import com.cobblemon.mod.common.net.messages.client.OpenBehaviourEditorPacket
|
||||
@@ -96,6 +97,7 @@ import com.cobblemon.mod.common.pokemon.activestate.InactivePokemonState
|
||||
import com.cobblemon.mod.common.pokemon.activestate.SentOutState
|
||||
import com.cobblemon.mod.common.pokemon.activestate.ShoulderedState
|
||||
import com.cobblemon.mod.common.pokemon.ai.FormPokemonBehaviour
|
||||
import com.cobblemon.mod.common.pokemon.ai.ObtainableItem
|
||||
import com.cobblemon.mod.common.pokemon.ai.PokemonBrain
|
||||
import com.cobblemon.mod.common.pokemon.evolution.variants.ItemInteractionEvolution
|
||||
import com.cobblemon.mod.common.pokemon.feature.StashHandler
|
||||
@@ -1049,9 +1051,10 @@ open class PokemonEntity(
|
||||
}
|
||||
|
||||
override fun wantsToPickUp(stack: ItemStack): Boolean {
|
||||
return this.canHoldItem(stack) && (behaviour.itemInteract.getMatchingEntry(stack)?.pickupPriority
|
||||
?: 0) > 0
|
||||
val pickupItems = config.getObjectList<ObtainableItem>(PokemonItemSensor.PICKUP_ITEMS)
|
||||
return this.canHoldItem(stack) && (pickupItems.findMatchingEntry(stack)?.pickupPriority ?: 0) > 0
|
||||
}
|
||||
|
||||
override fun mobInteract(player: Player, hand: InteractionHand): InteractionResult {
|
||||
if (!this.isBattling && this.isBattleClone()) {
|
||||
return InteractionResult.FAIL
|
||||
|
||||
+12
-6
@@ -9,33 +9,39 @@
|
||||
package com.cobblemon.mod.common.entity.pokemon.ai.sensors
|
||||
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.ai.ObtainableItem
|
||||
import com.cobblemon.mod.common.util.findMatchingEntry
|
||||
import com.cobblemon.mod.common.util.getObjectList
|
||||
import com.google.common.collect.ImmutableSet
|
||||
import java.util.Optional
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.Sensor
|
||||
import net.minecraft.world.entity.item.ItemEntity
|
||||
import net.minecraft.world.level.GameRules
|
||||
import java.util.*
|
||||
import java.util.function.Predicate
|
||||
|
||||
class PokemonItemSensor(
|
||||
private val width: Double = 16.0, // TODO: Can we configure sensors dynamically?
|
||||
private val width: Double = 16.0, // TODO: Can we configure sensors dynamically? // Nope. Could be done with a config struct option but it's a bit crass.
|
||||
private val height: Double = 8.0,
|
||||
private val maxTravelDistance: Double = 16.0,
|
||||
) : Sensor<PokemonEntity>(30) {
|
||||
companion object {
|
||||
const val PICKUP_ITEMS = "pickup_items"
|
||||
}
|
||||
|
||||
override fun requires(): MutableSet<MemoryModuleType<*>?> {
|
||||
return ImmutableSet.of<MemoryModuleType<*>?>(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM)
|
||||
}
|
||||
|
||||
override fun doTick(level: ServerLevel, entity: PokemonEntity) {
|
||||
|
||||
val pickupItems = entity.config.getObjectList<ObtainableItem>(PICKUP_ITEMS)
|
||||
if (!level.gameRules.getBoolean(GameRules.RULE_MOBGRIEFING) || !entity.pokemon.canDropHeldItem) {
|
||||
// Mob griefing is disabled or the Pokemon cannot swap out its item, so don't bother to search
|
||||
return
|
||||
}
|
||||
|
||||
val heldItemValue = entity.behaviour.itemInteract.getItemPriority(entity.pokemon.heldItem())
|
||||
if (heldItemValue >= entity.behaviour.itemInteract.highestPriorityItem) {
|
||||
val heldItemValue = pickupItems.findMatchingEntry(entity.pokemon.heldItem())?.pickupPriority ?: 0
|
||||
if (heldItemValue >= (pickupItems.maxOfOrNull { it.pickupPriority } ?: 0)) {
|
||||
// It's already holding the highest value item it can have, no need to look for better.
|
||||
return
|
||||
}
|
||||
|
||||
+8
-4
@@ -11,8 +11,11 @@ package com.cobblemon.mod.common.entity.pokemon.ai.tasks
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.sensors.PokemonItemSensor.Companion.PICKUP_ITEMS
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.tasks.MoveToItemTask.runtime
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.pokemon.ai.ObtainableItem
|
||||
import com.cobblemon.mod.common.util.findMatchingEntry
|
||||
import com.cobblemon.mod.common.util.getObjectList
|
||||
import com.cobblemon.mod.common.util.resolve
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.google.common.collect.ImmutableMap
|
||||
@@ -29,7 +32,7 @@ import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.Items
|
||||
|
||||
|
||||
class EatHeldItemTask : Behavior<PokemonEntity>(
|
||||
class EatHeldItemTask(entity: PokemonEntity) : Behavior<PokemonEntity>(
|
||||
ImmutableMap.of(
|
||||
MemoryModuleType.WALK_TARGET, MemoryStatus.VALUE_ABSENT
|
||||
)
|
||||
@@ -41,6 +44,7 @@ class EatHeldItemTask : Behavior<PokemonEntity>(
|
||||
}
|
||||
|
||||
private var timelastEaten: Long = 0
|
||||
val pickupItems = entity.config.getObjectList<ObtainableItem>(PICKUP_ITEMS)
|
||||
|
||||
override fun checkExtraStartConditions(world: ServerLevel, entity: PokemonEntity): Boolean {
|
||||
if (timelastEaten + COOLDOWN > world.gameTime) {
|
||||
@@ -55,7 +59,7 @@ class EatHeldItemTask : Behavior<PokemonEntity>(
|
||||
}
|
||||
|
||||
private fun canEat(item: ItemStack, entity: PokemonEntity): Boolean {
|
||||
return item.has(DataComponents.FOOD) || item.item == Items.POTION || entity.behaviour.itemInteract.getOnUseEffect(item) != null
|
||||
return item.has(DataComponents.FOOD) || item.item == Items.POTION || pickupItems.findMatchingEntry(item)?.onUseEffect != null
|
||||
}
|
||||
|
||||
override fun start(world: ServerLevel, entity: PokemonEntity, time: Long) {
|
||||
@@ -70,7 +74,7 @@ class EatHeldItemTask : Behavior<PokemonEntity>(
|
||||
override fun tick(world: ServerLevel, entity: PokemonEntity, time: Long) {
|
||||
if (!world.isClientSide && entity.isAlive && entity.isEffectiveAi) {
|
||||
val itemStack: ItemStack = entity.pokemon.heldItem()
|
||||
val itemConfig = entity.behaviour.itemInteract.getMatchingEntry(itemStack)
|
||||
val itemConfig = pickupItems.findMatchingEntry(itemStack)
|
||||
if (canEat(itemStack, entity)) {
|
||||
if (this.timelastEaten + MAX_DURATION <= time) {
|
||||
var resultItemStack = itemStack.finishUsingItem(world, entity)
|
||||
|
||||
@@ -259,7 +259,6 @@ class FormData(
|
||||
this.evolutions.size
|
||||
this._lightingData?.let { this._lightingData = it.copy(lightLevel = it.lightLevel.coerceIn(0, 15)) }
|
||||
behaviour.herd.initialize()
|
||||
behaviour.itemInteract.initialize()
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
@@ -31,8 +31,8 @@ import com.cobblemon.mod.common.api.pokemon.evolution.PreEvolution
|
||||
import com.cobblemon.mod.common.api.pokemon.experience.ExperienceGroups
|
||||
import com.cobblemon.mod.common.api.pokemon.moves.Learnset
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stat
|
||||
import com.cobblemon.mod.common.api.storage.InvalidSpeciesException
|
||||
import com.cobblemon.mod.common.api.riding.RidingProperties
|
||||
import com.cobblemon.mod.common.api.storage.InvalidSpeciesException
|
||||
import com.cobblemon.mod.common.api.types.ElementalType
|
||||
import com.cobblemon.mod.common.api.types.ElementalTypes
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.FLYING_POSES
|
||||
@@ -190,7 +190,6 @@ class Species : ClientDataSynchronizer<Species>, ShowdownIdentifiable {
|
||||
this.preEvolution?.form
|
||||
this.evolutions.size
|
||||
behaviour.herd.initialize()
|
||||
behaviour.itemInteract.initialize()
|
||||
}
|
||||
|
||||
// Ran after initialize due to us creating a Pokémon here which requires all the properties in #initialize to be present for both this and the results, this is the easiest way to quickly resolve species + form
|
||||
|
||||
@@ -8,47 +8,16 @@
|
||||
|
||||
package com.cobblemon.mod.common.pokemon.ai
|
||||
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import kotlin.math.max
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import com.cobblemon.mod.common.util.asArrayValue
|
||||
|
||||
class ItemBehavior {
|
||||
private val desiredItems = mutableListOf<ObtainableItem>()
|
||||
@Transient
|
||||
var highestPriorityItem = 0
|
||||
|
||||
fun getMatchingEntry(stack: ItemStack): ObtainableItem? {
|
||||
val registryAccess = server()?.registryAccess() ?: return null
|
||||
return if (stack == ItemStack.EMPTY) {
|
||||
null
|
||||
} else {
|
||||
desiredItems.find { it.item?.isItemObtainable(registryAccess, stack) != false }
|
||||
}
|
||||
}
|
||||
private val desiredItems = listOf<ObtainableItem>()
|
||||
|
||||
@Transient
|
||||
val struct = ObjectValue(this).also {
|
||||
it.addFunction("add_pickup_item") { params ->
|
||||
addPickupItem(params.get<ObjectValue<ObtainableItem>>(0).obj)
|
||||
it.addFunction("pickup_items") {
|
||||
return@addFunction desiredItems.asArrayValue(ObtainableItem::struct)
|
||||
}
|
||||
}
|
||||
|
||||
fun getItemPriority(stack: ItemStack): Int {
|
||||
return getMatchingEntry(stack)?.pickupPriority ?: 0
|
||||
}
|
||||
|
||||
fun getOnUseEffect(stack: ItemStack): ExpressionLike? {
|
||||
return getMatchingEntry(stack)?.onUseEffect
|
||||
}
|
||||
|
||||
fun addPickupItem(entry: ObtainableItem) {
|
||||
desiredItems.add(entry)
|
||||
highestPriorityItem = max(entry.pickupPriority, highestPriorityItem)
|
||||
}
|
||||
|
||||
fun initialize() {
|
||||
highestPriorityItem = desiredItems.maxOfOrNull { it.pickupPriority } ?: 0
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
|
||||
import com.cobblemon.mod.common.entity.npc.NPCEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.ai.ObtainableItem
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.screens.Screen
|
||||
import java.util.UUID
|
||||
@@ -27,6 +28,7 @@ import net.minecraft.network.chat.Component
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.entity.EquipmentSlot
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.pathfinder.Node
|
||||
import net.minecraft.world.level.pathfinder.Path
|
||||
import net.minecraft.world.phys.shapes.VoxelShape
|
||||
@@ -202,4 +204,14 @@ fun Path.deleteNode(index: Int) {
|
||||
for (node in correctNodes) {
|
||||
this.replaceNode(i++, node)
|
||||
}
|
||||
}
|
||||
|
||||
fun Collection<ObtainableItem>.findMatchingEntry(stack: ItemStack): ObtainableItem? {
|
||||
val server = server() ?: return null
|
||||
val registryAccess = server.registryAccess()
|
||||
return if (stack == ItemStack.EMPTY) {
|
||||
null
|
||||
} else {
|
||||
this.find { it.item?.isItemObtainable(registryAccess, stack) != false }
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.MoParams
|
||||
import com.bedrockk.molang.runtime.struct.ArrayStruct
|
||||
import com.bedrockk.molang.runtime.struct.ContextStruct
|
||||
import com.bedrockk.molang.runtime.struct.VariableStruct
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
@@ -203,6 +204,22 @@ fun ArrayStruct.getString(index: Int) = map["$index"]!!.asString()
|
||||
fun ArrayStruct.asBlockPos() = BlockPos(getDouble(0).toInt(), getDouble(1).toInt(), getDouble(2).toInt())
|
||||
fun ArrayStruct.asVec3d() = Vec3(getDouble(0), getDouble(1), getDouble(2))
|
||||
|
||||
fun <T> VariableStruct.getObject(name: String): T? {
|
||||
val value = map[name] ?: return null
|
||||
if (value !is ObjectValue<*>) {
|
||||
return null
|
||||
}
|
||||
return value.obj as? T
|
||||
}
|
||||
|
||||
fun <T> VariableStruct.getObjectList(name: String): List<T> {
|
||||
val value = map[name] ?: return emptyList()
|
||||
if (value !is ArrayStruct) {
|
||||
return emptyList()
|
||||
}
|
||||
return value.map.values.mapNotNull { (it as? ObjectValue<T>)?.obj }
|
||||
}
|
||||
|
||||
fun MoLangRuntime.clone(): MoLangRuntime {
|
||||
val runtime = MoLangRuntime()
|
||||
runtime.environment.cloneFrom(environment)
|
||||
|
||||
@@ -26,6 +26,10 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "script",
|
||||
"script": "cobblemon:add_pickup_items"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -5,15 +5,16 @@ q.entity.behaviour.block_interact.set_immune_to_sweet_berry_bush_block(true);
|
||||
t.fox_food = q.create_pickup_item('#minecraft:fox_food', 5);
|
||||
t.fox_food.set_fullness_value(2);
|
||||
t.fox_food.set_on_use_effect('q.entity.heal(2)');
|
||||
q.entity.behaviour.item_interact.add_pickup_item(t.fox_food);
|
||||
q.append(q.entity.config.pickup_items, t.fox_food);
|
||||
|
||||
'Add regular food to the pickup behaviour';
|
||||
t.regular_food = q.create_pickup_item('q.item.is_food()', 4);
|
||||
t.regular_food.set_fullness_value(1);
|
||||
t.regular_food.set_on_use_effect('q.entity.heal(1)');
|
||||
q.entity.behaviour.item_interact.add_pickup_item(t.regular_food);
|
||||
q.append(q.entity.config.pickup_items, t.regular_food);
|
||||
|
||||
'Add a generic item to the pickup behaviour';
|
||||
'Add items in general to the pickup behaviour since foxes love picking up shit';
|
||||
t.generic_item = q.create_pickup_item(true, 1);
|
||||
t.generic_item.set_fullness_value(0);
|
||||
q.entity.behaviour.item_interact.add_pickup_item(t.generic_item);
|
||||
q.entity.behaviour.item_interact.add_pickup_item(t.generic_item);
|
||||
q.append(q.entity.config.pickup_items, t.generic_item);
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
'This script adds all the pickup items from the Pokemon (the species file) to the config struct';
|
||||
|
||||
t.poke = q.entity;
|
||||
t.index = 0;
|
||||
t.pickup_items = q.array();
|
||||
for_each(t.item, t.poke.behaviour.item_interact.pickup_items, {
|
||||
t.pickup_items[t.index] = t.item;
|
||||
t.index = t.index + 1;
|
||||
});
|
||||
t.poke.config.pickup_items = t.pickup_items;
|
||||
Binary file not shown.
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>local.com.bedrockk</groupId>
|
||||
<artifactId>molang</artifactId>
|
||||
<version>1.1.19</version>
|
||||
</project>
|
||||
+3
-3
@@ -3,10 +3,10 @@
|
||||
<groupId>local.com.bedrockk</groupId>
|
||||
<artifactId>molang</artifactId>
|
||||
<versioning>
|
||||
<release>1.1.18</release>
|
||||
<release>1.1.19</release>
|
||||
<versions>
|
||||
<version>1.1.18</version>
|
||||
<version>1.1.19</version>
|
||||
</versions>
|
||||
<lastUpdated>20231949390005</lastUpdated>
|
||||
<lastUpdated>20231949390006</lastUpdated>
|
||||
</versioning>
|
||||
</metadata>
|
||||
|
||||
@@ -14,7 +14,7 @@ loom = "1.10-SNAPSHOT"
|
||||
architectury-plugin = "3.4-SNAPSHOT"
|
||||
|
||||
# Common
|
||||
molang = "1.1.18"
|
||||
molang = "1.1.19"
|
||||
graal = "22.3.0"
|
||||
icu4j = "71.1"
|
||||
jei-api = "19.21.2.313"
|
||||
|
||||
Reference in New Issue
Block a user