NaturesAura/src/main/java/de/ellpeck/naturesaura/blocks/tiles/BlockEntityAnimalSpawner.java
2024-03-10 15:54:58 +01:00

179 lines
7.8 KiB
Java

package de.ellpeck.naturesaura.blocks.tiles;
import de.ellpeck.naturesaura.Helper;
import de.ellpeck.naturesaura.api.NaturesAuraAPI;
import de.ellpeck.naturesaura.api.aura.chunk.IAuraChunk;
import de.ellpeck.naturesaura.api.aura.type.IAuraType;
import de.ellpeck.naturesaura.blocks.multi.Multiblocks;
import de.ellpeck.naturesaura.packet.PacketHandler;
import de.ellpeck.naturesaura.packet.PacketParticles;
import de.ellpeck.naturesaura.recipes.AnimalSpawnerRecipe;
import de.ellpeck.naturesaura.recipes.ModRecipes;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.RecipeHolder;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class BlockEntityAnimalSpawner extends BlockEntityImpl implements ITickableBlockEntity {
private RecipeHolder<AnimalSpawnerRecipe> currentRecipe;
private double spawnX;
private double spawnZ;
private int time;
private Entity entityClient;
public BlockEntityAnimalSpawner(BlockPos pos, BlockState state) {
super(ModBlockEntities.ANIMAL_SPAWNER, pos, state);
}
@Override
public void tick() {
if (!this.level.isClientSide) {
if (this.level.getGameTime() % 10 != 0)
return;
if (!Multiblocks.ANIMAL_SPAWNER.isComplete(this.level, this.worldPosition)) {
if (this.currentRecipe != null) {
this.currentRecipe = null;
this.time = 0;
this.sendToClients();
}
return;
}
if (this.currentRecipe != null) {
var drain = Mth.ceil(this.currentRecipe.value().aura / (float) this.currentRecipe.value().time * 10F);
if (!this.canUseRightNow(drain))
return;
var spot = IAuraChunk.getHighestSpot(this.level, this.worldPosition, 35, this.worldPosition);
IAuraChunk.getAuraChunk(this.level, spot).drainAura(spot, drain);
this.time += 10;
if (this.time >= this.currentRecipe.value().time) {
var entity = this.currentRecipe.value().makeEntity(this.level, BlockPos.containing(this.spawnX, this.worldPosition.getY() + 1, this.spawnZ));
this.level.addFreshEntity(entity);
this.currentRecipe = null;
this.time = 0;
this.sendToClients();
}
} else {
var items = this.level.getEntitiesOfClass(ItemEntity.class,
new AABB(this.worldPosition).inflate(2));
for (var recipe : this.level.getRecipeManager().getRecipesFor(ModRecipes.ANIMAL_SPAWNER_TYPE, null, this.level)) {
if (recipe.value().ingredients.size() != items.size())
continue;
List<Ingredient> required = new ArrayList<>(recipe.value().ingredients);
for (var item : items) {
if (!item.isAlive() || item.hasPickUpDelay())
break;
var stack = item.getItem();
if (stack.isEmpty())
break;
for (var ingredient : required) {
if (ingredient.test(stack) && Helper.getIngredientAmount(ingredient) == stack.getCount()) {
required.remove(ingredient);
break;
}
}
}
if (!required.isEmpty())
continue;
for (var item : items) {
item.remove(Entity.RemovalReason.KILLED);
PacketHandler.sendToAllAround(this.level, this.worldPosition, 32,
new PacketParticles((float) item.getX(), (float) item.getY(), (float) item.getZ(), PacketParticles.Type.ANIMAL_SPAWNER));
}
this.currentRecipe = recipe;
this.spawnX = this.worldPosition.getX() + 0.5 + this.level.random.nextFloat() * 4 - 2;
this.spawnZ = this.worldPosition.getZ() + 0.5 + this.level.random.nextFloat() * 4 - 2;
this.sendToClients();
break;
}
}
} else {
if (this.level.getGameTime() % 5 != 0)
return;
if (this.currentRecipe == null) {
this.entityClient = null;
return;
}
NaturesAuraAPI.instance().spawnParticleStream(
this.worldPosition.getX() + (float) this.level.random.nextGaussian() * 5F,
this.worldPosition.getY() + 1 + this.level.random.nextFloat() * 5F,
this.worldPosition.getZ() + (float) this.level.random.nextGaussian() * 5F,
this.worldPosition.getX() + this.level.random.nextFloat(),
this.worldPosition.getY() + this.level.random.nextFloat(),
this.worldPosition.getZ() + this.level.random.nextFloat(),
this.level.random.nextFloat() * 0.07F + 0.07F,
IAuraType.forLevel(this.level).getColor(),
this.level.random.nextFloat() + 0.5F);
if (this.entityClient == null) {
this.entityClient = this.currentRecipe.value().makeEntity(this.level, BlockPos.ZERO);
this.entityClient.setPos(this.spawnX, this.worldPosition.getY() + 1, this.spawnZ);
}
var bounds = this.entityClient.getBoundingBox();
for (var i = this.level.random.nextInt(5) + 5; i >= 0; i--)
NaturesAuraAPI.instance().spawnMagicParticle(
bounds.minX + this.level.random.nextFloat() * (bounds.maxX - bounds.minX),
bounds.minY + this.level.random.nextFloat() * (bounds.maxY - bounds.minY),
bounds.minZ + this.level.random.nextFloat() * (bounds.maxZ - bounds.minZ),
0F, 0F, 0F, 0x2fd8d3, 2F, 60, 0F, false, true);
}
}
@Override
public void writeNBT(CompoundTag compound, SaveType type) {
super.writeNBT(compound, type);
if (type != SaveType.BLOCK) {
if (this.currentRecipe != null) {
compound.putString("recipe", this.currentRecipe.id().toString());
compound.putDouble("spawn_x", this.spawnX);
compound.putDouble("spawn_z", this.spawnZ);
compound.putInt("time", this.time);
}
}
}
@SuppressWarnings("unchecked")
@Override
public void readNBT(CompoundTag compound, SaveType type) {
super.readNBT(compound, type);
if (type != SaveType.BLOCK) {
if (compound.contains("recipe")) {
if (this.hasLevel()) {
var name = new ResourceLocation(compound.getString("recipe"));
this.currentRecipe = (RecipeHolder<AnimalSpawnerRecipe>) this.level.getRecipeManager().byKey(name).orElse(null);
}
this.spawnX = compound.getDouble("spawn_x");
this.spawnZ = compound.getDouble("spawn_z");
this.time = compound.getInt("time");
} else {
this.currentRecipe = null;
this.time = 0;
}
}
}
@Override
public boolean allowsLowerLimiter() {
return true;
}
}