diff --git a/src/main/java/ru/betterend/blocks/EndPortalBlock.java b/src/main/java/ru/betterend/blocks/EndPortalBlock.java index a5d896cb..8efb8c81 100644 --- a/src/main/java/ru/betterend/blocks/EndPortalBlock.java +++ b/src/main/java/ru/betterend/blocks/EndPortalBlock.java @@ -18,6 +18,7 @@ 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; @@ -28,7 +29,6 @@ import ru.betterend.interfaces.TeleportingEntity; import ru.betterend.registry.BlockTagRegistry; import ru.betterend.registry.ParticleRegistry; import ru.betterend.util.PortalFrameHelper; -import ru.betterend.world.features.DefaultFeature; public class EndPortalBlock extends NetherPortalBlock implements IRenderTypeable { public EndPortalBlock() { @@ -91,16 +91,13 @@ public class EndPortalBlock extends NetherPortalBlock implements IRenderTypeable private BlockPos findExitPos(ServerWorld world, BlockPos pos, Entity entity) { Registry registry = world.getRegistryManager().getDimensionTypes(); double mult = registry.get(DimensionType.THE_END_ID).getCoordinateScale(); - int topY; BlockPos.Mutable basePos; if (world.getRegistryKey().equals(World.OVERWORLD)) { basePos = pos.mutableCopy().set(pos.getX() / mult, pos.getY(), pos.getZ() / mult); - topY = DefaultFeature.getPosOnSurface(world, basePos).getY(); } else { basePos = pos.mutableCopy().set(pos.getX() * mult, pos.getY(), pos.getZ() * mult); - topY = world.getHeight(); } - BlockPos top = basePos.mutableCopy().set(basePos.getX() + 32, topY, basePos.getZ() + 32); + BlockPos top = basePos.mutableCopy().set(basePos.getX() + 32, world.getHeight(), 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); @@ -141,7 +138,7 @@ public class EndPortalBlock extends NetherPortalBlock implements IRenderTypeable if (world.getRegistryKey().equals(World.END)) { ConfiguredFeatures.END_ISLAND.generate(world, world.getChunkManager().getChunkGenerator(), new Random(basePos.asLong()), basePos); } else { - basePos.setY(topY); + basePos.setY(world.getChunk(basePos).sampleHeightmap(Heightmap.Type.WORLD_SURFACE, basePos.getX(), basePos.getZ())); } PortalFrameHelper.generatePortalFrame(world, basePos, axis, true); if (axis.equals(Direction.Axis.X)) { diff --git a/src/main/java/ru/betterend/util/PortalFrameHelper.java b/src/main/java/ru/betterend/util/PortalFrameHelper.java index 79c0401f..95a7c4b7 100644 --- a/src/main/java/ru/betterend/util/PortalFrameHelper.java +++ b/src/main/java/ru/betterend/util/PortalFrameHelper.java @@ -17,98 +17,107 @@ public class PortalFrameHelper { if (world == null || pos == null) return false; if (!world.getBlockState(pos).isOf(frameBlock)) return false; BlockPos bottomCorner = findBottomCorner(world, pos, frameBlock); - if (bottomCorner == null) return false; + BlockPos topCorner = findTopCorner(world, pos, frameBlock); + if (bottomCorner == null || topCorner == null) return false; boolean valid = true; + int width = 1, height = 1; Direction.Axis axis = Direction.Axis.X; BlockPos checkPos = bottomCorner.up(); Direction moveDir = Direction.UP; - while(!checkPos.equals(bottomCorner)) { - while(valid && !checkPos.equals(bottomCorner)) { - valid = world.getBlockState(checkPos).isOf(frameBlock); - if (!valid) { - switch(moveDir) { - case UP: { - checkPos = checkPos.down(); - if (world.getBlockState(checkPos.east()).isOf(frameBlock)) { - checkPos = checkPos.east(); - moveDir = Direction.EAST; - valid = true; - } else if (world.getBlockState(checkPos.north()).isOf(frameBlock)) { - axis = Direction.Axis.Z; - checkPos = checkPos.north(); - moveDir = Direction.NORTH; - valid = true; - } - break; - } - case DOWN: { - checkPos = checkPos.up(); - if (world.getBlockState(checkPos.west()).isOf(frameBlock)) { - checkPos = checkPos.west(); - moveDir = Direction.WEST; - valid = true; - } else if (world.getBlockState(checkPos.south()).isOf(frameBlock)) { - checkPos = checkPos.south(); - moveDir = Direction.SOUTH; - valid = true; - } - break; - } - case NORTH: - case EAST: { - checkPos = moveDir.equals(Direction.NORTH) ? checkPos.south() : checkPos.west(); - if (world.getBlockState(checkPos.down()).isOf(frameBlock)) { - checkPos = checkPos.down(); - moveDir = Direction.DOWN; - valid = true; - } - break; - } - default: - return false; - } - if (!valid) return false; - } else { - switch(moveDir) { - case UP: { - checkPos = checkPos.up(); - break; - } - case DOWN: { - checkPos = checkPos.down(); - break; - } - case NORTH: { - checkPos = checkPos.north(); - break; - } - case SOUTH: { - checkPos = checkPos.south(); - break; - } - case EAST: { + while(valid && !checkPos.equals(bottomCorner)) { + valid = world.getBlockState(checkPos).isOf(frameBlock); + if (!valid) { + switch(moveDir) { + case UP: { + checkPos = checkPos.down(); + if (world.getBlockState(checkPos.east()).isOf(frameBlock)) { checkPos = checkPos.east(); - break; + moveDir = Direction.EAST; + valid = true; + } else if (world.getBlockState(checkPos.south()).isOf(frameBlock)) { + axis = Direction.Axis.Z; + checkPos = checkPos.south(); + moveDir = Direction.SOUTH; + valid = true; } - case WEST: { + break; + } + case DOWN: { + checkPos = checkPos.up(); + if (world.getBlockState(checkPos.west()).isOf(frameBlock)) { checkPos = checkPos.west(); - break; + moveDir = Direction.WEST; + valid = true; + } else if (world.getBlockState(checkPos.north()).isOf(frameBlock)) { + checkPos = checkPos.north(); + moveDir = Direction.NORTH; + valid = true; } + break; + } + case SOUTH: + case EAST: { + checkPos = moveDir.equals(Direction.SOUTH) ? checkPos.north() : checkPos.west(); + if (world.getBlockState(checkPos.down()).isOf(frameBlock)) { + checkPos = checkPos.down(); + moveDir = Direction.DOWN; + valid = true; + } + break; + } + default: + return false; + } + if (!valid) return false; + } else { + switch(moveDir) { + case UP: { + height++; + checkPos = checkPos.up(); + break; + } + case DOWN: { + checkPos = checkPos.down(); + break; + } + case NORTH: { + checkPos = checkPos.north(); + break; + } + case SOUTH: { + width++; + checkPos = checkPos.south(); + break; + } + case EAST: { + width++; + checkPos = checkPos.east(); + break; + } + case WEST: { + checkPos = checkPos.west(); + break; } } } } + if (width < 4 || height < 5 || width > 40 || height > 40) return false; + if (axis.equals(Direction.Axis.X)) { + if(!checkIsAreaEmpty(world, bottomCorner.add(1, 1, 0), topCorner.add(-1, -1, 0))) return false; + } else { + if(!checkIsAreaEmpty(world, bottomCorner.add(0, 1, 1), topCorner.add(0, -1, -1))) return false; + } if (valid) { if (world.getBlockState(bottomCorner).isOf(BlockRegistry.FLAVOLITE_RUNED)) { - generatePortalFrame(world, bottomCorner, axis, true); + generatePortalFrame(world, bottomCorner, axis, width, height, true); } else { - generateEternalPortalFrame(world, bottomCorner, axis, true); + generateEternalPortalFrame(world, bottomCorner, axis, width, height, true); } } return valid; } - private static BlockPos findBottomCorner(World world, BlockPos pos, Block frameBlock) { + public static BlockPos findBottomCorner(World world, BlockPos pos, Block frameBlock) { BlockState up = world.getBlockState(pos.up()); BlockState down = world.getBlockState(pos.down()); BlockState north = world.getBlockState(pos.north()); @@ -116,30 +125,79 @@ public class PortalFrameHelper { BlockState west = world.getBlockState(pos.west()); BlockState east = world.getBlockState(pos.east()); if (up.isOf(frameBlock) && !down.isOf(frameBlock)) { - if (north.isOf(frameBlock) || east.isOf(frameBlock)) { + if (south.isOf(frameBlock) || east.isOf(frameBlock)) { return pos; } else if (west.isOf(frameBlock)) { return findBottomCorner(world, pos.west(), frameBlock); - } else if (south.isOf(frameBlock)){ - return findBottomCorner(world, pos.south(), frameBlock); + } else if (north.isOf(frameBlock)){ + return findBottomCorner(world, pos.north(), frameBlock); } return null; } else if (down.isOf(frameBlock)) { if (west.isOf(frameBlock)) { return findBottomCorner(world, pos.west(), frameBlock); - } else if (south.isOf(frameBlock)) { - return findBottomCorner(world, pos.south(), frameBlock); + } else if (north.isOf(frameBlock)) { + return findBottomCorner(world, pos.north(), frameBlock); } else { return findBottomCorner(world, pos.down(), frameBlock); } } else if (west.isOf(frameBlock)) { return findBottomCorner(world, pos.west(), frameBlock); - } else if (south.isOf(frameBlock)) { - return findBottomCorner(world, pos.south(), frameBlock); + } else if (north.isOf(frameBlock)) { + return findBottomCorner(world, pos.north(), frameBlock); } return null; } + + public static BlockPos findTopCorner(World world, BlockPos pos, Block frameBlock) { + BlockState up = world.getBlockState(pos.up()); + BlockState down = world.getBlockState(pos.down()); + BlockState north = world.getBlockState(pos.north()); + BlockState south = world.getBlockState(pos.south()); + BlockState west = world.getBlockState(pos.west()); + BlockState east = world.getBlockState(pos.east()); + if (!up.isOf(frameBlock) && down.isOf(frameBlock)) { + if (north.isOf(frameBlock) || west.isOf(frameBlock)) { + return pos; + } else if (east.isOf(frameBlock)) { + return findTopCorner(world, pos.east(), frameBlock); + } else if (south.isOf(frameBlock)){ + return findTopCorner(world, pos.south(), frameBlock); + } + return null; + } else if (up.isOf(frameBlock)) { + if (east.isOf(frameBlock)) { + return findTopCorner(world, pos.east(), frameBlock); + } else if (south.isOf(frameBlock)){ + return findTopCorner(world, pos.south(), frameBlock); + } else { + return findTopCorner(world, pos.up(), frameBlock); + } + } else if (east.isOf(frameBlock)) { + return findTopCorner(world, pos.east(), frameBlock); + } else if (south.isOf(frameBlock)){ + return findTopCorner(world, pos.south(), frameBlock); + } + return null; + } + + private static boolean checkIsAreaEmpty(World world, BlockPos bottom, BlockPos top) { + boolean valid = true; + for (BlockPos current : BlockPos.iterate(bottom, top)) { + BlockState state = world.getBlockState(current); + valid &= state.isAir(); + } + return valid; + } + public static void generatePortalFrame(ServerWorld world, BlockPos pos, Direction.Axis axis, int width, int height, boolean active) { + FeatureRegistry.END_PORTAL.configure(axis, width, height, active).getFeatureConfigured().generate(world, world.getChunkManager().getChunkGenerator(), new Random(), pos); + } + + public static void generateEternalPortalFrame(ServerWorld world, BlockPos pos, Direction.Axis axis, int width, int height, boolean active) { + FeatureRegistry.END_PORTAL_ETERNAL.configure(axis, width, height, active).getFeatureConfigured().generate(world, world.getChunkManager().getChunkGenerator(), new Random(), pos); + } + 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); } diff --git a/src/main/java/ru/betterend/world/features/DefaultEndPortalFeature.java b/src/main/java/ru/betterend/world/features/DefaultEndPortalFeature.java index dbe8f8b8..79135baf 100644 --- a/src/main/java/ru/betterend/world/features/DefaultEndPortalFeature.java +++ b/src/main/java/ru/betterend/world/features/DefaultEndPortalFeature.java @@ -27,10 +27,12 @@ public class DefaultEndPortalFeature extends Feature { BlockState portalBlock = BlockRegistry.END_PORTAL_BLOCK.getDefaultState().with(EndPortalBlock.AXIS, config.axis); BlockPos bottomCorner = pos; BlockPos topCorner; + int width = config.width - 1; + int height = config.height - 1; if (config.axis.equals(Direction.Axis.X)) { - topCorner = bottomCorner.add(3, 4, 0); + topCorner = bottomCorner.add(width, height, 0); } else { - topCorner = bottomCorner.add(0, 4, 3); + topCorner = bottomCorner.add(0, height, width); } for(BlockPos position : BlockPos.iterate(bottomCorner, topCorner)) { diff --git a/src/main/java/ru/betterend/world/features/EndPortalFeature.java b/src/main/java/ru/betterend/world/features/EndPortalFeature.java index 55127f11..14453934 100644 --- a/src/main/java/ru/betterend/world/features/EndPortalFeature.java +++ b/src/main/java/ru/betterend/world/features/EndPortalFeature.java @@ -14,8 +14,13 @@ public class EndPortalFeature extends EndFeature { this.frameBlock = frameBlock; } + public EndPortalFeature configure(Direction.Axis axis, int width, int height, boolean active) { + this.featureConfigured = ((DefaultEndPortalFeature) this.feature).configure(EndPortalFeatureConfig.create(frameBlock, axis, width, height, active)); + return this; + } + public EndPortalFeature configure(Direction.Axis axis, boolean active) { - this.featureConfigured = ((DefaultEndPortalFeature) this.feature).configure(EndPortalFeatureConfig.create(frameBlock, axis, active)); + this.featureConfigured = ((DefaultEndPortalFeature) this.feature).configure(EndPortalFeatureConfig.create(frameBlock, axis, 4, 5, active)); return this; } } diff --git a/src/main/java/ru/betterend/world/features/EndPortalFeatureConfig.java b/src/main/java/ru/betterend/world/features/EndPortalFeatureConfig.java index 50a5a143..04988f03 100644 --- a/src/main/java/ru/betterend/world/features/EndPortalFeatureConfig.java +++ b/src/main/java/ru/betterend/world/features/EndPortalFeatureConfig.java @@ -15,6 +15,10 @@ public class EndPortalFeatureConfig implements FeatureConfig { return Registry.BLOCK.getId(endPortalFeatureConfig.frameBlock).toString(); }), Codec.STRING.fieldOf("axis").forGetter(endPortalFeatureConfig -> { return endPortalFeatureConfig.axis.getName(); + }), Codec.INT.fieldOf("width").forGetter(endPortalFeatureConfig -> { + return endPortalFeatureConfig.width; + }), Codec.INT.fieldOf("heigth").forGetter(endPortalFeatureConfig -> { + return endPortalFeatureConfig.height; }), Codec.BOOL.fieldOf("activated").forGetter(endPortalFeatureConfig -> { return endPortalFeatureConfig.activated; })).apply(instance, EndPortalFeatureConfig::new); @@ -23,20 +27,26 @@ public class EndPortalFeatureConfig implements FeatureConfig { public final RunedFlavolite frameBlock; public final Direction.Axis axis; public final boolean activated; + public final int width; + public final int height; - private EndPortalFeatureConfig(String frameBlock, String axis, boolean active) { + private EndPortalFeatureConfig(String frameBlock, String axis, int width, int height, boolean active) { this.frameBlock = (RunedFlavolite) Registry.BLOCK.get(new Identifier(frameBlock)); this.axis = Direction.Axis.fromName(axis); this.activated = active; + this.width = width; + this.height = height; } - private EndPortalFeatureConfig(RunedFlavolite frameBlock, Direction.Axis axis, boolean active) { + private EndPortalFeatureConfig(RunedFlavolite frameBlock, Direction.Axis axis, int width, int height, boolean active) { this.frameBlock = frameBlock; this.axis = axis; this.activated = active; + this.width = width; + this.height = height; } - public static EndPortalFeatureConfig create(RunedFlavolite block, Direction.Axis axis, boolean active) { - return new EndPortalFeatureConfig(block, axis, active); + public static EndPortalFeatureConfig create(RunedFlavolite block, Direction.Axis axis, int width, int height, boolean active) { + return new EndPortalFeatureConfig(block, axis, width, height, active); } }