mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-12-22 22:45:04 +01:00
Fix #4837 by not hardcoding dimension IDs
This commit is contained in:
parent
93b0a61265
commit
6e0bad3c40
12 changed files with 135 additions and 98 deletions
|
@ -30,7 +30,11 @@ import org.cloudburstmc.math.vector.Vector3f;
|
|||
import org.cloudburstmc.protocol.bedrock.data.ParticleType;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.*;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.AddEntityPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.PlaySoundPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.SpawnParticleEffectPacket;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.entity.type.Tickable;
|
||||
import org.geysermc.geyser.entity.type.living.MobEntity;
|
||||
|
@ -260,7 +264,7 @@ public class EnderDragonEntity extends MobEntity implements Tickable {
|
|||
// so we need to manually spawn particles
|
||||
for (int i = 0; i < 8; i++) {
|
||||
SpawnParticleEffectPacket spawnParticleEffectPacket = new SpawnParticleEffectPacket();
|
||||
spawnParticleEffectPacket.setDimensionId(DimensionUtils.javaToBedrock(session.getDimension()));
|
||||
spawnParticleEffectPacket.setDimensionId(DimensionUtils.javaToBedrock(session));
|
||||
spawnParticleEffectPacket.setPosition(head.getPosition().add(random.nextGaussian() / 2f, random.nextGaussian() / 2f, random.nextGaussian() / 2f));
|
||||
spawnParticleEffectPacket.setIdentifier("minecraft:dragon_breath_fire");
|
||||
spawnParticleEffectPacket.setMolangVariablesJson(Optional.empty());
|
||||
|
|
|
@ -25,15 +25,17 @@
|
|||
|
||||
package org.geysermc.geyser.level;
|
||||
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.geysermc.geyser.session.cache.registry.RegistryEntryContext;
|
||||
import org.geysermc.geyser.util.DimensionUtils;
|
||||
|
||||
/**
|
||||
* Represents the information we store from the current Java dimension
|
||||
* @param piglinSafe Whether piglins and hoglins are safe from conversion in this dimension.
|
||||
* This controls if they have the shaking effect applied in the dimension.
|
||||
*/
|
||||
public record JavaDimension(int minY, int maxY, boolean piglinSafe, double worldCoordinateScale) {
|
||||
public record JavaDimension(int minY, int maxY, boolean piglinSafe, double worldCoordinateScale, int bedrockId, boolean isNetherLike) {
|
||||
|
||||
public static JavaDimension read(RegistryEntryContext entry) {
|
||||
NbtMap dimension = entry.data();
|
||||
|
@ -46,6 +48,22 @@ public record JavaDimension(int minY, int maxY, boolean piglinSafe, double world
|
|||
// Load world coordinate scale for the world border
|
||||
double coordinateScale = dimension.getDouble("coordinate_scale");
|
||||
|
||||
return new JavaDimension(minY, maxY, piglinSafe, coordinateScale);
|
||||
boolean isNetherLike;
|
||||
// Cache the Bedrock version of this dimension, and base it off the ID - THE ID CAN CHANGE!!!
|
||||
// https://github.com/GeyserMC/Geyser/issues/4837
|
||||
int bedrockId;
|
||||
Key id = entry.id();
|
||||
if ("minecraft".equals(id.namespace())) {
|
||||
String identifier = id.asString();
|
||||
bedrockId = DimensionUtils.javaToBedrock(identifier);
|
||||
isNetherLike = DimensionUtils.NETHER_IDENTIFIER.equals(identifier);
|
||||
} else {
|
||||
// Effects should give is a clue on how this (custom) dimension is supposed to look like
|
||||
String effects = dimension.getString("effects");
|
||||
bedrockId = DimensionUtils.javaToBedrock(effects);
|
||||
isNetherLike = DimensionUtils.NETHER_IDENTIFIER.equals(effects);
|
||||
}
|
||||
|
||||
return new JavaDimension(minY, maxY, piglinSafe, coordinateScale, bedrockId, isNetherLike);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -312,8 +312,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||
* The dimension of the player.
|
||||
* As all entities are in the same world, this can be safely applied to all other entities.
|
||||
*/
|
||||
@Setter
|
||||
private int dimension = DimensionUtils.OVERWORLD;
|
||||
@MonotonicNonNull
|
||||
@Setter
|
||||
private JavaDimension dimensionType = null;
|
||||
|
|
|
@ -27,6 +27,7 @@ package org.geysermc.geyser.translator.protocol.java;
|
|||
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.erosion.Constants;
|
||||
import org.geysermc.geyser.level.JavaDimension;
|
||||
import org.geysermc.geyser.util.MinecraftKey;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.PlayerSpawnInfo;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.common.serverbound.ServerboundCustomPayloadPacket;
|
||||
|
@ -65,12 +66,15 @@ public class JavaLoginTranslator extends PacketTranslator<ClientboundLoginPacket
|
|||
}
|
||||
|
||||
PlayerSpawnInfo spawnInfo = packet.getCommonPlayerSpawnInfo();
|
||||
JavaDimension newDimension = session.getRegistryCache().dimensions().byId(spawnInfo.getDimension());
|
||||
boolean forceDimSwitch = false;
|
||||
|
||||
// If the player is already initialized and a join game packet is sent, they
|
||||
// are swapping servers
|
||||
if (session.isSpawned()) {
|
||||
int fakeDim = DimensionUtils.getTemporaryDimension(session.getDimension(), spawnInfo.getDimension());
|
||||
DimensionUtils.switchDimension(session, fakeDim);
|
||||
int fakeDim = DimensionUtils.getTemporaryDimension(session.getDimensionType().bedrockId(), newDimension.bedrockId());
|
||||
DimensionUtils.fastSwitchDimension(session, fakeDim);
|
||||
forceDimSwitch = true;
|
||||
|
||||
session.getWorldCache().removeScoreboard();
|
||||
|
||||
|
@ -103,13 +107,12 @@ public class JavaLoginTranslator extends PacketTranslator<ClientboundLoginPacket
|
|||
session.setWorldName(spawnInfo.getWorldName());
|
||||
session.setLevels(Arrays.stream(packet.getWorldNames()).map(Key::asString).toArray(String[]::new));
|
||||
session.setGameMode(spawnInfo.getGameMode());
|
||||
int newDimension = spawnInfo.getDimension();
|
||||
|
||||
boolean needsSpawnPacket = !session.isSentSpawnPacket();
|
||||
if (needsSpawnPacket) {
|
||||
// The player has yet to spawn so let's do that using some of the information in this Java packet
|
||||
session.setDimension(newDimension);
|
||||
DimensionUtils.setBedrockDimension(session, newDimension);
|
||||
session.setDimensionType(newDimension);
|
||||
DimensionUtils.setBedrockDimension(session, newDimension.bedrockId());
|
||||
session.connect();
|
||||
|
||||
// It is now safe to send these packets
|
||||
|
@ -143,9 +146,9 @@ public class JavaLoginTranslator extends PacketTranslator<ClientboundLoginPacket
|
|||
}
|
||||
session.sendDownstreamPacket(new ServerboundCustomPayloadPacket(register, Constants.PLUGIN_MESSAGE.getBytes(StandardCharsets.UTF_8)));
|
||||
|
||||
if (newDimension != session.getDimension()) {
|
||||
if (newDimension != session.getDimensionType() || forceDimSwitch) {
|
||||
DimensionUtils.switchDimension(session, newDimension);
|
||||
} else if (DimensionUtils.isCustomBedrockNetherId() && newDimension == DimensionUtils.NETHER) {
|
||||
} else if (DimensionUtils.isCustomBedrockNetherId() && newDimension.isNetherLike()) {
|
||||
// If the player is spawning into the "fake" nether, send them some fog
|
||||
session.camera().sendFog(DimensionUtils.BEDROCK_FOG_HELL);
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket;
|
|||
import org.cloudburstmc.protocol.bedrock.packet.SetPlayerGameTypePacket;
|
||||
import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
|
||||
import org.geysermc.geyser.entity.type.player.SessionPlayerEntity;
|
||||
import org.geysermc.geyser.level.JavaDimension;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
|
@ -92,12 +93,12 @@ public class JavaRespawnTranslator extends PacketTranslator<ClientboundRespawnPa
|
|||
session.setThunder(false);
|
||||
}
|
||||
|
||||
int newDimension = spawnInfo.getDimension();
|
||||
if (session.getDimension() != newDimension || !spawnInfo.getWorldName().equals(session.getWorldName())) {
|
||||
JavaDimension newDimension = session.getRegistryCache().dimensions().byId(spawnInfo.getDimension());
|
||||
if (session.getDimensionType() != newDimension || !spawnInfo.getWorldName().equals(session.getWorldName())) {
|
||||
// Switching to a new world (based off the world name change or new dimension); send a fake dimension change
|
||||
if (DimensionUtils.javaToBedrock(session.getDimension()) == DimensionUtils.javaToBedrock(newDimension)) {
|
||||
int fakeDim = DimensionUtils.getTemporaryDimension(session.getDimension(), newDimension);
|
||||
DimensionUtils.switchDimension(session, fakeDim);
|
||||
if (session.getDimensionType().bedrockId() == newDimension.bedrockId()) {
|
||||
int fakeDim = DimensionUtils.getTemporaryDimension(session.getDimensionType().bedrockId(), newDimension.bedrockId());
|
||||
DimensionUtils.fastSwitchDimension(session, fakeDim);
|
||||
}
|
||||
session.setWorldName(spawnInfo.getWorldName());
|
||||
DimensionUtils.switchDimension(session, newDimension);
|
||||
|
|
|
@ -92,7 +92,7 @@ public class JavaAnimateTranslator extends PacketTranslator<ClientboundAnimatePa
|
|||
// Spawn custom particle
|
||||
SpawnParticleEffectPacket stringPacket = new SpawnParticleEffectPacket();
|
||||
stringPacket.setIdentifier("geyseropt:enchanted_hit_multiple");
|
||||
stringPacket.setDimensionId(DimensionUtils.javaToBedrock(session.getDimension()));
|
||||
stringPacket.setDimensionId(DimensionUtils.javaToBedrock(session));
|
||||
stringPacket.setPosition(Vector3f.ZERO);
|
||||
stringPacket.setUniqueEntityId(entity.getGeyserId());
|
||||
stringPacket.setMolangVariablesJson(Optional.empty());
|
||||
|
|
|
@ -28,7 +28,6 @@ package org.geysermc.geyser.translator.protocol.java.level;
|
|||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.cloudburstmc.math.vector.Vector3i;
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.protocol.bedrock.data.LevelEvent;
|
||||
import org.cloudburstmc.protocol.bedrock.data.ParticleType;
|
||||
import org.cloudburstmc.protocol.bedrock.data.SoundEvent;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.LevelEventGenericPacket;
|
||||
|
@ -481,7 +480,7 @@ public class JavaLevelEventTranslator extends PacketTranslator<ClientboundLevelE
|
|||
}
|
||||
|
||||
private static void spawnOminousTrialSpawnerParticles(GeyserSession session, Vector3f pos) {
|
||||
int dimensionId = DimensionUtils.javaToBedrock(session.getDimension());
|
||||
int dimensionId = DimensionUtils.javaToBedrock(session);
|
||||
SpawnParticleEffectPacket stringPacket = new SpawnParticleEffectPacket();
|
||||
stringPacket.setIdentifier("minecraft:trial_spawner_detection_ominous");
|
||||
stringPacket.setDimensionId(dimensionId);
|
||||
|
|
|
@ -191,7 +191,7 @@ public class JavaLevelParticlesTranslator extends PacketTranslator<ClientboundLe
|
|||
return packet;
|
||||
};
|
||||
} else if (particleMapping.identifier() != null) {
|
||||
int dimensionId = DimensionUtils.javaToBedrock(session.getDimension());
|
||||
int dimensionId = DimensionUtils.javaToBedrock(session);
|
||||
return (position) -> {
|
||||
SpawnParticleEffectPacket stringPacket = new SpawnParticleEffectPacket();
|
||||
stringPacket.setIdentifier(particleMapping.identifier());
|
||||
|
|
|
@ -46,7 +46,7 @@ public class JavaMapItemDataTranslator extends PacketTranslator<ClientboundMapIt
|
|||
org.cloudburstmc.protocol.bedrock.packet.ClientboundMapItemDataPacket mapItemDataPacket = new org.cloudburstmc.protocol.bedrock.packet.ClientboundMapItemDataPacket();
|
||||
|
||||
mapItemDataPacket.setUniqueMapId(packet.getMapId());
|
||||
mapItemDataPacket.setDimensionId(DimensionUtils.javaToBedrock(session.getDimension()));
|
||||
mapItemDataPacket.setDimensionId(DimensionUtils.javaToBedrock(session));
|
||||
mapItemDataPacket.setLocked(packet.isLocked());
|
||||
mapItemDataPacket.setOrigin(Vector3i.ZERO); // Required since 1.19.20
|
||||
mapItemDataPacket.setScale(packet.getScale());
|
||||
|
|
|
@ -39,7 +39,7 @@ public class JavaSetDefaultSpawnPositionTranslator extends PacketTranslator<Clie
|
|||
public void translate(GeyserSession session, ClientboundSetDefaultSpawnPositionPacket packet) {
|
||||
SetSpawnPositionPacket spawnPositionPacket = new SetSpawnPositionPacket();
|
||||
spawnPositionPacket.setBlockPosition(packet.getPosition());
|
||||
spawnPositionPacket.setDimensionId(DimensionUtils.javaToBedrock(session.getDimension()));
|
||||
spawnPositionPacket.setDimensionId(DimensionUtils.javaToBedrock(session));
|
||||
spawnPositionPacket.setSpawnType(SetSpawnPositionPacket.Type.WORLD_SPAWN);
|
||||
session.sendUpstreamPacket(spawnPositionPacket);
|
||||
}
|
||||
|
|
|
@ -203,8 +203,7 @@ public class ChunkUtils {
|
|||
* This must be done after the player has switched dimensions so we know what their dimension is
|
||||
*/
|
||||
public static void loadDimension(GeyserSession session) {
|
||||
JavaDimension dimension = session.getRegistryCache().dimensions().byId(session.getDimension());
|
||||
session.setDimensionType(dimension);
|
||||
JavaDimension dimension = session.getDimensionType();
|
||||
int minY = dimension.minY();
|
||||
int maxY = dimension.maxY();
|
||||
|
||||
|
@ -223,7 +222,7 @@ public class ChunkUtils {
|
|||
session.getGeyser().getLogger().warning(GeyserLocale.getLocaleStringLog("geyser.network.translator.chunk.out_of_bounds",
|
||||
String.valueOf(bedrockDimension.minY()),
|
||||
String.valueOf(bedrockDimension.height()),
|
||||
session.getDimension()));
|
||||
session.getRegistryCache().dimensions().byValue(session.getDimensionType())));
|
||||
}
|
||||
|
||||
session.getChunkCache().setMinY(minY);
|
||||
|
|
|
@ -28,9 +28,14 @@ package org.geysermc.geyser.util;
|
|||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.cloudburstmc.math.vector.Vector3i;
|
||||
import org.cloudburstmc.protocol.bedrock.data.PlayerActionType;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.*;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.ChangeDimensionPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.ChunkRadiusUpdatedPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.MobEffectPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.PlayerActionPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.StopSoundPacket;
|
||||
import org.geysermc.geyser.entity.type.Entity;
|
||||
import org.geysermc.geyser.level.BedrockDimension;
|
||||
import org.geysermc.geyser.level.JavaDimension;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.Effect;
|
||||
|
||||
|
@ -43,22 +48,18 @@ public class DimensionUtils {
|
|||
|
||||
public static final String BEDROCK_FOG_HELL = "minecraft:fog_hell";
|
||||
|
||||
/**
|
||||
* String reference to vanilla Java overworld dimension identifier
|
||||
*/
|
||||
public static final int OVERWORLD = 0;
|
||||
/**
|
||||
* String reference to vanilla Java nether dimension identifier
|
||||
*/
|
||||
public static final int NETHER = 3;
|
||||
/**
|
||||
* String reference to vanilla Java end dimension identifier
|
||||
*/
|
||||
public static final int THE_END = 2;
|
||||
public static final String NETHER_IDENTIFIER = "minecraft:the_nether";
|
||||
|
||||
public static void switchDimension(GeyserSession session, int javaDimension) {
|
||||
int bedrockDimension = javaToBedrock(javaDimension); // new bedrock dimension
|
||||
int previousDimension = session.getDimension(); // previous java dimension
|
||||
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());
|
||||
}
|
||||
|
||||
public static void switchDimension(GeyserSession session, JavaDimension javaDimension, int bedrockDimension) {
|
||||
JavaDimension previousDimension = session.getDimensionType(); // previous java dimension
|
||||
|
||||
Entity player = session.getPlayerEntity();
|
||||
|
||||
|
@ -69,6 +70,44 @@ public class DimensionUtils {
|
|||
session.getPistonCache().clear();
|
||||
session.getSkullCache().clear();
|
||||
|
||||
changeDimension(session, bedrockDimension);
|
||||
|
||||
session.setDimensionType(javaDimension);
|
||||
|
||||
Set<Effect> entityEffects = session.getEffectCache().getEntityEffects();
|
||||
for (Effect effect : entityEffects) {
|
||||
MobEffectPacket mobEffectPacket = new MobEffectPacket();
|
||||
mobEffectPacket.setEvent(MobEffectPacket.Event.REMOVE);
|
||||
mobEffectPacket.setRuntimeEntityId(player.getGeyserId());
|
||||
mobEffectPacket.setEffectId(EntityUtils.toBedrockEffectId(effect));
|
||||
session.sendUpstreamPacket(mobEffectPacket);
|
||||
}
|
||||
// Effects are re-sent from server
|
||||
entityEffects.clear();
|
||||
|
||||
finalizeDimensionSwitch(session, player);
|
||||
|
||||
// If the bedrock nether height workaround is enabled, meaning the client is told it's in the end dimension,
|
||||
// we check if the player is entering the nether and apply the nether fog to fake the fact that the client
|
||||
// thinks they are in the end dimension.
|
||||
if (isCustomBedrockNetherId()) {
|
||||
if (javaDimension.isNetherLike()) {
|
||||
session.camera().sendFog(BEDROCK_FOG_HELL);
|
||||
} else if (previousDimension.isNetherLike()) {
|
||||
session.camera().removeFog(BEDROCK_FOG_HELL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch dimensions without clearing internal logic.
|
||||
*/
|
||||
public static void fastSwitchDimension(GeyserSession session, int bedrockDimension) {
|
||||
changeDimension(session, bedrockDimension);
|
||||
finalizeDimensionSwitch(session, session.getPlayerEntity());
|
||||
}
|
||||
|
||||
private static void changeDimension(GeyserSession session, int bedrockDimension) {
|
||||
if (session.getServerRenderDistance() > 32 && !session.isEmulatePost1_13Logic()) {
|
||||
// The server-sided view distance wasn't a thing until Minecraft Java 1.14
|
||||
// So ViaVersion compensates by sending a "view distance" of 64
|
||||
|
@ -77,7 +116,7 @@ public class DimensionUtils {
|
|||
// To solve this, we cap at 32 unless we know that the render distance actually exceeds 32
|
||||
// Also, as of 1.19: PS4 crashes with a ChunkRadiusUpdatedPacket too large
|
||||
session.getGeyser().getLogger().debug("Applying dimension switching workaround for Bedrock render distance of "
|
||||
+ session.getServerRenderDistance());
|
||||
+ session.getServerRenderDistance());
|
||||
ChunkRadiusUpdatedPacket chunkRadiusUpdatedPacket = new ChunkRadiusUpdatedPacket();
|
||||
chunkRadiusUpdatedPacket.setRadius(32);
|
||||
session.sendUpstreamPacket(chunkRadiusUpdatedPacket);
|
||||
|
@ -92,24 +131,14 @@ public class DimensionUtils {
|
|||
changeDimensionPacket.setPosition(pos);
|
||||
session.sendUpstreamPacket(changeDimensionPacket);
|
||||
|
||||
session.setDimension(javaDimension);
|
||||
setBedrockDimension(session, javaDimension);
|
||||
setBedrockDimension(session, bedrockDimension);
|
||||
|
||||
player.setPosition(pos);
|
||||
session.getPlayerEntity().setPosition(pos);
|
||||
session.setSpawned(false);
|
||||
session.setLastChunkPosition(null);
|
||||
}
|
||||
|
||||
Set<Effect> entityEffects = session.getEffectCache().getEntityEffects();
|
||||
for (Effect effect : entityEffects) {
|
||||
MobEffectPacket mobEffectPacket = new MobEffectPacket();
|
||||
mobEffectPacket.setEvent(MobEffectPacket.Event.REMOVE);
|
||||
mobEffectPacket.setRuntimeEntityId(player.getGeyserId());
|
||||
mobEffectPacket.setEffectId(EntityUtils.toBedrockEffectId(effect));
|
||||
session.sendUpstreamPacket(mobEffectPacket);
|
||||
}
|
||||
// Effects are re-sent from server
|
||||
entityEffects.clear();
|
||||
|
||||
private static void finalizeDimensionSwitch(GeyserSession session, Entity player) {
|
||||
//let java server handle portal travel sound
|
||||
StopSoundPacket stopSoundPacket = new StopSoundPacket();
|
||||
stopSoundPacket.setStoppingAllSound(true);
|
||||
|
@ -130,23 +159,12 @@ public class DimensionUtils {
|
|||
// TODO - fix this hack of a fix by sending the final dimension switching logic after sections have been sent.
|
||||
// The client wants sections sent to it before it can successfully respawn.
|
||||
ChunkUtils.sendEmptyChunks(session, player.getPosition().toInt(), 3, true);
|
||||
|
||||
// If the bedrock nether height workaround is enabled, meaning the client is told it's in the end dimension,
|
||||
// we check if the player is entering the nether and apply the nether fog to fake the fact that the client
|
||||
// thinks they are in the end dimension.
|
||||
if (isCustomBedrockNetherId()) {
|
||||
if (NETHER == javaDimension) {
|
||||
session.camera().sendFog(BEDROCK_FOG_HELL);
|
||||
} else if (NETHER == previousDimension) {
|
||||
session.camera().removeFog(BEDROCK_FOG_HELL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void setBedrockDimension(GeyserSession session, int javaDimension) {
|
||||
session.getChunkCache().setBedrockDimension(switch (javaDimension) {
|
||||
case DimensionUtils.THE_END -> BedrockDimension.THE_END;
|
||||
case DimensionUtils.NETHER -> DimensionUtils.isCustomBedrockNetherId() ? BedrockDimension.THE_END : BedrockDimension.THE_NETHER;
|
||||
public static void setBedrockDimension(GeyserSession session, int bedrockDimension) {
|
||||
session.getChunkCache().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;
|
||||
});
|
||||
}
|
||||
|
@ -155,26 +173,12 @@ public class DimensionUtils {
|
|||
if (dimension == BedrockDimension.THE_NETHER) {
|
||||
return BEDROCK_NETHER_ID;
|
||||
} else if (dimension == BedrockDimension.THE_END) {
|
||||
return 2;
|
||||
return BEDROCK_END_ID;
|
||||
} else {
|
||||
return 0;
|
||||
return BEDROCK_OVERWORLD_ID;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Map the Java edition dimension IDs to Bedrock edition
|
||||
*
|
||||
* @param javaDimension Dimension ID to convert
|
||||
* @return Converted Bedrock edition dimension ID
|
||||
*/
|
||||
public static int javaToBedrock(int javaDimension) {
|
||||
return switch (javaDimension) {
|
||||
case NETHER -> BEDROCK_NETHER_ID;
|
||||
case THE_END -> 2;
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Map the Java edition dimension IDs to Bedrock edition
|
||||
*
|
||||
|
@ -183,12 +187,23 @@ public class DimensionUtils {
|
|||
*/
|
||||
public static int javaToBedrock(String javaDimension) {
|
||||
return switch (javaDimension) {
|
||||
case "minecraft:the_nether" -> BEDROCK_NETHER_ID;
|
||||
case NETHER_IDENTIFIER -> BEDROCK_NETHER_ID;
|
||||
case "minecraft:the_end" -> 2;
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Bedrock dimension ID, with a safety check if a packet is created before the player is logged/spawned in.
|
||||
*/
|
||||
public static int javaToBedrock(GeyserSession session) {
|
||||
JavaDimension dimension = session.getDimensionType();
|
||||
if (dimension == null) {
|
||||
return BEDROCK_OVERWORLD_ID;
|
||||
}
|
||||
return dimension.bedrockId();
|
||||
}
|
||||
|
||||
/**
|
||||
* The Nether dimension in Bedrock does not permit building above Y128 - the Bedrock above the dimension.
|
||||
* This workaround sets the Nether as the End dimension to ignore this limit.
|
||||
|
@ -197,28 +212,28 @@ public class DimensionUtils {
|
|||
*/
|
||||
public static void changeBedrockNetherId(boolean isAboveNetherBedrockBuilding) {
|
||||
// Change dimension ID to the End to allow for building above Bedrock
|
||||
BEDROCK_NETHER_ID = isAboveNetherBedrockBuilding ? 2 : 1;
|
||||
BEDROCK_NETHER_ID = isAboveNetherBedrockBuilding ? BEDROCK_END_ID : BEDROCK_DEFAULT_NETHER_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the fake, temporary dimension we send clients to so we aren't switching to the same dimension without an additional
|
||||
* dimension switch.
|
||||
*
|
||||
* @param currentDimension the current dimension of the player
|
||||
* @param newDimension the new dimension that the player will be transferred to
|
||||
* @return the fake dimension to transfer to
|
||||
* @param currentBedrockDimension the current dimension of the player
|
||||
* @param newBedrockDimension the new dimension that the player will be transferred to
|
||||
* @return the Bedrock fake dimension to transfer to
|
||||
*/
|
||||
public static int getTemporaryDimension(int currentDimension, int newDimension) {
|
||||
public static int getTemporaryDimension(int currentBedrockDimension, int newBedrockDimension) {
|
||||
if (isCustomBedrockNetherId()) {
|
||||
// Prevents rare instances of Bedrock locking up
|
||||
return javaToBedrock(newDimension) == 2 ? OVERWORLD : NETHER;
|
||||
return newBedrockDimension == BEDROCK_END_ID ? BEDROCK_OVERWORLD_ID : BEDROCK_END_ID;
|
||||
}
|
||||
// Check current Bedrock dimension and not just the Java dimension.
|
||||
// Fixes rare instances like https://github.com/GeyserMC/Geyser/issues/3161
|
||||
return javaToBedrock(currentDimension) == 0 ? NETHER : OVERWORLD;
|
||||
return currentBedrockDimension == BEDROCK_OVERWORLD_ID ? BEDROCK_DEFAULT_NETHER_ID : BEDROCK_OVERWORLD_ID;
|
||||
}
|
||||
|
||||
public static boolean isCustomBedrockNetherId() {
|
||||
return BEDROCK_NETHER_ID == 2;
|
||||
return BEDROCK_NETHER_ID == BEDROCK_END_ID;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue