TheWildBackport/common/src/main/java/com/cursedcauldron/wildbackport/common/entities/brain/WardenBrain.java
2023-08-29 17:39:30 +02:00

277 lines
11 KiB
Java

package com.cursedcauldron.wildbackport.common.entities.brain;
import java.util.List;
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.FindRoarTarget;
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.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;
//<>
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<SensorType<? extends Sensor<? super Warden>>> SENSOR_TYPES
= List.of(SensorType.NEAREST_PLAYERS, WBSensorTypes.WARDEN_ENTITY_SENSOR.get());
private static final List<MemoryModuleType<?>> 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<Warden> 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<Warden> provider = Brain.provider(MEMORY_TYPES, SENSOR_TYPES);
Brain<Warden> 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<Warden> 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<Warden> brain) {
brain.addActivityAndRemoveMemoryWhenStopped(
WBActivities.EMERGE.get(),
5,
ImmutableList.of(new Emerging<>(EMERGE_DURATION)),
WBMemoryModules.IS_EMERGING.get()
);
}
private static void initDiggingActivity(Brain<Warden> 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<Warden> 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<Warden> 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<Warden> 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<Warden> brain) {
brain.addActivityAndRemoveMemoryWhenStopped(
WBActivities.ROAR.get(),
10,
ImmutableList.of(new Roar()),
WBMemoryModules.ROAR_TARGET.get()
);
}
private static void initFightActivity(Warden warden, Brain<Warden> 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);
}
}
}