mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-24 05:47:59 +01:00
Fix teleportation issues which puts the player inside blocks/in the air above leaves/prevents teleporting to snow covered blocks
This commit is contained in:
parent
a36a654a09
commit
dce29e46a6
1 changed files with 38 additions and 17 deletions
|
@ -16,6 +16,9 @@ import com.minelittlepony.unicopia.particle.MagicParticleEffect;
|
||||||
import com.minelittlepony.unicopia.util.Trace;
|
import com.minelittlepony.unicopia.util.Trace;
|
||||||
|
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.block.Blocks;
|
||||||
|
import net.minecraft.block.LeavesBlock;
|
||||||
|
import net.minecraft.block.PowderSnowBlock;
|
||||||
import net.minecraft.block.ShapeContext;
|
import net.minecraft.block.ShapeContext;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
@ -78,8 +81,7 @@ public class UnicornTeleportAbility implements Ability<Pos> {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
int maxDistance = player.asEntity().isCreative() ? 1000 : 100;
|
int maxDistance = (int)((player.asEntity().isCreative() ? 1000 : 100) + (player.getLevel().get() * 0.25F));
|
||||||
|
|
||||||
|
|
||||||
World w = player.asWorld();
|
World w = player.asWorld();
|
||||||
|
|
||||||
|
@ -87,10 +89,16 @@ public class UnicornTeleportAbility implements Ability<Pos> {
|
||||||
return trace.getBlockOrEntityPos().map(pos -> {
|
return trace.getBlockOrEntityPos().map(pos -> {
|
||||||
final BlockPos originalPos = pos;
|
final BlockPos originalPos = pos;
|
||||||
|
|
||||||
boolean airAbove = enterable(w, pos.up()) && enterable(w, pos.up(2));
|
boolean originalPosHasSupport = exception(w, pos, player.asEntity());
|
||||||
|
boolean originalPosValid = enterable(w, pos.up()) && enterable(w, pos.up(2));
|
||||||
|
|
||||||
if (exception(w, pos, player.asEntity())) {
|
if (w.getBlockState(pos).isOf(Blocks.POWDER_SNOW) && !PowderSnowBlock.canWalkOnPowderSnow(player.asEntity())) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (originalPosHasSupport) {
|
||||||
final BlockPos p = pos;
|
final BlockPos p = pos;
|
||||||
|
// offset to adjacent
|
||||||
pos = trace.getSide().map(sideHit -> {
|
pos = trace.getSide().map(sideHit -> {
|
||||||
if (player.asEntity().isSneaking()) {
|
if (player.asEntity().isSneaking()) {
|
||||||
sideHit = sideHit.getOpposite();
|
sideHit = sideHit.getOpposite();
|
||||||
|
@ -100,15 +108,19 @@ public class UnicornTeleportAbility implements Ability<Pos> {
|
||||||
}).orElse(pos);
|
}).orElse(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enterable(w, pos.down())) {
|
if (pos.getX() != originalPos.getX() || pos.getZ() != originalPos.getZ()) {
|
||||||
pos = pos.down();
|
// check support
|
||||||
|
int steps = 0;
|
||||||
if (enterable(w, pos.down())) {
|
while (enterable(w, pos.down())) {
|
||||||
if (!airAbove) {
|
pos = pos.down();
|
||||||
return null;
|
if (++steps > 2) {
|
||||||
|
if (originalPosValid) {
|
||||||
|
pos = originalPos.up();
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pos = originalPos.up(2);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,11 +174,17 @@ public class UnicornTeleportAbility implements Ability<Pos> {
|
||||||
participant.getZ() - Math.floor(participant.getZ())
|
participant.getZ() - Math.floor(participant.getZ())
|
||||||
);
|
);
|
||||||
|
|
||||||
Vec3d dest = destination.vec().add(offset);
|
double yPos = getTargetYPosition(participant.getEntityWorld(), destination.pos(), ShapeContext.of(participant));
|
||||||
|
Vec3d dest = new Vec3d(
|
||||||
dest = new Vec3d(dest.x, getTargetYPosition(participant.getEntityWorld(), BlockPos.ofFloored(dest), ShapeContext.of(participant)), dest.z);
|
destination.x() + offset.getX(),
|
||||||
|
yPos,
|
||||||
|
destination.z() + offset.getZ()
|
||||||
|
);
|
||||||
participant.teleport(dest.x, dest.y, dest.z);
|
participant.teleport(dest.x, dest.y, dest.z);
|
||||||
|
if (participant.getWorld().getBlockCollisions(participant, participant.getBoundingBox()).iterator().hasNext()) {
|
||||||
|
dest = destination.vec();
|
||||||
|
participant.teleport(dest.x, participant.getY(), dest.z);
|
||||||
|
}
|
||||||
teleporter.subtractEnergyCost(distance);
|
teleporter.subtractEnergyCost(distance);
|
||||||
|
|
||||||
participant.fallDistance /= distance;
|
participant.fallDistance /= distance;
|
||||||
|
@ -183,7 +201,10 @@ public class UnicornTeleportAbility implements Ability<Pos> {
|
||||||
|
|
||||||
private boolean enterable(World w, BlockPos pos) {
|
private boolean enterable(World w, BlockPos pos) {
|
||||||
BlockState state = w.getBlockState(pos);
|
BlockState state = w.getBlockState(pos);
|
||||||
return w.isAir(pos) || !state.isOpaque();
|
if (StatePredicate.isFluid(state) || state.getBlock() instanceof LeavesBlock) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return w.isAir(pos) || !state.isOpaque() || !state.shouldSuffocate(w, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean exception(World w, BlockPos pos, PlayerEntity player) {
|
private boolean exception(World w, BlockPos pos, PlayerEntity player) {
|
||||||
|
|
Loading…
Reference in a new issue