From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Aikar Date: Wed, 4 Jul 2018 15:22:06 -0400 Subject: [PATCH] Configurable Bed Search Radius Allows you to increase how far to check for a safe place to respawn a player near their bed, allowing a better chance to respawn the player at their bed should it of became obstructed. Defaults to vanilla 1. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -0,0 +0,0 @@ public class PaperWorldConfig { private void scanForLegacyEnderDragon() { scanForLegacyEnderDragon = getBoolean("game-mechanics.scan-for-legacy-ender-dragon", true); } + + public int bedSearchRadius = 1; + private void bedSearchRadius() { + bedSearchRadius = getInt("bed-search-radius", 1); + if (bedSearchRadius < 1) { + bedSearchRadius = 1; + } + if (bedSearchRadius > 1) { + log("Bed Search Radius: " + bedSearchRadius); + } + } } diff --git a/src/main/java/net/minecraft/server/BlockBed.java b/src/main/java/net/minecraft/server/BlockBed.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/BlockBed.java +++ b/src/main/java/net/minecraft/server/BlockBed.java @@ -0,0 +0,0 @@ public class BlockBed extends BlockFacingHorizontal implements ITileEntity { public static Optional a(EntityTypes entitytypes, IWorldReader iworldreader, BlockPosition blockposition, int i) { EnumDirection enumdirection = (EnumDirection) iworldreader.getType(blockposition).get(BlockBed.FACING); + // Paper start - configurable bed search radius + if (entitytypes == EntityTypes.PLAYER) return findSafePosition(entitytypes, (World) iworldreader, enumdirection, blockposition); int j = blockposition.getX(); int k = blockposition.getY(); int l = blockposition.getZ(); @@ -0,0 +0,0 @@ public class BlockBed extends BlockFacingHorizontal implements ITileEntity { return Optional.empty(); } - public static Optional a(EntityTypes entitytypes, IWorldReader iworldreader, BlockPosition blockposition) { + private static Optional findSafePosition(EntityTypes entitytypes, World world, EnumDirection updirection, BlockPosition blockposition){ + int radius = world.paperConfig.bedSearchRadius; + double angle = Math.PI / 2; + int tmpX = (int)(updirection.getAdjacentX() * Math.cos(angle) - updirection.getAdjacentZ() * Math.sin(angle)); + int tmpZ = (int)(updirection.getAdjacentX() * Math.sin(angle) + updirection.getAdjacentZ() * Math.cos(angle)); + + EnumDirection rightDirection = EnumDirection.a(tmpX, 0, tmpZ); + EnumDirection downDirection = updirection.opposite(); + EnumDirection leftDirection = rightDirection.opposite(); + + EnumDirection[] corePositionOutDirection = new EnumDirection[6]; + corePositionOutDirection[0] = updirection; + corePositionOutDirection[1] = leftDirection; + corePositionOutDirection[2] = leftDirection; + corePositionOutDirection[3] = downDirection; + corePositionOutDirection[4] = rightDirection; + corePositionOutDirection[5] = rightDirection; + + BlockPosition[] corePosition = new BlockPosition[6]; + corePosition[0] = blockposition.add(updirection.getAdjacentX(), 0, updirection.getAdjacentZ()); + corePosition[1] = blockposition.add(leftDirection.getAdjacentX(), 0, leftDirection.getAdjacentZ()); + corePosition[2] = corePosition[1].add(downDirection.getAdjacentX(), 0, downDirection.getAdjacentZ()); + corePosition[3] = blockposition.add(2 * downDirection.getAdjacentX(), 0, 2 * downDirection.getAdjacentZ()); + corePosition[5] = blockposition.add(rightDirection.getAdjacentX(), 0, rightDirection.getAdjacentZ()); + corePosition[4] = corePosition[5].add(downDirection.getAdjacentX(), 0, downDirection.getAdjacentZ()); + + BlockPosition[] tmpPosition = new BlockPosition[8]; + EnumDirection[] tmpPositionDirection = new EnumDirection[8]; + tmpPositionDirection[0] = rightDirection; + tmpPositionDirection[1] = leftDirection; + tmpPositionDirection[2] = updirection; + tmpPositionDirection[3] = downDirection; + tmpPositionDirection[4] = leftDirection; + tmpPositionDirection[5] = rightDirection; + tmpPositionDirection[6] = downDirection; + tmpPositionDirection[7] = updirection; + + BlockPosition pos; + Optional vector; + for (int r = 1; r <= radius; r++) { + int h = 0; + while (h <= 1) { + int numIterated = 0; + for (int index = (int)(Math.random() * corePosition.length); numIterated < corePosition.length; index = (index+1) % corePosition.length) { + numIterated++; + + pos = corePosition[index].add(0, h, 0); + vector = isSafeRespawn(entitytypes, world, pos, 0); + if (vector.isPresent()) { + return vector; + } + } + tmpPosition[0] = corePosition[0].add(0, h, 0); + tmpPosition[1] = corePosition[0].add(0, h, 0); + tmpPosition[2] = corePosition[1].add(0, h, 0); + tmpPosition[3] = corePosition[2].add(0, h, 0); + tmpPosition[4] = corePosition[3].add(0, h, 0); + tmpPosition[5] = corePosition[3].add(0, h, 0); + tmpPosition[6] = corePosition[4].add(0, h, 0); + tmpPosition[7] = corePosition[5].add(0, h, 0); + for (int rr = 1; rr <= r; rr++){ + numIterated = 0; + for (int index = (int)(Math.random() * tmpPosition.length); numIterated < tmpPosition.length; index = (index+1) % tmpPosition.length) { + numIterated++; + tmpPosition[index] = tmpPosition[index].add(tmpPositionDirection[index].getAdjacentX(), 0, tmpPositionDirection[index].getAdjacentZ()); + pos = tmpPosition[index]; + + vector = isSafeRespawn(entitytypes, world, pos, 0); + if (vector.isPresent()) { + return vector; + } + } + } + switch (h) { + case 0: + h = -1; + break; + case -1: + h = -2; + break; + case -2: + h = Integer.MAX_VALUE; + break; + } + } + for (int index = 0; index < corePosition.length; index++) { + EnumDirection tmp = corePositionOutDirection[index]; + corePosition[index] = corePosition[index].add(tmp.getAdjacentX(), 0, tmp.getAdjacentZ()); + } + } + return Optional.empty(); + } + // Paper end + + // Paper start -- add maxBelow param + public static Optional a(EntityTypes entitytypes, IWorldReader iworldreader, BlockPosition blockposition) { return isSafeRespawn(entitytypes, iworldreader, blockposition, 2); } + public static Optional isSafeRespawn(EntityTypes entitytypes, IWorldReader iworldreader, BlockPosition blockposition, int maxBelow) { + // Paper end VoxelShape voxelshape = iworldreader.getType(blockposition).getCollisionShape(iworldreader, blockposition); if (voxelshape.c(EnumDirection.EnumAxis.Y) > 0.4375D) { @@ -0,0 +0,0 @@ public class BlockBed extends BlockFacingHorizontal implements ITileEntity { } else { BlockPosition.MutableBlockPosition blockposition_mutableblockposition = blockposition.i(); - while (blockposition_mutableblockposition.getY() >= 0 && blockposition.getY() - blockposition_mutableblockposition.getY() <= 2 && iworldreader.getType(blockposition_mutableblockposition).getCollisionShape(iworldreader, blockposition_mutableblockposition).isEmpty()) { + while (blockposition_mutableblockposition.getY() >= 0 && blockposition.getY() - blockposition_mutableblockposition.getY() <= maxBelow && iworldreader.getType(blockposition_mutableblockposition).getCollisionShape(iworldreader, blockposition_mutableblockposition).isEmpty()) { // Paper -- configurable max distance to search below blockposition_mutableblockposition.c(EnumDirection.DOWN); }