Skip to content

Commit

Permalink
Started work on climbing behaviour for critters and crustaceans, need…
Browse files Browse the repository at this point in the history
…s refining @dragon@Dragon@Dragon@Dragon@Dragon@Dragon@Dragon@Dragon@Dragon@Dragon@Dragon@Dragon@Dragon@Dragon@Dragon
  • Loading branch information
MysticKoko committed Dec 20, 2024
1 parent f7bb114 commit aa3f9b0
Show file tree
Hide file tree
Showing 12 changed files with 273 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package dev.hybridlabs.aquatic.client.model.entity.critter

import dev.hybridlabs.aquatic.HybridAquatic
import dev.hybridlabs.aquatic.entity.critter.HybridAquaticCritterEntity
import net.minecraft.client.render.entity.model.EntityModelPartNames
import net.minecraft.util.Identifier
import software.bernie.geckolib.core.animation.AnimationState
import software.bernie.geckolib.model.GeoModel

abstract class HybridAquaticCritterEntityModel<T: HybridAquaticCritterEntity> (private val id: String) : GeoModel<T>() {
Expand All @@ -26,4 +28,22 @@ abstract class HybridAquaticCritterEntityModel<T: HybridAquaticCritterEntity> (p
return Identifier(HybridAquatic.MOD_ID, "animations/${id}_${variant.getProvidedVariant(animatable)}.animation.json")
return Identifier(HybridAquatic.MOD_ID, "animations/$id.animation.json")
}

override fun setCustomAnimations(
animatable: T,
instanceId: Long,
animationState: AnimationState<T>
) {
super.setCustomAnimations(animatable, instanceId, animationState)

val body = animationProcessor.getBone(EntityModelPartNames.BODY)

if (animatable.isClimbing) {
body.rotY = 0.0f
body.rotZ = 1.5708f
} else {
body.rotY = 0.0f
body.rotZ = 0.0f
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package dev.hybridlabs.aquatic.client.model.entity.critter

import dev.hybridlabs.aquatic.entity.critter.HybridAquaticCritterEntity
import net.minecraft.util.Identifier

class NudibranchEntityModel : HybridAquaticCritterEntityModel<HybridAquaticCritterEntity>("nudibranch")
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,58 @@ package dev.hybridlabs.aquatic.client.model.entity.crustacean

import dev.hybridlabs.aquatic.HybridAquatic
import dev.hybridlabs.aquatic.entity.crustacean.HybridAquaticCrustaceanEntity
import net.minecraft.client.render.entity.model.EntityModelPartNames
import net.minecraft.util.Identifier
import software.bernie.geckolib.core.animation.AnimationState
import software.bernie.geckolib.model.GeoModel

abstract class HybridAquaticCrustaceanEntityModel<T: HybridAquaticCrustaceanEntity> (private val id: String) : GeoModel<T>() {
abstract class HybridAquaticCrustaceanEntityModel<T : HybridAquaticCrustaceanEntity>(private val id: String) :
GeoModel<T>() {
override fun getModelResource(animatable: T): Identifier {
val variant = animatable.variant
if (variant != null && !variant.ignore.contains(HybridAquaticCrustaceanEntity.CrustaceanVariant.Ignore.MODEL))
return Identifier(HybridAquatic.MOD_ID, "geo/crustacean/${id}/${id}_${variant.getProvidedVariant(animatable)}.geo.json")
return Identifier(
HybridAquatic.MOD_ID,
"geo/crustacean/${id}/${id}_${variant.getProvidedVariant(animatable)}.geo.json"
)
return Identifier(HybridAquatic.MOD_ID, "geo/crustacean/${id}/$id.geo.json")
}

override fun getTextureResource(animatable: T): Identifier {
val variant = animatable.variant
if (variant != null && !variant.ignore.contains(HybridAquaticCrustaceanEntity.CrustaceanVariant.Ignore.TEXTURE))
return Identifier(HybridAquatic.MOD_ID, "textures/entity/crustacean/${id}/${id}_${variant.getProvidedVariant(animatable)}.png")
return Identifier(
HybridAquatic.MOD_ID,
"textures/entity/crustacean/${id}/${id}_${variant.getProvidedVariant(animatable)}.png"
)
return Identifier(HybridAquatic.MOD_ID, "textures/entity/crustacean/${id}/$id.png")
}

override fun getAnimationResource(animatable: T): Identifier {
val variant = animatable.variant
if (variant != null && !variant.ignore.contains(HybridAquaticCrustaceanEntity.CrustaceanVariant.Ignore.ANIMATION))
return Identifier(HybridAquatic.MOD_ID, "animations/${id}_${variant.getProvidedVariant(animatable)}.animation.json")
return Identifier(
HybridAquatic.MOD_ID,
"animations/${id}_${variant.getProvidedVariant(animatable)}.animation.json"
)
return Identifier(HybridAquatic.MOD_ID, "animations/$id.animation.json")
}

override fun setCustomAnimations(
animatable: T,
instanceId: Long,
animationState: AnimationState<T>
) {
super.setCustomAnimations(animatable, instanceId, animationState)

val body = animationProcessor.getBone(EntityModelPartNames.BODY)

if (animatable.isClimbing) {
body.rotY = 0.0f
body.rotZ = 1.5708f
} else {
body.rotY = 0.0f
body.rotZ = 0.0f
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package dev.hybridlabs.aquatic.entity.ai

import net.minecraft.entity.ai.control.YawAdjustingLookControl
import net.minecraft.entity.mob.MobEntity


class WallClimbingLookControl(entity: MobEntity, yawAdjustThreshold: Int) :
YawAdjustingLookControl(entity, yawAdjustThreshold) {
override fun tick() {
if (!entity.isClimbing) {
super.tick()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package dev.hybridlabs.aquatic.entity.ai

import net.minecraft.entity.Entity
import net.minecraft.entity.ai.pathing.MobNavigation
import net.minecraft.entity.ai.pathing.Path
import net.minecraft.entity.mob.MobEntity
import net.minecraft.util.math.BlockPos
import net.minecraft.world.World
import kotlin.math.max


class WallClimbingNavigation(mobEntity: MobEntity?, world: World?) : MobNavigation(mobEntity, world) {
private var targetPos: BlockPos? = null

override fun findPathTo(target: BlockPos, distance: Int): Path? {
this.targetPos = target
return super.findPathTo(target, distance)
}

override fun findPathTo(entity: Entity, distance: Int): Path? {
this.targetPos = entity.blockPos
return super.findPathTo(entity, distance)
}

override fun startMovingTo(entity: Entity, speed: Double): Boolean {
val path: Path? = this.findPathTo(entity, 0)
if (path != null) {
return this.startMovingAlong(path, speed)
}
this.targetPos = entity.blockPos
this.speed = speed
return true
}

override fun tick() {
if (!this.isIdle) {
super.tick()
return
}

if (this.targetPos != null) {
if (!targetPos!!.isWithinDistance(
entity.pos, max(
entity.width.toDouble(), 1.0
)
)
&& (!(entity.y > targetPos!!.y.toDouble())
|| !BlockPos(
targetPos!!.x,
entity.blockY, targetPos!!.z
).isWithinDistance(
entity.pos, max(entity.width.toDouble(), 1.0)
)
)
) {
entity.moveControl.moveTo(
targetPos!!.x.toDouble(),
targetPos!!.y.toDouble(),
targetPos!!.z.toDouble(),
0.5
)
} else {
this.targetPos = null
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package dev.hybridlabs.aquatic.entity.critter

import dev.hybridlabs.aquatic.entity.ai.WallClimbingNavigation
import dev.hybridlabs.aquatic.entity.critter.HybridAquaticCritterEntity.VariantCollisionRules.ExclusionStatus.EXCLUSIVE
import dev.hybridlabs.aquatic.entity.critter.HybridAquaticCritterEntity.VariantCollisionRules.ExclusionStatus.INCLUSIVE
import net.minecraft.entity.EntityData
Expand All @@ -10,8 +11,6 @@ import net.minecraft.entity.ai.goal.EscapeDangerGoal
import net.minecraft.entity.ai.goal.LookAroundGoal
import net.minecraft.entity.ai.goal.MoveIntoWaterGoal
import net.minecraft.entity.ai.goal.WanderAroundGoal
import net.minecraft.entity.ai.pathing.EntityNavigation
import net.minecraft.entity.ai.pathing.MobNavigation
import net.minecraft.entity.ai.pathing.PathNodeType
import net.minecraft.entity.damage.DamageSource
import net.minecraft.entity.data.DataTracker
Expand All @@ -37,6 +36,7 @@ import software.bernie.geckolib.core.animation.*
import software.bernie.geckolib.core.`object`.PlayState
import software.bernie.geckolib.util.GeckoLibUtil


@Suppress("LeakingThis", "DEPRECATION", "UNUSED_PARAMETER")
open class HybridAquaticCritterEntity(
type: EntityType<out HybridAquaticCritterEntity>,
Expand All @@ -46,23 +46,18 @@ open class HybridAquaticCritterEntity(
open val collisionRules: List<VariantCollisionRules> = listOf()
) : WaterCreatureEntity(type, world), GeoEntity {
private val factory = GeckoLibUtil.createInstanceCache(this)
private var landNavigation: EntityNavigation = createNavigation(world)
private var fromFishingNet = false
private var climbingTicks = 0

init {
stepHeight = 1.0F
setPathfindingPenalty(PathNodeType.WATER, 0.0f)
setPathfindingPenalty(PathNodeType.WALKABLE, 10.0f)
moveControl = MoveControl(this)
navigation = this.landNavigation
}

override fun createNavigation(world: World): EntityNavigation {
return MobNavigation(this, world)
navigation = WallClimbingNavigation(this, world)
}

override fun hasNoDrag(): Boolean {
return false
return this.isClimbing
}

override fun tick() {
Expand All @@ -71,6 +66,42 @@ open class HybridAquaticCritterEntity(
if (!isWet) {
this.speed = 0.01F
}

if (!this.world.isClient) {
this.setClimbingWall(this.horizontalCollision)
}

if (this.isClimbingWall()) {
this.climbingTicks++

val blockStateAtPos = this.blockStateAtPos
if (this.isMoving() && !blockStateAtPos.isLiquid && this.climbingTicks % 6 == 0) {
this.playStepSound(this.blockPos, blockStateAtPos)
}
} else {
this.climbingTicks = 0
}

if (this.isClimbing) {
val velocity = this.velocity
this.setVelocity(velocity.x, velocity.y * 0.33F, velocity.z)
}
}

private fun isMoving(): Boolean {
return (this.isOnGround || this.isClimbing) && velocity.lengthSquared() >= 0.0001
}

override fun isClimbing(): Boolean {
return this.climbingTicks > 8 && this.isClimbingWall()
}

private fun isClimbingWall(): Boolean {
return dataTracker.get(IS_CLIMBING_WALL)
}

private fun setClimbingWall(isClimbingWall: Boolean) {
dataTracker.set(IS_CLIMBING_WALL, isClimbingWall)
}

override fun initDataTracker() {
Expand All @@ -79,6 +110,7 @@ open class HybridAquaticCritterEntity(
dataTracker.startTracking(VARIANT_DATA, NbtCompound())
dataTracker.startTracking(CRITTER_SIZE, 0)
dataTracker.startTracking(CRITTER_FLAGS, 0.toByte())
dataTracker.startTracking(IS_CLIMBING_WALL, false)
}

override fun initGoals() {
Expand Down Expand Up @@ -142,9 +174,8 @@ open class HybridAquaticCritterEntity(
return super.initialize(world, difficulty, spawnReason, entityData, entityNbt)
}


override fun shouldSwimInFluids(): Boolean {
return !isOnGround
return !isOnGround || !isClimbing
}

override fun isPushedByFluids(): Boolean {
Expand Down Expand Up @@ -277,6 +308,8 @@ open class HybridAquaticCritterEntity(
DataTracker.registerData(HybridAquaticCritterEntity::class.java, TrackedDataHandlerRegistry.INTEGER)
val CRITTER_FLAGS: TrackedData<Byte> =
DataTracker.registerData(HybridAquaticCritterEntity::class.java, TrackedDataHandlerRegistry.BYTE)
val IS_CLIMBING_WALL: TrackedData<Boolean> =
DataTracker.registerData(HybridAquaticCritterEntity::class.java, TrackedDataHandlerRegistry.BOOLEAN)

fun canSpawn(
type: EntityType<out WaterCreatureEntity>,
Expand Down
Loading

0 comments on commit aa3f9b0

Please sign in to comment.