Ensure overworld constraints are used everywhere

This commit is contained in:
Camotoy 2021-07-14 21:46:56 -04:00
parent feb64e08df
commit d19ff657de
No known key found for this signature in database
GPG key ID: 7EEFB66FE798081F
5 changed files with 27 additions and 14 deletions

View file

@ -29,6 +29,7 @@ import com.github.steveice10.mc.protocol.data.game.chunk.Chunk;
import com.github.steveice10.mc.protocol.data.game.chunk.Column; import com.github.steveice10.mc.protocol.data.game.chunk.Column;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.world.block.BlockStateValues; import org.geysermc.connector.network.translators.world.block.BlockStateValues;
@ -44,6 +45,13 @@ public class ChunkCache {
@Setter @Setter
private int heightY; private int heightY;
/**
* Whether the Bedrock client believes they are in a world with a minimum of -64 and maximum of 320
*/
@Getter
@Setter
private boolean isExtendedHeight = false;
public ChunkCache(GeyserSession session) { public ChunkCache(GeyserSession session) {
this.cache = !session.getConnector().getWorldManager().hasOwnChunkCache(); // To prevent Spigot from initializing this.cache = !session.getConnector().getWorldManager().hasOwnChunkCache(); // To prevent Spigot from initializing
chunks = cache ? new Long2ObjectOpenHashMap<>() : null; chunks = cache ? new Long2ObjectOpenHashMap<>() : null;

View file

@ -44,12 +44,12 @@ import org.geysermc.connector.network.translators.Translator;
@Translator(packet = MovePlayerPacket.class) @Translator(packet = MovePlayerPacket.class)
public class BedrockMovePlayerTranslator extends PacketTranslator<MovePlayerPacket> { public class BedrockMovePlayerTranslator extends PacketTranslator<MovePlayerPacket> {
/* The upper and lower bounds to check for the void floor that only exists in Bedrock */ /* The upper and lower bounds to check for the void floor that only exists in Bedrock */
private static final int BEDROCK_VOID_FLOOR_UPPER_Y; private static final int BEDROCK_OVERWORLD_VOID_FLOOR_UPPER_Y;
private static final int BEDROCK_VOID_FLOOR_LOWER_Y; private static final int BEDROCK_OVERWORLD_VOID_FLOOR_LOWER_Y;
static { static {
BEDROCK_VOID_FLOOR_LOWER_Y = GeyserConnector.getInstance().getConfig().isExtendedWorldHeight() ? -104 : -40; BEDROCK_OVERWORLD_VOID_FLOOR_UPPER_Y = GeyserConnector.getInstance().getConfig().isExtendedWorldHeight() ? -104 : -40;
BEDROCK_VOID_FLOOR_UPPER_Y = BEDROCK_VOID_FLOOR_LOWER_Y + 2; BEDROCK_OVERWORLD_VOID_FLOOR_LOWER_Y = BEDROCK_OVERWORLD_VOID_FLOOR_UPPER_Y + 2;
} }
@Override @Override
@ -117,10 +117,11 @@ public class BedrockMovePlayerTranslator extends PacketTranslator<MovePlayerPack
if (notMovingUp) { if (notMovingUp) {
int floorY = position.getFloorY(); int floorY = position.getFloorY();
if (floorY <= BEDROCK_VOID_FLOOR_LOWER_Y && floorY >= BEDROCK_VOID_FLOOR_UPPER_Y) { boolean overworld = session.getChunkCache().isExtendedHeight();
// Work around there being a floor at Y -40 and teleport the player below it if (floorY <= (overworld ? BEDROCK_OVERWORLD_VOID_FLOOR_LOWER_Y : -38)
&& floorY >= (overworld ? BEDROCK_OVERWORLD_VOID_FLOOR_UPPER_Y : -40)) {
// Work around there being a floor at Y -40 (Y - and teleport the player below it
// Moving from below Y -40 to above the void floor works fine // Moving from below Y -40 to above the void floor works fine
//TODO: This will need to be changed for 1.17
entity.setPosition(entity.getPosition().sub(0, 4f, 0)); entity.setPosition(entity.getPosition().sub(0, 4f, 0));
MovePlayerPacket movePlayerPacket = new MovePlayerPacket(); MovePlayerPacket movePlayerPacket = new MovePlayerPacket();
movePlayerPacket.setRuntimeEntityId(entity.getGeyserId()); movePlayerPacket.setRuntimeEntityId(entity.getGeyserId());

View file

@ -55,8 +55,6 @@ public class JavaJoinGameTranslator extends PacketTranslator<ServerJoinGamePacke
PlayerEntity entity = session.getPlayerEntity(); PlayerEntity entity = session.getPlayerEntity();
entity.setEntityId(packet.getEntityId()); entity.setEntityId(packet.getEntityId());
ChunkUtils.applyDimensionHeight(session, packet.getDimension());
// If the player is already initialized and a join game packet is sent, they // If the player is already initialized and a join game packet is sent, they
// are swapping servers // are swapping servers
String newDimension = DimensionUtils.getNewDimension(packet.getDimension()); String newDimension = DimensionUtils.getNewDimension(packet.getDimension());
@ -113,5 +111,7 @@ public class JavaJoinGameTranslator extends PacketTranslator<ServerJoinGamePacke
if (!newDimension.equals(session.getDimension())) { if (!newDimension.equals(session.getDimension())) {
DimensionUtils.switchDimension(session, newDimension); DimensionUtils.switchDimension(session, newDimension);
} }
ChunkUtils.applyDimensionHeight(session, packet.getDimension());
} }
} }

View file

@ -78,8 +78,6 @@ public class JavaRespawnTranslator extends PacketTranslator<ServerRespawnPacket>
session.setThunder(false); session.setThunder(false);
} }
ChunkUtils.applyDimensionHeight(session, packet.getDimension());
String newDimension = DimensionUtils.getNewDimension(packet.getDimension()); String newDimension = DimensionUtils.getNewDimension(packet.getDimension());
if (!session.getDimension().equals(newDimension) || !packet.getWorldName().equals(session.getWorldName())) { if (!session.getDimension().equals(newDimension) || !packet.getWorldName().equals(session.getWorldName())) {
// Switching to a new world (based off the world name change); send a fake dimension change // Switching to a new world (based off the world name change); send a fake dimension change
@ -93,5 +91,7 @@ public class JavaRespawnTranslator extends PacketTranslator<ServerRespawnPacket>
session.setWorldName(packet.getWorldName()); session.setWorldName(packet.getWorldName());
DimensionUtils.switchDimension(session, newDimension); DimensionUtils.switchDimension(session, newDimension);
} }
ChunkUtils.applyDimensionHeight(session, packet.getDimension());
} }
} }

