[Change] Improved Eternal Portal Code

This commit is contained in:
Frank 2023-06-08 23:05:28 +02:00
parent 7f8d8bef0c
commit 9f4999c966
10 changed files with 775 additions and 531 deletions

View file

@ -3,25 +3,15 @@ package org.betterx.betterend.blocks;
import org.betterx.bclib.client.render.BCLRenderLayer;
import org.betterx.bclib.interfaces.CustomColorProvider;
import org.betterx.bclib.interfaces.RenderLayerProvider;
import org.betterx.betterend.advancements.BECriteria;
import org.betterx.betterend.interfaces.TeleportingEntity;
import org.betterx.betterend.portal.TravelingEntity;
import org.betterx.betterend.registry.EndParticles;
import org.betterx.betterend.registry.EndPortals;
import org.betterx.betterend.rituals.EternalRitual;
import net.minecraft.client.color.block.BlockColor;
import net.minecraft.client.color.item.ItemColor;
import net.minecraft.core.BlockPos;
import net.minecraft.core.BlockPos.MutableBlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Direction.Axis;
import net.minecraft.core.Direction.AxisDirection;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.RandomSource;
@ -31,19 +21,14 @@ import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.NetherPortalBlock;
import net.minecraft.world.level.block.Rotation;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.IntegerProperty;
import net.minecraft.world.level.dimension.DimensionType;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import java.util.Objects;
import java.util.Optional;
public class EndPortalBlock extends NetherPortalBlock implements RenderLayerProvider, CustomColorProvider {
public static final IntegerProperty PORTAL = EndBlockProperties.PORTAL;
@ -104,39 +89,16 @@ public class EndPortalBlock extends NetherPortalBlock implements RenderLayerProv
return state;
}
@Override
public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
if (world.isClientSide || !validate(entity)) return;
entity.setPortalCooldown();
ServerLevel currentWorld = (ServerLevel) world;
MinecraftServer server = currentWorld.getServer();
ServerLevel targetWorld = EndPortals.getWorld(server, state.getValue(PORTAL));
boolean isInEnd = currentWorld.dimension().equals(Level.END);
ServerLevel destination = isInEnd ? targetWorld : server.getLevel(Level.END);
BlockPos exitPos = findExitPos(currentWorld, destination, pos, entity);
if (exitPos == null) return;
if (entity instanceof ServerPlayer sp && sp.isCreative()) {
((ServerPlayer) entity).teleportTo(
destination,
exitPos.getX() + 0.5,
exitPos.getY(),
exitPos.getZ() + 0.5,
entity.getYRot(),
entity.getXRot()
);
BECriteria.PORTAL_TRAVEL.trigger(sp);
} else {
if (entity instanceof ServerPlayer sp) {
BECriteria.PORTAL_TRAVEL.trigger(sp);
}
((TeleportingEntity) entity).be_setExitPos(exitPos);
Optional<Entity> teleported = Optional.ofNullable(entity.changeDimension(destination));
teleported.ifPresent(Entity::setPortalCooldown);
if (validate(entity) && entity instanceof TravelingEntity te && te.be_getTravelerState() != null) {
te.be_getTravelerState().handleInsidePortal(pos);
}
}
private boolean validate(Entity entity) {
return !entity.isPassenger() && !entity.isVehicle() && entity.canChangeDimensions() && !entity.isOnPortalCooldown();
return !entity.isPassenger() && !entity.isVehicle() && entity.canChangeDimensions();
}
@Override
@ -144,79 +106,6 @@ public class EndPortalBlock extends NetherPortalBlock implements RenderLayerProv
return BCLRenderLayer.TRANSLUCENT;
}
private BlockPos findExitPos(
ServerLevel currentWorld,
ServerLevel targetWorld,
BlockPos currentPos,
Entity entity
) {
if (targetWorld == null) return null;
Registry<DimensionType> registry = targetWorld.registryAccess()
.registryOrThrow(Registries.DIMENSION_TYPE);
ResourceLocation targetWorldId = targetWorld.dimension().location();
ResourceLocation currentWorldId = currentWorld.dimension().location();
double targetMultiplier = Objects.requireNonNull(registry.get(targetWorldId)).coordinateScale();
double currentMultiplier = Objects.requireNonNull(registry.get(currentWorldId)).coordinateScale();
double multiplier = targetMultiplier > currentMultiplier ? 1.0 / targetMultiplier : currentMultiplier;
MutableBlockPos basePos = currentPos.mutable()
.set(
currentPos.getX() * multiplier,
currentPos.getY(),
currentPos.getZ() * multiplier
);
MutableBlockPos checkPos = basePos.mutable();
BlockState currentState = currentWorld.getBlockState(currentPos);
int radius = (EternalRitual.SEARCH_RADIUS >> 4) + 1;
checkPos = EternalRitual.findBlockPos(
targetWorld,
checkPos,
radius,
this,
state -> state.is(this) && state.getValue(PORTAL).equals(currentState.getValue(PORTAL))
);
if (checkPos != null) {
BlockState checkState = targetWorld.getBlockState(checkPos);
Axis axis = checkState.getValue(AXIS);
checkPos = findCenter(targetWorld, checkPos, axis);
Direction frontDir = Direction.fromAxisAndDirection(axis, AxisDirection.POSITIVE).getClockWise();
Direction entityDir = entity.getMotionDirection();
if (entityDir.getAxis().isVertical()) {
entityDir = frontDir;
}
if (frontDir != entityDir && frontDir.getOpposite() != entityDir) {
entity.rotate(Rotation.CLOCKWISE_90);
entityDir = entityDir.getClockWise();
}
return checkPos.relative(entityDir);
}
return null;
}
private MutableBlockPos findCenter(Level world, MutableBlockPos pos, Direction.Axis axis) {
return findCenter(world, pos, axis, 1);
}
private MutableBlockPos findCenter(Level world, MutableBlockPos pos, Direction.Axis axis, int step) {
if (step > 8) return pos;
BlockState right, left;
Direction rightDir, leftDir;
rightDir = Direction.fromAxisAndDirection(axis, AxisDirection.POSITIVE);
leftDir = rightDir.getOpposite();
right = world.getBlockState(pos.relative(rightDir));
left = world.getBlockState(pos.relative(leftDir));
BlockState down = world.getBlockState(pos.below());
if (down.is(this)) {
return findCenter(world, pos.move(Direction.DOWN), axis, step);
} else if (right.is(this) && left.is(this)) {
return pos;
} else if (right.is(this)) {
return findCenter(world, pos.move(rightDir), axis, ++step);
} else if (left.is(this)) {
return findCenter(world, pos.move(leftDir), axis, ++step);
}
return pos;
}
@Override
public BlockColor getProvider() {
return (state, world, pos, tintIndex) -> EndPortals.getColor(state.getValue(PORTAL));

View file

@ -38,11 +38,11 @@ public class EternalPedestal extends PedestalBlock {
}
@Override
public void checkRitual(Level world, Player player, BlockPos pos) {
BlockEntity blockEntity = world.getBlockEntity(pos);
public void checkRitual(Level sourceLevel, Player player, BlockPos pos) {
BlockEntity blockEntity = sourceLevel.getBlockEntity(pos);
if (blockEntity instanceof EternalPedestalEntity) {
EternalPedestalEntity pedestal = (EternalPedestalEntity) blockEntity;
BlockState updatedState = world.getBlockState(pos);
BlockState updatedState = sourceLevel.getBlockState(pos);
if (pedestal.isEmpty()) {
if (pedestal.hasRitual()) {
EternalRitual ritual = pedestal.getRitual();
@ -57,16 +57,19 @@ public class EternalPedestal extends PedestalBlock {
ritual.disablePortal(portalId);
}
}
world.setBlockAndUpdate(pos, updatedState.setValue(ACTIVATED, false).setValue(HAS_LIGHT, false));
sourceLevel.setBlockAndUpdate(pos, updatedState.setValue(ACTIVATED, false).setValue(HAS_LIGHT, false));
} else {
ItemStack itemStack = pedestal.getItem(0);
ResourceLocation id = BuiltInRegistries.ITEM.getKey(itemStack.getItem());
if (EndPortals.isAvailableItem(id)) {
world.setBlockAndUpdate(pos, updatedState.setValue(ACTIVATED, true).setValue(HAS_LIGHT, true));
sourceLevel.setBlockAndUpdate(
pos,
updatedState.setValue(ACTIVATED, true).setValue(HAS_LIGHT, true)
);
if (pedestal.hasRitual()) {
pedestal.getRitual().checkStructure(player);
} else {
EternalRitual ritual = new EternalRitual(world, pos);
EternalRitual ritual = new EternalRitual(sourceLevel, pos);
ritual.checkStructure(player);
}
}