mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-11-06 08:18:53 -05:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d59892c65e | ||
|
|
d133c66f3f |
No files matched your search
@@ -47,7 +47,6 @@ import com.cobblemon.mod.common.block.RevivalHerbBlock
|
||||
import com.cobblemon.mod.common.block.SaccharineLeafBlock
|
||||
import com.cobblemon.mod.common.block.SaccharineLogBlock
|
||||
import com.cobblemon.mod.common.block.SaccharineLogSlatheredBlock
|
||||
import com.cobblemon.mod.common.block.ScarekrowBlock
|
||||
import com.cobblemon.mod.common.block.StackableItemBlock
|
||||
import com.cobblemon.mod.common.block.TumblestoneBlock
|
||||
import com.cobblemon.mod.common.block.TypeGemClusterBlock
|
||||
@@ -1161,15 +1160,6 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
}
|
||||
))
|
||||
|
||||
@JvmField
|
||||
val SCAREKROW = this.create("scarekrow", ScarekrowBlock(
|
||||
BlockBehaviour.Properties.of()
|
||||
.pushReaction(PushReaction.DESTROY)
|
||||
.sound(SoundType.GRASS)
|
||||
.strength(0.1f)
|
||||
.noOcclusion()
|
||||
))
|
||||
|
||||
init {
|
||||
/**
|
||||
* Makes all blocks in array flammable by adding them to FireBlock's flammableRegistry.
|
||||
|
||||
@@ -205,8 +205,6 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val CAMPFIRE_POT_WHITE = campfirePotItem(CobblemonBlocks.WHITE_CAMPFIRE_POT, CampfirePotColor.WHITE)
|
||||
|
||||
@JvmField
|
||||
val SCAREKROW = blockItem("scarekrow", CobblemonBlocks.SCAREKROW)
|
||||
@JvmField
|
||||
val HEARTY_GRAINS = compostableItem("hearty_grains", ItemNameBlockItem(CobblemonBlocks.HEARTY_GRAINS, Properties().rarity(Rarity.COMMON)))
|
||||
@JvmField
|
||||
|
||||
@@ -114,8 +114,6 @@ object CobblemonMemories {
|
||||
val DISABLE_WALK_TO_WANTED_ITEM = register<Boolean>("disable_walk_to_wanted_item")
|
||||
@JvmField
|
||||
val TIME_TRYING_TO_REACH_WANTED_ITEM = register<Int>("time_trying_to_wanted_item")
|
||||
@JvmField
|
||||
val NEARBY_SCAREKROW = register<BlockPos>("nearby_scarekrow", BlockPos.CODEC)
|
||||
|
||||
@JvmStatic
|
||||
fun <U> register(id: String, codec: Codec<U>): MemoryModuleType<U> {
|
||||
|
||||
-167
@@ -1,167 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.biggerbrain.objective
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.Priority
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asSimplifiedExpression
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.ai.biggerbrain.BiggerBrain
|
||||
import com.cobblemon.mod.common.api.ai.biggerbrain.LookingTracker
|
||||
import com.cobblemon.mod.common.api.ai.biggerbrain.RegularMovementTracker
|
||||
import com.cobblemon.mod.common.api.ai.biggerbrain.distraction.Distraction
|
||||
import com.cobblemon.mod.common.api.ai.biggerbrain.distraction.DistractionType
|
||||
import com.cobblemon.mod.common.api.ai.biggerbrain.fixation.ConditionalLockFixation
|
||||
import com.cobblemon.mod.common.api.ai.biggerbrain.fixation.EntityFixation
|
||||
import com.cobblemon.mod.common.api.ai.biggerbrain.fixation.LookAndMoveFixation
|
||||
import com.cobblemon.mod.common.api.ai.config.objective.ObjectiveConfig
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonBlockTags
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.mainThreadRuntime
|
||||
import com.cobblemon.mod.common.util.resolveFloat
|
||||
import com.cobblemon.mod.common.util.toVec3d
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.memory.WalkTarget
|
||||
import net.minecraft.world.entity.ai.util.LandRandomPos
|
||||
|
||||
class AvoidScarekrow(
|
||||
private val speedMultiplier: Expression = "0.5".asExpression(),
|
||||
) : Objective {
|
||||
private var movementTask: EntityFixation? = null
|
||||
private var remainingCooldownTicks = 0
|
||||
|
||||
override fun getDescription(entity: LivingEntity) = "Avoiding target block"
|
||||
|
||||
override fun perform(
|
||||
entity: LivingEntity,
|
||||
brain: BiggerBrain,
|
||||
activeObjectiveTags: MutableSet<String>
|
||||
): ObjectiveStatus {
|
||||
if (entity !is PokemonEntity || !entity.isAlive) return ObjectiveStatus.INVALID
|
||||
|
||||
val target = brain.getMemory(CobblemonMemories.NEARBY_SCAREKROW)
|
||||
?: return ObjectiveStatus.INACTIVE
|
||||
|
||||
// if the scarekrow is gone we dont need to be scared anymore
|
||||
if (!entity.level().getBlockState(target).`is`(CobblemonBlockTags.SCAREKROWS)) {
|
||||
brain.eraseMemory(CobblemonMemories.NEARBY_SCAREKROW)
|
||||
return ObjectiveStatus.INACTIVE
|
||||
}
|
||||
|
||||
// finish existing movement task
|
||||
if (brain.isFixation(movementTask)) {
|
||||
return ObjectiveStatus.FIXATED
|
||||
}
|
||||
|
||||
// aggro against the player should take priority
|
||||
if (brain.getMemory(MemoryModuleType.ATTACK_TARGET) != null) {
|
||||
return ObjectiveStatus.BLOCKED
|
||||
}
|
||||
|
||||
if (remainingCooldownTicks > 0) {
|
||||
remainingCooldownTicks--
|
||||
}
|
||||
val runtime = mainThreadRuntime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
val speed = runtime.resolveFloat(speedMultiplier)
|
||||
|
||||
if (!brain.distract(Distraction.FORCE)) return ObjectiveStatus.BLOCKED
|
||||
var targetPos : BlockPos? = null
|
||||
|
||||
// fixate on running from the scarekrow until it is out of range
|
||||
brain.fixate(ConditionalLockFixation("Avoiding scarekrow") {
|
||||
brain.getMemory(CobblemonMemories.NEARBY_SCAREKROW) != null
|
||||
})
|
||||
|
||||
// find position
|
||||
val direction = entity.position().subtract(target.toVec3d())
|
||||
for (j in 0..9) {
|
||||
val targetVec3 = LandRandomPos.getPosAway(entity, (Cobblemon.config.scarekrowRadius * 1.2).toInt(), 7, direction)
|
||||
if (targetVec3 != null) {
|
||||
targetPos = BlockPos.containing(targetVec3)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Start a look-and-move fixation only when navigation accepts the selected position.
|
||||
if (targetPos != null) {
|
||||
val movementTracker = RegularMovementTracker.attempt(
|
||||
entity = entity,
|
||||
walkTarget = WalkTarget(
|
||||
targetPos,
|
||||
speed,
|
||||
0
|
||||
)
|
||||
)
|
||||
if (movementTracker != null) {
|
||||
movementTask = brain.fixate(
|
||||
LookAndMoveFixation(
|
||||
distractionTypes = setOf(
|
||||
DistractionType.FORCE
|
||||
),
|
||||
lookingTracker = LookingTracker.fromNavigationPathOrWalkTarget(
|
||||
entity,
|
||||
movementTracker.walkTarget
|
||||
),
|
||||
movementTracker = movementTracker,
|
||||
description = "Moving away from target block",
|
||||
)
|
||||
)
|
||||
return ObjectiveStatus.FIXATED
|
||||
}
|
||||
}
|
||||
|
||||
return ObjectiveStatus.FIXATED
|
||||
}
|
||||
|
||||
override fun onRegister(entity: LivingEntity, brain: BiggerBrain) {
|
||||
brain.subscribe(
|
||||
priority = Priority.LOW,
|
||||
memory = CobblemonMemories.NEARBY_SCAREKROW,
|
||||
) { value, labels ->
|
||||
if (value == null) {
|
||||
if (brain.isFixation(movementTask)) {
|
||||
brain.distract(Distraction.FORCE)
|
||||
movementTask = null
|
||||
}
|
||||
}
|
||||
return@subscribe true
|
||||
}
|
||||
}
|
||||
|
||||
class Config : ObjectiveConfig {
|
||||
val speedMultiplier: ExpressionOrEntityVariable = Either.left("0.5".asExpression())
|
||||
|
||||
override fun getVariables(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): List<MoLangConfigVariable> {
|
||||
return listOf(speedMultiplier).asVariables()
|
||||
}
|
||||
|
||||
override fun create(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): Objective {
|
||||
return AvoidScarekrow(
|
||||
speedMultiplier = speedMultiplier.asSimplifiedExpression(entity),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -300,7 +300,7 @@ class DefendNest(
|
||||
description = "patrol method in DefendNest objective",
|
||||
lookingTracker = LookingTracker.fromNavigationPathOrWalkTarget(entity, tracker.walkTarget),
|
||||
movementTracker = tracker,
|
||||
onMovementComplete = { entity1, brain1, status -> patrolCooldownTicks = PATROL_PAUSE_TICKS + entity.random.nextInt(PATROL_PAUSE_RANDOM_TICKS) }
|
||||
onMovementComplete = { _, _ -> patrolCooldownTicks = PATROL_PAUSE_TICKS + entity.random.nextInt(PATROL_PAUSE_RANDOM_TICKS) }
|
||||
)
|
||||
)
|
||||
return ObjectiveStatus.FIXATED
|
||||
|
||||
+2
-1
@@ -33,6 +33,7 @@ import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.behavior.EntityTracker
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.memory.NearestVisibleLivingEntities
|
||||
import net.minecraft.world.entity.ai.memory.WalkTarget
|
||||
|
||||
|
||||
@@ -155,7 +156,7 @@ class FriendlyBehaviour(
|
||||
),
|
||||
lookingTracker = LookingTracker.forTargetEntity(entity, trackedEntity!!),
|
||||
movementTracker = movementTracker,
|
||||
onMovementComplete = { entity1, brain1, status -> attemptFixation(entity, brain) } // maintains fixation between moving and looking
|
||||
onMovementComplete = { _, _ -> attemptFixation(entity, brain) } // maintains fixation between moving and looking
|
||||
)
|
||||
)
|
||||
return ObjectiveStatus.FIXATED
|
||||
|
||||
+7
-1
@@ -14,15 +14,21 @@ import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.ai.biggerbrain.BiggerBrain
|
||||
import com.cobblemon.mod.common.api.ai.biggerbrain.LookingTracker
|
||||
import com.cobblemon.mod.common.api.ai.biggerbrain.MovementTracker
|
||||
import com.cobblemon.mod.common.api.ai.biggerbrain.RegularMovementTracker
|
||||
import com.cobblemon.mod.common.api.ai.biggerbrain.distraction.Distraction
|
||||
import com.cobblemon.mod.common.api.ai.biggerbrain.distraction.DistractionType
|
||||
import com.cobblemon.mod.common.api.ai.biggerbrain.distraction.comfortDistraction
|
||||
import com.cobblemon.mod.common.api.ai.biggerbrain.distraction.idleBoredomDistraction
|
||||
import com.cobblemon.mod.common.api.ai.biggerbrain.fixation.EntityFixation
|
||||
import com.cobblemon.mod.common.api.ai.biggerbrain.fixation.LookAndMoveFixation
|
||||
import com.cobblemon.mod.common.api.ai.biggerbrain.fixation.MovementTrackerFixation
|
||||
import com.cobblemon.mod.common.api.ai.config.objective.ObjectiveConfig
|
||||
import com.cobblemon.mod.common.api.ai.resolveFloat
|
||||
import com.cobblemon.mod.common.api.ai.resolveInt
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.PokemonMoveControl
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
@@ -86,7 +92,7 @@ class WalkTowardsParent(
|
||||
distractionTypes = setOf(DistractionType.DAMAGE, DistractionType.FORCE), // We are very fine to ignore this movement if forced or hurt
|
||||
lookingTracker = LookingTracker.forTargetEntity(entity, adult),
|
||||
movementTracker = movementTracker,
|
||||
onMovementComplete = { entity1, brain1, status -> cooldownTicks = 60 }
|
||||
onMovementComplete = { _, _ -> cooldownTicks = 60 }
|
||||
)
|
||||
)
|
||||
return ObjectiveStatus.FIXATED // We are now fixated on
|
||||
|
||||
-105
@@ -1,105 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.biggerbrain.sense
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.ai.biggerbrain.BiggerBrain
|
||||
import com.cobblemon.mod.common.api.ai.config.sense.SenseConfig
|
||||
import com.cobblemon.mod.common.api.ai.resolveInt
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonBlockTags
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.distanceTo
|
||||
import com.cobblemon.mod.common.util.getMemorySafely
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Vec3i
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
class ScarekrowSense(
|
||||
private var cooldownTicks: Int = SCAN_INTERVAL
|
||||
) : Sense {
|
||||
override var ticksUntilNextExecution: Int = cooldownTicks
|
||||
override val memories = setOf(
|
||||
CobblemonMemories.NEARBY_SCAREKROW,
|
||||
)
|
||||
|
||||
override fun merge(other: Sense): Boolean {
|
||||
if (other is ScarekrowSense) {
|
||||
this.cooldownTicks = minOf(this.cooldownTicks, other.cooldownTicks)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun tick(entity: LivingEntity, brain: BiggerBrain) {
|
||||
ticksUntilNextExecution = cooldownTicks
|
||||
val brain = entity.brain
|
||||
|
||||
val searchRadius = Cobblemon.config.scarekrowRadius
|
||||
val currPos: BlockPos? = brain.getMemorySafely(CobblemonMemories.NEARBY_SCAREKROW).orElse(null)
|
||||
|
||||
if (currPos != null && entity.level().getBlockState(currPos).`is`(CobblemonBlockTags.SCAREKROWS)) {
|
||||
val distance = entity.distanceTo(currPos)
|
||||
if (distance > searchRadius) {
|
||||
brain.eraseMemory(CobblemonMemories.NEARBY_SCAREKROW)
|
||||
}
|
||||
}
|
||||
|
||||
val centerPos = entity.blockPosition()
|
||||
var scarekrowPos: BlockPos? = null
|
||||
var shortestDist = Double.MAX_VALUE
|
||||
val world = entity.level()
|
||||
BlockPos.betweenClosedStream(
|
||||
centerPos.offset(-searchRadius, -searchRadius, -searchRadius),
|
||||
centerPos.offset(searchRadius, searchRadius, searchRadius)
|
||||
).forEach { pos ->
|
||||
val state = world.getBlockState(pos)
|
||||
if (state.`is`(CobblemonBlockTags.SCAREKROWS)) {
|
||||
val distance = pos.distSqr(Vec3i(centerPos.x, centerPos.y, centerPos.z))
|
||||
if (distance < shortestDist) {
|
||||
scarekrowPos = BlockPos(pos)
|
||||
shortestDist = distance
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (scarekrowPos != null) {
|
||||
brain.setMemory(CobblemonMemories.NEARBY_SCAREKROW, scarekrowPos)
|
||||
} else {
|
||||
brain.eraseMemory(CobblemonMemories.NEARBY_SCAREKROW)
|
||||
}
|
||||
}
|
||||
|
||||
class Config : SenseConfig {
|
||||
var condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
var cooldownTicks: ExpressionOrEntityVariable = Either.left("3".asExpression())
|
||||
|
||||
override fun getVariables(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
) = listOf(cooldownTicks).asVariables()
|
||||
|
||||
override fun create(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext): Sense {
|
||||
val cooldownTicks = cooldownTicks.resolveInt(behaviourConfigurationContext.runtime)
|
||||
return ScarekrowSense(
|
||||
cooldownTicks = cooldownTicks
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val SCAN_INTERVAL = 3
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+1
-2
@@ -40,7 +40,6 @@ import com.cobblemon.mod.common.api.ai.biggerbrain.objective.WanderAround
|
||||
import com.cobblemon.mod.common.api.ai.biggerbrain.objective.JumpOutOfWater
|
||||
import com.cobblemon.mod.common.api.ai.biggerbrain.objective.NeutralBehaviour
|
||||
import com.cobblemon.mod.common.api.ai.biggerbrain.objective.PointToSpawn
|
||||
import com.cobblemon.mod.common.api.ai.biggerbrain.objective.AvoidScarekrow
|
||||
import com.cobblemon.mod.common.api.ai.biggerbrain.objective.SkittishBehaviour
|
||||
import com.cobblemon.mod.common.api.ai.biggerbrain.objective.TerritorialBehaviour
|
||||
import com.cobblemon.mod.common.api.ai.biggerbrain.objective.WalkTowardsParent
|
||||
@@ -87,7 +86,7 @@ interface ObjectiveConfig {
|
||||
cobblemonResource("combat_neutral") to NeutralBehaviour.Config::class.java,
|
||||
cobblemonResource("combat_skittish") to SkittishBehaviour.Config::class.java,
|
||||
cobblemonResource("behaviour_friendly") to FriendlyBehaviour.Config::class.java,
|
||||
cobblemonResource("avoid_scarekrow") to AvoidScarekrow.Config::class.java,
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ import com.cobblemon.mod.common.api.ai.biggerbrain.sense.NearbyEntitiesSense
|
||||
import com.cobblemon.mod.common.api.ai.biggerbrain.sense.PokemonAdultSense
|
||||
import com.cobblemon.mod.common.api.ai.biggerbrain.sense.PokemonItemSense
|
||||
import com.cobblemon.mod.common.api.ai.biggerbrain.sense.SaccLeafSense
|
||||
import com.cobblemon.mod.common.api.ai.biggerbrain.sense.ScarekrowSense
|
||||
import com.cobblemon.mod.common.api.ai.biggerbrain.sense.Sense
|
||||
import com.cobblemon.mod.common.api.ai.biggerbrain.sense.SweetBerryBushSense
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
@@ -58,7 +57,6 @@ interface SenseConfig {
|
||||
cobblemonResource("flower_sense") to FlowerSense.Config::class.java,
|
||||
cobblemonResource("beehive_sense") to BeeHiveSense.Config::class.java,
|
||||
cobblemonResource("sacc_leaf_sense") to SaccLeafSense.Config::class.java,
|
||||
cobblemonResource("scarekrow_sense") to ScarekrowSense.Config::class.java,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -79,7 +79,6 @@ object CobblemonBlockTags {
|
||||
@JvmField val SEES_SKY = createTag("sees_sky")
|
||||
@JvmField val SHINY_STONE_ORES = createTag("shiny_stone_ores")
|
||||
@JvmField val SIGNS = createTag("signs")
|
||||
@JvmField val SCAREKROWS = createTag("scarekrows")
|
||||
@JvmField val SKY_TUMBLESTONE_BRICKS = createTag("sky_tumblestone_bricks")
|
||||
@JvmField val SKY_TUMBLESTONES = createTag("sky_tumblestones")
|
||||
@JvmField val SMALL_FLOWERS = createTag("small_flowers")
|
||||
|
||||
@@ -1,151 +0,0 @@
|
||||
package com.cobblemon.mod.common.block
|
||||
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.util.StringRepresentable
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.context.BlockPlaceContext
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.LevelAccessor
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.Blocks
|
||||
import net.minecraft.world.level.block.HorizontalDirectionalBlock
|
||||
import net.minecraft.world.level.block.LevelEvent
|
||||
import net.minecraft.world.level.block.Mirror
|
||||
import net.minecraft.world.level.block.Rotation
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.block.state.StateDefinition
|
||||
import net.minecraft.world.level.block.state.properties.EnumProperty
|
||||
import net.minecraft.world.level.block.state.properties.Property
|
||||
import net.minecraft.world.level.storage.loot.LootParams
|
||||
import net.minecraft.world.level.material.Fluids
|
||||
import net.minecraft.world.level.pathfinder.PathComputationType
|
||||
|
||||
/**
|
||||
* Based off PCBlock's double block functionality, but for less specific use cases
|
||||
*
|
||||
* @author whatsy
|
||||
* @since September 30, 2026
|
||||
* @see PCBlock
|
||||
*/
|
||||
open class DoubleBlock(properties: Properties): Block(properties) {
|
||||
|
||||
companion object {
|
||||
val HALF: Property<Half> = EnumProperty.create("half", Half::class.java)
|
||||
}
|
||||
|
||||
enum class Half(private val label: String): StringRepresentable {
|
||||
TOP("top"),
|
||||
BOTTOM("bottom"), ;
|
||||
override fun getSerializedName(): String = label
|
||||
}
|
||||
|
||||
init {
|
||||
registerDefaultState(stateDefinition.any()
|
||||
.setValue(HALF, Half.BOTTOM)
|
||||
.setValue(HorizontalDirectionalBlock.FACING, Direction.NORTH)
|
||||
)
|
||||
}
|
||||
|
||||
fun getPositionOfOtherPart(state: BlockState, pos: BlockPos): BlockPos {
|
||||
return if(state.getValue(HALF) == Half.BOTTOM) {
|
||||
pos.above()
|
||||
} else {
|
||||
pos.below()
|
||||
}
|
||||
}
|
||||
|
||||
fun getBasePosition(state: BlockState, pos: BlockPos): BlockPos {
|
||||
return if (isBase(state)) {
|
||||
pos
|
||||
} else {
|
||||
pos.below()
|
||||
}
|
||||
}
|
||||
|
||||
private fun isBase(state: BlockState): Boolean = state.getValue(HALF) == Half.BOTTOM
|
||||
|
||||
override fun setPlacedBy(level: Level, pos: BlockPos, state: BlockState, placer: LivingEntity?, stack: ItemStack) {
|
||||
level.setBlock(pos.above(),state.setValue(HALF, Half.TOP), 3)
|
||||
level.blockUpdated(pos, Blocks.AIR)
|
||||
state.updateNeighbourShapes(level, pos, 3)
|
||||
}
|
||||
|
||||
override fun getDrops(state: BlockState, params: LootParams.Builder): List<ItemStack> {
|
||||
return if (state.getValue(HALF) == Half.TOP) emptyList() else super.getDrops(state, params)
|
||||
}
|
||||
|
||||
override fun getStateForPlacement(context: BlockPlaceContext): BlockState? {
|
||||
val abovePosition = context.clickedPos.above()
|
||||
val world = context.level
|
||||
if (world.getBlockState(abovePosition).canBeReplaced(context) && !world.isOutsideBuildHeight(abovePosition)) {
|
||||
return defaultBlockState()
|
||||
.setValue(HorizontalDirectionalBlock.FACING, context.horizontalDirection)
|
||||
.setValue(HALF, Half.BOTTOM)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
override fun playerWillDestroy(world: Level, pos: BlockPos, state: BlockState, player: Player): BlockState {
|
||||
if (!world.isClientSide && player.isCreative) {
|
||||
var blockPos: BlockPos = BlockPos.ZERO
|
||||
var blockState: BlockState = state
|
||||
val part = state.getValue(HALF)
|
||||
if (part == Half.TOP && world.getBlockState(pos.below().also { blockPos = it }).also { blockState = it }.`is`(state.block) && blockState.getValue(HALF) == Half.BOTTOM) {
|
||||
val blockState2 = if (blockState.fluidState.`is`(Fluids.WATER)) Blocks.WATER.defaultBlockState() else Blocks.AIR.defaultBlockState()
|
||||
world.setBlock(blockPos, blockState2, UPDATE_ALL or UPDATE_SUPPRESS_DROPS)
|
||||
world.levelEvent(player, LevelEvent.PARTICLES_DESTROY_BLOCK, blockPos, getId(blockState))
|
||||
}
|
||||
}
|
||||
return super.playerWillDestroy(world, pos, state, player)
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun isPathfindable(
|
||||
blockState: BlockState,
|
||||
pathComputationType: PathComputationType
|
||||
): Boolean = false
|
||||
|
||||
override fun createBlockStateDefinition(builder: StateDefinition.Builder<Block?, BlockState?>) {
|
||||
builder.add(HorizontalDirectionalBlock.FACING)
|
||||
builder.add(HALF)
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun rotate(blockState: BlockState, rotation: Rotation) =
|
||||
blockState.setValue(
|
||||
HorizontalDirectionalBlock.FACING, rotation.rotate(blockState.getValue(
|
||||
HorizontalDirectionalBlock.FACING)))
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun mirror(blockState: BlockState, mirror: Mirror): BlockState {
|
||||
return blockState.rotate(mirror.getRotation(blockState.getValue(HorizontalDirectionalBlock.FACING)))
|
||||
}
|
||||
|
||||
override fun onRemove(state: BlockState, world: Level, pos: BlockPos, newState: BlockState, moved: Boolean) {
|
||||
if (!state.`is`(newState.block)) super.onRemove(state, world, pos, newState, moved)
|
||||
}
|
||||
|
||||
override fun updateShape(
|
||||
state: BlockState,
|
||||
direction: Direction,
|
||||
neighborState: BlockState,
|
||||
world: LevelAccessor,
|
||||
pos: BlockPos,
|
||||
neighborPos: BlockPos
|
||||
): BlockState {
|
||||
val isThis = neighborState.`is`(this)
|
||||
val part = state.getValue(HALF)
|
||||
if (!isThis && part == Half.TOP && neighborPos == pos.below()) {
|
||||
return Blocks.AIR.defaultBlockState()
|
||||
} else if (!isThis && part == Half.BOTTOM && neighborPos == pos.above()) {
|
||||
return Blocks.AIR.defaultBlockState()
|
||||
}
|
||||
|
||||
return state
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
package com.cobblemon.mod.common.block
|
||||
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.util.StringRepresentable
|
||||
import net.minecraft.world.InteractionResult
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.level.BlockGetter
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.HorizontalDirectionalBlock
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.block.state.StateDefinition
|
||||
import net.minecraft.world.level.block.state.properties.EnumProperty
|
||||
import net.minecraft.world.level.pathfinder.PathComputationType
|
||||
import net.minecraft.world.phys.BlockHitResult
|
||||
import net.minecraft.world.phys.shapes.CollisionContext
|
||||
import net.minecraft.world.phys.shapes.VoxelShape
|
||||
|
||||
class ScarekrowBlock(properties: Properties): DoubleBlock(properties) {
|
||||
|
||||
companion object {
|
||||
val POSE = EnumProperty.create("pose", Pose::class.java)
|
||||
}
|
||||
|
||||
init {
|
||||
registerDefaultState(stateDefinition.any()
|
||||
.setValue(HALF, Half.BOTTOM)
|
||||
.setValue(POSE, Pose.DEFAULT)
|
||||
.setValue(HorizontalDirectionalBlock.FACING, Direction.NORTH)
|
||||
)
|
||||
}
|
||||
|
||||
override fun createBlockStateDefinition(builder: StateDefinition.Builder<Block?, BlockState?>) {
|
||||
builder.add(POSE)
|
||||
super.createBlockStateDefinition(builder)
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun isPathfindable(
|
||||
blockState: BlockState,
|
||||
pathComputationType: PathComputationType
|
||||
): Boolean = false
|
||||
|
||||
override fun useWithoutItem(
|
||||
state: BlockState,
|
||||
level: Level,
|
||||
pos: BlockPos,
|
||||
player: Player,
|
||||
hitResult: BlockHitResult
|
||||
): InteractionResult {
|
||||
if (player !is ServerPlayer) return InteractionResult.SUCCESS
|
||||
|
||||
level.setBlock(pos, state.cycle(POSE), 3)
|
||||
return InteractionResult.SUCCESS
|
||||
}
|
||||
|
||||
enum class Pose(private val label: String): StringRepresentable {
|
||||
DEFAULT("default"),
|
||||
RELAXED("relaxed"),
|
||||
SCARY("scary");
|
||||
override fun getSerializedName(): String = label
|
||||
}
|
||||
|
||||
override fun getShape(
|
||||
state: BlockState,
|
||||
level: BlockGetter,
|
||||
pos: BlockPos,
|
||||
context: CollisionContext
|
||||
): VoxelShape {
|
||||
return super.getShape(state, level, pos, context)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,8 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.client
|
||||
|
||||
import RealtimeAoeEntityRenderer
|
||||
import RealtimeProjectileEntityRenderer
|
||||
import com.cobblemon.mod.common.Cobblemon.LOGGER
|
||||
import com.cobblemon.mod.common.CobblemonBlockEntities
|
||||
import com.cobblemon.mod.common.CobblemonBlocks
|
||||
@@ -26,7 +24,6 @@ import com.cobblemon.mod.common.api.storage.player.client.ClientPokedexManager
|
||||
import com.cobblemon.mod.common.api.storage.player.client.ClientTMMoveManager
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
|
||||
import com.cobblemon.mod.common.block.entity.TintBlockEntity
|
||||
import com.cobblemon.mod.common.block.sign.CobblemonSignBlock
|
||||
import com.cobblemon.mod.common.client.battle.ClientBattle
|
||||
import com.cobblemon.mod.common.client.gui.BrainDebugOverlay
|
||||
import com.cobblemon.mod.common.client.gui.PartyOverlay
|
||||
@@ -47,6 +44,8 @@ import com.cobblemon.mod.common.client.render.color.PokeSnackItemColorProvider
|
||||
import com.cobblemon.mod.common.client.render.color.PonigiriItemColorProvider
|
||||
import com.cobblemon.mod.common.client.render.color.SinisterTeaItemColorProvider
|
||||
import com.cobblemon.mod.common.client.render.entity.PokeBobberEntityRenderer
|
||||
import com.cobblemon.mod.common.client.render.entity.RealtimeAoeEntityRenderer
|
||||
import com.cobblemon.mod.common.client.render.entity.RealtimeProjectileEntityRenderer
|
||||
import com.cobblemon.mod.common.client.render.generic.GenericBedrockRenderer
|
||||
import com.cobblemon.mod.common.client.render.item.CobblemonBuiltinItemRendererRegistry
|
||||
import com.cobblemon.mod.common.client.render.item.PokemonItemRenderer
|
||||
@@ -79,7 +78,6 @@ import com.cobblemon.mod.common.pokedex.scanner.PokedexUsageContext
|
||||
import com.cobblemon.mod.common.util.isLookingAt
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.color.block.BlockColor
|
||||
import net.minecraft.client.color.item.ItemColor
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.screens.MenuScreens
|
||||
import net.minecraft.client.gui.screens.Screen
|
||||
@@ -534,7 +532,9 @@ object CobblemonClient {
|
||||
LOGGER.info("Registering PokéBall renderer")
|
||||
this.implementation.registerEntityRenderer(CobblemonEntities.EMPTY_POKEBALL, ::PokeBallRenderer)
|
||||
LOGGER.info("Registering Realtime move Projectile renderer")
|
||||
this.implementation.registerEntityRenderer(CobblemonEntities.REALTIME_MOVE_PROJECTILE_ENTITY, ::RealtimeProjectileEntityRenderer)
|
||||
this.implementation.registerEntityRenderer(CobblemonEntities.REALTIME_MOVE_PROJECTILE_ENTITY,
|
||||
::RealtimeProjectileEntityRenderer
|
||||
)
|
||||
LOGGER.info("Registering Realtime move AOE renderer")
|
||||
this.implementation.registerEntityRenderer(CobblemonEntities.REALTIME_MOVE_PROJECTILE_AOE, ::RealtimeAoeEntityRenderer)
|
||||
LOGGER.info("Registering Boat renderer")
|
||||
|
||||
+1
@@ -5,6 +5,7 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package com.cobblemon.mod.common.client.render.entity
|
||||
|
||||
import com.cobblemon.mod.common.pokemon.ai.moves.AreaOfEffectMove
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
|
||||
+1
@@ -6,6 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.render.entity
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer
|
||||
import net.minecraft.client.renderer.MultiBufferSource
|
||||
|
||||
@@ -441,9 +441,6 @@ class CobblemonConfig {
|
||||
@CobblemonConfigField(Category.Spawning, lang = "data_monitor_shiny_rate", SERVER)
|
||||
var monitorShinyRate = 200
|
||||
|
||||
@CobblemonConfigField(Category.Pokemon, lang = "scarekrow_radius", SERVER)
|
||||
var scarekrowRadius = 16
|
||||
|
||||
@Transient
|
||||
val struct = ObjectValue(this).also {
|
||||
it.addFunction("last_saved_version") { StringValue(lastSavedVersion) }
|
||||
|
||||
@@ -10,8 +10,6 @@ package com.example.mod.entity
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonEntities.REALTIME_MOVE_PROJECTILE_AOE
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.CobblemonAttackTargetData
|
||||
import com.cobblemon.mod.common.pokemon.ai.moves.AreaOfEffectMove
|
||||
import com.cobblemon.mod.common.pokemon.ai.moves.AreaOfEffectMoveInstance
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
|
||||
@@ -364,7 +364,7 @@ object CobblemonItemGroups {
|
||||
entries.accept(CobblemonItems.SACCHARINE_HANGING_SIGN)
|
||||
entries.accept(CobblemonItems.SACCHARINE_LEAVES)
|
||||
//entries.accept(CobblemonItems.SACCHARINE_SAPLING)
|
||||
entries.accept(CobblemonItems.SCAREKROW)
|
||||
|
||||
entries.accept(CobblemonItems.HEARTY_GRAIN_BALE)
|
||||
|
||||
entries.accept(CobblemonItems.TATAMI_BLOCK)
|
||||
|
||||
-1
@@ -27,7 +27,6 @@ class AreaOfEffectMoveInstance(
|
||||
RealTimeMoveInstance(move = areaOfEffectMove, pokemonEntity = pokemonEntity, targetEntity, parentEntity) {
|
||||
|
||||
var durationTicks = 0
|
||||
var position = (parentEntity ?: pokemonEntity).position()
|
||||
|
||||
override fun start() {
|
||||
if (this.parentEntity is PokemonEntity) {
|
||||
|
||||
+3
@@ -38,6 +38,9 @@ abstract class RealTimeMoveInstance(
|
||||
var rotation: Vec3 = pokemonEntity.lookAngle
|
||||
var positionOffset: Vec3 = Vec3.ZERO
|
||||
|
||||
val position : Vec3?
|
||||
get() = parentEntity.let { it?.position() } ?: pokemonEntity.position() ?: null
|
||||
|
||||
abstract fun start()
|
||||
|
||||
abstract fun tick() : Boolean
|
||||
|
||||
+9
-4
@@ -8,6 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common.pokemon.ai.moves
|
||||
|
||||
import com.cobblemon.mod.common.util.toBlockPos
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
@@ -34,11 +35,15 @@ object RealTimeMoveManager {
|
||||
}
|
||||
|
||||
fun tick() {
|
||||
// TODO: Handle whether stuff is loaded in chunks
|
||||
realTimeMoveMap.forEachEntry(Long.MAX_VALUE) { it ->
|
||||
if (!it.value.tick()) {
|
||||
it.value.end()
|
||||
realTimeMoveMap.remove(it.key)
|
||||
// Only tick instances whose parent currently exists and is loaded
|
||||
val level = it.value.parentEntity?.level() ?: it.value.pokemonEntity.level()
|
||||
val blockPos = it.value.position?.toBlockPos()
|
||||
if ( blockPos != null && level.hasChunk( blockPos.x.shr(4), blockPos.z.shr(4))) {
|
||||
if (!it.value.tick()) {
|
||||
it.value.end()
|
||||
realTimeMoveMap.remove(it.key)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
{
|
||||
"variants": {
|
||||
"facing=south,half=top": {
|
||||
"model": "cobblemon:block/pc_top"
|
||||
},
|
||||
"facing=west,half=top": {
|
||||
"model": "cobblemon:block/pc_top",
|
||||
"y": 90
|
||||
},
|
||||
"facing=north,half=top": {
|
||||
"model": "cobblemon:block/pc_top",
|
||||
"y": 180
|
||||
},
|
||||
"facing=east,half=top": {
|
||||
"model": "cobblemon:block/pc_top",
|
||||
"y": 270
|
||||
},
|
||||
"facing=south,half=bottom": {
|
||||
"model": "cobblemon:block/pc_bottom"
|
||||
},
|
||||
"facing=west,half=bottom": {
|
||||
"model": "cobblemon:block/pc_bottom",
|
||||
"y": 90
|
||||
},
|
||||
"facing=north,half=bottom": {
|
||||
"model": "cobblemon:block/pc_bottom",
|
||||
"y": 180
|
||||
},
|
||||
"facing=east,half=bottom": {
|
||||
"model": "cobblemon:block/pc_bottom",
|
||||
"y": 270
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"parent": "block/cube_all",
|
||||
"textures": {
|
||||
"all": "cobblemon:block/evolution/moon_stone_ore"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"parent": "block/cube_all",
|
||||
"textures": {
|
||||
"all": "cobblemon:block/evolution/moon_stone_ore"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"parent": "block/cube_all",
|
||||
"textures": {
|
||||
"all": "cobblemon:block/evolution/moon_stone_ore"
|
||||
}
|
||||
}
|
||||
-16
@@ -71,22 +71,6 @@
|
||||
"senses": [
|
||||
"cobblemon:pokemon_nearby_wanted_item"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "cobblemon:add_senses",
|
||||
"condition": "!q.entity.is_in_party && !q.entity.is_alpha",
|
||||
"senses": [
|
||||
"cobblemon:scarekrow_sense"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "cobblemon:add_objectives",
|
||||
"condition": "!q.entity.is_in_party && !q.entity.is_alpha",
|
||||
"objectivesByPriority": {
|
||||
"0": [
|
||||
"cobblemon:avoid_scarekrow"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"type": "minecraft:block",
|
||||
"pools": [
|
||||
{
|
||||
"rolls": 1.0,
|
||||
"bonus_rolls": 0.0,
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "cobblemon:scarekrow"
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
{
|
||||
"condition": "minecraft:survives_explosion"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
"cobblemon:scarekrow"
|
||||
]
|
||||
}
|
||||
Reference in new issue
Block a user