View file

@ -123,7 +123,7 @@ public class ChunkUtils {
BitSet waterloggedPaletteIds = new BitSet(); BitSet waterloggedPaletteIds = new BitSet();
BitSet pistonOrFlowerPaletteIds = new BitSet(); BitSet pistonOrFlowerPaletteIds = new BitSet();
boolean overworld = session.getDimension().equals(DimensionUtils.OVERWORLD); boolean overworld = session.getChunkCache().isExtendedHeight();
for (int sectionY = 0; sectionY < javaSections.length; sectionY++) { for (int sectionY = 0; sectionY < javaSections.length; sectionY++) {
if (yOffset < ((overworld ? MINIMUM_ACCEPTED_HEIGHT_OVERWORLD : MINIMUM_ACCEPTED_HEIGHT) >> 4) && sectionY < -yOffset) { if (yOffset < ((overworld ? MINIMUM_ACCEPTED_HEIGHT_OVERWORLD : MINIMUM_ACCEPTED_HEIGHT) >> 4) && sectionY < -yOffset) {
@ -434,7 +434,8 @@ public class ChunkUtils {
} }
/** /**
* Process the minimum and maximum heights for this dimension * Process the minimum and maximum heights for this dimension.
* This must be done after the player has switched dimensions so we know what their dimension is
*/ */
public static void applyDimensionHeight(GeyserSession session, CompoundTag dimensionTag) { public static void applyDimensionHeight(GeyserSession session, CompoundTag dimensionTag) {
int minY = ((IntTag) dimensionTag.get("min_y")).getValue(); int minY = ((IntTag) dimensionTag.get("min_y")).getValue();
@ -448,7 +449,10 @@ public class ChunkUtils {
throw new RuntimeException("Maximum Y must be a multiple of 16!"); throw new RuntimeException("Maximum Y must be a multiple of 16!");
} }
if (minY < MINIMUM_ACCEPTED_HEIGHT || maxY > MAXIMUM_ACCEPTED_HEIGHT) { session.getChunkCache().setExtendedHeight(DimensionUtils.javaToBedrock(session.getDimension()) == 0 && session.getConnector().getConfig().isExtendedWorldHeight());
if (minY < (session.getChunkCache().isExtendedHeight() ? MINIMUM_ACCEPTED_HEIGHT_OVERWORLD : MINIMUM_ACCEPTED_HEIGHT)
|| maxY > (session.getChunkCache().isExtendedHeight() ? MAXIMUM_ACCEPTED_HEIGHT_OVERWORLD : MAXIMUM_ACCEPTED_HEIGHT)) {
session.getConnector().getLogger().warning(LanguageUtils.getLocaleStringLog("geyser.network.translator.chunk.out_of_bounds")); session.getConnector().getLogger().warning(LanguageUtils.getLocaleStringLog("geyser.network.translator.chunk.out_of_bounds"));
} }