Skip to content

Commit

Permalink
Trough changes:
Browse files Browse the repository at this point in the history
- no longer ticks
- cooldown is per animals
- animals eat immediately when they reach one
- added give up cooldown so they dont get stuck
- improved fake player positioning
- fixed animals still targeting trough when it gets empties after they start targeting it
- animals will get much closer to the through, done by adjusting the fake player position while they walk
  • Loading branch information
MehVahdJukaar committed Dec 27, 2023
1 parent 0607296 commit 6c58141
Show file tree
Hide file tree
Showing 3 changed files with 287 additions and 217 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public class FeedingTroughBlock extends ZetaBlock implements EntityBlock {

private static final SoundType WOOD_WITH_PLANT_STEP = new ForgeSoundType(1.0F, 1.0F, () -> SoundEvents.WOOD_BREAK, () -> SoundEvents.GRASS_STEP, () -> SoundEvents.WOOD_PLACE, () -> SoundEvents.WOOD_HIT, () -> SoundEvents.WOOD_FALL);

public static BooleanProperty FULL = BooleanProperty.create("full");
public static final BooleanProperty FULL = BooleanProperty.create("full");

public static final VoxelShape CUBOID_SHAPE = box(0, 0, 0, 16, 8, 16);
public static final VoxelShape EMPTY_SHAPE = Shapes.join(CUBOID_SHAPE, box(2, 2, 2, 14, 8, 14), BooleanOp.ONLY_FIRST);
Expand Down Expand Up @@ -106,8 +106,8 @@ public void fallOn(Level level, @NotNull BlockState state, @NotNull BlockPos pos
public void onRemove(BlockState state, @NotNull Level world, @NotNull BlockPos pos, @NotNull BlockState newState, boolean isMoving) {
if(state.getBlock() != newState.getBlock()) {
BlockEntity tile = world.getBlockEntity(pos);
if(tile instanceof FeedingTroughBlockEntity) {
Containers.dropContents(world, pos, (FeedingTroughBlockEntity) tile);
if(tile instanceof FeedingTroughBlockEntity f) {
Containers.dropContents(world, pos, f);
world.updateNeighbourForOutputSignal(pos, this);
}

Expand Down Expand Up @@ -150,17 +150,12 @@ public boolean triggerEvent(@NotNull BlockState state, @NotNull Level world, @No
@Nullable
public MenuProvider getMenuProvider(@NotNull BlockState state, Level world, @NotNull BlockPos pos) {
BlockEntity tile = world.getBlockEntity(pos);
return tile instanceof MenuProvider ? (MenuProvider) tile : null;
return tile instanceof MenuProvider m ? m : null;
}

@Override
public BlockEntity newBlockEntity(@NotNull BlockPos pos, @NotNull BlockState state) {
return new FeedingTroughBlockEntity(pos, state);
}

@Override
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(@NotNull Level world, @NotNull BlockState state, @NotNull BlockEntityType<T> type) {
return createTickerHelper(type, FeedingTroughModule.blockEntityType, FeedingTroughBlockEntity::tick);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@
import net.minecraft.sounds.SoundEvent;
import net.minecraft.world.ContainerHelper;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.ai.goal.TemptGoal;
import net.minecraft.world.entity.animal.Animal;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.DispenserMenu;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
Expand All @@ -30,6 +30,7 @@

import org.jetbrains.annotations.NotNull;

import org.jetbrains.annotations.Nullable;
import org.violetmoon.quark.base.handler.MiscUtil;
import org.violetmoon.quark.content.automation.block.FeedingTroughBlock;
import org.violetmoon.quark.content.automation.module.FeedingTroughModule;
Expand All @@ -44,84 +45,70 @@
*/
public class FeedingTroughBlockEntity extends RandomizableContainerBlockEntity {

private static final GameProfile DUMMY_PROFILE = new GameProfile(UUID.randomUUID(), "[FeedingTrough]");

private NonNullList<ItemStack> stacks;

private int cooldown = 0;
private long internalRng = 0;

public FeedingTroughBlockEntity(BlockPos pos, BlockState state) {
super(FeedingTroughModule.blockEntityType, pos, state);
this.stacks = NonNullList.withSize(9, ItemStack.EMPTY);
}

public FakePlayer getFoodHolder(Animal mob, Ingredient temptations) {
FakePlayer foodHolder = null;
if(level instanceof ServerLevel serverLevel)
foodHolder = FakePlayerFactory.get(serverLevel, DUMMY_PROFILE);

if(foodHolder != null) {
for(int i = 0; i < getContainerSize(); i++) {
ItemStack stack = getItem(i);
if(temptations.test(stack) && mob.isFood(stack)) {
Inventory inventory = foodHolder.getInventory();
inventory.items.set(inventory.selected, stack);
Vec3 position = new Vec3(worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()).add(0.5, -1, 0.5);
Vec3 direction = mob.position().subtract(position).normalize();
Vec2 angles = MiscUtil.getMinecraftAngles(direction);

Vec3 shift = direction.scale(-0.5 / Math.max(
Math.abs(direction.x), Math.max(
Math.abs(direction.y),
Math.abs(direction.z))));

Vec3 truePos = position.add(shift);

foodHolder.moveTo(truePos.x, truePos.y, truePos.z, angles.x, angles.y);
return foodHolder;
public void updateFoodHolder(Animal mob, Ingredient temptations, FakePlayer foodHolder) {
for(int i = 0; i < getContainerSize(); i++) {
ItemStack stack = getItem(i);
if(temptations.test(stack) && mob.isFood(stack)) {
Inventory inventory = foodHolder.getInventory();
inventory.items.set(inventory.selected, stack);
Vec3 througPos = new Vec3(worldPosition.getX(), worldPosition.getY(), worldPosition.getZ())
.add(0.5, -1, 0.5);
Vec3 mobPosition = mob.position();
Vec3 direction = mobPosition.subtract(througPos);
Vec2 angles = MiscUtil.getMinecraftAngles(direction);

Vec3 newPos = Vec3.ZERO;
// Fake player will always be at most maxDist blocks away from animal.
// If animal is closer to target, then we will be on target itself.
float maxDist = 3;
if(direction.lengthSqr() > (maxDist*maxDist)){
newPos = mobPosition.add(direction.normalize().scale(-maxDist));
}else{
//place slightly behind trough
newPos = througPos.add(direction.normalize().scale(-1));
}

foodHolder.moveTo(newPos.x, newPos.y, newPos.z, angles.x, angles.y);
return;
}
}

return null;
}

public static void tick(Level level, BlockPos pos, BlockState state, FeedingTroughBlockEntity be) {
if(level != null && !level.isClientSide) {
if(be.cooldown > 0)
be.cooldown--;
else {
be.cooldown = FeedingTroughModule.cooldown; // minimize aabb calls
List<Animal> animals = level.getEntitiesOfClass(Animal.class, new AABB(be.worldPosition).inflate(1.5, 0, 1.5).contract(0, 0.75, 0));

for(Animal creature : animals) {
if(creature.canFallInLove() && creature.getAge() == 0) {
for(int i = 0; i < be.getContainerSize(); i++) {
ItemStack stack = be.getItem(i);
if(creature.isFood(stack)) {
SoundEvent soundEvent = creature.getEatingSound(stack);
if(soundEvent != null)
creature.playSound(soundEvent, 0.5F + 0.5F * level.random.nextInt(2), (level.random.nextFloat() - level.random.nextFloat()) * 0.2F + 1.0F);

be.addItemParticles(creature, stack, 16);

if(be.getSpecialRand().nextDouble() < FeedingTroughModule.loveChance) {
List<Animal> animalsAround = level.getEntitiesOfClass(Animal.class, new AABB(be.worldPosition).inflate(FeedingTroughModule.range));
if(animalsAround.size() <= FeedingTroughModule.maxAnimals)
creature.setInLove(null);
}

stack.shrink(1);
be.setChanged();

return;
}
}
}
public enum FeedResult{
FED,SECS,NONE
}
public FeedResult tryFeedingAnimal(Animal animal) {
for(int i = 0; i < this.getContainerSize(); i++) {
ItemStack stack = this.getItem(i);
if(animal.isFood(stack)) {
SoundEvent soundEvent = animal.getEatingSound(stack);
animal.playSound(soundEvent, 0.5F + 0.5F * level.random.nextInt(2), (level.random.nextFloat() - level.random.nextFloat()) * 0.2F + 1.0F);

this.addItemParticles(animal, stack, 16);

stack.shrink(1);
this.setChanged();

if(this.getSpecialRand().nextDouble() < FeedingTroughModule.loveChance) {
List<Animal> animalsAround = level.getEntitiesOfClass(Animal.class, new AABB(this.worldPosition).inflate(FeedingTroughModule.range));
if(animalsAround.size() <= FeedingTroughModule.maxAnimals)
animal.setInLove(null);
return FeedResult.SECS;
}

return FeedResult.FED;
}
}
return FeedResult.NONE;
}

@Override
Expand All @@ -148,8 +135,8 @@ private void addItemParticles(Entity entity, ItemStack stack, int count) {
position = position.xRot(-entity.getXRot() * ((float) Math.PI / 180F));
position = position.yRot(-entity.getYRot() * ((float) Math.PI / 180F));
position = position.add(entityPos.x, entityPos.y + entity.getEyeHeight(), entityPos.z);
if(this.level instanceof ServerLevel)
((ServerLevel) this.level).sendParticles(new ItemParticleOption(ParticleTypes.ITEM, stack), position.x, position.y, position.z, 1, direction.x, direction.y + 0.05D, direction.z, 0.0D);
if(this.level instanceof ServerLevel serverLevel)
serverLevel.sendParticles(new ItemParticleOption(ParticleTypes.ITEM, stack), position.x, position.y, position.z, 1, direction.x, direction.y + 0.05D, direction.z, 0.0D);
else if(this.level != null)
this.level.addParticle(new ItemParticleOption(ParticleTypes.ITEM, stack), position.x, position.y, position.z, direction.x, direction.y + 0.05D, direction.z);
}
Expand Down Expand Up @@ -187,7 +174,6 @@ protected Component getDefaultName() {
public void load(@NotNull CompoundTag nbt) {
super.load(nbt);

this.cooldown = nbt.getInt("Cooldown");
this.internalRng = nbt.getLong("rng");
this.stacks = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY);
if(!this.tryLoadLootTable(nbt))
Expand All @@ -199,7 +185,6 @@ public void load(@NotNull CompoundTag nbt) {
protected void saveAdditional(@NotNull CompoundTag nbt) {
super.saveAdditional(nbt);

nbt.putInt("Cooldown", cooldown);
nbt.putLong("rng", internalRng);
if(!this.trySaveLootTable(nbt))
ContainerHelper.saveAllItems(nbt, this.stacks);
Expand Down
Loading

0 comments on commit 6c58141

Please sign in to comment.