2020-04-15 14:22:03 +02:00
|
|
|
package com.minelittlepony.unicopia.ability;
|
2018-09-12 01:29:49 +02:00
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.List;
|
2020-01-16 12:35:46 +01:00
|
|
|
import org.lwjgl.glfw.GLFW;
|
2018-09-12 01:29:49 +02:00
|
|
|
|
2019-02-07 14:47:33 +01:00
|
|
|
import com.google.common.collect.Lists;
|
2018-09-12 22:37:06 +02:00
|
|
|
import com.google.gson.annotations.Expose;
|
2020-04-15 14:22:03 +02:00
|
|
|
import com.minelittlepony.unicopia.Race;
|
|
|
|
import com.minelittlepony.unicopia.SpeciesList;
|
|
|
|
import com.minelittlepony.unicopia.entity.player.IPlayer;
|
|
|
|
import com.minelittlepony.unicopia.item.AppleItem;
|
|
|
|
import com.minelittlepony.unicopia.util.AwaitTickQueue;
|
|
|
|
import com.minelittlepony.unicopia.util.MagicalDamageSource;
|
|
|
|
import com.minelittlepony.unicopia.util.PosHelper;
|
|
|
|
import com.minelittlepony.unicopia.util.VecHelper;
|
|
|
|
import com.minelittlepony.unicopia.util.WorldEvent;
|
|
|
|
import com.minelittlepony.unicopia.util.shape.IShape;
|
|
|
|
import com.minelittlepony.unicopia.util.shape.Sphere;
|
2018-09-12 01:29:49 +02:00
|
|
|
|
|
|
|
import net.minecraft.block.Block;
|
2020-01-16 12:35:46 +01:00
|
|
|
import net.minecraft.block.BlockState;
|
|
|
|
import net.minecraft.block.Blocks;
|
|
|
|
import net.minecraft.block.LeavesBlock;
|
|
|
|
import net.minecraft.block.LogBlock;
|
|
|
|
import net.minecraft.entity.EntityContext;
|
|
|
|
import net.minecraft.entity.EntityType;
|
|
|
|
import net.minecraft.entity.ItemEntity;
|
|
|
|
import net.minecraft.entity.attribute.EntityAttributes;
|
|
|
|
import net.minecraft.entity.damage.DamageSource;
|
|
|
|
import net.minecraft.entity.player.PlayerEntity;
|
2018-09-12 01:29:49 +02:00
|
|
|
import net.minecraft.item.ItemStack;
|
2020-01-16 12:35:46 +01:00
|
|
|
import net.minecraft.particle.BlockStateParticleEffect;
|
|
|
|
import net.minecraft.particle.ParticleTypes;
|
|
|
|
import net.minecraft.util.hit.BlockHitResult;
|
|
|
|
import net.minecraft.util.hit.HitResult;
|
2018-09-12 01:29:49 +02:00
|
|
|
import net.minecraft.util.math.BlockPos;
|
2020-01-16 12:35:46 +01:00
|
|
|
import net.minecraft.util.math.Box;
|
|
|
|
import net.minecraft.util.math.Direction;
|
2018-09-12 01:29:49 +02:00
|
|
|
import net.minecraft.util.math.Vec3d;
|
|
|
|
import net.minecraft.world.World;
|
|
|
|
|
2020-01-27 17:37:22 +01:00
|
|
|
/**
|
|
|
|
* Earth Pony stomping ability
|
|
|
|
*/
|
2020-04-15 17:22:29 +02:00
|
|
|
public class EarthPonyStompAbility implements Ability<EarthPonyStompAbility.Data> {
|
2018-09-12 01:29:49 +02:00
|
|
|
|
2019-02-03 10:45:45 +01:00
|
|
|
private final double rad = 4;
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
private final Box areaOfEffect = new Box(
|
2019-02-03 10:45:45 +01:00
|
|
|
-rad, -rad, -rad,
|
|
|
|
rad, rad, rad
|
|
|
|
);
|
|
|
|
|
2018-09-12 01:29:49 +02:00
|
|
|
@Override
|
|
|
|
public String getKeyName() {
|
|
|
|
return "unicopia.power.earth";
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int getKeyCode() {
|
2020-01-16 12:35:46 +01:00
|
|
|
return GLFW.GLFW_KEY_M;
|
2018-09-12 01:29:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int getWarmupTime(IPlayer player) {
|
2019-02-07 10:46:59 +01:00
|
|
|
return 3;
|
2018-09-12 01:29:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int getCooldownTime(IPlayer player) {
|
2019-02-07 10:46:59 +01:00
|
|
|
return 50;
|
2018-09-12 01:29:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean canUse(Race playerSpecies) {
|
|
|
|
return playerSpecies.canUseEarth();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2020-04-15 17:22:29 +02:00
|
|
|
public EarthPonyStompAbility.Data tryActivate(IPlayer player) {
|
2020-01-16 12:35:46 +01:00
|
|
|
HitResult mop = VecHelper.getObjectMouseOver(player.getOwner(), 6, 1);
|
|
|
|
|
|
|
|
if (mop instanceof BlockHitResult && mop.getType() == HitResult.Type.BLOCK) {
|
|
|
|
BlockPos pos = ((BlockHitResult)mop).getBlockPos();
|
|
|
|
BlockState state = player.getWorld().getBlockState(pos);
|
2019-02-07 10:46:59 +01:00
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
if (state.getBlock() instanceof LogBlock) {
|
2019-02-03 10:45:45 +01:00
|
|
|
pos = getBaseOfTree(player.getWorld(), state, pos);
|
|
|
|
if (measureTree(player.getWorld(), state, pos) > 0) {
|
2018-09-12 01:29:49 +02:00
|
|
|
return new Data(pos.getX(), pos.getY(), pos.getZ(), 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
if (!player.getOwner().onGround && !player.getOwner().abilities.flying) {
|
2019-02-03 10:45:45 +01:00
|
|
|
player.getOwner().addVelocity(0, -6, 0);
|
2018-09-12 01:29:49 +02:00
|
|
|
return new Data(0, 0, 0, 0);
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2020-04-15 17:22:29 +02:00
|
|
|
public Class<EarthPonyStompAbility.Data> getPackageType() {
|
|
|
|
return EarthPonyStompAbility.Data.class;
|
2018-09-12 01:29:49 +02:00
|
|
|
}
|
|
|
|
|
2018-09-13 14:04:24 +02:00
|
|
|
public static BlockPos getSolidBlockBelow(BlockPos pos, World w) {
|
2020-01-16 12:35:46 +01:00
|
|
|
while (World.isValid(pos)) {
|
2018-09-13 14:04:24 +02:00
|
|
|
pos = pos.down();
|
2020-01-16 12:35:46 +01:00
|
|
|
|
|
|
|
if (Block.isFaceFullSquare(w.getBlockState(pos).getCollisionShape(w, pos, EntityContext.absent()), Direction.UP)) {
|
2018-09-13 14:04:24 +02:00
|
|
|
return pos;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return pos;
|
|
|
|
}
|
|
|
|
|
2018-09-12 01:29:49 +02:00
|
|
|
@Override
|
2019-02-03 10:45:45 +01:00
|
|
|
public void apply(IPlayer iplayer, Data data) {
|
2018-09-12 22:37:06 +02:00
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
PlayerEntity player = iplayer.getOwner();
|
2018-09-12 22:37:06 +02:00
|
|
|
|
2018-09-12 01:29:49 +02:00
|
|
|
if (data.hitType == 0) {
|
2020-01-16 12:35:46 +01:00
|
|
|
BlockPos ppos = player.getBlockPos();
|
2018-09-13 14:04:24 +02:00
|
|
|
BlockPos pos = getSolidBlockBelow(ppos, player.getEntityWorld());
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
player.addVelocity(0, -(ppos.getSquaredDistance(pos)), 0);
|
2018-09-13 14:04:24 +02:00
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
iplayer.getWorld().getEntities(player, areaOfEffect.offset(iplayer.getOriginVector())).forEach(i -> {
|
|
|
|
double dist = Math.sqrt(pos.getSquaredDistance(i.getBlockPos()));
|
2018-09-13 14:04:24 +02:00
|
|
|
|
2018-09-12 01:29:49 +02:00
|
|
|
if (dist <= rad + 3) {
|
2018-09-13 14:04:24 +02:00
|
|
|
double force = dist / 5;
|
|
|
|
i.addVelocity(
|
2020-01-16 12:35:46 +01:00
|
|
|
-(player.x - i.x) / force,
|
|
|
|
-(player.y - i.y - 2) / force + (dist < 1 ? dist : 0),
|
|
|
|
-(player.z - i.z) / force);
|
2018-09-13 14:04:24 +02:00
|
|
|
|
2018-09-12 01:29:49 +02:00
|
|
|
DamageSource damage = MagicalDamageSource.causePlayerDamage("smash", player);
|
2018-09-13 14:04:24 +02:00
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
double amount = (4 * player.getAttributeInstance(EntityAttributes.ATTACK_DAMAGE).getValue()) / (float)dist;
|
2018-09-13 14:04:24 +02:00
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
if (i instanceof PlayerEntity) {
|
|
|
|
Race race = SpeciesList.instance().getPlayer((PlayerEntity)i).getSpecies();
|
2018-09-13 14:04:24 +02:00
|
|
|
if (race.canUseEarth()) {
|
|
|
|
amount /= 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (race.canFly()) {
|
|
|
|
amount *= 4;
|
|
|
|
}
|
2018-09-12 01:29:49 +02:00
|
|
|
}
|
2018-09-13 14:04:24 +02:00
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
i.damage(damage, (float)amount);
|
2018-09-12 01:29:49 +02:00
|
|
|
}
|
2019-02-03 10:45:45 +01:00
|
|
|
});
|
2018-09-12 22:37:06 +02:00
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
BlockPos.iterate(pos.add(-rad, -rad, -rad), pos.add(rad, rad, rad)).forEach(i -> {
|
|
|
|
if (i.getSquaredDistance(player.x, player.y, player.z, true) <= rad*rad) {
|
2018-09-12 01:29:49 +02:00
|
|
|
spawnEffect(player.world, i);
|
|
|
|
}
|
2019-02-03 10:45:45 +01:00
|
|
|
});
|
2018-09-12 22:37:06 +02:00
|
|
|
|
2018-09-12 01:29:49 +02:00
|
|
|
for (int i = 1; i < 202; i+= 2) {
|
|
|
|
spawnParticleRing(player, i);
|
|
|
|
}
|
2018-09-12 22:37:06 +02:00
|
|
|
|
2019-03-12 21:12:46 +01:00
|
|
|
iplayer.subtractEnergyCost(rad);
|
2018-09-12 01:29:49 +02:00
|
|
|
} else if (data.hitType == 1) {
|
2018-09-12 22:37:06 +02:00
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
boolean harmed = player.getHealth() < player.getHealthMaximum();
|
2019-02-09 19:50:01 +01:00
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
if (harmed && player.world.random.nextInt(30) == 0) {
|
2019-03-12 21:12:46 +01:00
|
|
|
iplayer.subtractEnergyCost(3);
|
2019-02-09 20:08:32 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
if (harmed || player.world.random.nextInt(5) == 0) {
|
2019-02-09 20:08:32 +01:00
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
if (!harmed || player.world.random.nextInt(30) == 0) {
|
2020-04-15 12:37:14 +02:00
|
|
|
AwaitTickQueue.enqueueTask(w -> removeTree(w, data.pos()));
|
2019-02-09 19:50:01 +01:00
|
|
|
}
|
2018-09-12 22:37:06 +02:00
|
|
|
|
2019-03-12 21:12:46 +01:00
|
|
|
iplayer.subtractEnergyCost(3);
|
2019-02-09 20:08:32 +01:00
|
|
|
} else {
|
|
|
|
int cost = dropApples(player.world, data.pos());
|
|
|
|
|
|
|
|
if (cost > 0) {
|
2019-03-12 21:12:46 +01:00
|
|
|
iplayer.subtractEnergyCost(cost * 3);
|
2019-02-09 20:08:32 +01:00
|
|
|
}
|
2019-02-09 19:50:01 +01:00
|
|
|
}
|
2018-09-12 01:29:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void spawnEffect(World w, BlockPos pos) {
|
2020-01-16 12:35:46 +01:00
|
|
|
BlockState state = w.getBlockState(pos);
|
2018-09-12 01:29:49 +02:00
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
if (!state.isAir() && w.getBlockState(pos.up()).isAir()) {
|
|
|
|
WorldEvent.DESTROY_BLOCK.play(w, pos, state);
|
2018-09-12 01:29:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2018-09-13 14:04:24 +02:00
|
|
|
public void preApply(IPlayer player) {
|
|
|
|
player.addExertion(40);
|
2020-01-16 12:35:46 +01:00
|
|
|
player.getOwner().attemptSprintingParticles();
|
2018-09-12 01:29:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2018-09-13 14:04:24 +02:00
|
|
|
public void postApply(IPlayer player) {
|
|
|
|
int timeDiff = getCooldownTime(player) - player.getAbilities().getRemainingCooldown();
|
2018-09-12 01:29:49 +02:00
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
if (player.getOwner().getEntityWorld().getTime() % 1 == 0 || timeDiff == 0) {
|
2018-09-13 14:04:24 +02:00
|
|
|
spawnParticleRing(player.getOwner(), timeDiff, 1);
|
2018-09-12 01:29:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
private void spawnParticleRing(PlayerEntity player, int timeDiff) {
|
2018-09-12 01:29:49 +02:00
|
|
|
spawnParticleRing(player, timeDiff, 0);
|
|
|
|
}
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
private void spawnParticleRing(PlayerEntity player, int timeDiff, double yVel) {
|
|
|
|
int animationTicks = timeDiff / 10;
|
2018-09-12 01:29:49 +02:00
|
|
|
if (animationTicks < 6) {
|
|
|
|
IShape shape = new Sphere(true, animationTicks, 1, 0, 1);
|
|
|
|
|
|
|
|
double y = 0.5 + (Math.sin(animationTicks) * 1.5);
|
|
|
|
|
|
|
|
yVel *= y * 5;
|
|
|
|
|
|
|
|
for (int i = 0; i < shape.getVolumeOfSpawnableSpace(); i++) {
|
2020-01-16 12:35:46 +01:00
|
|
|
Vec3d point = shape.computePoint(player.getEntityWorld().random);
|
|
|
|
player.world.addParticle(new BlockStateParticleEffect(ParticleTypes.BLOCK, Blocks.DIRT.getDefaultState()),
|
|
|
|
player.x + point.x,
|
|
|
|
player.y + y + point.y,
|
|
|
|
player.z + point.z,
|
|
|
|
0, yVel, 0
|
|
|
|
);
|
2018-09-12 01:29:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void removeTree(World w, BlockPos pos) {
|
2020-01-16 12:35:46 +01:00
|
|
|
BlockState log = w.getBlockState(pos);
|
|
|
|
|
2018-09-12 01:29:49 +02:00
|
|
|
int size = measureTree(w, log, pos);
|
2019-02-09 19:50:01 +01:00
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
if (size > 0) {
|
|
|
|
removeTreePart( w, log, ascendTrunk(new ArrayList<BlockPos>(), w, pos, log, 0), 0);
|
2018-09-12 01:29:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
private BlockPos ascendTrunk(List<BlockPos> done, World w, BlockPos pos, BlockState log, int level) {
|
2018-09-12 01:29:49 +02:00
|
|
|
if (level < 3 && !done.contains(pos)) {
|
|
|
|
done.add(pos);
|
|
|
|
|
|
|
|
BlockPos result = ascendTree(w, log, pos, true);
|
|
|
|
|
|
|
|
if (variantAndBlockEquals(w.getBlockState(pos.east()), log)) {
|
|
|
|
result = ascendTrunk(done, w, pos.east(), log, level + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (variantAndBlockEquals(w.getBlockState(pos.west()), log)) {
|
|
|
|
result = ascendTrunk(done, w, pos.west(), log, level + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (variantAndBlockEquals(w.getBlockState(pos.north()), log)) {
|
|
|
|
result = ascendTrunk(done, w, pos.north(), log, level + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (variantAndBlockEquals(w.getBlockState(pos.south()), log)) {
|
|
|
|
result = ascendTrunk(done, w, pos.south(), log, level + 1);
|
|
|
|
}
|
2019-02-09 20:08:32 +01:00
|
|
|
|
2018-09-12 01:29:49 +02:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
return pos;
|
|
|
|
}
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
private void removeTreePart(World w, BlockState log, BlockPos pos, int level) {
|
2018-09-12 01:29:49 +02:00
|
|
|
if (level < 10 && isWoodOrLeaf(w, log, pos)) {
|
|
|
|
if (level < 5) {
|
2020-01-16 12:35:46 +01:00
|
|
|
w.breakBlock(pos, true);
|
2018-09-12 01:29:49 +02:00
|
|
|
} else {
|
2020-01-16 12:35:46 +01:00
|
|
|
Block.dropStacks(w.getBlockState(pos), w, pos);
|
2018-09-12 01:29:49 +02:00
|
|
|
w.setBlockState(pos, Blocks.AIR.getDefaultState(), 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
PosHelper.all(pos, p -> {
|
|
|
|
removeTreePart(w, log, p, level + 1);
|
2020-01-16 12:35:46 +01:00
|
|
|
}, Direction.UP, Direction.NORTH, Direction.SOUTH, Direction.EAST, Direction.WEST);
|
2018-09-12 01:29:49 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
private BlockPos ascendTree(World w, BlockState log, BlockPos pos, boolean remove) {
|
2018-09-12 01:29:49 +02:00
|
|
|
int breaks = 0;
|
2020-01-16 12:35:46 +01:00
|
|
|
BlockState state;
|
2018-09-12 01:29:49 +02:00
|
|
|
while (variantAndBlockEquals(w.getBlockState(pos.up()), log)) {
|
2020-01-17 14:27:26 +01:00
|
|
|
if (PosHelper.some(pos, p -> isLeaves(w.getBlockState(p), log), Direction.NORTH, Direction.SOUTH, Direction.EAST, Direction.WEST)) {
|
2018-09-12 01:29:49 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (remove) {
|
|
|
|
if (breaks < 10) {
|
2020-01-16 12:35:46 +01:00
|
|
|
w.breakBlock(pos, true);
|
2018-09-12 01:29:49 +02:00
|
|
|
} else {
|
|
|
|
state = w.getBlockState(pos);
|
2020-01-16 12:35:46 +01:00
|
|
|
Block.dropStacks(state, w, pos);
|
2018-09-12 01:29:49 +02:00
|
|
|
w.setBlockState(pos, Blocks.AIR.getDefaultState(), 3);
|
|
|
|
}
|
|
|
|
breaks++;
|
|
|
|
}
|
|
|
|
pos = pos.up();
|
|
|
|
}
|
|
|
|
return pos;
|
|
|
|
}
|
|
|
|
|
2019-02-09 19:50:01 +01:00
|
|
|
private int dropApples(World w, BlockPos pos) {
|
2020-01-16 12:35:46 +01:00
|
|
|
BlockState log = w.getBlockState(pos);
|
2018-09-12 01:29:49 +02:00
|
|
|
int size = measureTree(w, log, pos);
|
|
|
|
if (size > 0) {
|
2019-02-07 14:47:33 +01:00
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
List<ItemEntity> capturedDrops = Lists.newArrayList();
|
2019-02-07 14:47:33 +01:00
|
|
|
|
|
|
|
dropApplesPart(capturedDrops, new ArrayList<BlockPos>(), w, log, pos, 0);
|
|
|
|
|
2020-04-15 12:37:14 +02:00
|
|
|
AwaitTickQueue.enqueueTask(wo -> {
|
2019-02-09 19:50:01 +01:00
|
|
|
capturedDrops.forEach(item -> {
|
2020-01-16 12:35:46 +01:00
|
|
|
item.setToDefaultPickupDelay();
|
2019-02-19 11:44:50 +01:00
|
|
|
wo.spawnEntity(item);
|
2019-02-09 19:50:01 +01:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
return capturedDrops.size() / 3;
|
2018-09-12 01:29:49 +02:00
|
|
|
}
|
2019-02-09 19:50:01 +01:00
|
|
|
|
|
|
|
return 0;
|
2018-09-12 01:29:49 +02:00
|
|
|
}
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
private void dropApplesPart(List<ItemEntity> drops, List<BlockPos> done, World w, BlockState log, BlockPos pos, int level) {
|
2018-09-12 01:29:49 +02:00
|
|
|
if (!done.contains(pos)) {
|
|
|
|
done.add(pos);
|
|
|
|
pos = ascendTree(w, log, pos, false);
|
|
|
|
if (level < 10 && isWoodOrLeaf(w, log, pos)) {
|
2020-01-16 12:35:46 +01:00
|
|
|
BlockState state = w.getBlockState(pos);
|
2019-02-03 10:45:45 +01:00
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
if (state.getBlock() instanceof LeavesBlock && w.getBlockState(pos.down()).isAir()) {
|
2019-02-07 12:38:42 +01:00
|
|
|
WorldEvent.DESTROY_BLOCK.play(w, pos, state);
|
2019-02-03 10:45:45 +01:00
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
ItemEntity item = new ItemEntity(EntityType.ITEM, w);
|
|
|
|
item.setPosition(pos.getX() + w.random.nextFloat(), pos.getY() - 0.5, pos.getZ() + w.random.nextFloat());
|
|
|
|
item.setStack(getApple(w, log));
|
2019-02-07 14:47:33 +01:00
|
|
|
|
|
|
|
drops.add(item);
|
2018-09-12 01:29:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
PosHelper.all(pos, p -> {
|
2019-02-07 14:47:33 +01:00
|
|
|
dropApplesPart(drops, done, w, log, p, level + 1);
|
2020-01-16 12:35:46 +01:00
|
|
|
}, Direction.UP, Direction.NORTH, Direction.SOUTH, Direction.EAST, Direction.WEST);
|
2018-09-12 01:29:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
private ItemStack getApple(World w, BlockState log) {
|
2020-01-16 16:46:24 +01:00
|
|
|
return AppleItem.getRandomItemStack(getVariant(log));
|
2018-09-12 01:29:49 +02:00
|
|
|
}
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
private int measureTree(World w, BlockState log, BlockPos pos) {
|
|
|
|
List<BlockPos> logs = new ArrayList<>();
|
|
|
|
List<BlockPos> leaves = new ArrayList<>();
|
2019-02-03 10:45:45 +01:00
|
|
|
|
2018-09-12 01:29:49 +02:00
|
|
|
countParts(logs, leaves, w, log, pos);
|
2019-02-03 10:45:45 +01:00
|
|
|
|
2018-09-12 01:29:49 +02:00
|
|
|
return logs.size() <= (leaves.size() / 2) ? logs.size() + leaves.size() : 0;
|
|
|
|
}
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
private BlockPos getBaseOfTree(World w, BlockState log, BlockPos pos) {
|
2018-09-12 01:29:49 +02:00
|
|
|
return getBaseOfTreePart(new ArrayList<BlockPos>(), w, log, pos);
|
|
|
|
}
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
private BlockPos getBaseOfTreePart(List<BlockPos> done, World w, BlockState log, BlockPos pos) {
|
2018-09-12 01:29:49 +02:00
|
|
|
if (done.contains(pos) || !variantAndBlockEquals(w.getBlockState(pos), log)) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
done.add(pos);
|
|
|
|
|
|
|
|
while (variantAndBlockEquals(w.getBlockState(pos.down()), log)) {
|
|
|
|
pos = pos.down();
|
|
|
|
done.add(pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
BlockPos adjacent = getBaseOfTreePart(done, w, log, pos.north());
|
|
|
|
if (adjacent != null && adjacent.getY() < pos.getY()) {
|
|
|
|
pos = adjacent;
|
|
|
|
}
|
|
|
|
|
|
|
|
adjacent = getBaseOfTreePart(done, w, log, pos.south());
|
|
|
|
if (adjacent != null && adjacent.getY() < pos.getY()) {
|
|
|
|
pos = adjacent;
|
|
|
|
}
|
|
|
|
|
|
|
|
adjacent = getBaseOfTreePart(done, w, log, pos.east());
|
|
|
|
if (adjacent != null && adjacent.getY() < pos.getY()) {
|
|
|
|
pos = adjacent;
|
|
|
|
}
|
|
|
|
|
|
|
|
adjacent = getBaseOfTreePart(done, w, log, pos.west());
|
|
|
|
if (adjacent != null && adjacent.getY() < pos.getY()) {
|
|
|
|
pos = adjacent;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!done.contains(pos)) {
|
|
|
|
done.add(pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
return pos;
|
|
|
|
}
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
private boolean isWoodOrLeaf(World w, BlockState log, BlockPos pos) {
|
|
|
|
BlockState state = w.getBlockState(pos);
|
|
|
|
return variantAndBlockEquals(state, log) || (isLeaves(state, log) && state.get(LeavesBlock.PERSISTENT));
|
2018-09-12 01:29:49 +02:00
|
|
|
}
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
private void countParts(List<BlockPos> logs, List<BlockPos> leaves, World w, BlockState log, BlockPos pos) {
|
2018-09-12 01:29:49 +02:00
|
|
|
if (logs.contains(pos) || leaves.contains(pos)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
BlockState state = w.getBlockState(pos);
|
2018-09-12 01:29:49 +02:00
|
|
|
boolean yay = false;
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
if (state.getBlock() instanceof LeavesBlock && state.get(LeavesBlock.PERSISTENT) && variantEquals(state, log)) {
|
2018-09-12 01:29:49 +02:00
|
|
|
leaves.add(pos);
|
|
|
|
yay = true;
|
|
|
|
} else if (variantAndBlockEquals(state, log)) {
|
|
|
|
logs.add(pos);
|
|
|
|
yay = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (yay) {
|
|
|
|
PosHelper.all(pos, p -> {
|
|
|
|
countParts(logs, leaves, w, log, p);
|
2020-01-16 12:35:46 +01:00
|
|
|
}, Direction.UP, Direction.NORTH, Direction.SOUTH, Direction.EAST, Direction.WEST);
|
2018-09-12 01:29:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
private boolean isLeaves(BlockState state, BlockState log) {
|
|
|
|
return state.getBlock() instanceof LeavesBlock && variantEquals(state, log);
|
2018-09-12 01:29:49 +02:00
|
|
|
}
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
private boolean variantAndBlockEquals(BlockState one, BlockState two) {
|
2018-09-12 01:29:49 +02:00
|
|
|
return (one.getBlock() == two.getBlock()) && variantEquals(one, two);
|
|
|
|
}
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
private boolean variantEquals(BlockState one, BlockState two) {
|
2018-09-12 01:29:49 +02:00
|
|
|
return getVariant(one) == getVariant(two);
|
|
|
|
}
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
private Object getVariant(BlockState state) {
|
2020-04-15 14:22:03 +02:00
|
|
|
// TODO: Variants are gone
|
2020-01-17 14:27:26 +01:00
|
|
|
/*if (state.getBlock() instanceof LeavesBlock) {
|
2020-01-16 12:35:46 +01:00
|
|
|
return ((LeavesBlock)state.getBlock()).getWoodType(state);
|
2019-02-03 10:45:45 +01:00
|
|
|
}
|
|
|
|
|
2020-01-16 12:35:46 +01:00
|
|
|
return state.getEntries().entrySet().stream()
|
|
|
|
.filter(i -> i.getKey().getName().contentEquals("variant"))
|
|
|
|
.map(i -> i.getValue())
|
2020-01-17 14:27:26 +01:00
|
|
|
.findFirst().orElse(null);*/
|
|
|
|
return null;
|
2018-09-12 01:29:49 +02:00
|
|
|
}
|
|
|
|
|
2020-04-15 17:22:29 +02:00
|
|
|
protected static class Data extends Ability.Pos {
|
2018-09-12 22:37:06 +02:00
|
|
|
@Expose
|
2018-09-12 01:29:49 +02:00
|
|
|
public int hitType;
|
|
|
|
|
|
|
|
public Data(int x, int y, int z, int hit) {
|
|
|
|
super(x, y, z);
|
|
|
|
hitType = hit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|