WIP: portals

This commit is contained in:
Aleksey 2020-10-22 18:01:07 +03:00
parent 433ff01304
commit 9372d0ca02
12 changed files with 501 additions and 72 deletions

View file

@ -5,20 +5,29 @@ import java.util.Random;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.NetherPortalBlock;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.Heightmap;
import net.minecraft.world.World;
import net.minecraft.world.WorldAccess;
import net.minecraft.world.dimension.DimensionType;
import net.minecraft.world.gen.feature.ConfiguredFeatures;
import ru.betterend.client.ERenderLayer;
import ru.betterend.client.IRenderTypeable;
import ru.betterend.interfaces.TeleportingEntity;
import ru.betterend.registry.BlockTagRegistry;
import ru.betterend.registry.FeatureRegistry;
import ru.betterend.registry.ParticleRegistry;
public class EndPortalBlock extends NetherPortalBlock implements IRenderTypeable {
@ -58,7 +67,17 @@ public class EndPortalBlock extends NetherPortalBlock implements IRenderTypeable
@Override
public void onEntityCollision(BlockState state, World world, BlockPos pos, Entity entity) {
BlockPos exitPos = this.findExitPos(world, pos);
if (world instanceof ServerWorld && entity instanceof LivingEntity && !entity.hasVehicle() && !entity.hasPassengers() && entity.canUsePortals()) {
TeleportingEntity teleEntity = TeleportingEntity.class.cast(entity);
if (teleEntity.hasCooldown()) return;
teleEntity.beSetCooldown(500);
boolean isOverworld = world.getRegistryKey().equals(World.OVERWORLD);
ServerWorld destination = ((ServerWorld) world).getServer().getWorld(isOverworld ? World.END : World.OVERWORLD);
BlockPos exitPos = this.findExitPos(destination, pos, entity);
teleEntity.beSetExitPos(exitPos);
entity.moveToWorld(destination);
teleEntity.beSetExitPos(null);
}
}
@Override
@ -66,16 +85,96 @@ public class EndPortalBlock extends NetherPortalBlock implements IRenderTypeable
return ERenderLayer.TRANSLUCENT;
}
private BlockPos findExitPos(World world, BlockPos pos) {
private BlockPos findExitPos(ServerWorld world, BlockPos pos, Entity entity) {
Registry<DimensionType> registry = world.getRegistryManager().getDimensionTypes();
double mult = registry.get(DimensionType.THE_END_ID).getCoordinateScale();
int topY;
BlockPos.Mutable basePos;
if (world.getRegistryKey().equals(World.OVERWORLD)) {
BlockPos basePos = pos.mutableCopy().set(pos.getX() * 8, pos.getY() * 8, pos.getZ() * 8);
int height = world.getTopY(Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, basePos.getX(), basePos.getZ());
BlockPos.iterate(basePos.add(-16, -pos.getY() + 1, -16), basePos.add(16, height, 16)).forEach(position -> {
});
basePos = pos.mutableCopy().set(pos.getX() / mult, pos.getY(), pos.getZ() / mult);
topY = world.getTopY(Heightmap.Type.WORLD_SURFACE, basePos.getX(), basePos.getZ());
} else {
basePos = pos.mutableCopy().set(pos.getX() * mult, pos.getY(), pos.getZ() * mult);
topY = world.getHeight();
}
return pos;
BlockPos top = basePos.mutableCopy().set(basePos.getX() + 32, topY, basePos.getZ() + 32);
BlockPos.Mutable bottom = basePos.mutableCopy().set(basePos.getX() - 32, 5, basePos.getZ() - 32);
for(BlockPos position : BlockPos.iterate(bottom, top)) {
BlockState state = world.getBlockState(position);
if(state.isOf(this)) {
if (state.get(AXIS).equals(Direction.Axis.X)) {
return position.add(1, 0, 0);
} else {
return position.add(0, 0, 1);
}
}
}
bottom.setY(basePos.getY());
Direction.Axis axis = entity.getMovementDirection().getAxis();
if (checkIsAreaValid(world, bottom)) {
generatePortalFrame(world, bottom, axis, true);
if (axis.equals(Direction.Axis.X)) {
return bottom.add(1, 1, 0);
} else {
return bottom.add(0, 1, 1);
}
} else {
if (bottom.getY() > top.getY()) {
BlockPos buff = bottom;
bottom = top.mutableCopy();
top = buff;
}
for(BlockPos position : BlockPos.iterate(bottom, top)) {
if (checkIsAreaValid(world, position)) {
generatePortalFrame(world, position, axis, true);
if (axis.equals(Direction.Axis.X)) {
return position.add(1, 1, 0);
} else {
return position.add(0, 1, 1);
}
}
}
}
if (world.getRegistryKey().equals(World.END)) {
ConfiguredFeatures.END_ISLAND.generate(world, world.getChunkManager().getChunkGenerator(), new Random(basePos.asLong()), basePos);
} else {
basePos.setY(topY);
}
generatePortalFrame(world, basePos, axis, true);
if (axis.equals(Direction.Axis.X)) {
return basePos.add(1, 1, 0);
} else {
return basePos.add(0, 1, 1);
}
}
private boolean checkIsAreaValid(World world, BlockPos pos) {
BlockPos bottomCorner = pos.add(-1, 0, -1);
BlockPos topCorner = bottomCorner.add(4, 4, 1);
int airBlocks = 0;
boolean free = true;
for (BlockPos position : BlockPos.iterate(bottomCorner, topCorner)) {
BlockState state = world.getBlockState(position);
if (state.isAir()) airBlocks++;
if (world.getRegistryKey().equals(World.END)) {
free &= state.isAir() || BlockTagRegistry.validGenBlock(state);
} else {
BlockState surfaceBlock = world.getBiome(pos).getGenerationSettings().getSurfaceConfig().getTopMaterial();
free &= this.validBlock(state, surfaceBlock.getBlock());
}
}
return free && airBlocks == 48;
}
private boolean validBlock(BlockState state, Block surfaceBlock) {
return state.isAir() ||
state.isOf(surfaceBlock) ||
state.isOf(Blocks.STONE) ||
state.isOf(Blocks.SAND) ||
state.isOf(Blocks.GRAVEL);
}
public static void generatePortalFrame(ServerWorld world, BlockPos pos, Direction.Axis axis, boolean active) {
FeatureRegistry.END_PORTAL.configure(axis, active).getFeatureConfigured().generate(world, world.getChunkManager().getChunkGenerator(), new Random(), pos);
}
}

