Unicopia/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyGrowAbility.java

205 lines
7.3 KiB
Java
Raw Normal View History

package com.minelittlepony.unicopia.ability;
2020-01-16 12:35:46 +01:00
2023-08-16 00:18:41 +02:00
import java.util.Optional;
2024-01-04 22:41:27 +01:00
import java.util.function.DoubleSupplier;
import java.util.function.Supplier;
import com.minelittlepony.unicopia.Race;
2024-01-18 20:52:59 +01:00
import com.minelittlepony.unicopia.USounds;
2024-01-04 22:41:27 +01:00
import com.minelittlepony.unicopia.UTags;
import com.minelittlepony.unicopia.ability.data.Hit;
import com.minelittlepony.unicopia.ability.data.Pos;
import com.minelittlepony.unicopia.block.UBlocks;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.item.TransformCropsRecipe;
import com.minelittlepony.unicopia.item.URecipes;
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
2024-01-04 22:41:27 +01:00
import com.minelittlepony.unicopia.particle.ParticleUtils;
2024-01-18 20:52:59 +01:00
import com.minelittlepony.unicopia.server.world.BlockDestructionManager;
2022-10-01 18:20:53 +02:00
import com.minelittlepony.unicopia.util.TraceHelper;
2024-01-04 22:41:27 +01:00
import com.minelittlepony.unicopia.util.VecHelper;
2024-01-18 20:52:59 +01:00
import net.minecraft.block.Block;
2020-01-16 12:35:46 +01:00
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
2024-01-04 22:41:27 +01:00
import net.minecraft.block.CarrotsBlock;
2024-01-03 21:51:24 +01:00
import net.minecraft.block.FarmlandBlock;
2020-01-16 12:35:46 +01:00
import net.minecraft.item.BoneMealItem;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
2024-01-04 22:41:27 +01:00
import net.minecraft.particle.ParticleTypes;
2020-01-16 12:35:46 +01:00
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
2024-01-04 22:41:27 +01:00
import net.minecraft.util.math.Vec3d;
2020-01-16 12:35:46 +01:00
import net.minecraft.world.World;
2024-01-18 20:52:59 +01:00
import net.minecraft.world.WorldEvents;
2020-01-16 12:35:46 +01:00
/**
* Earth Pony ability to grow crops
*/
public class EarthPonyGrowAbility implements Ability<Pos> {
2020-01-16 12:35:46 +01:00
@Override
2020-04-15 18:12:00 +02:00
public int getWarmupTime(Pony player) {
2020-01-16 12:35:46 +01:00
return 10;
}
@Override
2020-04-15 18:12:00 +02:00
public int getCooldownTime(Pony player) {
2020-01-16 12:35:46 +01:00
return 50;
}
@Override
public boolean canUse(Race race) {
return race.canUseEarth();
2020-01-16 12:35:46 +01:00
}
@Override
2023-08-16 00:18:41 +02:00
public Optional<Pos> prepare(Pony player) {
return TraceHelper.findBlock(player.asEntity(), 3, 1).map(Pos::new);
2020-01-16 12:35:46 +01:00
}
@Override
public Hit.Serializer<Pos> getSerializer() {
return Pos.SERIALIZER;
2020-01-16 12:35:46 +01:00
}
@Override
public double getCostEstimate(Pony player) {
return 10;
}
2020-01-16 12:35:46 +01:00
@Override
2023-08-16 00:18:41 +02:00
public boolean apply(Pony player, Pos data) {
2020-01-16 12:35:46 +01:00
int count = 0;
2024-01-18 20:52:59 +01:00
if (!applyDirectly(player, data.pos())) {
for (BlockPos pos : BlockPos.iterate(
data.pos().add(-2, -2, -2),
data.pos().add( 2, 2, 2))) {
count += applySingle(player, player.asWorld(), player.asWorld().getBlockState(pos), pos);
}
} else {
count = 1;
2020-01-16 12:35:46 +01:00
}
if (count > 0) {
player.subtractEnergyCost(count / 5D);
2020-01-16 12:35:46 +01:00
}
2023-08-16 00:18:41 +02:00
return true;
2020-01-16 12:35:46 +01:00
}
2024-01-04 22:41:27 +01:00
protected int applySingle(Pony player, World w, BlockState state, BlockPos pos) {
2020-01-16 12:35:46 +01:00
ItemStack stack = new ItemStack(Items.BONE_MEAL);
if (state.getBlock() instanceof Growable growable) {
return growable.grow(w, state, pos) ? 1 : 0;
}
2024-01-04 22:41:27 +01:00
if (state.isOf(Blocks.CARROTS)) {
if (state.get(CarrotsBlock.AGE) == CarrotsBlock.MAX_AGE) {
boolean transform = w.random.nextInt(3) == 0;
2024-01-18 20:52:59 +01:00
spawnConversionParticles(w, pos, transform);
2024-01-04 22:41:27 +01:00
if (transform) {
w.setBlockState(pos, UBlocks.GOLD_ROOT.getDefaultState().with(CarrotsBlock.AGE, CarrotsBlock.MAX_AGE));
}
return 5;
}
}
if (w.getBlockState(pos).isIn(UTags.UNAFFECTED_BY_GROW_ABILITY)) {
return 0;
}
if (BoneMealItem.useOnFertilizable(stack, w, pos)) {
if (w.random.nextInt(350) == 0) {
if (w.getBlockState(pos.down()).isOf(Blocks.FARMLAND)) {
2024-01-04 22:41:27 +01:00
FarmlandBlock.setToDirt(null, state, w, pos.down());
}
w.setBlockState(pos, UBlocks.PLUNDER_VINE_BUD.getDefaultState());
} else if (w.random.nextInt(5000) == 0) {
2024-01-02 23:03:41 +01:00
if (w.getBlockState(pos.down()).isOf(Blocks.FARMLAND)) {
2024-01-03 21:51:24 +01:00
FarmlandBlock.setToDirt(null, state, w, pos.down());
2024-01-02 23:03:41 +01:00
}
UBlocks.CURING_JOKE.grow(w, state, pos);
}
return 1;
}
if (BoneMealItem.useOnGround(stack, w, pos, Direction.UP)) {
2020-01-16 12:35:46 +01:00
return 1;
}
return 0;
}
2024-01-18 20:52:59 +01:00
private boolean applyDirectly(Pony player, BlockPos pos) {
return player.asWorld().getRecipeManager()
.getAllMatches(URecipes.GROWING, new TransformCropsRecipe.PlacementArea(player, pos), player.asWorld())
.stream()
.map(recipe -> recipe.checkPattern(player.asWorld(), pos))
.filter(result -> result.matchedLocations().size() + 1 >= TransformCropsRecipe.MINIMUM_INPUT)
.filter(result -> {
boolean transform = result.shoudTransform(player.asWorld().random);
player.playSound(USounds.ENTITY_CRYSTAL_SHARDS_AMBIENT, 1);
result.matchedLocations().forEach(cell -> {
spawnConversionParticles(player.asWorld(), cell.up(), false);
BlockDestructionManager manager = BlockDestructionManager.of(player.asWorld());
2024-01-18 20:52:59 +01:00
if (transform) {
if (manager.damageBlock(cell, 8) >= BlockDestructionManager.MAX_DAMAGE || player.asWorld().random.nextInt(20) == 0) {
player.asWorld().setBlockState(cell, Blocks.DIRT.getDefaultState());
player.asWorld().syncWorldEvent(WorldEvents.BLOCK_BROKEN, cell, Block.getRawIdFromState(player.asWorld().getBlockState(cell)));
}
} else {
if (manager.damageBlock(cell, 4) >= BlockDestructionManager.MAX_DAMAGE || player.asWorld().random.nextInt(20) == 0) {
player.asWorld().setBlockState(cell, Blocks.DIRT.getDefaultState());
player.asWorld().syncWorldEvent(WorldEvents.BLOCK_BROKEN, cell, Block.getRawIdFromState(player.asWorld().getBlockState(cell)));
}
2024-01-18 20:52:59 +01:00
}
});
spawnConversionParticles(player.asWorld(), pos, transform);
if (transform) {
player.asWorld().setBlockState(pos, result.recipe().getResult(player.asWorld(), pos));
}
2024-01-18 20:52:59 +01:00
return true;
})
.findFirst()
.isPresent();
2024-01-18 20:52:59 +01:00
}
private static void spawnConversionParticles(World w, BlockPos pos, boolean success) {
DoubleSupplier vecComponentFactory = () -> w.random.nextTriangular(0, 0.5);
Supplier<Vec3d> posSupplier = () -> pos.toCenterPos().add(VecHelper.supply(vecComponentFactory));
for (int i = 0; i < 25; i++) {
ParticleUtils.spawnParticle(w, new MagicParticleEffect(0xFFFF00), posSupplier.get(), Vec3d.ZERO);
if (success) {
ParticleUtils.spawnParticle(w, ParticleTypes.CLOUD, posSupplier.get(), Vec3d.ZERO);
}
}
}
2020-01-16 12:35:46 +01:00
@Override
2023-08-16 00:18:41 +02:00
public void warmUp(Pony player, AbilitySlot slot) {
player.getMagicalReserves().getExertion().addPercent(30);
2020-01-16 12:35:46 +01:00
if (player.asWorld().isClient()) {
2020-04-22 16:28:20 +02:00
player.spawnParticles(MagicParticleEffect.UNICORN, 1);
2020-01-16 12:35:46 +01:00
}
}
@Override
2023-08-16 00:18:41 +02:00
public void coolDown(Pony player, AbilitySlot slot) {
2020-01-16 12:35:46 +01:00
}
public interface Growable {
boolean grow(World world, BlockState state, BlockPos pos);
}
2020-01-16 12:35:46 +01:00
}