feat: item exchange
This commit is contained in:
parent
f2ceaf176c
commit
e13d5ff178
@ -26,6 +26,7 @@ object Quaedam {
|
||||
val blockEntities = DeferredRegister.create(ID, Registries.BLOCK_ENTITY_TYPE)!!
|
||||
val entities = DeferredRegister.create(ID, Registries.ENTITY_TYPE)!!
|
||||
val schedules = DeferredRegister.create(ID, Registries.SCHEDULE)!!
|
||||
val memoryTypes = DeferredRegister.create(ID, Registries.MEMORY_MODULE_TYPE)!!
|
||||
val sensors = DeferredRegister.create(ID, Registries.SENSOR_TYPE)!!
|
||||
val projectionEffects = DeferredRegister.create(ID, ProjectionEffectType.registryKey)!!
|
||||
|
||||
@ -47,6 +48,7 @@ object Quaedam {
|
||||
blockEntities.register()
|
||||
entities.register()
|
||||
schedules.register()
|
||||
memoryTypes.register()
|
||||
sensors.register()
|
||||
projectionEffects.register()
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ package quaedam.projection.swarm.ai
|
||||
|
||||
import net.minecraft.core.GlobalPos
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.world.entity.Mob
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.memory.MemoryStatus
|
||||
import net.minecraft.world.entity.ai.sensing.Sensor
|
||||
@ -12,11 +12,13 @@ import net.minecraft.world.level.block.entity.BedBlockEntity
|
||||
import net.minecraft.world.level.block.state.properties.BedPart
|
||||
import quaedam.Quaedam
|
||||
|
||||
class BedInChunkSensor : Sensor<Mob>() {
|
||||
class BedInChunkSensor : Sensor<LivingEntity>() {
|
||||
|
||||
companion object {
|
||||
|
||||
val sensor = Quaedam.sensors.register("bed_in_chunk") {
|
||||
const val ID = "bed_in_chunk"
|
||||
|
||||
val sensor = Quaedam.sensors.register(ID) {
|
||||
SensorType(::BedInChunkSensor)
|
||||
}
|
||||
|
||||
@ -24,7 +26,7 @@ class BedInChunkSensor : Sensor<Mob>() {
|
||||
|
||||
override fun requires() = setOf(MemoryModuleType.NEAREST_BED)
|
||||
|
||||
override fun doTick(level: ServerLevel, entity: Mob) {
|
||||
override fun doTick(level: ServerLevel, entity: LivingEntity) {
|
||||
if (entity.tickCount and 0b11111 == 0 && !entity.isSleeping) { // 32gt
|
||||
level.getChunkAt(entity.blockPosition()).blockEntities
|
||||
.filterValues { it is BedBlockEntity }
|
||||
|
@ -0,0 +1,126 @@
|
||||
package quaedam.projection.swarm.ai
|
||||
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.sounds.SoundEvents
|
||||
import net.minecraft.world.Container
|
||||
import net.minecraft.world.entity.Mob
|
||||
import net.minecraft.world.entity.ai.behavior.Behavior
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.memory.MemoryStatus
|
||||
import net.minecraft.world.entity.ai.memory.WalkTarget
|
||||
import net.minecraft.world.entity.npc.InventoryCarrier
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.block.entity.BaseContainerBlockEntity
|
||||
import net.minecraft.world.level.block.entity.ChestBlockEntity
|
||||
import kotlin.math.min
|
||||
|
||||
class ExchangeItem<E> : Behavior<E>(
|
||||
mapOf(
|
||||
MemoryModuleType.WALK_TARGET to MemoryStatus.VALUE_ABSENT,
|
||||
NearestVisibleContainer.memory.get() to MemoryStatus.VALUE_PRESENT,
|
||||
), 5 * 20, 12 * 20
|
||||
) where E : Mob, E : InventoryCarrier {
|
||||
|
||||
private var target: BlockPos? = null
|
||||
private var closeAt: Long? = null
|
||||
|
||||
override fun start(level: ServerLevel, entity: E, l: Long) {
|
||||
target = entity.brain.getMemory(NearestVisibleContainer.memory.get()).get()
|
||||
closeAt = null
|
||||
entity.brain.setMemory(MemoryModuleType.WALK_TARGET, WalkTarget(target!!, 1.0f, 2))
|
||||
}
|
||||
|
||||
override fun canStillUse(level: ServerLevel, entity: E, l: Long) =
|
||||
entity.brain.getMemory(MemoryModuleType.WALK_TARGET).isPresent || entity.brain.getMemory(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE).isEmpty || (closeAt != null && closeAt!! < l)
|
||||
|
||||
override fun tick(level: ServerLevel, entity: E, l: Long) {
|
||||
if (closeAt == null) {
|
||||
if (entity.brain.getMemory(MemoryModuleType.WALK_TARGET).isEmpty) {
|
||||
// reached
|
||||
val chest = level.getBlockEntity(target!!) as BaseContainerBlockEntity
|
||||
if (chest is ChestBlockEntity) {
|
||||
ChestBlockEntity.playSound(level, target!!, level.getBlockState(target!!), SoundEvents.CHEST_OPEN)
|
||||
}
|
||||
if (chest.isEmpty) {
|
||||
closeAt = l + 7
|
||||
} else {
|
||||
closeAt = l + 10 + level.random.nextInt(100)
|
||||
exchangeItems(level, entity)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun stop(level: ServerLevel, entity: E, l: Long) {
|
||||
entity.brain.eraseMemory(MemoryModuleType.WALK_TARGET)
|
||||
if (closeAt != null) {
|
||||
// opened
|
||||
val chest = level.getBlockEntity(target!!)!!
|
||||
if (chest is ChestBlockEntity) {
|
||||
ChestBlockEntity.playSound(level, target!!, level.getBlockState(target!!), SoundEvents.CHEST_CLOSE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun exchangeItems(level: ServerLevel, entity: E) {
|
||||
val container = level.getBlockEntity(target!!) as Container
|
||||
val inventory = entity.inventory
|
||||
for (i in 1..6) {
|
||||
val maxCount = level.random.nextInt(16)
|
||||
if (level.random.nextBoolean()) {
|
||||
// take
|
||||
val slot = level.random.nextInt(container.containerSize)
|
||||
val item = container.getItem(slot)
|
||||
if (!item.isEmpty) {
|
||||
val takeCount = min(item.count, maxCount)
|
||||
val takeItem = item.copyWithCount(takeCount)
|
||||
if (inventory.canTakeItem(container, slot, takeItem) && entity.canHoldItem(takeItem)) {
|
||||
val remaining = entity.inventory.addItem(entity.equipItemIfPossible(takeItem))
|
||||
val actualCount = takeCount - remaining.count
|
||||
item.shrink(actualCount)
|
||||
container.setItem(slot, item)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// put
|
||||
val slot = level.random.nextInt(inventory.containerSize)
|
||||
val item = inventory.getItem(slot)
|
||||
if (!item.isEmpty) {
|
||||
val takeCount = min(item.count, maxCount)
|
||||
val takeItem = item.copyWithCount(takeCount)
|
||||
if (container.canTakeItem(inventory, slot, takeItem)) {
|
||||
for (target in 0 until container.containerSize) {
|
||||
val targetItem = container.getItem(target)
|
||||
if (ItemStack.isSameItemSameTags(targetItem, takeItem)) {
|
||||
val resultCount = min(targetItem.count + takeItem.count, item.maxStackSize)
|
||||
val putCount = resultCount - targetItem.count
|
||||
if (putCount != 0) {
|
||||
targetItem.grow(putCount)
|
||||
container.setItem(target, targetItem)
|
||||
takeItem.shrink(putCount)
|
||||
if (takeItem.isEmpty) break
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!takeItem.isEmpty) {
|
||||
for (target in 0 until container.containerSize) {
|
||||
val targetItem = container.getItem(target)
|
||||
if (targetItem.isEmpty) {
|
||||
container.setItem(target, takeItem.copyAndClear())
|
||||
println("put all at $target")
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
val putCount = takeCount - takeItem.count
|
||||
println("put $putCount")
|
||||
item.shrink(putCount)
|
||||
container.setItem(slot, item)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package quaedam.projection.swarm.ai
|
||||
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.Sensor
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
import net.minecraft.world.level.block.entity.BaseContainerBlockEntity
|
||||
import quaedam.Quaedam
|
||||
import quaedam.utils.getChunksNearby
|
||||
import java.util.*
|
||||
|
||||
class NearestVisibleContainer : Sensor<LivingEntity>() {
|
||||
|
||||
companion object {
|
||||
|
||||
const val ID = "nearest_visible_container"
|
||||
|
||||
val sensor = Quaedam.sensors.register(ID) {
|
||||
SensorType(::NearestVisibleContainer)
|
||||
}!!
|
||||
|
||||
val memory = Quaedam.memoryTypes.register(ID) {
|
||||
MemoryModuleType(Optional.of(BlockPos.CODEC))
|
||||
}!!
|
||||
|
||||
}
|
||||
|
||||
override fun requires() = setOf(memory.get())
|
||||
|
||||
override fun doTick(level: ServerLevel, entity: LivingEntity) {
|
||||
if (entity.tickCount and 0b11111 == 0) { // 32gt
|
||||
val pos = level.getChunksNearby(entity.blockPosition(), 1)
|
||||
.flatMap { it.blockEntities.filterValues { be -> be is BaseContainerBlockEntity }.keys }
|
||||
.minByOrNull { it.distManhattan(entity.blockPosition()) }
|
||||
entity.brain.setMemory(memory.get(), pos)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -52,6 +52,7 @@ object ProjectedPersonAI {
|
||||
|
||||
init {
|
||||
BedInChunkSensor
|
||||
NearestVisibleContainer
|
||||
}
|
||||
|
||||
private val memoryTypes by lazy {
|
||||
@ -67,6 +68,7 @@ object ProjectedPersonAI {
|
||||
MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE,
|
||||
MemoryModuleType.HOME,
|
||||
MemoryModuleType.LAST_WOKEN,
|
||||
NearestVisibleContainer.memory.get(),
|
||||
)
|
||||
}
|
||||
|
||||
@ -77,6 +79,7 @@ object ProjectedPersonAI {
|
||||
SensorType.HURT_BY,
|
||||
SensorType.NEAREST_ITEMS,
|
||||
BedInChunkSensor.sensor.get(),
|
||||
NearestVisibleContainer.sensor.get(),
|
||||
)
|
||||
}
|
||||
|
||||
@ -146,6 +149,7 @@ object ProjectedPersonAI {
|
||||
private fun initWorkActivity(brain: Brain<ProjectedPersonEntity>) {
|
||||
brain.addActivity(
|
||||
Activity.WORK, ImmutableList.of(
|
||||
7 weight ExchangeItem(),
|
||||
10 weight createStrollBehavior(),
|
||||
99 weight UpdateActivityFromSchedule.create(),
|
||||
)
|
||||
|
@ -4,3 +4,5 @@ accessible method net/minecraft/core/registries/BuiltInRegistries registerSimple
|
||||
accessible class net/minecraft/core/registries/BuiltInRegistries$RegistryBootstrap
|
||||
# Entity Brain AI
|
||||
accessible method net/minecraft/world/entity/ai/sensing/SensorType <init> (Ljava/util/function/Supplier;)V
|
||||
# ExchangeItem behaviour
|
||||
accessible method net/minecraft/world/level/block/entity/ChestBlockEntity playSound (Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/sounds/SoundEvent;)V
|
||||
|
Loading…
Reference in New Issue
Block a user