View file

@ -1,12 +1,18 @@
package ru.betterend.blocks;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.state.StateManager;
import net.minecraft.state.property.BooleanProperty;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import ru.betterend.blocks.basis.BlockBase;
import ru.betterend.registry.BlockRegistry;
import ru.betterend.util.BlocksHelper;
public class RunedFlavolite extends BlockBase {
public static final BooleanProperty ACTIVATED = BooleanProperty.of("active");
@ -22,4 +28,20 @@ public class RunedFlavolite extends BlockBase {
protected void appendProperties(StateManager.Builder<Block, BlockState> stateManager) {
stateManager.add(ACTIVATED);
}
@Override
public void onBreak(World world, BlockPos pos, BlockState state, PlayerEntity player) {
super.onBreak(world, pos, state, player);
if(state.get(ACTIVATED)) {
for (BlockPos position : BlockPos.iterate(pos.add(-3, -4, -3), pos.add(3, 4, 3))) {
if (position.equals(pos)) continue;
BlockState posState = world.getBlockState(position);
if (posState.getBlock() instanceof RunedFlavolite) {
BlocksHelper.setWithoutUpdate(world, position, posState.with(ACTIVATED, false));
} else if (posState.isOf(BlockRegistry.END_PORTAL_BLOCK)) {
world.removeBlock(position, false);
}
}
}
}
}