package com.cursedcauldron.wildbackport.common.entities.brain; import com.cursedcauldron.wildbackport.common.entities.Warden; import com.cursedcauldron.wildbackport.common.entities.brain.warden.Digging; import com.cursedcauldron.wildbackport.common.entities.brain.warden.Dismount; import com.cursedcauldron.wildbackport.common.entities.brain.warden.Emerging; import com.cursedcauldron.wildbackport.common.entities.brain.warden.ForgetAttackTarget; import com.cursedcauldron.wildbackport.common.entities.brain.warden.GoToTargetLocation; import com.cursedcauldron.wildbackport.common.entities.brain.warden.Roar; import com.cursedcauldron.wildbackport.common.entities.brain.warden.FindRoarTarget; import com.cursedcauldron.wildbackport.common.entities.brain.warden.SetWardenLookTarget; import com.cursedcauldron.wildbackport.common.entities.brain.warden.Sniffing; import com.cursedcauldron.wildbackport.common.entities.brain.warden.SonicBoom; import com.cursedcauldron.wildbackport.common.entities.brain.warden.TryToSniff; import com.cursedcauldron.wildbackport.common.registry.entity.WBActivities; import com.cursedcauldron.wildbackport.common.registry.entity.WBMemoryModules; import com.cursedcauldron.wildbackport.common.registry.entity.WBSensorTypes; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.mojang.datafixers.util.Pair; import com.mojang.serialization.Dynamic; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; import net.minecraft.util.Mth; import net.minecraft.util.Unit; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.ai.Brain; import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.ai.behavior.Behavior; import net.minecraft.world.entity.ai.behavior.BlockPosTracker; import net.minecraft.world.entity.ai.behavior.DoNothing; import net.minecraft.world.entity.ai.behavior.LookAtTargetSink; import net.minecraft.world.entity.ai.behavior.MeleeAttack; import net.minecraft.world.entity.ai.behavior.MoveToTargetSink; import net.minecraft.world.entity.ai.behavior.RandomStroll; import net.minecraft.world.entity.ai.behavior.RunOne; import net.minecraft.world.entity.ai.behavior.SetEntityLookTarget; import net.minecraft.world.entity.ai.behavior.SetWalkTargetFromAttackTargetIfTargetOutOfReach; import net.minecraft.world.entity.ai.behavior.Swim; import net.minecraft.world.entity.ai.memory.MemoryModuleType; import net.minecraft.world.entity.ai.memory.MemoryStatus; import net.minecraft.world.entity.ai.sensing.Sensor; import net.minecraft.world.entity.ai.sensing.SensorType; import net.minecraft.world.entity.schedule.Activity; import java.util.List; //<> public class WardenBrain { private static final int DIGGING_DURATION = Mth.ceil(100.0F); public static final int EMERGE_DURATION = Mth.ceil(133.59999F); public static final int ROAR_DURATION = Mth.ceil(84.0F); private static final int SNIFFING_DURATION = Mth.ceil(83.2F); private static final List>> SENSOR_TYPES = List.of(SensorType.NEAREST_PLAYERS, WBSensorTypes.WARDEN_ENTITY_SENSOR.get()); private static final List> MEMORY_TYPES = List.of(MemoryModuleType.NEAREST_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_NEMESIS, MemoryModuleType.LOOK_TARGET, MemoryModuleType.WALK_TARGET, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.PATH, MemoryModuleType.ATTACK_TARGET, MemoryModuleType.ATTACK_COOLING_DOWN, MemoryModuleType.NEAREST_ATTACKABLE, WBMemoryModules.ROAR_TARGET.get(), WBMemoryModules.DISTURBANCE_LOCATION.get(), WBMemoryModules.RECENT_PROJECTILE.get(), WBMemoryModules.IS_SNIFFING.get(), WBMemoryModules.IS_EMERGING.get(), WBMemoryModules.ROAR_SOUND_DELAY.get(), WBMemoryModules.DIG_COOLDOWN.get(), WBMemoryModules.ROAR_SOUND_COOLDOWN.get(), WBMemoryModules.SNIFF_COOLDOWN.get(), WBMemoryModules.TOUCH_COOLDOWN.get(), WBMemoryModules.VIBRATION_COOLDOWN.get(), WBMemoryModules.SONIC_BOOM_COOLDOWN.get(), WBMemoryModules.SONIC_BOOM_SOUND_COOLDOWN.get(), WBMemoryModules.SONIC_BOOM_SOUND_DELAY.get()); private static final Behavior DIG_COOLDOWN_SETTER = new Behavior<>(ImmutableMap.of(WBMemoryModules.DIG_COOLDOWN.get(), MemoryStatus.REGISTERED)) { @Override protected void start(ServerLevel level, Warden warden, long time) { resetDigCooldown(warden); } }; public static void updateActivities(Warden warden) { warden.getBrain().setActiveActivityToFirstValid(ImmutableList.of(WBActivities.EMERGE.get(), WBActivities.DIG.get(), WBActivities.ROAR.get(), Activity.FIGHT, WBActivities.INVESTIGATE.get(), WBActivities.SNIFF.get(), Activity.IDLE)); } public static Brain makeBrain(Warden warden, Dynamic dynamic) { Brain.Provider provider = Brain.provider(MEMORY_TYPES, SENSOR_TYPES); Brain brain = provider.makeBrain(dynamic); initCoreActivity(brain); initEmergeActivity(brain); initDiggingActivity(brain); initIdleActivity(brain); initRoarActivity(brain); initFightActivity(warden, brain); initInvestigateActivity(brain); initSniffingActivity(brain); brain.setCoreActivities(ImmutableSet.of(Activity.CORE)); brain.setDefaultActivity(Activity.IDLE); brain.useDefaultActivity(); return brain; } private static void initCoreActivity(Brain brain) { brain.addActivity(Activity.CORE, 0, ImmutableList.of(new Swim(0.8F), new SetWardenLookTarget(), new LookAtTargetSink(45, 90), new MoveToTargetSink())); } private static void initEmergeActivity(Brain brain) { brain.addActivityAndRemoveMemoryWhenStopped(WBActivities.EMERGE.get(), 5, ImmutableList.of(new Emerging<>(EMERGE_DURATION)), WBMemoryModules.IS_EMERGING.get()); } private static void initDiggingActivity(Brain brain) { brain.addActivityWithConditions(WBActivities.DIG.get(), ImmutableList.of(Pair.of(0, new Dismount()), Pair.of(1, new Digging<>(DIGGING_DURATION))), ImmutableSet.of(Pair.of(WBMemoryModules.ROAR_TARGET.get(), MemoryStatus.VALUE_ABSENT), Pair.of(WBMemoryModules.DIG_COOLDOWN.get(), MemoryStatus.VALUE_ABSENT))); } private static void initIdleActivity(Brain brain) { brain.addActivity(Activity.IDLE, 10, ImmutableList.of(new FindRoarTarget<>(Warden::getPrimeSuspect), new TryToSniff(), new RunOne<>(ImmutableMap.of(WBMemoryModules.IS_SNIFFING.get(), MemoryStatus.VALUE_ABSENT), ImmutableList.of(Pair.of(new RandomStroll(0.5F), 2), Pair.of(new DoNothing(30, 60), 1))))); } private static void initInvestigateActivity(Brain brain) { brain.addActivityAndRemoveMemoryWhenStopped(WBActivities.INVESTIGATE.get(), 5, ImmutableList.of(new FindRoarTarget<>(Warden::getPrimeSuspect), new GoToTargetLocation<>(WBMemoryModules.DISTURBANCE_LOCATION.get(), 2, 0.7F)), WBMemoryModules.DISTURBANCE_LOCATION.get()); } private static void initSniffingActivity(Brain brain) { brain.addActivityAndRemoveMemoryWhenStopped(WBActivities.SNIFF.get(), 5, ImmutableList.of(new FindRoarTarget<>(Warden::getPrimeSuspect), new Sniffing<>(SNIFFING_DURATION)), WBMemoryModules.IS_SNIFFING.get()); } private static void initRoarActivity(Brain brain) { brain.addActivityAndRemoveMemoryWhenStopped(WBActivities.ROAR.get(), 10, ImmutableList.of(new Roar()), WBMemoryModules.ROAR_TARGET.get()); } private static void initFightActivity(Warden warden, Brain brain) { brain.addActivityAndRemoveMemoryWhenStopped(Activity.FIGHT, 10, ImmutableList.of(DIG_COOLDOWN_SETTER, new ForgetAttackTarget<>(entity -> !warden.getAngriness().isAngry() || !warden.isValidTarget(entity), WardenBrain::removeDeadSuspect, false), new SetEntityLookTarget(entity -> isTargeting(warden, entity), (float)warden.getAttributeValue(Attributes.FOLLOW_RANGE)), new SetWalkTargetFromAttackTargetIfTargetOutOfReach(1.2F), new SonicBoom(), new MeleeAttack(18)), MemoryModuleType.ATTACK_TARGET); } private static boolean isTargeting(Warden warden, LivingEntity entity) { return warden.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).filter(target -> target == entity).isPresent(); } private static void removeDeadSuspect(Warden warden, LivingEntity suspect) { if (!warden.isValidTarget(suspect)) warden.removeSuspect(suspect); resetDigCooldown(warden); } public static void resetDigCooldown(LivingEntity warden) { if (warden.getBrain().hasMemoryValue(WBMemoryModules.DIG_COOLDOWN.get())) { warden.getBrain().setMemoryWithExpiry(WBMemoryModules.DIG_COOLDOWN.get(), Unit.INSTANCE, 1200L); } } public static void lookAtDisturbance(Warden warden, BlockPos pos) { if (warden.level.getWorldBorder().isWithinBounds(pos) && warden.getPrimeSuspect().isEmpty() && warden.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).isEmpty()) { resetDigCooldown(warden); warden.getBrain().setMemoryWithExpiry(WBMemoryModules.SNIFF_COOLDOWN.get(), Unit.INSTANCE, 100L); warden.getBrain().setMemoryWithExpiry(MemoryModuleType.LOOK_TARGET, new BlockPosTracker(pos), 100L); warden.getBrain().setMemoryWithExpiry(WBMemoryModules.DISTURBANCE_LOCATION.get(), pos, 100L); warden.getBrain().eraseMemory(MemoryModuleType.WALK_TARGET); } } }