Bump version; drop 1.17.40; support 1.18.30

This commit is contained in:
Camotoy 2022-04-17 19:53:06 -04:00
parent 0803c5d9af
commit cf8114543e
21 changed files with 1614 additions and 1459 deletions

View File

@ -17,7 +17,7 @@ The ultimate goal of this project is to allow Minecraft: Bedrock Edition users t
Special thanks to the DragonProxy project for being a trailblazer in protocol translation and for all the team members who have joined us here!
### Currently supporting Minecraft Bedrock 1.17.41 + 1.18.0 - 1.18.10 and Minecraft Java 1.18.2.
### Currently supporting Minecraft Bedrock 1.18.0 - 1.18.30 and Minecraft Java 1.18.2.
## Setting Up
Take a look [here](https://wiki.geysermc.org/geyser/setup/) for how to set up Geyser.

View File

@ -120,8 +120,8 @@
</dependency>
<dependency>
<groupId>com.github.CloudburstMC.Protocol</groupId>
<artifactId>bedrock-v486</artifactId>
<version>0cd24c0</version>
<artifactId>bedrock-v503</artifactId>
<version>29ecd7a</version>
<scope>compile</scope>
<exclusions>
<exclusion>

View File

@ -37,6 +37,7 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.math.vector.Vector3i;
import com.nukkitx.protocol.bedrock.data.AttributeData;
import com.nukkitx.protocol.bedrock.data.GameType;
import com.nukkitx.protocol.bedrock.data.PlayerPermission;
import com.nukkitx.protocol.bedrock.data.command.CommandPermission;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
@ -126,6 +127,7 @@ public class PlayerEntity extends LivingEntity {
addPlayerPacket.getAdventureSettings().setPlayerPermission(PlayerPermission.MEMBER);
addPlayerPacket.setDeviceId("");
addPlayerPacket.setPlatformChatId("");
addPlayerPacket.setGameType(GameType.SURVIVAL); //TODO
addPlayerPacket.getMetadata().putFlags(flags);
dirtyMetadata.apply(addPlayerPacket.getMetadata());

View File

@ -27,6 +27,7 @@ package org.geysermc.geyser.entity.type.player;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.math.vector.Vector3i;
import com.nukkitx.protocol.bedrock.data.GameType;
import com.nukkitx.protocol.bedrock.data.PlayerPermission;
import com.nukkitx.protocol.bedrock.data.command.CommandPermission;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
@ -84,6 +85,7 @@ public class SkullPlayerEntity extends PlayerEntity {
addPlayerPacket.getAdventureSettings().setPlayerPermission(PlayerPermission.MEMBER);
addPlayerPacket.setDeviceId("");
addPlayerPacket.setPlatformChatId("");
addPlayerPacket.setGameType(GameType.SURVIVAL);
addPlayerPacket.getMetadata().putFlags(flags);
dirtyMetadata.apply(addPlayerPacket.getMetadata());

View File

@ -0,0 +1,41 @@
/*
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.geyser.level;
/**
* A data structure to represent what Bedrock believes are the height requirements for a specific dimension.
* As of 1.18.30, biome count is representative of the height of the world, and out-of-bounds chunks can crash
* the client.
*
* @param minY The minimum height Bedrock Edition will accept.
* @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 BedrockDimension OVERWORLD = new BedrockDimension(-64, 384, true);
public static BedrockDimension THE_NETHER = new BedrockDimension(0, 128, false);
public static BedrockDimension THE_END = new BedrockDimension(0, 256, true);
}

View File

@ -26,8 +26,6 @@
package org.geysermc.geyser.level.block;
import com.nukkitx.network.util.Preconditions;
import lombok.Getter;
public class BlockPositionIterator {
private final int minX;

View File

@ -28,11 +28,14 @@ package org.geysermc.geyser.network;
import com.github.steveice10.mc.protocol.codec.MinecraftCodec;
import com.github.steveice10.mc.protocol.codec.PacketCodec;
import com.nukkitx.protocol.bedrock.BedrockPacketCodec;
import com.nukkitx.protocol.bedrock.v471.Bedrock_v471;
import com.nukkitx.protocol.bedrock.v475.Bedrock_v475;
import com.nukkitx.protocol.bedrock.v486.Bedrock_v486;
import com.nukkitx.protocol.bedrock.v503.Bedrock_v503;
import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.StringJoiner;
/**
* Contains information about the supported protocols in Geyser.
@ -42,7 +45,7 @@ public final class MinecraftProtocol {
* Default Bedrock codec that should act as a fallback. Should represent the latest available
* release of the game that Geyser supports.
*/
public static final BedrockPacketCodec DEFAULT_BEDROCK_CODEC = Bedrock_v486.V486_CODEC;
public static final BedrockPacketCodec DEFAULT_BEDROCK_CODEC = Bedrock_v503.V503_CODEC;
/**
* A list of all supported Bedrock versions that can join Geyser
*/
@ -55,11 +58,11 @@ public final class MinecraftProtocol {
private static final PacketCodec DEFAULT_JAVA_CODEC = MinecraftCodec.CODEC;
static {
SUPPORTED_BEDROCK_CODECS.add(Bedrock_v471.V471_CODEC);
SUPPORTED_BEDROCK_CODECS.add(Bedrock_v475.V475_CODEC.toBuilder().minecraftVersion("1.18.0/1.18.1/1.18.2").build());
SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC.toBuilder()
SUPPORTED_BEDROCK_CODECS.add(Bedrock_v486.V486_CODEC.toBuilder()
.minecraftVersion("1.18.10/1.18.12") // 1.18.11 is also supported, but was only on Switch and since that auto-updates it's not needed
.build());
SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC);
}
/**

View File

@ -30,18 +30,18 @@ import com.nukkitx.protocol.bedrock.BedrockPacketCodec;
import com.nukkitx.protocol.bedrock.data.ExperimentData;
import com.nukkitx.protocol.bedrock.data.ResourcePackType;
import com.nukkitx.protocol.bedrock.packet.*;
import com.nukkitx.protocol.bedrock.v471.Bedrock_v471;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.session.PendingMicrosoftAuthentication;
import org.geysermc.geyser.session.auth.AuthType;
import org.geysermc.geyser.configuration.GeyserConfiguration;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.pack.ResourcePack;
import org.geysermc.geyser.pack.ResourcePackManifest;
import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.PendingMicrosoftAuthentication;
import org.geysermc.geyser.session.auth.AuthType;
import org.geysermc.geyser.text.GeyserLocale;
import org.geysermc.geyser.util.*;
import org.geysermc.geyser.util.LoginEncryptionUtils;
import org.geysermc.geyser.util.MathUtils;
import java.io.FileInputStream;
import java.io.InputStream;
@ -165,11 +165,6 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
stackPacket.getExperiments().add(new ExperimentData("data_driven_items", true));
}
if (session.getUpstream().getProtocolVersion() <= Bedrock_v471.V471_CODEC.getProtocolVersion()) {
// Allow extended world height in the overworld to work for pre-1.18 clients
stackPacket.getExperiments().add(new ExperimentData("caves_and_cliffs", true));
}
session.sendUpstreamPacket(stackPacket);
break;

View File

@ -28,8 +28,9 @@ package org.geysermc.geyser.registry.populator;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.collect.ImmutableMap;
import com.nukkitx.nbt.*;
import com.nukkitx.protocol.bedrock.v471.Bedrock_v471;
import com.nukkitx.protocol.bedrock.v475.Bedrock_v475;
import com.nukkitx.protocol.bedrock.v486.Bedrock_v486;
import com.nukkitx.protocol.bedrock.v503.Bedrock_v503;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
@ -60,35 +61,50 @@ public class BlockRegistryPopulator {
private static final ImmutableMap<ObjectIntPair<String>, BiFunction<String, NbtMapBuilder, String>> BLOCK_MAPPERS;
private static final BiFunction<String, NbtMapBuilder, String> EMPTY_MAPPER = (bedrockIdentifier, statesBuilder) -> null;
private static final BiFunction<String, NbtMapBuilder, String> V486_MAPPER = (bedrockIdentifier, statesBuilder) -> {
statesBuilder.remove("no_drop_bit"); // Used in skulls
if (bedrockIdentifier.equals("minecraft:glow_lichen")) {
// Moved around north, south, west
int bits = (int) statesBuilder.get("multi_face_direction_bits");
boolean north = (bits & (1 << 2)) != 0;
boolean south = (bits & (1 << 3)) != 0;
boolean west = (bits & (1 << 4)) != 0;
if (north) {
bits |= 1 << 4;
} else {
bits &= ~(1 << 4);
}
if (south) {
bits |= 1 << 2;
} else {
bits &= ~(1 << 2);
}
if (west) {
bits |= 1 << 3;
} else {
bits &= ~(1 << 3);
}
statesBuilder.put("multi_face_direction_bits", bits);
}
return null;
};
static {
ImmutableMap.Builder<ObjectIntPair<String>, BiFunction<String, NbtMapBuilder, String>> stateMapperBuilder = ImmutableMap.<ObjectIntPair<String>, BiFunction<String, NbtMapBuilder, String>>builder()
.put(ObjectIntPair.of("1_17_40", Bedrock_v471.V471_CODEC.getProtocolVersion()), EMPTY_MAPPER)
.put(ObjectIntPair.of("1_18_10", Bedrock_v486.V486_CODEC.getProtocolVersion()), (bedrockIdentifier, statesBuilder) -> {
statesBuilder.remove("no_drop_bit"); // Used in skulls
if (bedrockIdentifier.equals("minecraft:glow_lichen")) {
// Moved around north, south, west
int bits = (int) statesBuilder.get("multi_face_direction_bits");
boolean north = (bits & (1 << 2)) != 0;
boolean south = (bits & (1 << 3)) != 0;
boolean west = (bits & (1 << 4)) != 0;
if (north) {
bits |= 1 << 4;
} else {
bits &= ~(1 << 4);
}
if (south) {
bits |= 1 << 2;
} else {
bits &= ~(1 << 2);
}
if (west) {
bits |= 1 << 3;
} else {
bits &= ~(1 << 3);
}
statesBuilder.put("multi_face_direction_bits", bits);
}
return null;
.put(ObjectIntPair.of("1_18_0", Bedrock_v475.V475_CODEC.getProtocolVersion()), EMPTY_MAPPER)
.put(ObjectIntPair.of("1_18_10", Bedrock_v486.V486_CODEC.getProtocolVersion()), V486_MAPPER)
.put(ObjectIntPair.of("1_18_30", Bedrock_v503.V503_CODEC.getProtocolVersion()), (bedrockIdentifier, statesBuilder) -> {
// Apply these fixes too
V486_MAPPER.apply(bedrockIdentifier, statesBuilder);
return switch (bedrockIdentifier) {
case "minecraft:pistonArmCollision" -> "minecraft:piston_arm_collision";
case "minecraft:stickyPistonArmCollision" -> "minecraft:sticky_piston_arm_collision";
case "minecraft:movingBlock" -> "minecraft:moving_block";
case "minecraft:tripWire" -> "minecraft:trip_wire";
case "minecraft:seaLantern" -> "minecraft:sea_lantern";
case "minecraft:concretePowder" -> "minecraft:concrete_powder";
default -> null;
};
});
BLOCK_MAPPERS = stateMapperBuilder.build();

View File

@ -35,10 +35,12 @@ import com.nukkitx.protocol.bedrock.data.SoundEvent;
import com.nukkitx.protocol.bedrock.data.inventory.ComponentItemData;
import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
import com.nukkitx.protocol.bedrock.packet.StartGamePacket;
import com.nukkitx.protocol.bedrock.v471.Bedrock_v471;
import com.nukkitx.protocol.bedrock.v475.Bedrock_v475;
import com.nukkitx.protocol.bedrock.v486.Bedrock_v486;
import it.unimi.dsi.fastutil.ints.*;
import com.nukkitx.protocol.bedrock.v503.Bedrock_v503;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import it.unimi.dsi.fastutil.objects.*;
import org.geysermc.geyser.GeyserBootstrap;
import org.geysermc.geyser.GeyserImpl;
@ -58,19 +60,16 @@ import java.util.*;
* Populates the item registries.
*/
public class ItemRegistryPopulator {
private static final Map<String, PaletteVersion> PALETTE_VERSIONS;
static {
PALETTE_VERSIONS = new Object2ObjectOpenHashMap<>();
PALETTE_VERSIONS.put("1_17_40", new PaletteVersion(Bedrock_v471.V471_CODEC.getProtocolVersion(), Collections.emptyMap()));
PALETTE_VERSIONS.put("1_18_0", new PaletteVersion(Bedrock_v475.V475_CODEC.getProtocolVersion(), Collections.emptyMap()));
PALETTE_VERSIONS.put("1_18_10", new PaletteVersion(Bedrock_v486.V486_CODEC.getProtocolVersion(), Collections.emptyMap()));
}
private record PaletteVersion(int protocolVersion, Map<String, String> additionalTranslatedItems) {
}
public static void populate() {
Map<String, PaletteVersion> paletteVersions = new Object2ObjectOpenHashMap<>();
paletteVersions.put("1_18_0", new PaletteVersion(Bedrock_v475.V475_CODEC.getProtocolVersion(), Collections.emptyMap()));
paletteVersions.put("1_18_10", new PaletteVersion(Bedrock_v486.V486_CODEC.getProtocolVersion(), Collections.emptyMap()));
paletteVersions.put("1_18_30", new PaletteVersion(Bedrock_v503.V503_CODEC.getProtocolVersion(), Collections.emptyMap()));
GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap();
TypeReference<Map<String, GeyserMappingItem>> mappingItemsType = new TypeReference<>() { };
@ -88,7 +87,7 @@ public class ItemRegistryPopulator {
Int2IntMap dyeColors = new FixedInt2IntMap();
/* Load item palette */
for (Map.Entry<String, PaletteVersion> palette : PALETTE_VERSIONS.entrySet()) {
for (Map.Entry<String, PaletteVersion> palette : paletteVersions.entrySet()) {
TypeReference<List<PaletteItem>> paletteEntriesType = new TypeReference<>() {};
// Used to get the Bedrock namespaced ID (in instances where there are small differences)
@ -232,12 +231,15 @@ public class ItemRegistryPopulator {
}
String bedrockIdentifier;
if (javaIdentifier.equals("minecraft:music_disc_otherside") && palette.getValue().protocolVersion() <= Bedrock_v471.V471_CODEC.getProtocolVersion()) {
bedrockIdentifier = "minecraft:music_disc_pigstep";
} else if (javaIdentifier.equals("minecraft:globe_banner_pattern") && palette.getValue().protocolVersion() < Bedrock_v486.V486_CODEC.getProtocolVersion()) {
if (javaIdentifier.equals("minecraft:globe_banner_pattern") && palette.getValue().protocolVersion() < Bedrock_v486.V486_CODEC.getProtocolVersion()) {
bedrockIdentifier = "minecraft:banner_pattern";
} else {
bedrockIdentifier = mappingItem.getBedrockIdentifier();
if (palette.getValue().protocolVersion() >= Bedrock_v503.V503_CODEC.getProtocolVersion()) {
if (bedrockIdentifier.equals("minecraft:sealantern")) {
bedrockIdentifier = "minecraft:sea_lantern";
}
}
}
if (usingFurnaceMinecart && javaIdentifier.equals("minecraft:furnace_minecart")) {

View File

@ -67,7 +67,6 @@ import com.nukkitx.protocol.bedrock.data.*;
import com.nukkitx.protocol.bedrock.data.command.CommandPermission;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import com.nukkitx.protocol.bedrock.packet.*;
import com.nukkitx.protocol.bedrock.v471.Bedrock_v471;
import io.netty.channel.Channel;
import io.netty.channel.EventLoop;
import it.unimi.dsi.fastutil.ints.*;
@ -1388,7 +1387,7 @@ public class GeyserSession implements GeyserConnection, CommandSender {
startGamePacket.setPlayerPosition(Vector3f.from(0, 69, 0));
startGamePacket.setRotation(Vector2f.from(1, 1));
startGamePacket.setSeed(-1);
startGamePacket.setSeed(-1L);
startGamePacket.setDimensionId(DimensionUtils.javaToBedrock(dimension));
startGamePacket.setGeneratorId(1);
startGamePacket.setLevelGameType(GameType.SURVIVAL);
@ -1437,10 +1436,6 @@ public class GeyserSession implements GeyserConnection, CommandSender {
settings.setServerAuthoritativeBlockBreaking(false);
startGamePacket.setPlayerMovementSettings(settings);
if (upstream.getProtocolVersion() <= Bedrock_v471.V471_CODEC.getProtocolVersion()) {
startGamePacket.getExperiments().add(new ExperimentData("caves_and_cliffs", true));
}
upstream.sendPacket(startGamePacket);
}

View File

@ -33,6 +33,7 @@ import lombok.Setter;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.level.chunk.GeyserChunk;
import org.geysermc.geyser.level.BedrockDimension;
import org.geysermc.geyser.util.MathUtils;
public class ChunkCache {
@ -45,11 +46,11 @@ public class ChunkCache {
private int heightY;
/**
* Whether the Bedrock client believes they are in a world with a minimum of -64 and maximum of 320
* Which dimension Bedrock understands themselves to be in.
*/
@Getter
@Setter
private boolean isExtendedHeight = false;
private BedrockDimension bedrockDimension = BedrockDimension.OVERWORLD;
public ChunkCache(GeyserSession session) {
this.cache = !session.getGeyser().getWorldManager().hasOwnChunkCache(); // To prevent Spigot from initializing

View File

@ -136,7 +136,7 @@ public class EnchantmentTranslator extends NbtItemStackTranslator {
CompoundTag bedrockTag = new CompoundTag("");
bedrockTag.put(new ShortTag("id", (short) enchantment.ordinal()));
// If the tag cannot parse, Java Edition 1.18.2 sets to 0
bedrockTag.put(new ShortTag("lvl", javaEnchLvl != null && javaEnchLvl.getValue() instanceof Number lvl ? lvl.shortValue() : 0));
bedrockTag.put(new ShortTag("lvl", javaEnchLvl != null && javaEnchLvl.getValue() instanceof Number lvl ? lvl.shortValue() : (short) 0));
return bedrockTag;
}

View File

@ -37,14 +37,12 @@ import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.entity.type.player.SessionPlayerEntity;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.ChatColor;
import org.geysermc.geyser.level.BedrockDimension;
import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.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. These are the constants for the overworld. */
private static final int BEDROCK_OVERWORLD_VOID_FLOOR_UPPER_Y = -104;
private static final int BEDROCK_OVERWORLD_VOID_FLOOR_LOWER_Y = BEDROCK_OVERWORLD_VOID_FLOOR_UPPER_Y + 2;
@Override
public void translate(GeyserSession session, MovePlayerPacket packet) {
@ -124,11 +122,10 @@ public class BedrockMovePlayerTranslator extends PacketTranslator<MovePlayerPack
if (notMovingUp) {
int floorY = position.getFloorY();
// If the client believes the world has extended height, then it also believes the void floor
// still exists, just at a lower spot
boolean extendedWorld = session.getChunkCache().isExtendedHeight();
if (floorY <= (extendedWorld ? BEDROCK_OVERWORLD_VOID_FLOOR_LOWER_Y : -38)
&& floorY >= (extendedWorld ? BEDROCK_OVERWORLD_VOID_FLOOR_UPPER_Y : -40)) {
// The void floor is offset about 40 blocks below the bottom of the world
BedrockDimension bedrockDimension = session.getChunkCache().getBedrockDimension();
int voidFloorLocation = bedrockDimension.minY() - 40;
if (floorY <= (voidFloorLocation + 2) && floorY >= voidFloorLocation) {
// Work around there being a floor at the bottom of the world and teleport the player below it
// Moving from below to above the void floor works fine
entity.setPosition(entity.getPosition().sub(0, 4f, 0));

View File

@ -43,7 +43,7 @@ import com.nukkitx.nbt.NbtMap;
import com.nukkitx.nbt.NbtUtils;
import com.nukkitx.network.VarInts;
import com.nukkitx.protocol.bedrock.packet.LevelChunkPacket;
import com.nukkitx.protocol.bedrock.v475.Bedrock_v475;
import com.nukkitx.protocol.bedrock.v503.Bedrock_v503;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.ByteBufOutputStream;
@ -52,26 +52,29 @@ import it.unimi.dsi.fastutil.ints.IntList;
import it.unimi.dsi.fastutil.ints.IntLists;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import org.geysermc.geyser.entity.type.ItemFrameEntity;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator;
import org.geysermc.geyser.translator.level.BiomeTranslator;
import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.translator.level.block.entity.BedrockOnlyBlockEntity;
import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator;
import org.geysermc.geyser.translator.level.block.entity.SkullBlockEntityTranslator;
import org.geysermc.geyser.level.chunk.BlockStorage;
import org.geysermc.geyser.level.chunk.GeyserChunkSection;
import org.geysermc.geyser.level.chunk.bitarray.BitArray;
import org.geysermc.geyser.level.chunk.bitarray.BitArrayVersion;
import org.geysermc.geyser.level.chunk.bitarray.SingletonBitArray;
import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.level.BedrockDimension;
import org.geysermc.geyser.translator.level.BiomeTranslator;
import org.geysermc.geyser.translator.level.block.entity.BedrockOnlyBlockEntity;
import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator;
import org.geysermc.geyser.translator.level.block.entity.SkullBlockEntityTranslator;
import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator;
import org.geysermc.geyser.util.BlockEntityUtils;
import org.geysermc.geyser.util.ChunkUtils;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.*;
import java.util.BitSet;
import java.util.List;
import java.util.Map;
import static org.geysermc.geyser.util.ChunkUtils.*;
@ -98,13 +101,13 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
BitSet waterloggedPaletteIds = new BitSet();
BitSet pistonOrFlowerPaletteIds = new BitSet();
boolean overworld = session.getChunkCache().isExtendedHeight();
int maxBedrockSectionY = ((overworld ? MAXIMUM_ACCEPTED_HEIGHT_OVERWORLD : MAXIMUM_ACCEPTED_HEIGHT) >> 4) - 1;
BedrockDimension bedrockDimension = session.getChunkCache().getBedrockDimension();
int maxBedrockSectionY = (bedrockDimension.height() >> 4) - 1;
int sectionCount;
byte[] payload;
ByteBuf byteBuf = null;
GeyserChunkSection[] sections = new GeyserChunkSection[javaChunks.length - (yOffset + ((overworld ? MINIMUM_ACCEPTED_HEIGHT_OVERWORLD : MINIMUM_ACCEPTED_HEIGHT) >> 4))];
GeyserChunkSection[] sections = new GeyserChunkSection[javaChunks.length - (yOffset + (bedrockDimension.minY() >> 4))];
try {
NetInput in = new StreamNetInput(new ByteArrayInputStream(packet.getChunkData()));
@ -113,7 +116,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
javaChunks[sectionY] = javaSection.getChunkData();
javaBiomes[sectionY] = javaSection.getBiomeData();
int bedrockSectionY = sectionY + (yOffset - ((overworld ? MINIMUM_ACCEPTED_HEIGHT_OVERWORLD : MINIMUM_ACCEPTED_HEIGHT) >> 4));
int bedrockSectionY = sectionY + (yOffset - (bedrockDimension.minY() >> 4));
if (bedrockSectionY < 0 || maxBedrockSectionY < bedrockSectionY) {
// Ignore this chunk section since it goes outside the bounds accepted by the Bedrock client
continue;
@ -309,11 +312,11 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
}
}
// As of 1.17.10, Bedrock hardcodes to always read 32 biome sections
// As of 1.18, this hardcode was lowered to 25
boolean isNewVersion = session.getUpstream().getProtocolVersion() >= Bedrock_v475.V475_CODEC.getProtocolVersion();
int biomeCount = isNewVersion ? 25 : 32;
int dimensionOffset = (overworld ? MINIMUM_ACCEPTED_HEIGHT_OVERWORLD : MINIMUM_ACCEPTED_HEIGHT) >> 4;
// As of 1.18.0, Bedrock hardcodes to always read 25 biome sections
// As of 1.18.30, the hardcode may now be tied to the dimension definition
boolean isNewVersion = session.getUpstream().getProtocolVersion() >= Bedrock_v503.V503_CODEC.getProtocolVersion();
int biomeCount = isNewVersion ? bedrockDimension.height() >> 4 : 25;
int dimensionOffset = bedrockDimension.minY() >> 4;
for (int i = 0; i < biomeCount; i++) {
int biomeYOffset = dimensionOffset + i;
if (biomeYOffset < yOffset) {

View File

@ -46,23 +46,13 @@ import org.geysermc.geyser.level.chunk.bitarray.SingletonBitArray;
import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.GeyserLocale;
import org.geysermc.geyser.level.BedrockDimension;
import org.geysermc.geyser.translator.level.block.entity.BedrockOnlyBlockEntity;
import static org.geysermc.geyser.level.block.BlockStateValues.JAVA_AIR_ID;
@UtilityClass
public class ChunkUtils {
/**
* The minimum height Bedrock Edition will accept.
*/
public static final int MINIMUM_ACCEPTED_HEIGHT = 0;
public static final int MINIMUM_ACCEPTED_HEIGHT_OVERWORLD = -64;
/**
* The maximum chunk height Bedrock Edition will accept, from the lowest point to the highest.
*/
public static final int MAXIMUM_ACCEPTED_HEIGHT = 256;
public static final int MAXIMUM_ACCEPTED_HEIGHT_OVERWORLD = 384;
/**
* An empty subchunk.
*/
@ -249,17 +239,20 @@ public class ChunkUtils {
throw new RuntimeException("Maximum Y must be a multiple of 16!");
}
int dimension = DimensionUtils.javaToBedrock(session.getDimension());
boolean extendedHeight = dimension == 0;
session.getChunkCache().setExtendedHeight(extendedHeight);
BedrockDimension bedrockDimension = switch (session.getDimension()) {
case DimensionUtils.THE_END -> BedrockDimension.THE_END;
case DimensionUtils.NETHER -> DimensionUtils.isCustomBedrockNetherId() ? BedrockDimension.THE_END : BedrockDimension.THE_NETHER;
default -> BedrockDimension.OVERWORLD;
};
session.getChunkCache().setBedrockDimension(bedrockDimension);
// Yell in the console if the world height is too height in the current scenario
// The constraints change depending on if the player is in the overworld or not, and if experimental height is enabled
if (minY < (extendedHeight ? MINIMUM_ACCEPTED_HEIGHT_OVERWORLD : MINIMUM_ACCEPTED_HEIGHT)
|| maxY > (extendedHeight ? MAXIMUM_ACCEPTED_HEIGHT_OVERWORLD : MAXIMUM_ACCEPTED_HEIGHT)) {
// (Ignore this for the Nether. We can't change that at the moment without the workaround. :/ )
if (minY < bedrockDimension.minY() || (bedrockDimension.doUpperHeightWarn() && maxY > bedrockDimension.height())) {
session.getGeyser().getLogger().warning(GeyserLocale.getLocaleStringLog("geyser.network.translator.chunk.out_of_bounds",
extendedHeight ? MINIMUM_ACCEPTED_HEIGHT_OVERWORLD : MINIMUM_ACCEPTED_HEIGHT,
extendedHeight ? MAXIMUM_ACCEPTED_HEIGHT_OVERWORLD : MAXIMUM_ACCEPTED_HEIGHT,
String.valueOf(bedrockDimension.minY()),
String.valueOf(bedrockDimension.height()),
session.getDimension()));
}

View File

@ -109,7 +109,7 @@ public class DimensionUtils {
// 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 (BEDROCK_NETHER_ID == 2) {
if (bedrockDimension == BEDROCK_NETHER_ID) {
if (NETHER.equals(javaDimension)) {
session.sendFog("minecraft:fog_hell");
} else if (previousDimension == BEDROCK_NETHER_ID) {
session.removeFog("minecraft:fog_hell");

View File

@ -7,6 +7,10 @@
"name" : "minecraft:acacia_button",
"id" : -140
},
{
"name" : "minecraft:acacia_chest_boat",
"id" : 637
},
{
"name" : "minecraft:acacia_door",
"id" : 556
@ -51,6 +55,10 @@
"name" : "minecraft:air",
"id" : -158
},
{
"name" : "minecraft:allay_spawn_egg",
"id" : 630
},
{
"name" : "minecraft:allow",
"id" : 210
@ -133,7 +141,7 @@
},
{
"name" : "minecraft:banner_pattern",
"id" : 628
"id" : 642
},
{
"name" : "minecraft:barrel",
@ -207,6 +215,10 @@
"name" : "minecraft:birch_button",
"id" : -141
},
{
"name" : "minecraft:birch_chest_boat",
"id" : 634
},
{
"name" : "minecraft:birch_door",
"id" : 554
@ -317,7 +329,7 @@
},
{
"name" : "minecraft:boat",
"id" : 626
"id" : 640
},
{
"name" : "minecraft:bone",
@ -363,10 +375,6 @@
"name" : "minecraft:brewing_stand",
"id" : 431
},
{
"name" : "minecraft:brewingstandblock",
"id" : 117
},
{
"name" : "minecraft:brick",
"id" : 383
@ -433,7 +441,7 @@
},
{
"name" : "minecraft:campfire",
"id" : 588
"id" : 589
},
{
"name" : "minecraft:candle",
@ -493,7 +501,7 @@
},
{
"name" : "minecraft:chain",
"id" : 618
"id" : 619
},
{
"name" : "minecraft:chain_command_block",
@ -531,6 +539,10 @@
"name" : "minecraft:chest",
"id" : 54
},
{
"name" : "minecraft:chest_boat",
"id" : 639
},
{
"name" : "minecraft:chest_minecart",
"id" : 389
@ -797,7 +809,7 @@
},
{
"name" : "minecraft:crimson_door",
"id" : 615
"id" : 616
},
{
"name" : "minecraft:crimson_double_slab",
@ -837,7 +849,7 @@
},
{
"name" : "minecraft:crimson_sign",
"id" : 613
"id" : 614
},
{
"name" : "minecraft:crimson_slab",
@ -907,6 +919,10 @@
"name" : "minecraft:dark_oak_button",
"id" : -142
},
{
"name" : "minecraft:dark_oak_chest_boat",
"id" : 638
},
{
"name" : "minecraft:dark_oak_door",
"id" : 557
@ -955,10 +971,6 @@
"name" : "minecraft:deadbush",
"id" : 32
},
{
"name" : "minecraft:debug_stick",
"id" : 590
},
{
"name" : "minecraft:deepslate",
"id" : -378
@ -1177,7 +1189,7 @@
},
{
"name" : "minecraft:dye",
"id" : 627
"id" : 641
},
{
"name" : "minecraft:egg",
@ -1705,7 +1717,7 @@
},
{
"name" : "minecraft:end_crystal",
"id" : 630
"id" : 644
},
{
"name" : "minecraft:end_gateway",
@ -1811,6 +1823,10 @@
"name" : "minecraft:fire_charge",
"id" : 509
},
{
"name" : "minecraft:firefly_spawn_egg",
"id" : 632
},
{
"name" : "minecraft:firework_rocket",
"id" : 519
@ -1863,6 +1879,14 @@
"name" : "minecraft:frame",
"id" : 513
},
{
"name" : "minecraft:frog_spawn",
"id" : -468
},
{
"name" : "minecraft:frog_spawn_egg",
"id" : 627
},
{
"name" : "minecraft:frosted_ice",
"id" : 207
@ -1899,13 +1923,17 @@
"name" : "minecraft:glistering_melon_slice",
"id" : 434
},
{
"name" : "minecraft:globe_banner_pattern",
"id" : 588
},
{
"name" : "minecraft:glow_berries",
"id" : 631
"id" : 645
},
{
"name" : "minecraft:glow_frame",
"id" : 622
"id" : 623
},
{
"name" : "minecraft:glow_ink_sac",
@ -1921,7 +1949,7 @@
},
{
"name" : "minecraft:glow_stick",
"id" : 166
"id" : 601
},
{
"name" : "minecraft:glowingobsidian",
@ -1935,10 +1963,6 @@
"name" : "minecraft:glowstone_dust",
"id" : 394
},
{
"name" : "minecraft:goat_horn",
"id" : 623
},
{
"name" : "minecraft:goat_spawn_egg",
"id" : 501
@ -2168,7 +2192,7 @@
"id" : 413
},
{
"name" : "minecraft:invisiblebedrock",
"name" : "minecraft:invisible_bedrock",
"id" : 95
},
{
@ -2255,6 +2279,10 @@
"name" : "minecraft:item.birch_door",
"id" : 194
},
{
"name" : "minecraft:item.brewing_stand",
"id" : 117
},
{
"name" : "minecraft:item.cake",
"id" : 92
@ -2363,6 +2391,10 @@
"name" : "minecraft:jungle_button",
"id" : -143
},
{
"name" : "minecraft:jungle_chest_boat",
"id" : 635
},
{
"name" : "minecraft:jungle_door",
"id" : 555
@ -2577,7 +2609,7 @@
},
{
"name" : "minecraft:lodestone_compass",
"id" : 601
"id" : 602
},
{
"name" : "minecraft:log",
@ -2619,6 +2651,18 @@
"name" : "minecraft:magma_cube_spawn_egg",
"id" : 455
},
{
"name" : "minecraft:mangrove_leaves",
"id" : -472
},
{
"name" : "minecraft:mangrove_propagule",
"id" : -474
},
{
"name" : "minecraft:mangrove_propagule_hanging",
"id" : -476
},
{
"name" : "minecraft:medicine",
"id" : 599
@ -2688,9 +2732,33 @@
"id" : -175
},
{
"name" : "minecraft:movingblock",
"name" : "minecraft:moving_block",
"id" : 250
},
{
"name" : "minecraft:mud",
"id" : -473
},
{
"name" : "minecraft:mud_brick_double_slab",
"id" : -479
},
{
"name" : "minecraft:mud_brick_slab",
"id" : -478
},
{
"name" : "minecraft:mud_brick_stairs",
"id" : -480
},
{
"name" : "minecraft:mud_brick_wall",
"id" : -481
},
{
"name" : "minecraft:mud_bricks",
"id" : -475
},
{
"name" : "minecraft:mule_spawn_egg",
"id" : 466
@ -2731,9 +2799,13 @@
"name" : "minecraft:music_disc_mellohi",
"id" : 540
},
{
"name" : "minecraft:music_disc_otherside",
"id" : 626
},
{
"name" : "minecraft:music_disc_pigstep",
"id" : 619
"id" : 620
},
{
"name" : "minecraft:music_disc_stal",
@ -2759,14 +2831,6 @@
"name" : "minecraft:mycelium",
"id" : 110
},
{
"name" : "minecraft:mysterious_frame",
"id" : -466
},
{
"name" : "minecraft:mysterious_frame_slot",
"id" : -467
},
{
"name" : "minecraft:name_tag",
"id" : 548
@ -2793,7 +2857,7 @@
},
{
"name" : "minecraft:nether_sprouts",
"id" : 620
"id" : 621
},
{
"name" : "minecraft:nether_star",
@ -2813,7 +2877,7 @@
},
{
"name" : "minecraft:netherite_axe",
"id" : 606
"id" : 607
},
{
"name" : "minecraft:netherite_block",
@ -2821,43 +2885,43 @@
},
{
"name" : "minecraft:netherite_boots",
"id" : 611
},
{
"name" : "minecraft:netherite_chestplate",
"id" : 609
},
{
"name" : "minecraft:netherite_helmet",
"id" : 608
},
{
"name" : "minecraft:netherite_hoe",
"id" : 607
},
{
"name" : "minecraft:netherite_ingot",
"id" : 602
},
{
"name" : "minecraft:netherite_leggings",
"id" : 610
},
{
"name" : "minecraft:netherite_pickaxe",
"id" : 605
},
{
"name" : "minecraft:netherite_scrap",
"id" : 612
},
{
"name" : "minecraft:netherite_chestplate",
"id" : 610
},
{
"name" : "minecraft:netherite_helmet",
"id" : 609
},
{
"name" : "minecraft:netherite_hoe",
"id" : 608
},
{
"name" : "minecraft:netherite_ingot",
"id" : 603
},
{
"name" : "minecraft:netherite_leggings",
"id" : 611
},
{
"name" : "minecraft:netherite_pickaxe",
"id" : 606
},
{
"name" : "minecraft:netherite_scrap",
"id" : 613
},
{
"name" : "minecraft:netherite_shovel",
"id" : 604
"id" : 605
},
{
"name" : "minecraft:netherite_sword",
"id" : 603
"id" : 604
},
{
"name" : "minecraft:netherrack",
@ -2883,6 +2947,10 @@
"name" : "minecraft:oak_boat",
"id" : 375
},
{
"name" : "minecraft:oak_chest_boat",
"id" : 633
},
{
"name" : "minecraft:oak_sign",
"id" : 358
@ -2903,6 +2971,10 @@
"name" : "minecraft:ocelot_spawn_egg",
"id" : 451
},
{
"name" : "minecraft:ochre_froglight",
"id" : -471
},
{
"name" : "minecraft:orange_candle",
"id" : -414
@ -2943,6 +3015,10 @@
"name" : "minecraft:packed_ice",
"id" : 174
},
{
"name" : "minecraft:packed_mud",
"id" : -477
},
{
"name" : "minecraft:painting",
"id" : 357
@ -2959,6 +3035,10 @@
"name" : "minecraft:parrot_spawn_egg",
"id" : 478
},
{
"name" : "minecraft:pearlescent_froglight",
"id" : -469
},
{
"name" : "minecraft:phantom_membrane",
"id" : 574
@ -3008,7 +3088,7 @@
"id" : 33
},
{
"name" : "minecraft:pistonarmcollision",
"name" : "minecraft:piston_arm_collision",
"id" : 34
},
{
@ -3387,6 +3467,10 @@
"name" : "minecraft:redstone_wire",
"id" : 55
},
{
"name" : "minecraft:reinforced_deepslate",
"id" : -466
},
{
"name" : "minecraft:repeater",
"id" : 419
@ -3467,6 +3551,10 @@
"name" : "minecraft:scute",
"id" : 572
},
{
"name" : "minecraft:sea_lantern",
"id" : 169
},
{
"name" : "minecraft:sea_pickle",
"id" : -156
@ -3475,10 +3563,6 @@
"name" : "minecraft:seagrass",
"id" : -130
},
{
"name" : "minecraft:sealantern",
"id" : 169
},
{
"name" : "minecraft:shears",
"id" : 421
@ -3593,7 +3677,7 @@
},
{
"name" : "minecraft:soul_campfire",
"id" : 621
"id" : 622
},
{
"name" : "minecraft:soul_fire",
@ -3621,7 +3705,7 @@
},
{
"name" : "minecraft:spawn_egg",
"id" : 629
"id" : 643
},
{
"name" : "minecraft:spider_eye",
@ -3651,6 +3735,10 @@
"name" : "minecraft:spruce_button",
"id" : -144
},
{
"name" : "minecraft:spruce_chest_boat",
"id" : 636
},
{
"name" : "minecraft:spruce_door",
"id" : 553
@ -3720,7 +3808,7 @@
"id" : 29
},
{
"name" : "minecraft:stickypistonarmcollision",
"name" : "minecraft:sticky_piston_arm_collision",
"id" : -217
},
{
@ -3845,7 +3933,7 @@
},
{
"name" : "minecraft:suspicious_stew",
"id" : 589
"id" : 590
},
{
"name" : "minecraft:sweet_berries",
@ -3855,6 +3943,14 @@
"name" : "minecraft:sweet_berry_bush",
"id" : -207
},
{
"name" : "minecraft:tadpole_bucket",
"id" : 629
},
{
"name" : "minecraft:tadpole_spawn_egg",
"id" : 628
},
{
"name" : "minecraft:tallgrass",
"id" : 31
@ -3896,7 +3992,7 @@
"id" : 546
},
{
"name" : "minecraft:tripwire",
"name" : "minecraft:trip_wire",
"id" : 132
},
{
@ -3959,6 +4055,10 @@
"name" : "minecraft:unpowered_repeater",
"id" : 93
},
{
"name" : "minecraft:verdant_froglight",
"id" : -470
},
{
"name" : "minecraft:vex_spawn_egg",
"id" : 476
@ -3987,13 +4087,17 @@
"name" : "minecraft:wandering_trader_spawn_egg",
"id" : 492
},
{
"name" : "minecraft:warden_spawn_egg",
"id" : 631
},
{
"name" : "minecraft:warped_button",
"id" : -261
},
{
"name" : "minecraft:warped_door",
"id" : 616
"id" : 617
},
{
"name" : "minecraft:warped_double_slab",
@ -4013,7 +4117,7 @@
},
{
"name" : "minecraft:warped_fungus_on_a_stick",
"id" : 617
"id" : 618
},
{
"name" : "minecraft:warped_hyphae",
@ -4037,7 +4141,7 @@
},
{
"name" : "minecraft:warped_sign",
"id" : 614
"id" : 615
},
{
"name" : "minecraft:warped_slab",