Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for extended world height #5002

Merged
merged 8 commits into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions core/src/main/java/org/geysermc/geyser/level/BedrockDimension.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,18 @@
* @param height The maximum chunk height Bedrock Edition will accept, from the lowest point to the highest.
* @param doUpperHeightWarn whether to warn in the console if the Java dimension height exceeds Bedrock's.
*/
public record BedrockDimension(int minY, int height, boolean doUpperHeightWarn) {
public static final BedrockDimension OVERWORLD = new BedrockDimension(-64, 384, true);
public static final BedrockDimension THE_NETHER = new BedrockDimension(0, 128, false);
public static final BedrockDimension THE_END = new BedrockDimension(0, 256, true);
public record BedrockDimension(int minY, int height, boolean doUpperHeightWarn, int bedrockId) {

public static final int OVERWORLD_ID = 0;
public static final int DEFAULT_NETHER_ID = 1;
public static final int END_ID = 2;

public static final BedrockDimension OVERWORLD = new BedrockDimension(-64, 384, true, OVERWORLD_ID);
public static final BedrockDimension THE_NETHER = new BedrockDimension(0, 128, false, DEFAULT_NETHER_ID);
public static final BedrockDimension THE_END = new BedrockDimension(0, 256, true, END_ID);
RaphiMC marked this conversation as resolved.
Show resolved Hide resolved

public int maxY() {
return minY + height;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
import org.cloudburstmc.protocol.bedrock.data.command.CommandEnumData;
import org.cloudburstmc.protocol.bedrock.data.command.CommandPermission;
import org.cloudburstmc.protocol.bedrock.data.command.SoftEnumUpdateType;
import org.cloudburstmc.protocol.bedrock.data.definitions.DimensionDefinition;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.cloudburstmc.protocol.bedrock.packet.AvailableEntityIdentifiersPacket;
Expand All @@ -82,6 +83,7 @@
import org.cloudburstmc.protocol.bedrock.packet.ClientboundCloseFormPacket;
import org.cloudburstmc.protocol.bedrock.packet.CraftingDataPacket;
import org.cloudburstmc.protocol.bedrock.packet.CreativeContentPacket;
import org.cloudburstmc.protocol.bedrock.packet.DimensionDataPacket;
import org.cloudburstmc.protocol.bedrock.packet.EmoteListPacket;
import org.cloudburstmc.protocol.bedrock.packet.GameRulesChangedPacket;
import org.cloudburstmc.protocol.bedrock.packet.ItemComponentPacket;
Expand Down Expand Up @@ -383,6 +385,11 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
@Setter
private boolean sprinting;

/**
* The overworld dimension which Bedrock Edition uses.
*/
@Getter
private BedrockDimension bedrockOverworldDimension = BedrockDimension.OVERWORLD;
RaphiMC marked this conversation as resolved.
Show resolved Hide resolved
/**
* The dimension of the player.
* As all entities are in the same world, this can be safely applied to all other entities.
Expand All @@ -396,7 +403,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
* right before the StartGamePacket is sent.
*/
@Setter
private BedrockDimension bedrockDimension = BedrockDimension.OVERWORLD;
private BedrockDimension bedrockDimension = this.bedrockOverworldDimension;

@Setter
private int breakingBlock;
Expand Down Expand Up @@ -706,6 +713,17 @@ public GeyserSession(GeyserImpl geyser, BedrockServerSession bedrockServerSessio
* Send all necessary packets to load Bedrock into the server
*/
public void connect() {
if (this.dimensionType.minY() < BedrockDimension.OVERWORLD.minY() || this.dimensionType.maxY() > BedrockDimension.OVERWORLD.maxY()) {
final int minY = Math.max(this.dimensionType.minY(), -512);
final int maxY = Math.min(this.dimensionType.maxY(), 512);
this.bedrockOverworldDimension = new BedrockDimension(minY, maxY - minY, true, BedrockDimension.OVERWORLD_ID);
this.bedrockDimension = this.bedrockOverworldDimension;

final DimensionDataPacket dimensionDataPacket = new DimensionDataPacket();
dimensionDataPacket.getDefinitions().add(new DimensionDefinition("minecraft:overworld", maxY, minY, 5));
upstream.sendPacket(dimensionDataPacket);
}
RaphiMC marked this conversation as resolved.
Show resolved Hide resolved

startGame();
sentSpawnPacket = true;
syncEntityProperties();
Expand Down
32 changes: 13 additions & 19 deletions core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,6 @@ public class DimensionUtils {

public static final String NETHER_IDENTIFIER = "minecraft:the_nether";

private static final int BEDROCK_OVERWORLD_ID = 0;
private static final int BEDROCK_DEFAULT_NETHER_ID = 1;
private static final int BEDROCK_END_ID = 2;

public static void switchDimension(GeyserSession session, JavaDimension javaDimension) {
switchDimension(session, javaDimension, javaDimension.bedrockId());
}
Expand Down Expand Up @@ -180,19 +176,17 @@ private static void finalizeDimensionSwitch(GeyserSession session, Entity player

public static void setBedrockDimension(GeyserSession session, int bedrockDimension) {
session.setBedrockDimension(switch (bedrockDimension) {
case BEDROCK_END_ID -> BedrockDimension.THE_END;
case BEDROCK_DEFAULT_NETHER_ID -> BedrockDimension.THE_NETHER; // JavaDimension *should* be set to BEDROCK_END_ID if the Nether workaround is enabled.
default -> BedrockDimension.OVERWORLD;
case BedrockDimension.END_ID -> BedrockDimension.THE_END;
case BedrockDimension.DEFAULT_NETHER_ID -> BedrockDimension.THE_NETHER; // JavaDimension *should* be set to BEDROCK_END_ID if the Nether workaround is enabled.
default -> session.getBedrockOverworldDimension();
});
}

public static int javaToBedrock(BedrockDimension dimension) {
if (dimension == BedrockDimension.THE_NETHER) {
if (dimension.bedrockId() == BedrockDimension.DEFAULT_NETHER_ID) {
return BEDROCK_NETHER_ID;
} else if (dimension == BedrockDimension.THE_END) {
return BEDROCK_END_ID;
} else {
return BEDROCK_OVERWORLD_ID;
} else {
return dimension.bedrockId();
}
}

Expand All @@ -205,8 +199,8 @@ public static int javaToBedrock(BedrockDimension dimension) {
public static int javaToBedrock(String javaDimension) {
return switch (javaDimension) {
case NETHER_IDENTIFIER -> BEDROCK_NETHER_ID;
case "minecraft:the_end" -> 2;
default -> 0;
case "minecraft:the_end" -> BedrockDimension.END_ID;
default -> BedrockDimension.OVERWORLD_ID;
};
}

Expand All @@ -216,7 +210,7 @@ public static int javaToBedrock(String javaDimension) {
public static int javaToBedrock(GeyserSession session) {
JavaDimension dimension = session.getDimensionType();
if (dimension == null) {
return BEDROCK_OVERWORLD_ID;
return BedrockDimension.OVERWORLD_ID;
}
return dimension.bedrockId();
}
Expand All @@ -229,7 +223,7 @@ public static int javaToBedrock(GeyserSession session) {
*/
public static void changeBedrockNetherId(boolean isAboveNetherBedrockBuilding) {
// Change dimension ID to the End to allow for building above Bedrock
BEDROCK_NETHER_ID = isAboveNetherBedrockBuilding ? BEDROCK_END_ID : BEDROCK_DEFAULT_NETHER_ID;
BEDROCK_NETHER_ID = isAboveNetherBedrockBuilding ? BedrockDimension.END_ID : BedrockDimension.DEFAULT_NETHER_ID;
}

/**
Expand All @@ -243,14 +237,14 @@ public static void changeBedrockNetherId(boolean isAboveNetherBedrockBuilding) {
public static int getTemporaryDimension(int currentBedrockDimension, int newBedrockDimension) {
if (isCustomBedrockNetherId()) {
// Prevents rare instances of Bedrock locking up
return newBedrockDimension == BEDROCK_END_ID ? BEDROCK_OVERWORLD_ID : BEDROCK_END_ID;
return newBedrockDimension == BedrockDimension.END_ID ? BedrockDimension.OVERWORLD_ID : BedrockDimension.END_ID;
}
// Check current Bedrock dimension and not just the Java dimension.
// Fixes rare instances like https://github.com/GeyserMC/Geyser/issues/3161
return currentBedrockDimension == BEDROCK_OVERWORLD_ID ? BEDROCK_DEFAULT_NETHER_ID : BEDROCK_OVERWORLD_ID;
return currentBedrockDimension == BedrockDimension.OVERWORLD_ID ? BedrockDimension.DEFAULT_NETHER_ID : BedrockDimension.OVERWORLD_ID;
}

public static boolean isCustomBedrockNetherId() {
return BEDROCK_NETHER_ID == BEDROCK_END_ID;
return BEDROCK_NETHER_ID == BedrockDimension.END_ID;
}
}