Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-11-16 04:50:07 +01:00
Fix #4837 by not hardcoding dimension IDs
Dieser Commit ist enthalten in:
Ursprung
93b0a61265
Commit
6e0bad3c40
@ -30,7 +30,11 @@ import org.cloudburstmc.math.vector.Vector3f;
|
|||||||
import org.cloudburstmc.protocol.bedrock.data.ParticleType;
|
import org.cloudburstmc.protocol.bedrock.data.ParticleType;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType;
|
import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
|
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.EntityDefinition;
|
||||||
import org.geysermc.geyser.entity.type.Tickable;
|
import org.geysermc.geyser.entity.type.Tickable;
|
||||||
import org.geysermc.geyser.entity.type.living.MobEntity;
|
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
|
// so we need to manually spawn particles
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < 8; i++) {
|
||||||
SpawnParticleEffectPacket spawnParticleEffectPacket = new SpawnParticleEffectPacket();
|
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.setPosition(head.getPosition().add(random.nextGaussian() / 2f, random.nextGaussian() / 2f, random.nextGaussian() / 2f));
|
||||||
spawnParticleEffectPacket.setIdentifier("minecraft:dragon_breath_fire");
|
spawnParticleEffectPacket.setIdentifier("minecraft:dragon_breath_fire");
|
||||||
spawnParticleEffectPacket.setMolangVariablesJson(Optional.empty());
|
spawnParticleEffectPacket.setMolangVariablesJson(Optional.empty());
|
||||||
|
@ -25,15 +25,17 @@
|
|||||||
|
|
||||||
package org.geysermc.geyser.level;
|
package org.geysermc.geyser.level;
|
||||||
|
|
||||||
|
import net.kyori.adventure.key.Key;
|
||||||
import org.cloudburstmc.nbt.NbtMap;
|
import org.cloudburstmc.nbt.NbtMap;
|
||||||
import org.geysermc.geyser.session.cache.registry.RegistryEntryContext;
|
import org.geysermc.geyser.session.cache.registry.RegistryEntryContext;
|
||||||
|
import org.geysermc.geyser.util.DimensionUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the information we store from the current Java dimension
|
* Represents the information we store from the current Java dimension
|
||||||
* @param piglinSafe Whether piglins and hoglins are safe from conversion in this 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.
|
* 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) {
|
public static JavaDimension read(RegistryEntryContext entry) {
|
||||||
NbtMap dimension = entry.data();
|
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
|
// Load world coordinate scale for the world border
|
||||||
double coordinateScale = dimension.getDouble("coordinate_scale");
|
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.
|
* The dimension of the player.
|
||||||
* As all entities are in the same world, this can be safely applied to all other entities.
|
* As all entities are in the same world, this can be safely applied to all other entities.
|
||||||
*/
|
*/
|
||||||
@Setter
|
|
||||||
private int dimension = DimensionUtils.OVERWORLD;
|
|
||||||
@MonotonicNonNull
|
@MonotonicNonNull
|
||||||
@Setter
|
@Setter
|
||||||
private JavaDimension dimensionType = null;
|
private JavaDimension dimensionType = null;
|
||||||
|
@ -27,6 +27,7 @@ package org.geysermc.geyser.translator.protocol.java;
|
|||||||
|
|
||||||
import net.kyori.adventure.key.Key;
|
import net.kyori.adventure.key.Key;
|
||||||
import org.geysermc.erosion.Constants;
|
import org.geysermc.erosion.Constants;
|
||||||
|
import org.geysermc.geyser.level.JavaDimension;
|
||||||
import org.geysermc.geyser.util.MinecraftKey;
|
import org.geysermc.geyser.util.MinecraftKey;
|
||||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.PlayerSpawnInfo;
|
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.PlayerSpawnInfo;
|
||||||
import org.geysermc.mcprotocollib.protocol.packet.common.serverbound.ServerboundCustomPayloadPacket;
|
import org.geysermc.mcprotocollib.protocol.packet.common.serverbound.ServerboundCustomPayloadPacket;
|
||||||
@ -65,12 +66,15 @@ public class JavaLoginTranslator extends PacketTranslator<ClientboundLoginPacket
|
|||||||
}
|
}
|
||||||
|
|
||||||
PlayerSpawnInfo spawnInfo = packet.getCommonPlayerSpawnInfo();
|
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
|
// If the player is already initialized and a join game packet is sent, they
|
||||||
// are swapping servers
|
// are swapping servers
|
||||||
if (session.isSpawned()) {
|
if (session.isSpawned()) {
|
||||||
int fakeDim = DimensionUtils.getTemporaryDimension(session.getDimension(), spawnInfo.getDimension());
|
int fakeDim = DimensionUtils.getTemporaryDimension(session.getDimensionType().bedrockId(), newDimension.bedrockId());
|
||||||
DimensionUtils.switchDimension(session, fakeDim);
|
DimensionUtils.fastSwitchDimension(session, fakeDim);
|
||||||
|
forceDimSwitch = true;
|
||||||
|
|
||||||
session.getWorldCache().removeScoreboard();
|
session.getWorldCache().removeScoreboard();
|
||||||
|
|
||||||
@ -103,13 +107,12 @@ public class JavaLoginTranslator extends PacketTranslator<ClientboundLoginPacket
|
|||||||
session.setWorldName(spawnInfo.getWorldName());
|
session.setWorldName(spawnInfo.getWorldName());
|
||||||
session.setLevels(Arrays.stream(packet.getWorldNames()).map(Key::asString).toArray(String[]::new));
|
session.setLevels(Arrays.stream(packet.getWorldNames()).map(Key::asString).toArray(String[]::new));
|
||||||
session.setGameMode(spawnInfo.getGameMode());
|
session.setGameMode(spawnInfo.getGameMode());
|
||||||
int newDimension = spawnInfo.getDimension();
|
|
||||||
|
|
||||||
boolean needsSpawnPacket = !session.isSentSpawnPacket();
|
boolean needsSpawnPacket = !session.isSentSpawnPacket();
|
||||||
if (needsSpawnPacket) {
|
if (needsSpawnPacket) {
|
||||||
// The player has yet to spawn so let's do that using some of the information in this Java packet
|
// The player has yet to spawn so let's do that using some of the information in this Java packet
|
||||||
session.setDimension(newDimension);
|
session.setDimensionType(newDimension);
|
||||||
DimensionUtils.setBedrockDimension(session, newDimension);
|
DimensionUtils.setBedrockDimension(session, newDimension.bedrockId());
|
||||||
session.connect();
|
session.connect();
|
||||||
|
|
||||||
// It is now safe to send these packets
|
// 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)));
|
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);
|
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
|
// If the player is spawning into the "fake" nether, send them some fog
|
||||||
session.camera().sendFog(DimensionUtils.BEDROCK_FOG_HELL);
|
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.cloudburstmc.protocol.bedrock.packet.SetPlayerGameTypePacket;
|
||||||
import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
|
import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
|
||||||
import org.geysermc.geyser.entity.type.player.SessionPlayerEntity;
|
import org.geysermc.geyser.entity.type.player.SessionPlayerEntity;
|
||||||
|
import org.geysermc.geyser.level.JavaDimension;
|
||||||
import org.geysermc.geyser.session.GeyserSession;
|
import org.geysermc.geyser.session.GeyserSession;
|
||||||
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
||||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||||
@ -92,12 +93,12 @@ public class JavaRespawnTranslator extends PacketTranslator<ClientboundRespawnPa
|
|||||||
session.setThunder(false);
|
session.setThunder(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
int newDimension = spawnInfo.getDimension();
|
JavaDimension newDimension = session.getRegistryCache().dimensions().byId(spawnInfo.getDimension());
|
||||||
if (session.getDimension() != newDimension || !spawnInfo.getWorldName().equals(session.getWorldName())) {
|
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
|
// 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)) {
|
if (session.getDimensionType().bedrockId() == newDimension.bedrockId()) {
|
||||||
int fakeDim = DimensionUtils.getTemporaryDimension(session.getDimension(), newDimension);
|
int fakeDim = DimensionUtils.getTemporaryDimension(session.getDimensionType().bedrockId(), newDimension.bedrockId());
|
||||||
DimensionUtils.switchDimension(session, fakeDim);
|
DimensionUtils.fastSwitchDimension(session, fakeDim);
|
||||||
}
|
}
|
||||||
session.setWorldName(spawnInfo.getWorldName());
|
session.setWorldName(spawnInfo.getWorldName());
|
||||||
DimensionUtils.switchDimension(session, newDimension);
|
DimensionUtils.switchDimension(session, newDimension);
|
||||||
|
@ -92,7 +92,7 @@ public class JavaAnimateTranslator extends PacketTranslator<ClientboundAnimatePa
|
|||||||
// Spawn custom particle
|
// Spawn custom particle
|
||||||
SpawnParticleEffectPacket stringPacket = new SpawnParticleEffectPacket();
|
SpawnParticleEffectPacket stringPacket = new SpawnParticleEffectPacket();
|
||||||
stringPacket.setIdentifier("geyseropt:enchanted_hit_multiple");
|
stringPacket.setIdentifier("geyseropt:enchanted_hit_multiple");
|
||||||
stringPacket.setDimensionId(DimensionUtils.javaToBedrock(session.getDimension()));
|
stringPacket.setDimensionId(DimensionUtils.javaToBedrock(session));
|
||||||
stringPacket.setPosition(Vector3f.ZERO);
|
stringPacket.setPosition(Vector3f.ZERO);
|
||||||
stringPacket.setUniqueEntityId(entity.getGeyserId());
|
stringPacket.setUniqueEntityId(entity.getGeyserId());
|
||||||
stringPacket.setMolangVariablesJson(Optional.empty());
|
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.Vector3f;
|
||||||
import org.cloudburstmc.math.vector.Vector3i;
|
import org.cloudburstmc.math.vector.Vector3i;
|
||||||
import org.cloudburstmc.nbt.NbtMap;
|
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.ParticleType;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.SoundEvent;
|
import org.cloudburstmc.protocol.bedrock.data.SoundEvent;
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.LevelEventGenericPacket;
|
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) {
|
private static void spawnOminousTrialSpawnerParticles(GeyserSession session, Vector3f pos) {
|
||||||
int dimensionId = DimensionUtils.javaToBedrock(session.getDimension());
|
int dimensionId = DimensionUtils.javaToBedrock(session);
|
||||||
SpawnParticleEffectPacket stringPacket = new SpawnParticleEffectPacket();
|
SpawnParticleEffectPacket stringPacket = new SpawnParticleEffectPacket();
|
||||||
stringPacket.setIdentifier("minecraft:trial_spawner_detection_ominous");
|
stringPacket.setIdentifier("minecraft:trial_spawner_detection_ominous");
|
||||||
stringPacket.setDimensionId(dimensionId);
|
stringPacket.setDimensionId(dimensionId);
|
||||||
|
@ -191,7 +191,7 @@ public class JavaLevelParticlesTranslator extends PacketTranslator<ClientboundLe
|
|||||||
return packet;
|
return packet;
|
||||||
};
|
};
|
||||||
} else if (particleMapping.identifier() != null) {
|
} else if (particleMapping.identifier() != null) {
|
||||||
int dimensionId = DimensionUtils.javaToBedrock(session.getDimension());
|
int dimensionId = DimensionUtils.javaToBedrock(session);
|
||||||
return (position) -> {
|
return (position) -> {
|
||||||
SpawnParticleEffectPacket stringPacket = new SpawnParticleEffectPacket();
|
SpawnParticleEffectPacket stringPacket = new SpawnParticleEffectPacket();
|
||||||
stringPacket.setIdentifier(particleMapping.identifier());
|
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();
|
org.cloudburstmc.protocol.bedrock.packet.ClientboundMapItemDataPacket mapItemDataPacket = new org.cloudburstmc.protocol.bedrock.packet.ClientboundMapItemDataPacket();
|
||||||
|
|
||||||
mapItemDataPacket.setUniqueMapId(packet.getMapId());
|
mapItemDataPacket.setUniqueMapId(packet.getMapId());
|
||||||
mapItemDataPacket.setDimensionId(DimensionUtils.javaToBedrock(session.getDimension()));
|
mapItemDataPacket.setDimensionId(DimensionUtils.javaToBedrock(session));
|
||||||
mapItemDataPacket.setLocked(packet.isLocked());
|
mapItemDataPacket.setLocked(packet.isLocked());
|
||||||
mapItemDataPacket.setOrigin(Vector3i.ZERO); // Required since 1.19.20
|
mapItemDataPacket.setOrigin(Vector3i.ZERO); // Required since 1.19.20
|
||||||
mapItemDataPacket.setScale(packet.getScale());
|
mapItemDataPacket.setScale(packet.getScale());
|
||||||
|
@ -39,7 +39,7 @@ public class JavaSetDefaultSpawnPositionTranslator extends PacketTranslator<Clie
|
|||||||
public void translate(GeyserSession session, ClientboundSetDefaultSpawnPositionPacket packet) {
|
public void translate(GeyserSession session, ClientboundSetDefaultSpawnPositionPacket packet) {
|
||||||
SetSpawnPositionPacket spawnPositionPacket = new SetSpawnPositionPacket();
|
SetSpawnPositionPacket spawnPositionPacket = new SetSpawnPositionPacket();
|
||||||
spawnPositionPacket.setBlockPosition(packet.getPosition());
|
spawnPositionPacket.setBlockPosition(packet.getPosition());
|
||||||
spawnPositionPacket.setDimensionId(DimensionUtils.javaToBedrock(session.getDimension()));
|
spawnPositionPacket.setDimensionId(DimensionUtils.javaToBedrock(session));
|
||||||
spawnPositionPacket.setSpawnType(SetSpawnPositionPacket.Type.WORLD_SPAWN);
|
spawnPositionPacket.setSpawnType(SetSpawnPositionPacket.Type.WORLD_SPAWN);
|
||||||
session.sendUpstreamPacket(spawnPositionPacket);
|
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
|
* This must be done after the player has switched dimensions so we know what their dimension is
|
||||||
*/
|
*/
|
||||||
public static void loadDimension(GeyserSession session) {
|
public static void loadDimension(GeyserSession session) {
|
||||||
JavaDimension dimension = session.getRegistryCache().dimensions().byId(session.getDimension());
|
JavaDimension dimension = session.getDimensionType();
|
||||||
session.setDimensionType(dimension);
|
|
||||||
int minY = dimension.minY();
|
int minY = dimension.minY();
|
||||||
int maxY = dimension.maxY();
|
int maxY = dimension.maxY();
|
||||||
|
|
||||||
@ -223,7 +222,7 @@ public class ChunkUtils {
|
|||||||
session.getGeyser().getLogger().warning(GeyserLocale.getLocaleStringLog("geyser.network.translator.chunk.out_of_bounds",
|
session.getGeyser().getLogger().warning(GeyserLocale.getLocaleStringLog("geyser.network.translator.chunk.out_of_bounds",
|
||||||
String.valueOf(bedrockDimension.minY()),
|
String.valueOf(bedrockDimension.minY()),
|
||||||
String.valueOf(bedrockDimension.height()),
|
String.valueOf(bedrockDimension.height()),
|
||||||
session.getDimension()));
|
session.getRegistryCache().dimensions().byValue(session.getDimensionType())));
|
||||||
}
|
}
|
||||||
|
|
||||||
session.getChunkCache().setMinY(minY);
|
session.getChunkCache().setMinY(minY);
|
||||||
|
@ -28,9 +28,14 @@ package org.geysermc.geyser.util;
|
|||||||
import org.cloudburstmc.math.vector.Vector3f;
|
import org.cloudburstmc.math.vector.Vector3f;
|
||||||
import org.cloudburstmc.math.vector.Vector3i;
|
import org.cloudburstmc.math.vector.Vector3i;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.PlayerActionType;
|
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.entity.type.Entity;
|
||||||
import org.geysermc.geyser.level.BedrockDimension;
|
import org.geysermc.geyser.level.BedrockDimension;
|
||||||
|
import org.geysermc.geyser.level.JavaDimension;
|
||||||
import org.geysermc.geyser.session.GeyserSession;
|
import org.geysermc.geyser.session.GeyserSession;
|
||||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.Effect;
|
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";
|
public static final String BEDROCK_FOG_HELL = "minecraft:fog_hell";
|
||||||
|
|
||||||
/**
|
public static final String NETHER_IDENTIFIER = "minecraft:the_nether";
|
||||||
* 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 void switchDimension(GeyserSession session, int javaDimension) {
|
private static final int BEDROCK_OVERWORLD_ID = 0;
|
||||||
int bedrockDimension = javaToBedrock(javaDimension); // new bedrock dimension
|
private static final int BEDROCK_DEFAULT_NETHER_ID = 1;
|
||||||
int previousDimension = session.getDimension(); // previous java dimension
|
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();
|
Entity player = session.getPlayerEntity();
|
||||||
|
|
||||||
@ -69,6 +70,44 @@ public class DimensionUtils {
|
|||||||
session.getPistonCache().clear();
|
session.getPistonCache().clear();
|
||||||
session.getSkullCache().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()) {
|
if (session.getServerRenderDistance() > 32 && !session.isEmulatePost1_13Logic()) {
|
||||||
// The server-sided view distance wasn't a thing until Minecraft Java 1.14
|
// The server-sided view distance wasn't a thing until Minecraft Java 1.14
|
||||||
// So ViaVersion compensates by sending a "view distance" of 64
|
// 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
|
// 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
|
// 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.getGeyser().getLogger().debug("Applying dimension switching workaround for Bedrock render distance of "
|
||||||
+ session.getServerRenderDistance());
|
+ session.getServerRenderDistance());
|
||||||
ChunkRadiusUpdatedPacket chunkRadiusUpdatedPacket = new ChunkRadiusUpdatedPacket();
|
ChunkRadiusUpdatedPacket chunkRadiusUpdatedPacket = new ChunkRadiusUpdatedPacket();
|
||||||
chunkRadiusUpdatedPacket.setRadius(32);
|
chunkRadiusUpdatedPacket.setRadius(32);
|
||||||
session.sendUpstreamPacket(chunkRadiusUpdatedPacket);
|
session.sendUpstreamPacket(chunkRadiusUpdatedPacket);
|
||||||
@ -92,24 +131,14 @@ public class DimensionUtils {
|
|||||||
changeDimensionPacket.setPosition(pos);
|
changeDimensionPacket.setPosition(pos);
|
||||||
session.sendUpstreamPacket(changeDimensionPacket);
|
session.sendUpstreamPacket(changeDimensionPacket);
|
||||||
|
|
||||||
session.setDimension(javaDimension);
|
setBedrockDimension(session, bedrockDimension);
|
||||||
setBedrockDimension(session, javaDimension);
|
|
||||||
|
|
||||||
player.setPosition(pos);
|
session.getPlayerEntity().setPosition(pos);
|
||||||
session.setSpawned(false);
|
session.setSpawned(false);
|
||||||
session.setLastChunkPosition(null);
|
session.setLastChunkPosition(null);
|
||||||
|
}
|
||||||
|
|
||||||
Set<Effect> entityEffects = session.getEffectCache().getEntityEffects();
|
private static void finalizeDimensionSwitch(GeyserSession session, Entity player) {
|
||||||
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();
|
|
||||||
|
|
||||||
//let java server handle portal travel sound
|
//let java server handle portal travel sound
|
||||||
StopSoundPacket stopSoundPacket = new StopSoundPacket();
|
StopSoundPacket stopSoundPacket = new StopSoundPacket();
|
||||||
stopSoundPacket.setStoppingAllSound(true);
|
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.
|
// 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.
|
// The client wants sections sent to it before it can successfully respawn.
|
||||||
ChunkUtils.sendEmptyChunks(session, player.getPosition().toInt(), 3, true);
|
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) {
|
public static void setBedrockDimension(GeyserSession session, int bedrockDimension) {
|
||||||
session.getChunkCache().setBedrockDimension(switch (javaDimension) {
|
session.getChunkCache().setBedrockDimension(switch (bedrockDimension) {
|
||||||
case DimensionUtils.THE_END -> BedrockDimension.THE_END;
|
case BEDROCK_END_ID -> BedrockDimension.THE_END;
|
||||||
case DimensionUtils.NETHER -> DimensionUtils.isCustomBedrockNetherId() ? BedrockDimension.THE_END : BedrockDimension.THE_NETHER;
|
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;
|
default -> BedrockDimension.OVERWORLD;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -155,26 +173,12 @@ public class DimensionUtils {
|
|||||||
if (dimension == BedrockDimension.THE_NETHER) {
|
if (dimension == BedrockDimension.THE_NETHER) {
|
||||||
return BEDROCK_NETHER_ID;
|
return BEDROCK_NETHER_ID;
|
||||||
} else if (dimension == BedrockDimension.THE_END) {
|
} else if (dimension == BedrockDimension.THE_END) {
|
||||||
return 2;
|
return BEDROCK_END_ID;
|
||||||
} else {
|
} 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
|
* Map the Java edition dimension IDs to Bedrock edition
|
||||||
*
|
*
|
||||||
@ -183,12 +187,23 @@ public class DimensionUtils {
|
|||||||
*/
|
*/
|
||||||
public static int javaToBedrock(String javaDimension) {
|
public static int javaToBedrock(String javaDimension) {
|
||||||
return switch (javaDimension) {
|
return switch (javaDimension) {
|
||||||
case "minecraft:the_nether" -> BEDROCK_NETHER_ID;
|
case NETHER_IDENTIFIER -> BEDROCK_NETHER_ID;
|
||||||
case "minecraft:the_end" -> 2;
|
case "minecraft:the_end" -> 2;
|
||||||
default -> 0;
|
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.
|
* 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.
|
* 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) {
|
public static void changeBedrockNetherId(boolean isAboveNetherBedrockBuilding) {
|
||||||
// Change dimension ID to the End to allow for building above Bedrock
|
// 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
|
* Gets the fake, temporary dimension we send clients to so we aren't switching to the same dimension without an additional
|
||||||
* dimension switch.
|
* dimension switch.
|
||||||
*
|
*
|
||||||
* @param currentDimension the current dimension of the player
|
* @param currentBedrockDimension the current dimension of the player
|
||||||
* @param newDimension the new dimension that the player will be transferred to
|
* @param newBedrockDimension the new dimension that the player will be transferred to
|
||||||
* @return the fake dimension to transfer 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()) {
|
if (isCustomBedrockNetherId()) {
|
||||||
// Prevents rare instances of Bedrock locking up
|
// 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.
|
// Check current Bedrock dimension and not just the Java dimension.
|
||||||
// Fixes rare instances like https://github.com/GeyserMC/Geyser/issues/3161
|
// 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() {
|
public static boolean isCustomBedrockNetherId() {
|
||||||
return BEDROCK_NETHER_ID == 2;
|
return BEDROCK_NETHER_ID == BEDROCK_END_ID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren