allay tweaks and note block event

This commit is contained in:
ItsBlackGear 2022-07-10 05:02:25 -04:00
parent 9675def3b3
commit 484129642c
10 changed files with 134 additions and 118 deletions

View file

@ -3,6 +3,7 @@ package com.cursedcauldron.wildbackport.client.registry;
import com.cursedcauldron.wildbackport.WildBackport;
import com.cursedcauldron.wildbackport.core.mixin.access.CriteriaTriggersAccessor;
import net.minecraft.advancements.CriterionTrigger;
import net.minecraft.advancements.critereon.ItemUsedOnBlockTrigger;
import net.minecraft.advancements.critereon.KilledTrigger;
import net.minecraft.advancements.critereon.LocationTrigger;
import net.minecraft.resources.ResourceLocation;

View file

@ -9,11 +9,9 @@ import com.cursedcauldron.wildbackport.common.registry.WBGameEvents;
import com.cursedcauldron.wildbackport.common.registry.entity.WBMemoryModules;
import com.cursedcauldron.wildbackport.common.tag.WBGameEventTags;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.mojang.serialization.Dynamic;
import net.minecraft.core.BlockPos;
import net.minecraft.core.GlobalPos;
import net.minecraft.core.Vec3i;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtOps;
import net.minecraft.network.protocol.game.DebugPackets;
@ -50,6 +48,7 @@ import net.minecraft.world.entity.npc.InventoryCarrier;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.level.GameRules;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.gameevent.GameEvent;
@ -59,16 +58,16 @@ import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
//<>
public class Allay extends PathfinderMob implements InventoryCarrier, VibrationListenerSource.VibrationConfig {
private static final Vec3i PICKUP_REACH = new Vec3i(1, 1, 1);
protected static final ImmutableList<? extends SensorType<? extends Sensor<? super Allay>>> SENSORS = ImmutableList.of(SensorType.NEAREST_LIVING_ENTITIES, SensorType.NEAREST_PLAYERS, SensorType.HURT_BY, SensorType.NEAREST_ITEMS);
protected static final ImmutableList<MemoryModuleType<?>> MEMORIES = ImmutableList.of(MemoryModuleType.PATH, MemoryModuleType.LOOK_TARGET, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.WALK_TARGET, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.HURT_BY, MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, WBMemoryModules.LIKED_PLAYER.get(), WBMemoryModules.LIKED_NOTEBLOCK.get(), WBMemoryModules.LIKED_NOTEBLOCK_COOLDOWN_TICKS.get(), WBMemoryModules.ITEM_PICKUP_COOLDOWN_TICKS.get());
public static final ImmutableList<Float> SOUND_PITCHES = ImmutableList.of(0.5625F, 0.625F, 0.75F, 0.9375F, 1.0F, 1.0F, 1.125F, 1.25F, 1.5F, 1.875F, 2.0F, 2.25F, 2.5F, 3.0F, 3.75F, 4.0F);
public static final ImmutableList<Float> THROW_SOUND_PITCHES = ImmutableList.of(0.5625F, 0.625F, 0.75F, 0.9375F, 1.0F, 1.0F, 1.125F, 1.25F, 1.5F, 1.875F, 2.0F, 2.25F, 2.5F, 3.0F, 3.75F, 4.0F);
private final GameEventListenerRegistrar registrar;
private VibrationListenerSource listener;
private final SimpleContainer inventory = new SimpleContainer(1);
@ -90,7 +89,7 @@ public class Allay extends PathfinderMob implements InventoryCarrier, VibrationL
@Override
protected Brain<?> makeBrain(Dynamic<?> dynamic) {
return AllayBrain.makeBrain(this.brainProvider().makeBrain(dynamic));
return AllayBrain.create(this.brainProvider().makeBrain(dynamic));
}
@Override @SuppressWarnings("unchecked")
@ -184,7 +183,16 @@ public class Allay extends PathfinderMob implements InventoryCarrier, VibrationL
this.getBrain().tick((ServerLevel)this.level, this);
this.level.getProfiler().pop();
this.level.getProfiler().push("allayActivityUpdate");
AllayBrain.updateActivity(this);
AllayBrain.updateActivities(this);
this.level.getProfiler().pop();
this.level.getProfiler().push("looting");
if (!this.level.isClientSide && this.canPickUpLoot() && this.isAlive() && !this.dead && this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
List<ItemEntity> items = this.level.getEntitiesOfClass(ItemEntity.class, this.getBoundingBox().inflate(1.0, 1.0, 1.0));
for (ItemEntity item : items) {
if (item.isRemoved() || item.getItem().isEmpty() || item.hasPickUpDelay() || !this.wantsToPickUp(item.getItem())) continue;
this.pickUpItem(item);
}
}
this.level.getProfiler().pop();
super.customServerAiStep();
}
@ -200,7 +208,7 @@ public class Allay extends PathfinderMob implements InventoryCarrier, VibrationL
super.tick();
if (this.level.isClientSide) {
this.holdingTicksOld = this.holdingTicks;
if (this.hasItemInHand()) {
if (this.isHoldingItem()) {
this.holdingTicks = Mth.clamp(this.holdingTicks + 1.0F, 0.0F, 5.0F);
} else {
this.holdingTicks = Mth.clamp(this.holdingTicks - 1.0F, 0.0F, 5.0F);
@ -212,10 +220,10 @@ public class Allay extends PathfinderMob implements InventoryCarrier, VibrationL
@Override
public boolean canPickUpLoot() {
return !this.isOnPickupCooldown() && this.hasItemInHand();
return !this.isOnItemPickupCooldown() && this.isHoldingItem();
}
public boolean hasItemInHand() {
public boolean isHoldingItem() {
return !this.getItemInHand(InteractionHand.MAIN_HAND).isEmpty();
}
@ -224,7 +232,7 @@ public class Allay extends PathfinderMob implements InventoryCarrier, VibrationL
return false;
}
private boolean isOnPickupCooldown() {
private boolean isOnItemPickupCooldown() {
return this.getBrain().checkMemory(WBMemoryModules.ITEM_PICKUP_COOLDOWN_TICKS.get(), MemoryStatus.VALUE_PRESENT);
}
@ -237,7 +245,6 @@ public class Allay extends PathfinderMob implements InventoryCarrier, VibrationL
stack.setCount(1);
this.setItemInHand(InteractionHand.MAIN_HAND, stack);
if (!player.getAbilities().instabuild) playerStack.shrink(1);
this.level.playSound(player, this, WBSoundEvents.ALLAY_ITEM_GIVEN, SoundSource.NEUTRAL, 2.0F, 1.0F);
this.getBrain().setMemory(WBMemoryModules.LIKED_PLAYER.get(), player.getUUID());
return InteractionResult.SUCCESS;
@ -245,9 +252,7 @@ public class Allay extends PathfinderMob implements InventoryCarrier, VibrationL
this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY);
this.level.playSound(player, this, WBSoundEvents.ALLAY_ITEM_TAKEN, SoundSource.NEUTRAL, 2.0F, 1.0F);
this.swing(InteractionHand.MAIN_HAND);
for (ItemStack stack : this.getInventory().removeAllItems()) BehaviorUtils.throwItem(this, stack, this.position());
this.getBrain().eraseMemory(WBMemoryModules.LIKED_PLAYER.get());
player.addItem(allayStack);
return InteractionResult.SUCCESS;
@ -261,10 +266,6 @@ public class Allay extends PathfinderMob implements InventoryCarrier, VibrationL
return this.inventory;
}
public static Vec3i getPickupReach() {
return PICKUP_REACH;
}
@Override
public boolean wantsToPickUp(ItemStack stack) {
ItemStack allayStack = this.getItemInHand(InteractionHand.MAIN_HAND);
@ -306,10 +307,6 @@ public class Allay extends PathfinderMob implements InventoryCarrier, VibrationL
return this.registrar;
}
public boolean isFlying() {
return this.animationSpeed > 0.3F;
}
public float getHoldingItemAnimationProgress(float animationProgress) {
return Mth.lerp(animationProgress, this.holdingTicksOld, this.holdingTicks) / 5.0F;
}
@ -346,7 +343,7 @@ public class Allay extends PathfinderMob implements InventoryCarrier, VibrationL
@Override
public void onSignalReceive(ServerLevel level, GameEventListener listener, BlockPos pos, GameEvent event, @Nullable Entity entity, @Nullable Entity source, float distance) {
if (event == WBGameEvents.NOTE_BLOCK_PLAY.get()) AllayBrain.hearNoteblock(this, new BlockPos(pos));
if (event == WBGameEvents.NOTE_BLOCK_PLAY.get()) AllayBrain.rememberNoteBlock(this, new BlockPos(pos));
}
@Override
@ -368,7 +365,7 @@ public class Allay extends PathfinderMob implements InventoryCarrier, VibrationL
if (tag.contains("listener", 10)) VibrationListenerSource.codec(this).parse(new Dynamic<>(NbtOps.INSTANCE, tag.getCompound("listener"))).resultOrPartial(WildBackport.LOGGER::error).ifPresent(listener -> this.listener = listener);
}
public Iterable<BlockPos> iteratePathfindingStartNodeCandidatePositions() {
public Iterable<BlockPos> getPotentialEscapePositions() {
AABB box = this.getBoundingBox();
int minX = Mth.floor(box.minX - 0.5D);
int maxX = Mth.floor(box.maxX + 0.5D);

View file

@ -79,8 +79,8 @@ public class Frog extends Animal {
public static final Ingredient FOOD = Ingredient.of(Items.SLIME_BALL);
protected static final ImmutableList<? extends SensorType<? extends Sensor<? super Frog>>> SENSORS = ImmutableList.of(SensorType.NEAREST_LIVING_ENTITIES, SensorType.HURT_BY, WBSensorTypes.FROG_ATTACKABLES.get(), WBSensorTypes.FROG_TEMPTATIONS.get(), WBSensorTypes.IS_IN_WATER.get());
protected static final ImmutableList<? extends MemoryModuleType<?>> MEMORIES = ImmutableList.of(MemoryModuleType.LOOK_TARGET, MemoryModuleType.NEAREST_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.WALK_TARGET, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.PATH, MemoryModuleType.BREED_TARGET, MemoryModuleType.LONG_JUMP_COOLDOWN_TICKS, MemoryModuleType.LONG_JUMP_MID_JUMP, MemoryModuleType.ATTACK_TARGET, MemoryModuleType.TEMPTING_PLAYER, MemoryModuleType.TEMPTATION_COOLDOWN_TICKS, MemoryModuleType.IS_TEMPTED, MemoryModuleType.HURT_BY, MemoryModuleType.HURT_BY_ENTITY, MemoryModuleType.NEAREST_ATTACKABLE, WBMemoryModules.IS_IN_WATER.get(), WBMemoryModules.IS_PREGNANT.get(), WBMemoryModules.UNREACHABLE_TONGUE_TARGETS.get());
private static final EntityDataAccessor<Integer> VARIANT_ID = SynchedEntityData.defineId(Frog.class, EntityDataSerializers.INT);
private static final EntityDataAccessor<OptionalInt> TARGET_ID = SynchedEntityData.defineId(Frog.class, EntityDataSerializers.OPTIONAL_UNSIGNED_INT);
private static final EntityDataAccessor<Integer> VARIANT = SynchedEntityData.defineId(Frog.class, EntityDataSerializers.INT);
private static final EntityDataAccessor<OptionalInt> TARGET = SynchedEntityData.defineId(Frog.class, EntityDataSerializers.OPTIONAL_UNSIGNED_INT);
public final AnimationState longJumpingAnimationState = new AnimationState();
public final AnimationState croakingAnimationState = new AnimationState();
public final AnimationState usingTongueAnimationState = new AnimationState();
@ -115,20 +115,20 @@ public class Frog extends Animal {
@Override
protected void defineSynchedData() {
super.defineSynchedData();
this.entityData.define(VARIANT_ID, 0);
this.entityData.define(TARGET_ID, OptionalInt.empty());
this.entityData.define(VARIANT, 0);
this.entityData.define(TARGET, OptionalInt.empty());
}
public void clearFrogTarget() {
this.entityData.set(TARGET_ID, OptionalInt.empty());
this.entityData.set(TARGET, OptionalInt.empty());
}
public Optional<Entity> getFrogTarget() {
return this.entityData.get(TARGET_ID).stream().mapToObj(this.level::getEntity).filter(Objects::nonNull).findFirst();
return this.entityData.get(TARGET).stream().mapToObj(this.level::getEntity).filter(Objects::nonNull).findFirst();
}
public void setFrogTarget(Entity entity) {
this.entityData.set(TARGET_ID, OptionalInt.of(entity.getId()));
this.entityData.set(TARGET, OptionalInt.of(entity.getId()));
}
@Override
@ -142,11 +142,11 @@ public class Frog extends Animal {
}
public Variant getVariant() {
return Variant.byId(this.entityData.get(VARIANT_ID));
return Variant.byId(this.entityData.get(VARIANT));
}
public void setVariant(Variant variant) {
this.entityData.set(VARIANT_ID, variant.getId());
this.entityData.set(VARIANT, variant.getId());
}
@Override
@ -166,11 +166,11 @@ public class Frog extends Animal {
return true;
}
private boolean isMovingOnLand() {
private boolean shouldWalk() {
return this.onGround && this.getDeltaMovement().horizontalDistanceSqr() > 1.0E-6D && !this.isInWaterOrBubble();
}
private boolean isMovingOnWater() {
private boolean shouldSwim() {
return this.getDeltaMovement().horizontalDistanceSqr() > 1.0E-6D && this.isInWaterOrBubble();
}
@ -188,13 +188,13 @@ public class Frog extends Animal {
@Override
public void tick() {
if (this.level.isClientSide()) {
if (this.isMovingOnLand()) {
if (this.shouldWalk()) {
this.walkingAnimationState.startIfNotRunning(this.tickCount);
} else {
this.walkingAnimationState.stop();
}
if (this.isMovingOnWater()) {
if (this.shouldSwim()) {
this.idlingInWaterAnimationState.stop();
this.swimmingAnimationState.startIfNotRunning(this.tickCount);
} else if (this.isInWaterOrBubble()) {
@ -282,7 +282,6 @@ public class Frog extends Animal {
} else {
this.setVariant(Variant.TEMPERATE);
}
FrogBrain.coolDownLongJump(this, accessor.getRandom());
return super.finalizeSpawn(accessor, difficulty, spawnType, groupData, tag);
}
@ -328,19 +327,19 @@ public class Frog extends Animal {
}
@Override
public void travel(Vec3 motion) {
public void travel(Vec3 input) {
if (this.isEffectiveAi() && this.isInWater()) {
this.moveRelative(this.getSpeed(), motion);
this.moveRelative(this.getSpeed(), input);
this.move(MoverType.SELF, this.getDeltaMovement());
this.setDeltaMovement(this.getDeltaMovement().scale(0.9D));
} else {
super.travel(motion);
super.travel(input);
}
}
@Override
public boolean canCutCorner(BlockPathTypes path) {
return super.canCutCorner(path) && path != BlockPathTypes.WATER_BORDER;
public boolean canCutCorner(BlockPathTypes type) {
return super.canCutCorner(type) && type != BlockPathTypes.WATER_BORDER;
}
public static boolean isValidFrogFood(LivingEntity entity) {
@ -387,12 +386,13 @@ public class Frog extends Animal {
}
static class FrogPathNavigator extends WaterBoundPathNavigation {
FrogPathNavigator(Frog frog, Level world) {
super(frog, world);
FrogPathNavigator(Frog frog, Level level) {
super(frog, level);
}
@Override
protected PathFinder createPathFinder(int range) {
this.nodeEvaluator = new FrogNodeEvaluator(true);
this.nodeEvaluator.setCanPassDoors(true);
return new PathFinder(this.nodeEvaluator, range);
}

View file

@ -2,7 +2,7 @@ package com.cursedcauldron.wildbackport.common.entities.brain;
import com.cursedcauldron.wildbackport.common.entities.Allay;
import com.cursedcauldron.wildbackport.common.entities.brain.allay.FlyingRandomStroll;
import com.cursedcauldron.wildbackport.common.entities.brain.allay.GoAndGiveItemsToTarget;
import com.cursedcauldron.wildbackport.common.entities.brain.allay.GiveInventoryToLookTarget;
import com.cursedcauldron.wildbackport.common.entities.brain.allay.StayCloseToTarget;
import com.cursedcauldron.wildbackport.common.registry.entity.WBMemoryModules;
import com.google.common.collect.ImmutableList;
@ -39,62 +39,62 @@ import java.util.UUID;
//<>
public class AllayBrain {
public static Brain<?> makeBrain(Brain<Allay> brain) {
initCoreActivity(brain);
initIdleActivity(brain);
public static Brain<?> create(Brain<Allay> brain) {
addCoreActivities(brain);
addIdleActivities(brain);
brain.setCoreActivities(ImmutableSet.of(Activity.CORE));
brain.setDefaultActivity(Activity.IDLE);
brain.useDefaultActivity();
return brain;
}
private static void initCoreActivity(Brain<Allay> brain) {
private static void addCoreActivities(Brain<Allay> brain) {
brain.addActivity(Activity.CORE, 0, ImmutableList.of(new Swim(0.8F), new AnimalPanic(2.5F), new LookAtTargetSink(45, 90), new MoveToTargetSink(), new CountDownCooldownTicks(WBMemoryModules.LIKED_NOTEBLOCK_COOLDOWN_TICKS.get()), new CountDownCooldownTicks(WBMemoryModules.ITEM_PICKUP_COOLDOWN_TICKS.get())));
}
private static void initIdleActivity(Brain<Allay> brain) {
private static void addIdleActivities(Brain<Allay> brain) {
brain.addActivityWithConditions(Activity.IDLE, ImmutableList.of(Pair.of(0, new GoToWantedItem<>(entity -> {
return true;
}, 1.75F, true, 32)), Pair.of(1, new GoAndGiveItemsToTarget<>(AllayBrain::getItemDepositPosition, 2.25F)), Pair.of(2, new StayCloseToTarget<>(AllayBrain::getItemDepositPosition, 4, 16, 2.25F)), Pair.of(3, new RunSometimes<>(new SetEntityLookTarget(entity -> {
}, 1.75F, true, 32)), Pair.of(1, new GiveInventoryToLookTarget<>(AllayBrain::getLookTarget, 2.25F)), Pair.of(2, new StayCloseToTarget<>(AllayBrain::getLookTarget, 4, 16, 2.25F)), Pair.of(3, new RunSometimes<>(new SetEntityLookTarget(entity -> {
return true;
}, 6.0F), UniformInt.of(30, 60))), Pair.of(4, new RunOne<>(ImmutableList.of(Pair.of(new FlyingRandomStroll(1.0F), 2), Pair.of(new SetWalkTargetFromLookTarget(1.0F, 3), 2), Pair.of(new DoNothing(30, 60), 1))))), ImmutableSet.of());
}
public static void updateActivity(Allay allay) {
public static void updateActivities(Allay allay) {
allay.getBrain().setActiveActivityToFirstValid(ImmutableList.of(Activity.IDLE));
}
public static void hearNoteblock(LivingEntity entity, BlockPos pos) {
public static void rememberNoteBlock(LivingEntity entity, BlockPos pos) {
Brain<?> brain = entity.getBrain();
GlobalPos globalPos = GlobalPos.of(entity.getLevel().dimension(), pos);
Optional<GlobalPos> likedNoteblock = brain.getMemory(WBMemoryModules.LIKED_NOTEBLOCK.get());
if (likedNoteblock.isEmpty()) {
Optional<GlobalPos> likedNoteBlock = brain.getMemory(WBMemoryModules.LIKED_NOTEBLOCK.get());
if (likedNoteBlock.isEmpty()) {
brain.setMemory(WBMemoryModules.LIKED_NOTEBLOCK.get(), globalPos);
brain.setMemory(WBMemoryModules.LIKED_NOTEBLOCK_COOLDOWN_TICKS.get(), 600);
} else if (likedNoteblock.get().equals(globalPos)) {
} else if (likedNoteBlock.get().equals(globalPos)) {
brain.setMemory(WBMemoryModules.LIKED_NOTEBLOCK_COOLDOWN_TICKS.get(), 600);
}
}
private static Optional<PositionTracker> getItemDepositPosition(LivingEntity entity) {
private static Optional<PositionTracker> getLookTarget(LivingEntity entity) {
Brain<?> brain = entity.getBrain();
Optional<GlobalPos> likedNoteblock = brain.getMemory(WBMemoryModules.LIKED_NOTEBLOCK.get());
if (likedNoteblock.isPresent()) {
GlobalPos pos = likedNoteblock.get();
if (shouldDepositItemsAtLikedNoteblock(entity, brain, pos)) return Optional.of(new BlockPosTracker(pos.pos().above()));
Optional<GlobalPos> likedNoteBlock = brain.getMemory(WBMemoryModules.LIKED_NOTEBLOCK.get());
if (likedNoteBlock.isPresent()) {
GlobalPos pos = likedNoteBlock.get();
if (shouldGoTowardsNoteBlock(entity, brain, pos)) return Optional.of(new BlockPosTracker(pos.pos().above()));
brain.eraseMemory(WBMemoryModules.LIKED_NOTEBLOCK.get());
}
return getLikedPlayerPositionTracker(entity);
return getLikedLookTarget(entity);
}
private static boolean shouldDepositItemsAtLikedNoteblock(LivingEntity entity, Brain<?> brain, GlobalPos pos) {
private static boolean shouldGoTowardsNoteBlock(LivingEntity entity, Brain<?> brain, GlobalPos pos) {
Optional<Integer> cooldownTicks = brain.getMemory(WBMemoryModules.LIKED_NOTEBLOCK_COOLDOWN_TICKS.get());
Level level = entity.getLevel();
return level.dimension() == pos.dimension() && level.getBlockState(pos.pos()).is(Blocks.NOTE_BLOCK) && cooldownTicks.isPresent();
}
private static Optional<PositionTracker> getLikedPlayerPositionTracker(LivingEntity entity) {
private static Optional<PositionTracker> getLikedLookTarget(LivingEntity entity) {
return getLikedPlayer(entity).map(player -> new EntityTracker(player, true));
}

View file

@ -26,71 +26,70 @@ import java.util.function.Function;
//<>
public class GoAndGiveItemsToTarget<E extends LivingEntity & InventoryCarrier> extends Behavior<E> {
private final Function<LivingEntity, Optional<PositionTracker>> targetPosition;
private final float speedModifier;
public class GiveInventoryToLookTarget<E extends LivingEntity & InventoryCarrier> extends Behavior<E> {
private final Function<LivingEntity, Optional<PositionTracker>> lookTarget;
private final float speed;
public GoAndGiveItemsToTarget(Function<LivingEntity, Optional<PositionTracker>> targetPosition, float speedModifier) {
public GiveInventoryToLookTarget(Function<LivingEntity, Optional<PositionTracker>> lookTarget, float speed) {
super(ImmutableMap.of(MemoryModuleType.LOOK_TARGET, MemoryStatus.REGISTERED, MemoryModuleType.WALK_TARGET, MemoryStatus.REGISTERED, WBMemoryModules.ITEM_PICKUP_COOLDOWN_TICKS.get(), MemoryStatus.REGISTERED));
this.targetPosition = targetPosition;
this.speedModifier = speedModifier;
this.lookTarget = lookTarget;
this.speed = speed;
}
@Override
protected boolean checkExtraStartConditions(ServerLevel level, E entity) {
return this.canThrowItemToTarget(entity);
return this.hasItemAndTarget(entity);
}
@Override
protected boolean canStillUse(ServerLevel level, E entity, long time) {
return this.canThrowItemToTarget(entity);
return this.hasItemAndTarget(entity);
}
@Override
protected void start(ServerLevel level, E entity, long time) {
this.targetPosition.apply(entity).ifPresent(target -> MobUtils.setWalkAndLookTargetMemories(entity, target, this.speedModifier, 3));
this.lookTarget.apply(entity).ifPresent(target -> MobUtils.walkTowards(entity, target, this.speed, 3));
}
@Override
protected void tick(ServerLevel level, E entity, long time) {
Optional<PositionTracker> optional = this.targetPosition.apply(entity);
if (optional.isPresent()) {
PositionTracker tracker = optional.get();
double d0 = tracker.currentPosition().distanceTo(entity.getEyePosition());
if (d0 < 3.0D) {
ItemStack itemstack = entity.getInventory().removeItem(0, 1);
if (!itemstack.isEmpty()) {
throwItem(entity, itemstack, getThrowPosition(tracker));
Optional<PositionTracker> lookTarget = this.lookTarget.apply(entity);
if (lookTarget.isPresent()) {
PositionTracker target = lookTarget.get();
double distance = target.currentPosition().distanceTo(entity.getEyePosition());
if (distance < 3.0D) {
ItemStack stack = entity.getInventory().removeItem(0, 1);
if (!stack.isEmpty()) {
playThrowSound(entity, stack, offsetTarget(target));
if (entity instanceof Allay allay) {
AllayBrain.getLikedPlayer(allay).ifPresent(p_217224_ -> this.triggerDropItemOnBlock(tracker, itemstack, p_217224_));
AllayBrain.getLikedPlayer(allay).ifPresent(player -> this.triggerCriteria(target, stack, player));
}
entity.getBrain().setMemory(WBMemoryModules.ITEM_PICKUP_COOLDOWN_TICKS.get(), 60);
}
}
}
}
private void triggerDropItemOnBlock(PositionTracker tracker, ItemStack stack, ServerPlayer player) {
BlockPos pos = tracker.currentBlockPosition().below();
private void triggerCriteria(PositionTracker target, ItemStack stack, ServerPlayer player) {
BlockPos pos = target.currentBlockPosition().below();
// WBCriteriaTriggers.ALLAY_DROP_ITEM_ON_BLOCK.trigger(player, pos, stack);
}
private boolean canThrowItemToTarget(E entity) {
return !entity.getInventory().isEmpty() && this.targetPosition.apply(entity).isPresent();
private boolean hasItemAndTarget(E entity) {
return !entity.getInventory().isEmpty() && this.lookTarget.apply(entity).isPresent();
}
private static Vec3 getThrowPosition(PositionTracker tracker) {
private static Vec3 offsetTarget(PositionTracker tracker) {
return tracker.currentPosition().add(0.0D, 1.0D, 0.0D);
}
public static void throwItem(LivingEntity entity, ItemStack stack, Vec3 position) {
Vec3 vec3 = new Vec3(0.2F, 0.3F, 0.2F);
MobUtils.throwItem(entity, stack, position, vec3, 0.2F);
public static void playThrowSound(LivingEntity entity, ItemStack stack, Vec3 pos) {
Vec3 velocity = new Vec3(0.2F, 0.3F, 0.2F);
MobUtils.give(entity, stack, pos, velocity, 0.2F);
Level level = entity.level;
if (level.getGameTime() % 7L == 0L && level.random.nextDouble() < 0.9D) {
float pitch = Util.getRandom(Allay.SOUND_PITCHES, level.getRandom());
float pitch = Util.getRandom(Allay.THROW_SOUND_PITCHES, level.getRandom());
level.playSound(null, entity, WBSoundEvents.ALLAY_ITEM_THROW, SoundSource.NEUTRAL, 1.0F, pitch);
}
}

View file

@ -13,27 +13,27 @@ import java.util.Optional;
import java.util.function.Function;
public class StayCloseToTarget<E extends LivingEntity> extends Behavior<E> {
private final Function<LivingEntity, Optional<PositionTracker>> targetPosition;
private final int closeEnough;
private final int tooFar;
private final float speedModifier;
private final Function<LivingEntity, Optional<PositionTracker>> lookTarget;
private final int completitionRange;
private final int searchRange;
private final float speed;
public StayCloseToTarget(Function<LivingEntity, Optional<PositionTracker>> targetPosition, int closeEnough, int tooFar, float speedModifier) {
public StayCloseToTarget(Function<LivingEntity, Optional<PositionTracker>> lookTarget, int completitionRange, int searchRange, float speed) {
super(ImmutableMap.of(MemoryModuleType.WALK_TARGET, MemoryStatus.VALUE_ABSENT));
this.targetPosition = targetPosition;
this.closeEnough = closeEnough;
this.tooFar = tooFar;
this.speedModifier = speedModifier;
this.lookTarget = lookTarget;
this.completitionRange = completitionRange;
this.searchRange = searchRange;
this.speed = speed;
}
@Override
protected boolean checkExtraStartConditions(ServerLevel level, E entity) {
Optional<PositionTracker> tracker = this.targetPosition.apply(entity);
return tracker.isPresent() && !entity.position().closerThan(tracker.get().currentPosition(), this.tooFar);
Optional<PositionTracker> tracker = this.lookTarget.apply(entity);
return tracker.isPresent() && !entity.position().closerThan(tracker.get().currentPosition(), this.searchRange);
}
@Override
protected void start(ServerLevel level, E entity, long time) {
MobUtils.setWalkAndLookTargetMemories(entity, this.targetPosition.apply(entity).get(), this.speedModifier, this.closeEnough);
MobUtils.walkTowards(entity, this.lookTarget.apply(entity).get(), this.speed, this.completitionRange);
}
}

View file

@ -31,20 +31,20 @@ public class MobUtils {
return Mth.lengthSquared(x, z) < Mth.square(xzRange) && Mth.square(y) < Mth.square(yRange);
}
public static void setWalkAndLookTargetMemories(LivingEntity entity, PositionTracker tracker, float speedModifier, int closeEnough) {
WalkTarget target = new WalkTarget(tracker, speedModifier, closeEnough);
entity.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, tracker);
entity.getBrain().setMemory(MemoryModuleType.WALK_TARGET, target);
public static void walkTowards(LivingEntity entity, PositionTracker target, float speed, int closeEnough) {
WalkTarget walkTarget = new WalkTarget(target, speed, closeEnough);
entity.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, target);
entity.getBrain().setMemory(MemoryModuleType.WALK_TARGET, walkTarget);
}
public static void throwItem(LivingEntity entity, ItemStack stack, Vec3 source, Vec3 target, float p_217138_) {
double y = entity.getEyeY() - (double)p_217138_;
ItemEntity itemEntity = new ItemEntity(entity.level, entity.getX(), y, entity.getZ(), stack);
itemEntity.setThrower(entity.getUUID());
Vec3 distance = source.subtract(entity.position());
distance = distance.normalize().multiply(target.x, target.y, target.z);
itemEntity.setDeltaMovement(distance);
itemEntity.setDefaultPickUpDelay();
entity.level.addFreshEntity(itemEntity);
public static void give(LivingEntity entity, ItemStack stack, Vec3 target, Vec3 velocity, float yOffset) {
double y = entity.getEyeY() - (double)yOffset;
ItemEntity item = new ItemEntity(entity.level, entity.getX(), y, entity.getZ(), stack);
item.setThrower(entity.getUUID());
Vec3 distance = target.subtract(entity.position());
distance = distance.normalize().multiply(velocity.x, velocity.y, velocity.z);
item.setDeltaMovement(distance);
item.setDefaultPickUpDelay();
entity.level.addFreshEntity(item);
}
}

View file

@ -28,7 +28,7 @@ public abstract class FlyNodeEvaluatorMixin extends WalkNodeEvaluator {
@Inject(method = "getStart", at = @At(value = "INVOKE", target = "Lcom/google/common/collect/ImmutableSet;of(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Lcom/google/common/collect/ImmutableSet;", shift = At.Shift.AFTER), cancellable = true)
private void wb$start(CallbackInfoReturnable<Node> cir) {
if (this.mob instanceof Allay allay) {
for (BlockPos pos : allay.iteratePathfindingStartNodeCandidatePositions()) {
for (BlockPos pos : allay.getPotentialEscapePositions()) {
BlockPathTypes types = this.getCachedBlockPathType(pos.getX(), pos.getY(), pos.getZ());
if (this.mob.getPathfindingMalus(types) >= 0.0F) {
Node node = this.getNode(pos);

View file

@ -0,0 +1,18 @@
package com.cursedcauldron.wildbackport.core.mixin.common;
import com.cursedcauldron.wildbackport.common.registry.WBGameEvents;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.NoteBlock;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(NoteBlock.class)
public class NoteBlockMixin {
@Inject(method = "playNote", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;blockEvent(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/Block;II)V", shift = At.Shift.AFTER))
private void wb$playNote(Level level, BlockPos pos, CallbackInfo ci) {
level.gameEvent(WBGameEvents.NOTE_BLOCK_PLAY.get(), pos);
}
}

View file

@ -24,6 +24,7 @@
"common.BlockEntityTypeMixin",
"common.FlyNodeEvaluatorMixin",
"common.LivingEntityMixin",
"common.NoteBlockMixin",
"common.PathfinderMobMixin",
"common.PlayerMixin",
"extension.BoatTypeMixin",