generated from Nekojimi/ForgeModTemplate
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
115 lines
4.6 KiB
115 lines
4.6 KiB
package moe.nekojimi.dimensionwalker;
|
|
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.Direction;
|
|
import net.minecraft.server.level.ServerLevel;
|
|
import net.minecraft.world.entity.Entity;
|
|
import net.minecraft.world.level.block.state.BlockState;
|
|
import net.minecraft.world.level.border.WorldBorder;
|
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
|
import net.minecraft.world.level.levelgen.Heightmap;
|
|
import net.minecraft.world.level.portal.PortalInfo;
|
|
import net.minecraft.world.phys.Vec3;
|
|
import net.minecraftforge.common.util.ITeleporter;
|
|
import org.apache.http.io.SessionOutputBuffer;
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Comparator;
|
|
import java.util.List;
|
|
import java.util.function.Function;
|
|
|
|
public class DimensionwalkerTeleporter implements ITeleporter
|
|
{
|
|
private static DimensionwalkerTeleporter INSTANCE = null;
|
|
|
|
@Override
|
|
public Entity placeEntity(Entity entity, ServerLevel currentWorld, ServerLevel destWorld, float yaw, Function<Boolean, Entity> repositionEntity)
|
|
{
|
|
return repositionEntity.apply(true);
|
|
}
|
|
|
|
@Override
|
|
public @Nullable PortalInfo getPortalInfo(Entity entity, ServerLevel destWorld, Function<ServerLevel, PortalInfo> defaultPortalInfo)
|
|
{
|
|
// return ITeleporter.super.getPortalInfo(entity, destWorld, defaultPortalInfo);
|
|
|
|
BlockPos startPos = new BlockPos(entity.getBlockX(), entity.getBlockY(), entity.getBlockZ());
|
|
System.out.println("Current player position: " + startPos);
|
|
// ChunkAccess chunk = destWorld.getChunk(startPos);
|
|
// int maxHeight = startPos.getY();
|
|
// destWorld.get
|
|
// for (Heightmap.Types type : Heightmap.Types.values())
|
|
// {
|
|
// int height = chunk.getHeight(type,startPos.getX(),startPos.getZ());
|
|
// System.out.println("Heightmap type: " + type.name() + ", height: " + height);
|
|
// if (height > maxHeight)
|
|
// maxHeight = height;
|
|
// }
|
|
BlockPos blockPos = findSafePosition(destWorld,startPos);
|
|
if (blockPos == null)
|
|
blockPos = startPos;
|
|
return new PortalInfo(new Vec3((double)blockPos.getX() + 0.5D, (double)blockPos.getY()+1.0D, (double)blockPos.getZ() + 0.5D), entity.getDeltaMovement(), entity.getYRot(), entity.getXRot());
|
|
}
|
|
|
|
public @Nullable BlockPos findSafePosition(ServerLevel destWorld, BlockPos startPos)
|
|
{
|
|
// List<BlockPos> candidates = new ArrayList<>();
|
|
|
|
WorldBorder worldborder = destWorld.getWorldBorder();
|
|
int worldHeight = Math.min(destWorld.getMaxBuildHeight(), destWorld.getMinBuildHeight() + destWorld.getLogicalHeight()) - 1;
|
|
|
|
outer:
|
|
for (BlockPos.MutableBlockPos pos : BlockPos.spiralAround(startPos, 16, Direction.EAST, Direction.SOUTH))
|
|
{
|
|
if (pos == null)
|
|
return null;
|
|
ChunkAccess chunk = destWorld.getChunk(pos);
|
|
int terrainHeight = chunk.getHeight(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES,pos.getX(),pos.getZ());
|
|
int freeBlocksAbove = 999;
|
|
int startY = Math.min(worldHeight, terrainHeight);
|
|
System.out.println("Starting search for safe destination at Y=" + startY);
|
|
for (int y = startY; y >= destWorld.getMinBuildHeight(); y--)
|
|
{
|
|
pos.setY(y);
|
|
|
|
// check that y is solid
|
|
BlockState blockState = chunk.getBlockState(pos);
|
|
if (blockState.getMaterial().isSolid())
|
|
{
|
|
if (worldborder.isWithinBounds(pos) && y < worldHeight-3 && freeBlocksAbove >= 2)
|
|
{
|
|
System.out.println("Found safe destination! pos: " + pos + " material: " + blockState.getMaterial() + " state: " + blockState);
|
|
return pos;
|
|
// candidates.add(pos);
|
|
// if (candidates.size() >= 16)
|
|
// break outer;
|
|
}
|
|
freeBlocksAbove = 0;
|
|
}
|
|
else if (blockState.getMaterial().isLiquid() || !blockState.isAir())
|
|
{
|
|
freeBlocksAbove = 0; // liquid blocks aren't free
|
|
}
|
|
else
|
|
{
|
|
freeBlocksAbove++;
|
|
}
|
|
}
|
|
}
|
|
// if (candidates.size() > 0)
|
|
// {
|
|
// candidates.sort(Comparator.comparingDouble(a -> a.distSqr(startPos)));
|
|
// return candidates.get(0);
|
|
// }
|
|
|
|
return null;
|
|
}
|
|
|
|
public static ITeleporter instance()
|
|
{
|
|
if (INSTANCE == null)
|
|
INSTANCE = new DimensionwalkerTeleporter();
|
|
return INSTANCE;
|
|
}
|
|
}
|
|
|