Portals fixes
This commit is contained in:
parent
afc1cd888a
commit
86a57a1bd8
2 changed files with 222 additions and 121 deletions
|
@ -27,10 +27,8 @@ import net.minecraft.util.math.Direction;
|
||||||
import net.minecraft.util.math.Direction.Axis;
|
import net.minecraft.util.math.Direction.Axis;
|
||||||
import net.minecraft.util.math.Direction.AxisDirection;
|
import net.minecraft.util.math.Direction.AxisDirection;
|
||||||
import net.minecraft.util.registry.Registry;
|
import net.minecraft.util.registry.Registry;
|
||||||
import net.minecraft.world.Heightmap;
|
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraft.world.WorldAccess;
|
import net.minecraft.world.WorldAccess;
|
||||||
import net.minecraft.world.chunk.Chunk;
|
|
||||||
import net.minecraft.world.dimension.DimensionType;
|
import net.minecraft.world.dimension.DimensionType;
|
||||||
import ru.betterend.client.render.ERenderLayer;
|
import ru.betterend.client.render.ERenderLayer;
|
||||||
import ru.betterend.interfaces.IColorProvider;
|
import ru.betterend.interfaces.IColorProvider;
|
||||||
|
@ -38,14 +36,15 @@ import ru.betterend.interfaces.IRenderTypeable;
|
||||||
import ru.betterend.interfaces.TeleportingEntity;
|
import ru.betterend.interfaces.TeleportingEntity;
|
||||||
import ru.betterend.registry.EndParticles;
|
import ru.betterend.registry.EndParticles;
|
||||||
import ru.betterend.registry.EndPortals;
|
import ru.betterend.registry.EndPortals;
|
||||||
|
import ru.betterend.rituals.EternalRitual;
|
||||||
|
|
||||||
public class EndPortalBlock extends NetherPortalBlock implements IRenderTypeable, IColorProvider {
|
public class EndPortalBlock extends NetherPortalBlock implements IRenderTypeable, IColorProvider {
|
||||||
public static final IntProperty PORTAL = BlockProperties.PORTAL;
|
public static final IntProperty PORTAL = BlockProperties.PORTAL;
|
||||||
|
|
||||||
public EndPortalBlock() {
|
public EndPortalBlock() {
|
||||||
super(FabricBlockSettings.copyOf(Blocks.NETHER_PORTAL).resistance(Blocks.BEDROCK.getBlastResistance()).luminance(15));
|
super(FabricBlockSettings.copyOf(Blocks.NETHER_PORTAL).resistance(Blocks.BEDROCK.getBlastResistance()).luminance(15));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
|
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
|
||||||
super.appendProperties(builder);
|
super.appendProperties(builder);
|
||||||
|
@ -82,30 +81,33 @@ public class EndPortalBlock extends NetherPortalBlock implements IRenderTypeable
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEntityCollision(BlockState state, World world, BlockPos pos, Entity entity) {
|
public void onEntityCollision(BlockState state, World world, BlockPos pos, Entity entity) {
|
||||||
if (world instanceof ServerWorld && !entity.hasVehicle() && !entity.hasPassengers() && entity.canUsePortals()) {
|
if (world.isClient || !validate(entity)) return;
|
||||||
if (entity.hasNetherPortalCooldown()) return;
|
entity.resetNetherPortalCooldown();
|
||||||
entity.resetNetherPortalCooldown();
|
ServerWorld currentWorld = (ServerWorld) world;
|
||||||
ServerWorld currentWorld = (ServerWorld) world;
|
MinecraftServer server = currentWorld.getServer();
|
||||||
MinecraftServer server = currentWorld.getServer();
|
ServerWorld targetWorld = EndPortals.getWorld(server, state.get(PORTAL));
|
||||||
ServerWorld targetWorld = EndPortals.getWorld(server, state.get(PORTAL));
|
boolean isInEnd = currentWorld.getRegistryKey().equals(World.END);
|
||||||
boolean isInEnd = currentWorld.getRegistryKey().equals(World.END);
|
ServerWorld destination = isInEnd ? targetWorld : server.getWorld(World.END);
|
||||||
ServerWorld destination = isInEnd ? targetWorld : server.getWorld(World.END);
|
BlockPos exitPos = findExitPos(currentWorld, destination, pos, entity);
|
||||||
BlockPos exitPos = findExitPos(currentWorld, destination, pos, entity);
|
if (exitPos == null) return;
|
||||||
if (exitPos == null) return;
|
if (entity instanceof ServerPlayerEntity) {
|
||||||
if (entity instanceof ServerPlayerEntity) {
|
ServerPlayerEntity player = (ServerPlayerEntity) entity;
|
||||||
ServerPlayerEntity player = (ServerPlayerEntity) entity;
|
teleportPlayer(player, destination, exitPos);
|
||||||
this.teleportPlayer(player, destination, exitPos);
|
} else {
|
||||||
} else {
|
TeleportingEntity teleEntity = (TeleportingEntity) entity;
|
||||||
TeleportingEntity teleEntity = (TeleportingEntity) entity;
|
teleEntity.beSetExitPos(exitPos);
|
||||||
teleEntity.beSetExitPos(exitPos);
|
Entity teleported = entity.moveToWorld(destination);
|
||||||
Entity teleported = entity.moveToWorld(destination);
|
if (teleported != null) {
|
||||||
if (teleported != null) {
|
teleported.resetNetherPortalCooldown();
|
||||||
teleported.resetNetherPortalCooldown();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean validate(Entity entity) {
|
||||||
|
return !entity.hasVehicle() && !entity.hasPassengers() &&
|
||||||
|
entity.canUsePortals() && !entity.hasNetherPortalCooldown();
|
||||||
|
}
|
||||||
|
|
||||||
private void teleportPlayer(ServerPlayerEntity player, ServerWorld destination, BlockPos exitPos) {
|
private void teleportPlayer(ServerPlayerEntity player, ServerWorld destination, BlockPos exitPos) {
|
||||||
if (player.isCreative()) {
|
if (player.isCreative()) {
|
||||||
player.teleport(destination, exitPos.getX() + 0.5, exitPos.getY(), exitPos.getZ() + 0.5, player.yaw, player.pitch);
|
player.teleport(destination, exitPos.getX() + 0.5, exitPos.getY(), exitPos.getZ() + 0.5, player.yaw, player.pitch);
|
||||||
|
@ -114,7 +116,6 @@ public class EndPortalBlock extends NetherPortalBlock implements IRenderTypeable
|
||||||
teleEntity.beSetExitPos(exitPos);
|
teleEntity.beSetExitPos(exitPos);
|
||||||
player.moveToWorld(destination);
|
player.moveToWorld(destination);
|
||||||
}
|
}
|
||||||
player.resetNetherPortalCooldown();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -131,47 +132,31 @@ public class EndPortalBlock extends NetherPortalBlock implements IRenderTypeable
|
||||||
double currentMultiplier = Objects.requireNonNull(registry.get(currentWorldId)).getCoordinateScale();
|
double currentMultiplier = Objects.requireNonNull(registry.get(currentWorldId)).getCoordinateScale();
|
||||||
double multiplier = targetMultiplier > currentMultiplier ? 1.0 / targetMultiplier : currentMultiplier;
|
double multiplier = targetMultiplier > currentMultiplier ? 1.0 / targetMultiplier : currentMultiplier;
|
||||||
BlockPos.Mutable basePos = currentPos.mutableCopy().set(currentPos.getX() * multiplier, currentPos.getY(), currentPos.getZ() * multiplier);
|
BlockPos.Mutable basePos = currentPos.mutableCopy().set(currentPos.getX() * multiplier, currentPos.getY(), currentPos.getZ() * multiplier);
|
||||||
Direction direction = Direction.EAST;
|
|
||||||
BlockPos.Mutable checkPos = basePos.mutableCopy();
|
BlockPos.Mutable checkPos = basePos.mutableCopy();
|
||||||
for (int step = 1; step <= 128; step++) {
|
BlockState currentState = currentWorld.getBlockState(currentPos);
|
||||||
for (int i = 0; i < (step >> 1); i++) {
|
int radius = (EternalRitual.SEARCH_RADIUS >> 4) + 1;
|
||||||
Chunk chunk = targetWorld.getChunk(checkPos);
|
checkPos = EternalRitual.findBlockPos(targetWorld, checkPos, radius, this, state -> state.isOf(this) &&
|
||||||
if (chunk != null) {
|
state.get(PORTAL).equals(currentState.get(PORTAL)));
|
||||||
int surfaceY = chunk.sampleHeightmap(Heightmap.Type.WORLD_SURFACE, checkPos.getX() & 15, checkPos.getZ() & 15);
|
if (checkPos != null) {
|
||||||
int motionY = chunk.sampleHeightmap(Heightmap.Type.MOTION_BLOCKING, checkPos.getX() & 15, checkPos.getZ() & 15);
|
BlockState checkState = targetWorld.getBlockState(checkPos);
|
||||||
int ceil = Math.max(surfaceY, motionY) + 1;
|
Axis axis = checkState.get(AXIS);
|
||||||
if (ceil < 5) continue;
|
checkPos = findCenter(targetWorld, checkPos, axis);
|
||||||
checkPos.setY(ceil);
|
Direction frontDir = Direction.from(axis, AxisDirection.POSITIVE).rotateYClockwise();
|
||||||
while (checkPos.getY() >= 5) {
|
Direction entityDir = entity.getMovementDirection();
|
||||||
BlockState state = targetWorld.getBlockState(checkPos);
|
if (entityDir.getAxis().isVertical()) {
|
||||||
if (state.isOf(this)) {
|
entityDir = frontDir;
|
||||||
Axis axis = state.get(AXIS);
|
|
||||||
checkPos = findCenter(targetWorld, checkPos, axis);
|
|
||||||
|
|
||||||
Direction frontDir = Direction.from(axis, AxisDirection.POSITIVE).rotateYClockwise();
|
|
||||||
Direction entityDir = entity.getMovementDirection();
|
|
||||||
if (entityDir.getAxis().isVertical()) {
|
|
||||||
entityDir = frontDir;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (frontDir != entityDir && frontDir.getOpposite() != entityDir) {
|
|
||||||
entity.applyRotation(BlockRotation.CLOCKWISE_90);
|
|
||||||
entityDir = entityDir.rotateYClockwise();
|
|
||||||
}
|
|
||||||
return checkPos.offset(entityDir);
|
|
||||||
}
|
|
||||||
checkPos.move(Direction.DOWN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
checkPos.move(direction);
|
|
||||||
}
|
}
|
||||||
direction = direction.rotateYClockwise();
|
if (frontDir != entityDir && frontDir.getOpposite() != entityDir) {
|
||||||
|
entity.applyRotation(BlockRotation.CLOCKWISE_90);
|
||||||
|
entityDir = entityDir.rotateYClockwise();
|
||||||
|
}
|
||||||
|
return checkPos.offset(entityDir);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private BlockPos.Mutable findCenter(World world, BlockPos.Mutable pos, Direction.Axis axis) {
|
private BlockPos.Mutable findCenter(World world, BlockPos.Mutable pos, Direction.Axis axis) {
|
||||||
return this.findCenter(world, pos, axis, 1);
|
return findCenter(world, pos, axis, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BlockPos.Mutable findCenter(World world, BlockPos.Mutable pos, Direction.Axis axis, int step) {
|
private BlockPos.Mutable findCenter(World world, BlockPos.Mutable pos, Direction.Axis axis, int step) {
|
||||||
|
|
|
@ -1,10 +1,16 @@
|
||||||
package ru.betterend.rituals;
|
package ru.betterend.rituals;
|
||||||
|
|
||||||
import java.awt.Point;
|
import java.awt.Point;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import net.minecraft.util.BlockRotation;
|
||||||
|
import net.minecraft.world.chunk.ChunkSection;
|
||||||
|
import net.minecraft.world.chunk.WorldChunk;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
@ -64,6 +70,8 @@ public class EternalRitual {
|
||||||
private final static Block PORTAL = EndBlocks.END_PORTAL_BLOCK;
|
private final static Block PORTAL = EndBlocks.END_PORTAL_BLOCK;
|
||||||
private final static BooleanProperty ACTIVE = BlockProperties.ACTIVE;
|
private final static BooleanProperty ACTIVE = BlockProperties.ACTIVE;
|
||||||
|
|
||||||
|
public final static int SEARCH_RADIUS = calculateSearchSteps(48);
|
||||||
|
|
||||||
private World world;
|
private World world;
|
||||||
private Direction.Axis axis;
|
private Direction.Axis axis;
|
||||||
private Identifier targetWorldId;
|
private Identifier targetWorldId;
|
||||||
|
@ -152,11 +160,14 @@ public class EternalRitual {
|
||||||
int portalId = EndPortals.getPortalIdByItem(itemId);
|
int portalId = EndPortals.getPortalIdByItem(itemId);
|
||||||
activatePortal(world, center, portalId);
|
activatePortal(world, center, portalId);
|
||||||
doEffects((ServerWorld) world, center);
|
doEffects((ServerWorld) world, center);
|
||||||
|
World targetWorld = getTargetWorld(portalId);
|
||||||
|
Identifier worldId = targetWorld.getRegistryKey().getValue();
|
||||||
if (exit == null) {
|
if (exit == null) {
|
||||||
exit = findPortalPos(portalId);
|
initPortal(worldId, portalId);
|
||||||
} else {
|
} else {
|
||||||
World targetWorld = getTargetWorld(portalId);
|
if (!worldId.equals(targetWorldId)) {
|
||||||
if (!checkFrame(targetWorld, exit)) {
|
initPortal(worldId, portalId);
|
||||||
|
} else if (!checkFrame(targetWorld, exit.down())) {
|
||||||
Direction.Axis portalAxis = (Direction.Axis.X == axis) ? Direction.Axis.Z : Direction.Axis.X;
|
Direction.Axis portalAxis = (Direction.Axis.X == axis) ? Direction.Axis.Z : Direction.Axis.X;
|
||||||
generatePortal(targetWorld, exit, portalAxis, portalId);
|
generatePortal(targetWorld, exit, portalAxis, portalId);
|
||||||
}
|
}
|
||||||
|
@ -165,6 +176,11 @@ public class EternalRitual {
|
||||||
this.active = true;
|
this.active = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initPortal(Identifier worldId, int portalId) {
|
||||||
|
targetWorldId = worldId;
|
||||||
|
exit = findPortalPos(portalId);
|
||||||
|
}
|
||||||
|
|
||||||
private void doEffects(ServerWorld serverWorld, BlockPos center) {
|
private void doEffects(ServerWorld serverWorld, BlockPos center) {
|
||||||
Direction moveX, moveY;
|
Direction moveX, moveY;
|
||||||
if (Direction.Axis.X == axis) {
|
if (Direction.Axis.X == axis) {
|
||||||
|
@ -255,22 +271,38 @@ public class EternalRitual {
|
||||||
this.active = false;
|
this.active = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private BlockPos findFrame(World world, BlockPos.Mutable startPos) {
|
||||||
|
List<BlockPos.Mutable> foundPos = findAllBlockPos(world, startPos, (SEARCH_RADIUS >> 4) + 1, FRAME,
|
||||||
|
blockState -> blockState.isOf(FRAME) && !blockState.get(ACTIVE));
|
||||||
|
for(BlockPos.Mutable testPos : foundPos) {
|
||||||
|
if (checkFrame(world, testPos)) {
|
||||||
|
return testPos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private BlockPos findPortalPos(int portalId) {
|
private BlockPos findPortalPos(int portalId) {
|
||||||
targetWorldId = EndPortals.getWorldId(portalId);
|
|
||||||
MinecraftServer server = world.getServer();
|
MinecraftServer server = world.getServer();
|
||||||
ServerWorld targetWorld = (ServerWorld) getTargetWorld(portalId);
|
ServerWorld targetWorld = (ServerWorld) getTargetWorld(portalId);
|
||||||
Registry<DimensionType> registry = Objects.requireNonNull(server).getRegistryManager().getDimensionTypes();
|
Registry<DimensionType> registry = Objects.requireNonNull(server).getRegistryManager().getDimensionTypes();
|
||||||
double multiplier = Objects.requireNonNull(registry.get(targetWorldId)).getCoordinateScale();
|
double multiplier = Objects.requireNonNull(registry.get(targetWorldId)).getCoordinateScale();
|
||||||
BlockPos.Mutable basePos = center.mutableCopy().set(center.getX() / multiplier, center.getY(), center.getZ() / multiplier);
|
BlockPos.Mutable basePos = center.mutableCopy().set(center.getX() / multiplier, center.getY(), center.getZ() / multiplier);
|
||||||
|
BlockPos framePos = findFrame(targetWorld, basePos.mutableCopy());
|
||||||
|
if (framePos != null) {
|
||||||
|
return framePos.up();
|
||||||
|
}
|
||||||
Direction.Axis portalAxis = (Direction.Axis.X == axis) ? Direction.Axis.Z : Direction.Axis.X;
|
Direction.Axis portalAxis = (Direction.Axis.X == axis) ? Direction.Axis.Z : Direction.Axis.X;
|
||||||
int worldCeil = targetWorld.getDimensionHeight() - 1;
|
int worldCeil = targetWorld.getDimensionHeight() - 1;
|
||||||
if (checkIsAreaValid(targetWorld, basePos, portalAxis)) {
|
if (checkIsAreaValid(targetWorld, basePos, portalAxis)) {
|
||||||
EternalRitual.generatePortal(targetWorld, basePos, portalAxis, portalId);
|
generatePortal(targetWorld, basePos, portalAxis, portalId);
|
||||||
return basePos.toImmutable();
|
return basePos.toImmutable();
|
||||||
} else {
|
} else {
|
||||||
Direction direction = Direction.EAST;
|
Direction direction = Direction.EAST;
|
||||||
BlockPos.Mutable checkPos = basePos.mutableCopy();
|
BlockPos.Mutable checkPos = basePos.mutableCopy();
|
||||||
for (int step = 1; step <= 96; step++) {
|
int radius = (int) ((SEARCH_RADIUS / multiplier) + 1);
|
||||||
|
for (int step = 1; step < radius; step++) {
|
||||||
for (int i = 0; i < (step >> 1); i++) {
|
for (int i = 0; i < (step >> 1); i++) {
|
||||||
Chunk chunk = targetWorld.getChunk(checkPos);
|
Chunk chunk = targetWorld.getChunk(checkPos);
|
||||||
if (chunk != null) {
|
if (chunk != null) {
|
||||||
|
@ -340,62 +372,6 @@ public class EternalRitual {
|
||||||
return state.isSolidBlock(world, pos) && state.isFullCube(world, pos);
|
return state.isSolidBlock(world, pos) && state.isFullCube(world, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void generatePortal(World world, BlockPos center, Direction.Axis axis, int portalId) {
|
|
||||||
BlockPos framePos = center.down();
|
|
||||||
Direction moveDir = Direction.Axis.X == axis ? Direction.EAST : Direction.NORTH;
|
|
||||||
BlockState frame = FRAME.getDefaultState().with(ACTIVE, true);
|
|
||||||
FRAME_MAP.forEach(point -> {
|
|
||||||
BlockPos pos = framePos.mutableCopy().move(moveDir, point.x).move(Direction.UP, point.y);
|
|
||||||
world.setBlockState(pos, frame);
|
|
||||||
pos = framePos.mutableCopy().move(moveDir, -point.x).move(Direction.UP, point.y);
|
|
||||||
world.setBlockState(pos, frame);
|
|
||||||
});
|
|
||||||
BlockState portal = PORTAL.getDefaultState().with(EndPortalBlock.AXIS, axis).with(EndPortalBlock.PORTAL, portalId);
|
|
||||||
PORTAL_MAP.forEach(point -> {
|
|
||||||
BlockPos pos = center.mutableCopy().move(moveDir, point.x).move(Direction.UP, point.y);
|
|
||||||
world.setBlockState(pos, portal);
|
|
||||||
pos = center.mutableCopy().move(moveDir, -point.x).move(Direction.UP, point.y);
|
|
||||||
world.setBlockState(pos, portal);
|
|
||||||
});
|
|
||||||
generateBase(world, framePos, moveDir);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void generateBase(World world, BlockPos center, Direction moveX) {
|
|
||||||
BlockState base = BASE.getDefaultState();
|
|
||||||
Direction moveY = moveX.rotateYClockwise();
|
|
||||||
BASE_MAP.forEach(point -> {
|
|
||||||
BlockPos pos = center.mutableCopy().move(moveX, point.x).move(moveY, point.y);
|
|
||||||
world.setBlockState(pos, base);
|
|
||||||
pos = center.mutableCopy().move(moveX, -point.x).move(moveY, point.y);
|
|
||||||
world.setBlockState(pos, base);
|
|
||||||
pos = center.mutableCopy().move(moveX, point.x).move(moveY, -point.y);
|
|
||||||
world.setBlockState(pos, base);
|
|
||||||
pos = center.mutableCopy().move(moveX, -point.x).move(moveY, -point.y);
|
|
||||||
world.setBlockState(pos, base);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean checkArea(World world, BlockPos center, Direction.Axis axis) {
|
|
||||||
Direction moveDir = Direction.Axis.X == axis ? Direction.NORTH : Direction.EAST;
|
|
||||||
for (BlockPos checkPos : BlockPos.iterate(center.offset(moveDir.rotateYClockwise()), center.offset(moveDir.rotateYCounterclockwise()))) {
|
|
||||||
for (Point point : PORTAL_MAP) {
|
|
||||||
BlockPos pos = checkPos.mutableCopy().move(moveDir, point.x).move(Direction.UP, point.y);
|
|
||||||
BlockState state = world.getBlockState(pos);
|
|
||||||
if (isStateInvalid(state)) return false;
|
|
||||||
pos = checkPos.mutableCopy().move(moveDir, -point.x).move(Direction.UP, point.y);
|
|
||||||
state = world.getBlockState(pos);
|
|
||||||
if (isStateInvalid(state)) return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isStateInvalid(BlockState state) {
|
|
||||||
if (!state.getFluidState().isEmpty()) return true;
|
|
||||||
Material material = state.getMaterial();
|
|
||||||
return !material.isReplaceable() && !material.equals(Material.PLANT);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void configure(BlockPos initial) {
|
public void configure(BlockPos initial) {
|
||||||
BlockPos checkPos = initial.east(12);
|
BlockPos checkPos = initial.east(12);
|
||||||
if (this.hasPedestal(checkPos)) {
|
if (this.hasPedestal(checkPos)) {
|
||||||
|
@ -523,4 +499,144 @@ public class EternalRitual {
|
||||||
Objects.equals(center, ritual.center) &&
|
Objects.equals(center, ritual.center) &&
|
||||||
Objects.equals(exit, ritual.exit);
|
Objects.equals(exit, ritual.exit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void generatePortal(World world, BlockPos center, Direction.Axis axis, int portalId) {
|
||||||
|
BlockPos framePos = center.down();
|
||||||
|
Direction moveDir = Direction.Axis.X == axis ? Direction.EAST : Direction.NORTH;
|
||||||
|
BlockState frame = FRAME.getDefaultState().with(ACTIVE, true);
|
||||||
|
FRAME_MAP.forEach(point -> {
|
||||||
|
BlockPos pos = framePos.mutableCopy().move(moveDir, point.x).move(Direction.UP, point.y);
|
||||||
|
world.setBlockState(pos, frame);
|
||||||
|
pos = framePos.mutableCopy().move(moveDir, -point.x).move(Direction.UP, point.y);
|
||||||
|
world.setBlockState(pos, frame);
|
||||||
|
});
|
||||||
|
BlockState portal = PORTAL.getDefaultState().with(EndPortalBlock.AXIS, axis).with(EndPortalBlock.PORTAL, portalId);
|
||||||
|
PORTAL_MAP.forEach(point -> {
|
||||||
|
BlockPos pos = center.mutableCopy().move(moveDir, point.x).move(Direction.UP, point.y);
|
||||||
|
world.setBlockState(pos, portal);
|
||||||
|
pos = center.mutableCopy().move(moveDir, -point.x).move(Direction.UP, point.y);
|
||||||
|
world.setBlockState(pos, portal);
|
||||||
|
});
|
||||||
|
generateBase(world, framePos, moveDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void generateBase(World world, BlockPos center, Direction moveX) {
|
||||||
|
BlockState base = BASE.getDefaultState();
|
||||||
|
Direction moveY = moveX.rotateYClockwise();
|
||||||
|
BASE_MAP.forEach(point -> {
|
||||||
|
BlockPos pos = center.mutableCopy().move(moveX, point.x).move(moveY, point.y);
|
||||||
|
world.setBlockState(pos, base);
|
||||||
|
pos = center.mutableCopy().move(moveX, -point.x).move(moveY, point.y);
|
||||||
|
world.setBlockState(pos, base);
|
||||||
|
pos = center.mutableCopy().move(moveX, point.x).move(moveY, -point.y);
|
||||||
|
world.setBlockState(pos, base);
|
||||||
|
pos = center.mutableCopy().move(moveX, -point.x).move(moveY, -point.y);
|
||||||
|
world.setBlockState(pos, base);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean checkArea(World world, BlockPos center, Direction.Axis axis) {
|
||||||
|
Direction moveDir = Direction.Axis.X == axis ? Direction.NORTH : Direction.EAST;
|
||||||
|
for (BlockPos checkPos : BlockPos.iterate(center.offset(moveDir.rotateYClockwise()), center.offset(moveDir.rotateYCounterclockwise()))) {
|
||||||
|
for (Point point : PORTAL_MAP) {
|
||||||
|
BlockPos pos = checkPos.mutableCopy().move(moveDir, point.x).move(Direction.UP, point.y);
|
||||||
|
BlockState state = world.getBlockState(pos);
|
||||||
|
if (isStateInvalid(state)) return false;
|
||||||
|
pos = checkPos.mutableCopy().move(moveDir, -point.x).move(Direction.UP, point.y);
|
||||||
|
state = world.getBlockState(pos);
|
||||||
|
if (isStateInvalid(state)) return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isStateInvalid(BlockState state) {
|
||||||
|
if (!state.getFluidState().isEmpty()) return true;
|
||||||
|
Material material = state.getMaterial();
|
||||||
|
return !material.isReplaceable() && !material.equals(Material.PLANT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param world World for search
|
||||||
|
* @param checkPos Start search position
|
||||||
|
* @param radius Search radius
|
||||||
|
* @param searchBlock Target block
|
||||||
|
* @param condition Predicate for test block states in the chunk section
|
||||||
|
*
|
||||||
|
* @return Position of the first found block or null.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public static BlockPos.Mutable findBlockPos(World world, BlockPos.Mutable checkPos, int radius, Block searchBlock, Predicate<BlockState> condition) {
|
||||||
|
Direction moveDirection = Direction.EAST;
|
||||||
|
for (int step = 1; step < radius; step++) {
|
||||||
|
for (int i = 0; i < (step >> 1); i++) {
|
||||||
|
Chunk chunk = world.getChunk(checkPos);
|
||||||
|
if (!(chunk instanceof WorldChunk) || ((WorldChunk) chunk).isEmpty()) continue;
|
||||||
|
for (ChunkSection section : chunk.getSectionArray()) {
|
||||||
|
if (section == null || !section.getContainer().hasAny(condition)) continue;
|
||||||
|
for (int x = 0; x < 16; x++) {
|
||||||
|
for (int y = 0; y < 16; y++) {
|
||||||
|
for(int z = 0; z < 16; z++) {
|
||||||
|
BlockState checkState = section.getBlockState(x, y, z);
|
||||||
|
if (checkState.isOf(searchBlock)) {
|
||||||
|
int worldX = (chunk.getPos().x << 4) + x;
|
||||||
|
int worldY = section.getYOffset() + y;
|
||||||
|
int worldZ = (chunk.getPos().z << 4) + z;
|
||||||
|
checkPos.set(worldX, worldY, worldZ);
|
||||||
|
return checkPos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checkPos.move(moveDirection, 16);
|
||||||
|
}
|
||||||
|
moveDirection = moveDirection.rotateYClockwise();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param world World for search
|
||||||
|
* @param checkPos Start search position
|
||||||
|
* @param radius Search radius
|
||||||
|
* @param searchBlock Target block
|
||||||
|
* @param condition Predicate for test block states in the chunk section
|
||||||
|
*
|
||||||
|
* @return List of positions of the all found blocks or empty list.
|
||||||
|
*/
|
||||||
|
public static List<BlockPos.Mutable> findAllBlockPos(World world, BlockPos.Mutable checkPos, int radius, Block searchBlock, Predicate<BlockState> condition) {
|
||||||
|
List<BlockPos.Mutable> posFound = Lists.newArrayList();
|
||||||
|
Direction moveDirection = Direction.EAST;
|
||||||
|
for (int step = 1; step < radius; step++) {
|
||||||
|
for (int i = 0; i < (step >> 1); i++) {
|
||||||
|
Chunk chunk = world.getChunk(checkPos);
|
||||||
|
if (!(chunk instanceof WorldChunk) || ((WorldChunk) chunk).isEmpty()) continue;
|
||||||
|
for (ChunkSection section : chunk.getSectionArray()) {
|
||||||
|
if (section == null || !section.getContainer().hasAny(condition)) continue;
|
||||||
|
for (int x = 0; x < 16; x++) {
|
||||||
|
for (int y = 0; y < 16; y++) {
|
||||||
|
for(int z = 0; z < 16; z++) {
|
||||||
|
BlockState checkState = section.getBlockState(x, y, z);
|
||||||
|
if (checkState.isOf(searchBlock)) {
|
||||||
|
int worldX = (chunk.getPos().x << 4) + x;
|
||||||
|
int worldY = section.getYOffset() + y;
|
||||||
|
int worldZ = (chunk.getPos().z << 4) + z;
|
||||||
|
checkPos.set(worldX, worldY, worldZ);
|
||||||
|
posFound.add(checkPos.mutableCopy());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checkPos.move(moveDirection, 16);
|
||||||
|
}
|
||||||
|
moveDirection = moveDirection.rotateYClockwise();
|
||||||
|
}
|
||||||
|
return posFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int calculateSearchSteps(int radius) {
|
||||||
|
return radius * 4 - 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue