feat: projection person AI (incomplete)
This commit is contained in:
parent
24080f0437
commit
89473d2dcc
@ -25,6 +25,7 @@ object Quaedam {
|
|||||||
val blocks = DeferredRegister.create(ID, Registries.BLOCK)!!
|
val blocks = DeferredRegister.create(ID, Registries.BLOCK)!!
|
||||||
val blockEntities = DeferredRegister.create(ID, Registries.BLOCK_ENTITY_TYPE)!!
|
val blockEntities = DeferredRegister.create(ID, Registries.BLOCK_ENTITY_TYPE)!!
|
||||||
val entities = DeferredRegister.create(ID, Registries.ENTITY_TYPE)!!
|
val entities = DeferredRegister.create(ID, Registries.ENTITY_TYPE)!!
|
||||||
|
val schedule = DeferredRegister.create(ID, Registries.SCHEDULE)!!
|
||||||
val projectionEffects = DeferredRegister.create(ID, ProjectionEffectType.registryKey)!!
|
val projectionEffects = DeferredRegister.create(ID, ProjectionEffectType.registryKey)!!
|
||||||
|
|
||||||
val creativeModeTab: RegistrySupplier<CreativeModeTab> = creativeModeTabs.register("quaedam") {
|
val creativeModeTab: RegistrySupplier<CreativeModeTab> = creativeModeTabs.register("quaedam") {
|
||||||
@ -43,6 +44,7 @@ object Quaedam {
|
|||||||
blocks.register()
|
blocks.register()
|
||||||
blockEntities.register()
|
blockEntities.register()
|
||||||
entities.register()
|
entities.register()
|
||||||
|
schedule.register()
|
||||||
projectionEffects.register()
|
projectionEffects.register()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,126 @@
|
|||||||
|
package quaedam.projection.swarm
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList
|
||||||
|
import com.mojang.datafixers.util.Pair
|
||||||
|
import net.minecraft.world.entity.ai.Brain
|
||||||
|
import net.minecraft.world.entity.ai.behavior.*
|
||||||
|
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||||
|
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||||
|
import net.minecraft.world.entity.schedule.Activity
|
||||||
|
import net.minecraft.world.entity.schedule.Schedule
|
||||||
|
import net.minecraft.world.entity.schedule.ScheduleBuilder
|
||||||
|
import quaedam.Quaedam
|
||||||
|
|
||||||
|
object ProjectedPersonAI {
|
||||||
|
|
||||||
|
private val memoryTypes = listOf(
|
||||||
|
MemoryModuleType.PATH,
|
||||||
|
MemoryModuleType.LOOK_TARGET,
|
||||||
|
MemoryModuleType.WALK_TARGET,
|
||||||
|
MemoryModuleType.ATTACK_TARGET,
|
||||||
|
MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES,
|
||||||
|
MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM,
|
||||||
|
MemoryModuleType.HURT_BY,
|
||||||
|
MemoryModuleType.ATTACK_COOLING_DOWN
|
||||||
|
)
|
||||||
|
|
||||||
|
private val sensorTypes = listOf(
|
||||||
|
SensorType.NEAREST_LIVING_ENTITIES,
|
||||||
|
SensorType.NEAREST_PLAYERS,
|
||||||
|
SensorType.HURT_BY,
|
||||||
|
SensorType.NEAREST_ITEMS
|
||||||
|
)
|
||||||
|
|
||||||
|
val defaultSchedule = Quaedam.schedule.register("projected_person_default") {
|
||||||
|
ScheduleBuilder(Schedule()).changeActivityAt(10, Activity.IDLE)
|
||||||
|
.changeActivityAt(10, Activity.IDLE)
|
||||||
|
.changeActivityAt(2000, Activity.WORK)
|
||||||
|
.changeActivityAt(7300, Activity.IDLE)
|
||||||
|
.changeActivityAt(9000, Activity.WORK)
|
||||||
|
.changeActivityAt(10700, Activity.IDLE)
|
||||||
|
.changeActivityAt(11000, Activity.PLAY)
|
||||||
|
.changeActivityAt(11500, Activity.IDLE)
|
||||||
|
.changeActivityAt(12000, Activity.REST)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
val babySchedule = Quaedam.schedule.register("projected_person_baby") {
|
||||||
|
ScheduleBuilder(Schedule()).changeActivityAt(10, Activity.IDLE)
|
||||||
|
.changeActivityAt(10, Activity.IDLE)
|
||||||
|
.changeActivityAt(3200, Activity.PLAY)
|
||||||
|
.changeActivityAt(7000, Activity.IDLE)
|
||||||
|
.changeActivityAt(9000, Activity.PLAY)
|
||||||
|
.changeActivityAt(11000, Activity.REST)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun provider(): Brain.Provider<out ProjectedPersonEntity> = Brain.provider(memoryTypes, sensorTypes)
|
||||||
|
|
||||||
|
fun initBrain(entity: ProjectedPersonEntity, brain: Brain<ProjectedPersonEntity>) {
|
||||||
|
if (entity.shape.baby) {
|
||||||
|
brain.schedule = babySchedule.get()
|
||||||
|
} else {
|
||||||
|
brain.schedule = defaultSchedule.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
initCoreActivity(brain)
|
||||||
|
initIdleActivity(brain)
|
||||||
|
initPlayActivity(brain)
|
||||||
|
initWorkActivity(brain)
|
||||||
|
initRestActivity(brain)
|
||||||
|
brain.setCoreActivities(setOf(Activity.CORE))
|
||||||
|
brain.setDefaultActivity(Activity.IDLE)
|
||||||
|
brain.updateActivityFromSchedule(entity.level().dayTime, entity.level().gameTime)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initCoreActivity(brain: Brain<ProjectedPersonEntity>) {
|
||||||
|
brain.addActivity(
|
||||||
|
Activity.CORE, 0, ImmutableList.of(
|
||||||
|
Swim(0.8f),
|
||||||
|
InteractWithDoor.create(),
|
||||||
|
LookAtTargetSink(40, 70),
|
||||||
|
MoveToTargetSink(),
|
||||||
|
WakeUp.create(),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
brain.addActivity(
|
||||||
|
Activity.CORE, 3, ImmutableList.of(
|
||||||
|
GoToWantedItem.create(0.7f, false, 7)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initIdleActivity(brain: Brain<ProjectedPersonEntity>) {
|
||||||
|
brain.addActivity(Activity.IDLE, 99, ImmutableList.of(UpdateActivityFromSchedule.create()))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initPlayActivity(brain: Brain<ProjectedPersonEntity>) {
|
||||||
|
brain.addActivity(
|
||||||
|
Activity.PLAY, 3, ImmutableList.of(
|
||||||
|
GoToWantedItem.create(1.75f, true, 32),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
brain.addActivity(
|
||||||
|
Activity.PLAY, 5, ImmutableList.of(
|
||||||
|
JumpOnBed(0.5f),
|
||||||
|
RunOne(
|
||||||
|
listOf(
|
||||||
|
Pair.of(RandomStroll.stroll(0.5f), 2),
|
||||||
|
Pair.of(SetWalkTargetFromLookTarget.create(1.0f, 5), 2),
|
||||||
|
Pair.of(DoNothing(30, 60), 1)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
brain.addActivity(Activity.PLAY, 99, ImmutableList.of(UpdateActivityFromSchedule.create()))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initWorkActivity(brain: Brain<ProjectedPersonEntity>) {
|
||||||
|
brain.addActivity(Activity.WORK, 99, ImmutableList.of(UpdateActivityFromSchedule.create()))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initRestActivity(brain: Brain<ProjectedPersonEntity>) {
|
||||||
|
brain.addActivity(Activity.REST, 99, ImmutableList.of(UpdateActivityFromSchedule.create()))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
package quaedam.projection.swarm
|
package quaedam.projection.swarm
|
||||||
|
|
||||||
|
import com.mojang.serialization.Dynamic
|
||||||
import dev.architectury.platform.Platform
|
import dev.architectury.platform.Platform
|
||||||
import dev.architectury.registry.client.level.entity.EntityRendererRegistry
|
|
||||||
import dev.architectury.registry.level.entity.EntityAttributeRegistry
|
import dev.architectury.registry.level.entity.EntityAttributeRegistry
|
||||||
import net.fabricmc.api.EnvType
|
import net.fabricmc.api.EnvType
|
||||||
import net.minecraft.nbt.CompoundTag
|
import net.minecraft.nbt.CompoundTag
|
||||||
@ -13,6 +13,7 @@ import net.minecraft.network.syncher.SynchedEntityData
|
|||||||
import net.minecraft.world.DifficultyInstance
|
import net.minecraft.world.DifficultyInstance
|
||||||
import net.minecraft.world.SimpleContainer
|
import net.minecraft.world.SimpleContainer
|
||||||
import net.minecraft.world.entity.*
|
import net.minecraft.world.entity.*
|
||||||
|
import net.minecraft.world.entity.ai.Brain
|
||||||
import net.minecraft.world.entity.ai.attributes.AttributeSupplier
|
import net.minecraft.world.entity.ai.attributes.AttributeSupplier
|
||||||
import net.minecraft.world.entity.ai.attributes.Attributes
|
import net.minecraft.world.entity.ai.attributes.Attributes
|
||||||
import net.minecraft.world.entity.item.ItemEntity
|
import net.minecraft.world.entity.item.ItemEntity
|
||||||
@ -22,8 +23,8 @@ import net.minecraft.world.level.ServerLevelAccessor
|
|||||||
import quaedam.Quaedam
|
import quaedam.Quaedam
|
||||||
import quaedam.projector.Projector
|
import quaedam.projector.Projector
|
||||||
|
|
||||||
class ProjectedPersonEntity(entityType: EntityType<out PathfinderMob>, level: Level) :
|
class ProjectedPersonEntity(entityType: EntityType<out PathfinderMob>, level: Level) : PathfinderMob(entityType, level),
|
||||||
PathfinderMob(entityType, level), InventoryCarrier {
|
InventoryCarrier {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
@ -35,28 +36,24 @@ class ProjectedPersonEntity(entityType: EntityType<out PathfinderMob>, level: Le
|
|||||||
const val BOUNDING_HEIGHT = 1.8f
|
const val BOUNDING_HEIGHT = 1.8f
|
||||||
|
|
||||||
val entity = Quaedam.entities.register(ID) {
|
val entity = Quaedam.entities.register(ID) {
|
||||||
EntityType.Builder.of(::ProjectedPersonEntity, MobCategory.CREATURE)
|
EntityType.Builder.of(::ProjectedPersonEntity, MobCategory.CREATURE).canSpawnFarFromPlayer()
|
||||||
.canSpawnFarFromPlayer()
|
.sized(BOUNDING_WIDTH, BOUNDING_HEIGHT * 1.2f).build("quaedam:$ID")
|
||||||
.sized(BOUNDING_WIDTH, BOUNDING_HEIGHT * 1.2f)
|
|
||||||
.build("quaedam:$ID")
|
|
||||||
}!!
|
}!!
|
||||||
|
|
||||||
val dataShape =
|
val dataShape =
|
||||||
SynchedEntityData.defineId(ProjectedPersonEntity::class.java, EntityDataSerializers.COMPOUND_TAG)
|
SynchedEntityData.defineId(ProjectedPersonEntity::class.java, EntityDataSerializers.COMPOUND_TAG)
|
||||||
|
|
||||||
private fun createAttributes(): AttributeSupplier.Builder = Mob.createMobAttributes()
|
|
||||||
.add(Attributes.ATTACK_DAMAGE, 1.5)
|
|
||||||
.add(Attributes.MOVEMENT_SPEED, 0.11)
|
|
||||||
.add(Attributes.ATTACK_SPEED)
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
EntityAttributeRegistry.register(entity, ::createAttributes)
|
EntityAttributeRegistry.register(entity, ::createAttributes)
|
||||||
if (Platform.getEnv() == EnvType.CLIENT) {
|
if (Platform.getEnv() == EnvType.CLIENT) ProjectedPersonRenderer
|
||||||
EntityRendererRegistry.register(entity, ::ProjectedPersonRenderer)
|
|
||||||
}
|
|
||||||
ProjectedPersonShape
|
ProjectedPersonShape
|
||||||
|
ProjectedPersonAI
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun createAttributes(): AttributeSupplier.Builder =
|
||||||
|
Mob.createMobAttributes().add(Attributes.ATTACK_DAMAGE, 1.5).add(Attributes.MOVEMENT_SPEED, 0.11)
|
||||||
|
.add(Attributes.ATTACK_SPEED)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun finalizeSpawn(
|
override fun finalizeSpawn(
|
||||||
@ -106,8 +103,8 @@ class ProjectedPersonEntity(entityType: EntityType<out PathfinderMob>, level: Le
|
|||||||
|
|
||||||
override fun shouldShowName() = true
|
override fun shouldShowName() = true
|
||||||
|
|
||||||
override fun getTypeName(): Component = shape.name.takeIf { it.isNotEmpty() }?.let { Component.literal(it) }
|
override fun getTypeName(): Component =
|
||||||
?: super.getTypeName()
|
shape.name.takeIf { it.isNotEmpty() }?.let { Component.literal(it) } ?: super.getTypeName()
|
||||||
|
|
||||||
override fun getNameTagOffsetY() = super.getNameTagOffsetY() - (BOUNDING_HEIGHT * (1.2f - shape.scaleY))
|
override fun getNameTagOffsetY() = super.getNameTagOffsetY() - (BOUNDING_HEIGHT * (1.2f - shape.scaleY))
|
||||||
|
|
||||||
@ -116,8 +113,7 @@ class ProjectedPersonEntity(entityType: EntityType<out PathfinderMob>, level: Le
|
|||||||
override fun tick() {
|
override fun tick() {
|
||||||
super.tick()
|
super.tick()
|
||||||
if (tickCount % 20 == 0) {
|
if (tickCount % 20 == 0) {
|
||||||
if (!checkProjectionEffect())
|
if (!checkProjectionEffect()) remove(RemovalReason.KILLED)
|
||||||
remove(RemovalReason.KILLED)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,8 +122,7 @@ class ProjectedPersonEntity(entityType: EntityType<out PathfinderMob>, level: Le
|
|||||||
|
|
||||||
override fun checkDespawn() {
|
override fun checkDespawn() {
|
||||||
super.checkDespawn()
|
super.checkDespawn()
|
||||||
if (!checkProjectionEffect())
|
if (!checkProjectionEffect()) discard()
|
||||||
discard()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val inventory = SimpleContainer(10)
|
private val inventory = SimpleContainer(10)
|
||||||
@ -146,4 +141,16 @@ class ProjectedPersonEntity(entityType: EntityType<out PathfinderMob>, level: Le
|
|||||||
|
|
||||||
override fun removeWhenFarAway(d: Double) = false
|
override fun removeWhenFarAway(d: Double) = false
|
||||||
|
|
||||||
|
// Type signature referenced from: https://github.com/bbrk24/amurians-mod/blob/7a0f0c3c7a3e84c22e5c631286ad23795207adc0/src/main/kotlin/org/bbrk24/amurians/amurian/AmurianEntity.kt#L220
|
||||||
|
override fun brainProvider() = ProjectedPersonAI.provider()
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
override fun makeBrain(dynamic: Dynamic<*>): Brain<out ProjectedPersonEntity> = brainProvider().makeBrain(dynamic)
|
||||||
|
.also { ProjectedPersonAI.initBrain(this, it as Brain<ProjectedPersonEntity>) }
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
override fun getBrain(): Brain<ProjectedPersonEntity> = super.getBrain() as Brain<ProjectedPersonEntity>
|
||||||
|
|
||||||
|
override fun isBaby() = shape.baby
|
||||||
|
|
||||||
}
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package quaedam.projection.swarm
|
package quaedam.projection.swarm
|
||||||
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack
|
import com.mojang.blaze3d.vertex.PoseStack
|
||||||
|
import dev.architectury.registry.client.level.entity.EntityRendererRegistry
|
||||||
import net.fabricmc.api.EnvType
|
import net.fabricmc.api.EnvType
|
||||||
import net.fabricmc.api.Environment
|
import net.fabricmc.api.Environment
|
||||||
import net.minecraft.client.model.PlayerModel
|
import net.minecraft.client.model.PlayerModel
|
||||||
@ -18,6 +19,12 @@ class ProjectedPersonRenderer(context: EntityRendererProvider.Context) :
|
|||||||
0.4f
|
0.4f
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
init {
|
||||||
|
EntityRendererRegistry.register(ProjectedPersonEntity.entity, ::ProjectedPersonRenderer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
addLayer(CustomHeadLayer(this, context.modelSet, context.itemInHandRenderer))
|
addLayer(CustomHeadLayer(this, context.modelSet, context.itemInHandRenderer))
|
||||||
addLayer(ItemInHandLayer(this, context.itemInHandRenderer))
|
addLayer(ItemInHandLayer(this, context.itemInHandRenderer))
|
||||||
|
@ -22,6 +22,7 @@ data class ProjectedPersonShape(
|
|||||||
val scaleZ: Float = 1.0f,
|
val scaleZ: Float = 1.0f,
|
||||||
val name: String = "",
|
val name: String = "",
|
||||||
val skin: Int = 0,
|
val skin: Int = 0,
|
||||||
|
val baby: Boolean = false,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@ -31,6 +32,7 @@ data class ProjectedPersonShape(
|
|||||||
const val KEY_SCALE_Z = "ScaleZ"
|
const val KEY_SCALE_Z = "ScaleZ"
|
||||||
const val KEY_NAME = "Name"
|
const val KEY_NAME = "Name"
|
||||||
const val KEY_SKIN = "Skin"
|
const val KEY_SKIN = "Skin"
|
||||||
|
const val KEY_BABY = "Baby"
|
||||||
|
|
||||||
init {
|
init {
|
||||||
Names
|
Names
|
||||||
@ -45,6 +47,7 @@ data class ProjectedPersonShape(
|
|||||||
scaleZ = rand.nextInt(0..2 * 4) * 0.025f + 0.9f,
|
scaleZ = rand.nextInt(0..2 * 4) * 0.025f + 0.9f,
|
||||||
name = Names.random(rand),
|
name = Names.random(rand),
|
||||||
skin = Skins.random(rand),
|
skin = Skins.random(rand),
|
||||||
|
baby = rand.nextInt(500) == 1
|
||||||
)
|
)
|
||||||
|
|
||||||
fun fromTag(tag: CompoundTag) = ProjectedPersonShape(
|
fun fromTag(tag: CompoundTag) = ProjectedPersonShape(
|
||||||
@ -53,6 +56,7 @@ data class ProjectedPersonShape(
|
|||||||
scaleZ = tag.getFloat(KEY_SCALE_Z),
|
scaleZ = tag.getFloat(KEY_SCALE_Z),
|
||||||
name = tag.getString(KEY_NAME),
|
name = tag.getString(KEY_NAME),
|
||||||
skin = tag.getInt(KEY_SKIN),
|
skin = tag.getInt(KEY_SKIN),
|
||||||
|
baby = tag.getBoolean(KEY_BABY)
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -63,6 +67,7 @@ data class ProjectedPersonShape(
|
|||||||
putFloat(KEY_SCALE_Z, scaleZ)
|
putFloat(KEY_SCALE_Z, scaleZ)
|
||||||
putString(KEY_NAME, name)
|
putString(KEY_NAME, name)
|
||||||
putInt(KEY_SKIN, skin)
|
putInt(KEY_SKIN, skin)
|
||||||
|
putBoolean(KEY_BABY, baby)
|
||||||
}
|
}
|
||||||
|
|
||||||
object Names {
|
object Names {
|
||||||
|
Loading…
Reference in New Issue
Block a user