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 it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import lombok.Getter;
import lombok.Setter;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.world.block.BlockStateValues;
@ -44,6 +45,13 @@ public class ChunkCache {
@Setter
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) {
this.cache = !session.getConnector().getWorldManager().hasOwnChunkCache(); // To prevent Spigot from initializing
chunks = cache ? new Long2ObjectOpenHashMap<>() : null;

View file

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

View file

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

View file

@ -78,8 +78,6 @@ public class JavaRespawnTranslator extends PacketTranslator<ServerRespawnPacket>
session.setThunder(false);
}
ChunkUtils.applyDimensionHeight(session, packet.getDimension());
String newDimension = DimensionUtils.getNewDimension(packet.getDimension());
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
@ -93,5 +91,7 @@ public class JavaRespawnTranslator extends PacketTranslator<ServerRespawnPacket>
session.setWorldName(packet.getWorldName());
DimensionUtils.switchDimension(session, newDimension);
}
ChunkUtils.applyDimensionHeight(session, packet.getDimension());
}
}

View file

@ -123,7 +123,7 @@ public class ChunkUtils {
BitSet waterloggedPaletteIds = 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++) {
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) {
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!");
}
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"));
}