minecraft-src/net/minecraft/world/level/block/EndPortalBlock.java
2025-07-04 01:41:11 +03:00

112 lines
4.2 KiB
Java

package net.minecraft.world.level.block;
import com.mojang.serialization.MapCodec;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.TheEndPortalBlockEntity;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.feature.EndPlatformFeature;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.portal.DimensionTransition;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.BooleanOp;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
public class EndPortalBlock extends BaseEntityBlock implements Portal {
public static final MapCodec<EndPortalBlock> CODEC = simpleCodec(EndPortalBlock::new);
protected static final VoxelShape SHAPE = Block.box(0.0, 6.0, 0.0, 16.0, 12.0, 16.0);
@Override
public MapCodec<EndPortalBlock> codec() {
return CODEC;
}
protected EndPortalBlock(BlockBehaviour.Properties properties) {
super(properties);
}
@Override
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
return new TheEndPortalBlockEntity(pos, state);
}
@Override
protected VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
return SHAPE;
}
@Override
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) {
if (entity.canUsePortal(false)
&& Shapes.joinIsNotEmpty(Shapes.create(entity.getBoundingBox().move(-pos.getX(), -pos.getY(), -pos.getZ())), state.getShape(level, pos), BooleanOp.AND)) {
if (!level.isClientSide && level.dimension() == Level.END && entity instanceof ServerPlayer serverPlayer && !serverPlayer.seenCredits) {
serverPlayer.showEndCredits();
} else {
entity.setAsInsidePortal(this, pos);
}
}
}
@Override
public DimensionTransition getPortalDestination(ServerLevel level, Entity entity, BlockPos pos) {
ResourceKey<Level> resourceKey = level.dimension() == Level.END ? Level.OVERWORLD : Level.END;
ServerLevel serverLevel = level.getServer().getLevel(resourceKey);
if (serverLevel == null) {
return null;
} else {
boolean bl = resourceKey == Level.END;
BlockPos blockPos = bl ? ServerLevel.END_SPAWN_POINT : serverLevel.getSharedSpawnPos();
Vec3 vec3 = blockPos.getBottomCenter();
float f = entity.getYRot();
if (bl) {
EndPlatformFeature.createEndPlatform(serverLevel, BlockPos.containing(vec3).below(), true);
f = Direction.WEST.toYRot();
if (entity instanceof ServerPlayer) {
vec3 = vec3.subtract(0.0, 1.0, 0.0);
}
} else {
if (entity instanceof ServerPlayer serverPlayer) {
return serverPlayer.findRespawnPositionAndUseSpawnBlock(false, DimensionTransition.DO_NOTHING);
}
vec3 = entity.adjustSpawnLocation(serverLevel, blockPos).getBottomCenter();
}
return new DimensionTransition(
serverLevel, vec3, entity.getDeltaMovement(), f, entity.getXRot(), DimensionTransition.PLAY_PORTAL_SOUND.then(DimensionTransition.PLACE_PORTAL_TICKET)
);
}
}
@Override
public void animateTick(BlockState state, Level level, BlockPos pos, RandomSource random) {
double d = pos.getX() + random.nextDouble();
double e = pos.getY() + 0.8;
double f = pos.getZ() + random.nextDouble();
level.addParticle(ParticleTypes.SMOKE, d, e, f, 0.0, 0.0, 0.0);
}
@Override
public ItemStack getCloneItemStack(LevelReader level, BlockPos pos, BlockState state) {
return ItemStack.EMPTY;
}
@Override
protected boolean canBeReplaced(BlockState state, Fluid fluid) {
return false;
}
}