You can connect now. Command translation doesn't work though.

This commit is contained in:
Camotoy 2022-12-23 16:18:48 -05:00
parent ebcb82c7e7
commit 08c15a86ec
No known key found for this signature in database
GPG Key ID: 7EEFB66FE798081F
23 changed files with 174 additions and 128 deletions

View File

@ -37,7 +37,7 @@ import java.util.Map;
public final class GeyserDirtyMetadata {
private final Map<EntityDataType<?>, Object> metadata = new Object2ObjectLinkedOpenHashMap<>();
public void put(EntityDataType<?> entityData, Object value) {
public <T> void put(EntityDataType<T> entityData, T value) {
metadata.put(entityData, value);
}

View File

@ -73,7 +73,7 @@ public class BoatEntity extends Entity {
super(session, entityId, geyserId, uuid, definition, position.add(0d, definition.offset(), 0d), motion, yaw + 90, 0, yaw + 90);
// Required to be able to move on land 1.16.200+ or apply gravity not in the water 1.16.100+
dirtyMetadata.put(EntityDataTypes.IS_BUOYANT, (byte) 1);
dirtyMetadata.put(EntityDataTypes.IS_BUOYANT, true);
dirtyMetadata.put(EntityDataTypes.BUOYANCY_DATA, BUOYANCY_DATA);
}

View File

@ -50,7 +50,7 @@ public class CommandBlockMinecartEntity extends DefaultBlockMinecartEntity {
dirtyMetadata.put(EntityDataTypes.CONTAINER_TYPE, (byte) 16);
dirtyMetadata.put(EntityDataTypes.CONTAINER_SIZE, 1);
// Required, or else the client does not bother to send a packet back with the new information
dirtyMetadata.put(EntityDataTypes.COMMAND_BLOCK_ENABLED, (byte) 1);
dirtyMetadata.put(EntityDataTypes.COMMAND_BLOCK_ENABLED, true);
}
/**

View File

@ -62,7 +62,7 @@ public class ThrownPotionEntity extends ThrowableItemEntity {
if (potionTag instanceof StringTag) {
Potion potion = Potion.getByJavaIdentifier(((StringTag) potionTag).getValue());
if (potion != null) {
dirtyMetadata.put(EntityDataTypes.EFFECT_COLOR, potion.getBedrockId());
dirtyMetadata.put(EntityDataTypes.EFFECT_COLOR, (int) potion.getBedrockId());
setFlag(EntityFlag.ENCHANTED, !NON_ENCHANTED_POTIONS.contains(potion));
} else {
dirtyMetadata.put(EntityDataTypes.EFFECT_COLOR, 0);

View File

@ -47,13 +47,13 @@ public class TippedArrowEntity extends AbstractArrowEntity {
int potionColor = entityMetadata.getPrimitiveValue();
// -1 means no color
if (potionColor == -1) {
dirtyMetadata.put(EntityDataTypes.CUSTOM_DISPLAY, 0);
dirtyMetadata.put(EntityDataTypes.CUSTOM_DISPLAY, (byte) 0);
} else {
TippedArrowPotion potion = TippedArrowPotion.getByJavaColor(potionColor);
if (potion != null && potion.getJavaColor() != -1) {
dirtyMetadata.put(EntityDataTypes.CUSTOM_DISPLAY, (byte) potion.getBedrockId());
} else {
dirtyMetadata.put(EntityDataTypes.CUSTOM_DISPLAY, 0);
dirtyMetadata.put(EntityDataTypes.CUSTOM_DISPLAY, (byte) 0);
}
}
}

View File

@ -47,7 +47,7 @@ public class ShulkerEntity extends GolemEntity {
public void setAttachedFace(EntityMetadata<Direction, ?> entityMetadata) {
Direction direction = entityMetadata.getValue();
dirtyMetadata.put(EntityDataTypes.SHULKER_ATTACH_FACE, (byte) direction.ordinal());
dirtyMetadata.put(EntityDataTypes.SHULKER_ATTACH_FACE, direction.ordinal());
}
public void setShulkerHeight(ByteEntityMetadata entityMetadata) {
@ -56,7 +56,7 @@ public class ShulkerEntity extends GolemEntity {
}
public void setShulkerColor(ByteEntityMetadata entityMetadata) {
byte color = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
byte color = entityMetadata.getPrimitiveValue();
if (color == 16) {
// 16 is default on both editions
dirtyMetadata.put(EntityDataTypes.VARIANT, 16);

View File

@ -288,7 +288,7 @@ public class PlayerEntity extends LivingEntity {
ParrotEntity parrot = new ParrotEntity(session, 0, session.getEntityCache().getNextEntityId().incrementAndGet(),
null, EntityDefinitions.PARROT, position, motion, getYaw(), getPitch(), getHeadYaw());
parrot.spawnEntity();
parrot.getDirtyMetadata().put(EntityDataTypes.VARIANT, tag.get("Variant").getValue());
parrot.getDirtyMetadata().put(EntityDataTypes.VARIANT, (Integer) tag.get("Variant").getValue());
// Different position whether the parrot is left or right
float offset = isLeft ? 0.4f : -0.4f;
parrot.getDirtyMetadata().put(EntityDataTypes.SEAT_OFFSET, Vector3f.from(offset, -0.22, -0.1));

View File

@ -244,9 +244,9 @@ public class SessionPlayerEntity extends PlayerEntity {
if (pos != null) {
dirtyMetadata.put(EntityDataTypes.PLAYER_LAST_DEATH_POS, pos.getPosition());
dirtyMetadata.put(EntityDataTypes.PLAYER_LAST_DEATH_DIMENSION, DimensionUtils.javaToBedrock(pos.getDimension()));
dirtyMetadata.put(EntityDataTypes.PLAYER_HAS_DIED, (byte) 1);
dirtyMetadata.put(EntityDataTypes.PLAYER_HAS_DIED, true);
} else {
dirtyMetadata.put(EntityDataTypes.PLAYER_HAS_DIED, (byte) 0);
dirtyMetadata.put(EntityDataTypes.PLAYER_HAS_DIED, false);
}
}
}

View File

@ -92,9 +92,10 @@ public class GeyserItemStack {
}
public ItemData getItemData(GeyserSession session) {
ItemData itemData = ItemTranslator.translateToBedrock(session, getItemStack());
itemData.setNetId(getNetId());
return itemData;
ItemData.Builder itemData = ItemTranslator.translateToBedrock(session, javaId, amount, nbt);
itemData.netId(getNetId());
itemData.usingNetId(true);
return itemData.build();
}
public ItemMapping getMapping(GeyserSession session) {

View File

@ -28,8 +28,6 @@ package org.geysermc.geyser.network;
import io.netty.channel.DefaultEventLoopGroup;
import io.netty.util.concurrent.DefaultThreadFactory;
import org.cloudburstmc.protocol.bedrock.BedrockServerSession;
import org.cloudburstmc.protocol.bedrock.codec.v554.Bedrock_v554;
import org.cloudburstmc.protocol.bedrock.data.PacketCompressionAlgorithm;
import org.cloudburstmc.protocol.bedrock.netty.initializer.BedrockServerInitializer;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.session.GeyserSession;
@ -72,14 +70,9 @@ public class GeyserServerInitializer extends BedrockServerInitializer {
@Override
public void initSession(@Nonnull BedrockServerSession bedrockServerSession) {
System.out.println("init session");
try {
bedrockServerSession.setCodec(Bedrock_v554.CODEC); // Has the RequestNetworkSettingsPacket
bedrockServerSession.setLogging(true);
bedrockServerSession.setPacketHandler(new UpstreamPacketHandler(this.geyser, new GeyserSession(this.geyser, bedrockServerSession, this.eventLoopGroup.next())));
bedrockServerSession.setCompression(PacketCompressionAlgorithm.ZLIB);
bedrockServerSession.setCompressionLevel(this.geyser.getConfig().getBedrock().getCompressionLevel());
// Set the packet codec to default just in case we need to send disconnect packets.
} catch (Throwable e) {
// Error must be caught or it will be swallowed
this.geyser.getLogger().error("Error occurred while initializing player!", e);

View File

@ -73,7 +73,8 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
}
private PacketSignal translateAndDefault(BedrockPacket packet) {
return Registries.BEDROCK_PACKET_TRANSLATORS.translate(packet.getClass(), packet, session) ? PacketSignal.HANDLED : PacketSignal.UNHANDLED;
Registries.BEDROCK_PACKET_TRANSLATORS.translate(packet.getClass(), packet, session);
return PacketSignal.HANDLED; // PacketSignal.UNHANDLED will log a WARN publicly
}
@Override
@ -109,6 +110,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
} else if (BedrockDisconnectReasons.TIMEOUT.equals(reason)) {
this.session.getUpstream().getSession().setDisconnectReason(GeyserLocale.getLocaleStringLog("geyser.network.disconnect.timed_out"));
}
this.session.disconnect(this.session.getUpstream().getSession().getDisconnectReason());
}
@Override
@ -128,6 +130,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
session.sendUpstreamPacketImmediately(responsePacket);
session.getUpstream().getSession().setCompression(algorithm);
session.getUpstream().getSession().setCompressionLevel(this.geyser.getConfig().getBedrock().getCompressionLevel());
return PacketSignal.HANDLED;
}
@ -139,6 +142,8 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
return PacketSignal.HANDLED;
}
// session.getUpstream().getSession().getCodec() == null
if (!newProtocol) {
if (!setCorrectCodec(loginPacket.getProtocolVersion())) { // REMOVE WHEN ONLY 1.19.30 IS SUPPORTED OR 1.20
return PacketSignal.HANDLED;

View File

@ -27,9 +27,7 @@ package org.geysermc.geyser.registry;
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundTabListPacket;
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundLightUpdatePacket;
import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket;
import io.netty.channel.EventLoop;
import org.geysermc.common.PlatformType;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.registry.loader.RegistryLoaders;
import org.geysermc.geyser.session.GeyserSession;
@ -68,9 +66,10 @@ public class PacketTranslatorRegistry<T> extends AbstractMappedRegistry<Class<?
}
return true;
} else {
if ((GeyserImpl.getInstance().getPlatformType() != PlatformType.STANDALONE || !(packet instanceof BedrockPacket)) && !IGNORED_PACKETS.contains(clazz)) {
// Other debug logs already take care of Bedrock packets for us if on standalone
GeyserImpl.getInstance().getLogger().debug("Could not find packet for " + (packet.toString().length() > 25 ? packet.getClass().getSimpleName() : packet));
if (GeyserImpl.getInstance().getConfig().isDebugMode()) {
if (!IGNORED_PACKETS.contains(clazz)) {
GeyserImpl.getInstance().getLogger().debug("Could not find packet for " + (packet.toString().length() > 25 ? packet.getClass().getSimpleName() : packet));
}
}
return false;

View File

@ -28,22 +28,13 @@ package org.geysermc.geyser.registry.populator;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.google.common.collect.ImmutableMap;
import org.cloudburstmc.nbt.NBTInputStream;
import org.cloudburstmc.nbt.NbtList;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.nbt.NbtType;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectMaps;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectIntPair;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import it.unimi.dsi.fastutil.objects.*;
import org.cloudburstmc.nbt.*;
import org.cloudburstmc.protocol.bedrock.codec.v544.Bedrock_v544;
import org.cloudburstmc.protocol.bedrock.codec.v560.Bedrock_v560;
import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition;
import org.cloudburstmc.protocol.bedrock.data.defintions.SimpleBlockDefinition;
import org.cloudburstmc.protocol.common.SimpleDefinitionRegistry;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.level.block.BlockStateValues;
@ -51,6 +42,7 @@ import org.geysermc.geyser.level.physics.PistonBehavior;
import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.registry.type.BlockMapping;
import org.geysermc.geyser.registry.type.BlockMappings;
import org.geysermc.geyser.registry.type.GeyserBedrockBlock;
import org.geysermc.geyser.util.BlockUtils;
import java.io.DataInputStream;
@ -93,7 +85,7 @@ public final class BlockRegistryPopulator {
}
// New since 1.16.100 - find the block runtime ID by the order given to us in the block palette,
// as we no longer send a block palette
Object2ObjectMap<NbtMap, BlockDefinition> blockStateOrderedMap = new Object2ObjectOpenHashMap<>(blocksTag.size());
Object2ObjectMap<NbtMap, GeyserBedrockBlock> blockStateOrderedMap = new Object2ObjectOpenHashMap<>(blocksTag.size());
int stateVersion = -1;
for (int i = 0; i < blocksTag.size(); i++) {
@ -103,14 +95,15 @@ public final class BlockRegistryPopulator {
if (blockStateOrderedMap.containsKey(tag)) {
throw new AssertionError("Duplicate block states in Bedrock palette: " + tag);
}
blockStateOrderedMap.put(tag, new SimpleBlockDefinition(tag.getString("name"), i, tag));
GeyserBedrockBlock block = new GeyserBedrockBlock(i, tag);
blockStateOrderedMap.put(tag, block);
if (stateVersion == -1) {
stateVersion = tag.getInt("version");
}
}
int javaRuntimeId = -1;
BlockDefinition airDefinition = null;
GeyserBedrockBlock airDefinition = null;
BlockDefinition commandBlockDefinition = null;
BlockDefinition waterDefinition = null;
BlockDefinition movingBlockDefinition = null;
@ -118,7 +111,7 @@ public final class BlockRegistryPopulator {
BiFunction<String, NbtMapBuilder, String> stateMapper = blockMappers.getOrDefault(palette.getKey(), emptyMapper);
BlockDefinition[] javaToBedrockBlocks = new BlockDefinition[BLOCKS_JSON.size()];
GeyserBedrockBlock[] javaToBedrockBlocks = new GeyserBedrockBlock[BLOCKS_JSON.size()];
SimpleDefinitionRegistry.Builder<BlockDefinition> registry = SimpleDefinitionRegistry.builder();
Map<String, NbtMap> flowerPotBlocks = new Object2ObjectOpenHashMap<>();
@ -132,7 +125,7 @@ public final class BlockRegistryPopulator {
Map.Entry<String, JsonNode> entry = blocksIterator.next();
String javaId = entry.getKey();
BlockDefinition bedrockDefinition = blockStateOrderedMap.get(buildBedrockState(entry.getValue(), stateVersion, stateMapper));
GeyserBedrockBlock bedrockDefinition = blockStateOrderedMap.get(buildBedrockState(entry.getValue(), stateVersion, stateMapper));
if (bedrockDefinition == null) {
throw new RuntimeException("Unable to find " + javaId + " Bedrock BlockDefinition! Built NBT tag: \n" +
buildBedrockState(entry.getValue(), stateVersion, stateMapper));

View File

@ -34,7 +34,6 @@ import org.geysermc.geyser.GeyserBootstrap;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.registry.type.BlockMappings;
import org.geysermc.geyser.registry.type.ItemMappings;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@ -80,7 +79,7 @@ public class CreativeItemRegistryPopulator {
private static ItemData.Builder createItemData(JsonNode itemNode, BlockMappings blockMappings, Map<String, ItemDefinition> definitions) {
int count = 1;
int damage = 0;
int blockRuntimeId = 0;
int bedrockBlockRuntimeId = 0;
NbtMap tag = null;
JsonNode damageNode = itemNode.get("damage");
if (damageNode != null) {
@ -94,7 +93,7 @@ public class CreativeItemRegistryPopulator {
JsonNode blockRuntimeIdNode = itemNode.get("blockRuntimeId");
if (blockRuntimeIdNode != null) {
blockRuntimeId = blockRuntimeIdNode.asInt();
bedrockBlockRuntimeId = blockRuntimeIdNode.asInt();
}
JsonNode nbtNode = itemNode.get("nbt_b64");
@ -126,6 +125,6 @@ public class CreativeItemRegistryPopulator {
.damage(damage)
.count(count)
.tag(tag)
.blockDefinition(blockMappings.getBedrockBlock(blockRuntimeId));
.blockDefinition(blockMappings.getDefinitionRegistry().getDefinition(bedrockBlockRuntimeId));
}
}

View File

@ -29,6 +29,7 @@ import com.fasterxml.jackson.core.type.TypeReference;
import com.google.common.collect.Multimap;
import com.google.common.collect.MultimapBuilder;
import it.unimi.dsi.fastutil.Pair;
import it.unimi.dsi.fastutil.objects.*;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.nbt.NbtType;
@ -37,15 +38,10 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import org.cloudburstmc.protocol.bedrock.codec.v544.Bedrock_v544;
import org.cloudburstmc.protocol.bedrock.codec.v560.Bedrock_v560;
import org.cloudburstmc.protocol.bedrock.data.SoundEvent;
import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition;
import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.inventory.ComponentItemData;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
@ -141,7 +137,7 @@ public class ItemRegistryPopulator {
registry.add(definition);
}
Object2IntMap<String> bedrockBlockIdOverrides = new Object2IntOpenHashMap<>();
Object2ObjectMap<String, BlockDefinition> bedrockBlockIdOverrides = new Object2ObjectOpenHashMap<>();
Object2IntMap<String> blacklistedIdentifiers = new Object2IntOpenHashMap<>();
List<ItemDefinition> boats = new ObjectArrayList<>();
@ -157,7 +153,7 @@ public class ItemRegistryPopulator {
AtomicInteger creativeNetId = new AtomicInteger();
CreativeItemRegistryPopulator.populate(palette, definitions, itemBuilder -> {
ItemData item = itemBuilder.netId(creativeNetId.getAndIncrement()).build();
ItemData item = itemBuilder.netId(creativeNetId.incrementAndGet()).build();
creativeItems.add(item);
if (item.getBlockDefinition() != null) {
@ -166,12 +162,12 @@ public class ItemRegistryPopulator {
// Add override for item mapping, unless it already exists... then we know multiple states can exist
if (!blacklistedIdentifiers.containsKey(identifier)) {
if (bedrockBlockIdOverrides.containsKey(identifier)) {
bedrockBlockIdOverrides.removeInt(identifier);
bedrockBlockIdOverrides.remove(identifier);
// Save this as a blacklist, but also as knowledge of what the block state name should be
blacklistedIdentifiers.put(identifier, item.getBlockDefinition().getRuntimeId());
} else {
// Unless there's multiple possibilities for this one state, let this be
bedrockBlockIdOverrides.put(identifier, item.getBlockDefinition().getRuntimeId());
bedrockBlockIdOverrides.put(identifier, item.getBlockDefinition());
}
}
}
@ -221,19 +217,19 @@ public class ItemRegistryPopulator {
int stackSize = mappingItem.getStackSize();
int bedrockBlockId = -1;
BlockDefinition bedrockBlock = null;
Integer firstBlockRuntimeId = entry.getValue().getFirstBlockRuntimeId();
if (firstBlockRuntimeId != null) {
int blockIdOverride = bedrockBlockIdOverrides.getOrDefault(bedrockIdentifier, -1);
if (blockIdOverride != -1) {
BlockDefinition blockOverride = bedrockBlockIdOverrides.get(bedrockIdentifier);
if (blockOverride != null) {
// Straight from BDS is our best chance of getting an item that doesn't run into issues
bedrockBlockId = blockIdOverride;
bedrockBlock = blockOverride;
} else {
// Try to get an example block runtime ID from the creative contents packet, for Bedrock identifier obtaining
int aValidBedrockBlockId = blacklistedIdentifiers.getOrDefault(bedrockIdentifier, -1);
if (aValidBedrockBlockId == -1) {
// Fallback
bedrockBlockId = blockMappings.getBedrockBlockId(firstBlockRuntimeId);
bedrockBlock = blockMappings.getBedrockBlock(firstBlockRuntimeId);
} else {
// As of 1.16.220, every item requires a block runtime ID attached to it.
// This is mostly for identifying different blocks with the same item ID - wool, slabs, some walls.
@ -247,8 +243,8 @@ public class ItemRegistryPopulator {
// and the last, if relevant. We then iterate over all those values and get their Bedrock equivalents
Integer lastBlockRuntimeId = entry.getValue().getLastBlockRuntimeId() == null ? firstBlockRuntimeId : entry.getValue().getLastBlockRuntimeId();
for (int i = firstBlockRuntimeId; i <= lastBlockRuntimeId; i++) {
int bedrockBlockRuntimeId = blockMappings.getBedrockBlockId(i);
NbtMap blockTag = blockMappings.getBedrockBlockPalette().get(bedrockBlockRuntimeId);
GeyserBedrockBlock bedrockBlockRuntimeId = blockMappings.getBedrockBlock(i);
NbtMap blockTag = bedrockBlockRuntimeId.getState();
String bedrockName = blockTag.getString("name");
if (!bedrockName.equals(correctBedrockIdentifier)) {
continue;
@ -259,7 +255,7 @@ public class ItemRegistryPopulator {
firstPass = false;
if (states.size() == 0) {
// No need to iterate and find all block states - this is the one, as there can't be any others
bedrockBlockId = bedrockBlockRuntimeId;
bedrockBlock = bedrockBlockRuntimeId;
break;
}
requiredBlockStatesBuilder.putAll(states);
@ -282,7 +278,7 @@ public class ItemRegistryPopulator {
}
NbtMap requiredBlockStates = requiredBlockStatesBuilder.build();
if (bedrockBlockId == -1) {
if (bedrockBlock == null) {
int i = -1;
// We need to loop around again (we can't cache the block tags above) because Bedrock can include states that we don't have a pairing for
// in it's "preferred" block state - I.E. the first matching block state in the list
@ -299,12 +295,12 @@ public class ItemRegistryPopulator {
}
}
if (valid) {
bedrockBlockId = i;
bedrockBlock = blockMappings.getDefinitionRegistry().getDefinition(i);
break;
}
}
}
if (bedrockBlockId == -1) {
if (bedrockBlock == null) {
throw new RuntimeException("Could not find a block match for " + entry.getKey());
}
}
@ -328,7 +324,7 @@ public class ItemRegistryPopulator {
}
}
if (valid) {
creativeItems.set(j, itemData.toBuilder().blockDefinition(blockMappings.getBedrockBlock(bedrockBlockId)).build());
creativeItems.set(j, itemData.toBuilder().blockDefinition(bedrockBlock).build());
break;
}
}
@ -343,7 +339,7 @@ public class ItemRegistryPopulator {
.bedrockIdentifier(bedrockIdentifier.intern())
.bedrockDefinition(definition)
.bedrockData(mappingItem.getBedrockData())
.bedrockBlockDefinition(blockMappings.getBedrockBlock(bedrockBlockId))
.bedrockBlockDefinition(bedrockBlock)
.stackSize(stackSize)
.maxDamage(mappingItem.getMaxDamage())
.hasSuspiciousStewEffect(mappingItem.isHasSuspiciousStewEffect());
@ -364,7 +360,7 @@ public class ItemRegistryPopulator {
if (javaOnlyItems.contains(javaIdentifier)) {
// These items don't exist on Bedrock, so set up a variable that indicates they should have custom names
mappingBuilder = mappingBuilder.translationString((bedrockBlockId != -1 ? "block." : "item.") + entry.getKey().replace(":", "."));
mappingBuilder = mappingBuilder.translationString((bedrockBlock != null ? "block." : "item.") + entry.getKey().replace(":", "."));
GeyserImpl.getInstance().getLogger().debug("Adding " + entry.getKey() + " as an item that needs to be translated.");
}

View File

@ -30,7 +30,6 @@ import lombok.Value;
import org.cloudburstmc.nbt.NbtList;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition;
import org.cloudburstmc.protocol.bedrock.data.defintions.SimpleBlockDefinition;
import org.cloudburstmc.protocol.common.DefinitionRegistry;
import java.util.Map;
@ -39,13 +38,13 @@ import java.util.Set;
@Builder
@Value
public class BlockMappings {
BlockDefinition bedrockAir;
GeyserBedrockBlock bedrockAir;
BlockDefinition bedrockWater;
BlockDefinition bedrockMovingBlock;
int blockStateVersion;
BlockDefinition[] javaToBedrockBlocks;
GeyserBedrockBlock[] javaToBedrockBlocks;
DefinitionRegistry<BlockDefinition> definitionRegistry;
NbtList<NbtMap> bedrockBlockPalette;
@ -57,18 +56,15 @@ public class BlockMappings {
Set<BlockDefinition> jigsawStates;
public int getBedrockBlockId(int state) {
if (state < 0 || state >= this.javaToBedrockBlocks.length) {
return bedrockAir.getRuntimeId();
}
return this.javaToBedrockBlocks[state].getRuntimeId();
public int getBedrockBlockId(int javaState) {
return getBedrockBlock(javaState).getRuntimeId();
}
public BlockDefinition getBedrockBlock(int state) {
if (state < 0 || state >= this.javaToBedrockBlocks.length) {
public GeyserBedrockBlock getBedrockBlock(int javaState) {
if (javaState < 0 || javaState >= this.javaToBedrockBlocks.length) {
return bedrockAir;
}
return this.javaToBedrockBlocks[state];
return this.javaToBedrockBlocks[javaState];
}
public BlockDefinition getItemFrame(NbtMap tag) {
@ -76,7 +72,7 @@ public class BlockMappings {
}
public boolean isItemFrame(BlockDefinition definition) {
if (definition instanceof SimpleBlockDefinition def) {
if (definition instanceof GeyserBedrockBlock def) {
return this.itemFrames.containsKey(def.getState());
}

View File

@ -0,0 +1,53 @@
/*
* 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.registry.type;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition;
public class GeyserBedrockBlock implements BlockDefinition {
private final int runtimeId;
private final NbtMap state;
public GeyserBedrockBlock(int runtimeId, NbtMap state) {
this.runtimeId = runtimeId;
this.state = state;
}
@Override
public int getRuntimeId() {
return runtimeId;
}
public NbtMap getState() {
return state;
}
@Override
public String toString() {
return "GeyserBedrockBlock{" + state.getString("name") + "}";
}
}

View File

@ -89,19 +89,11 @@ import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.protocol.bedrock.BedrockServerSession;
import org.cloudburstmc.protocol.bedrock.data.Ability;
import org.cloudburstmc.protocol.bedrock.data.AbilityLayer;
import org.cloudburstmc.protocol.bedrock.data.AttributeData;
import org.cloudburstmc.protocol.bedrock.data.AuthoritativeMovementMode;
import org.cloudburstmc.protocol.bedrock.data.ChatRestrictionLevel;
import org.cloudburstmc.protocol.bedrock.data.GamePublishSetting;
import org.cloudburstmc.protocol.bedrock.data.GameRuleData;
import org.cloudburstmc.protocol.bedrock.data.GameType;
import org.cloudburstmc.protocol.bedrock.data.PlayerPermission;
import org.cloudburstmc.protocol.bedrock.data.SoundEvent;
import org.cloudburstmc.protocol.bedrock.data.*;
import org.cloudburstmc.protocol.bedrock.data.command.CommandPermission;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.cloudburstmc.protocol.bedrock.packet.*;
import org.cloudburstmc.protocol.common.util.OptionalBoolean;
import org.geysermc.api.util.BedrockPlatform;
import org.geysermc.api.util.InputMode;
import org.geysermc.api.util.UiProfile;
@ -879,14 +871,13 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
downstream = new LocalSession(this.remoteServer.address(), this.remoteServer.port(),
geyser.getBootstrap().getSocketAddress(), upstream.getAddress().getAddress().getHostAddress(),
this.protocol, this.protocol.createHelper());
this.downstream = new DownstreamSession(downstream);
} else {
downstream = new TcpClientSession(this.remoteServer.address(), this.remoteServer.port(), this.protocol);
this.downstream = new DownstreamSession(downstream);
disableSrvResolving();
}
// Wrap in DownstreamSession
this.downstream = new DownstreamSession(downstream);
if (geyser.getConfig().getRemote().isUseProxyProtocol()) {
downstream.setFlag(BuiltinFlags.ENABLE_CLIENT_PROXY_PROTOCOL, true);
downstream.setFlag(BuiltinFlags.CLIENT_PROXIED_ADDRESS, upstream.getAddress());
@ -1473,6 +1464,10 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
startGamePacket.setUsingMsaGamertagsOnly(false);
startGamePacket.setFromWorldTemplate(false);
startGamePacket.setWorldTemplateOptionLocked(false);
startGamePacket.setSpawnBiomeType(SpawnBiomeType.DEFAULT);
startGamePacket.setCustomBiomeName("");
startGamePacket.setEducationProductionId("");
startGamePacket.setForceExperimentalGameplay(OptionalBoolean.empty());
String serverName = geyser.getConfig().getBedrock().serverName();
startGamePacket.setLevelId(serverName);

View File

@ -147,6 +147,16 @@ public abstract class ItemTranslator {
return itemStack;
}
@Nonnull
public static ItemData.Builder translateToBedrock(GeyserSession session, int javaId, int count, CompoundTag tag) {
ItemMapping bedrockItem = session.getItemMappings().getMapping(javaId);
if (bedrockItem == ItemMapping.AIR) {
session.getGeyser().getLogger().debug("ItemMapping returned air: " + javaId);
return ItemData.builder();
}
return translateToBedrock(session, bedrockItem, count, tag);
}
@Nonnull
public static ItemData translateToBedrock(GeyserSession session, ItemStack stack) {
if (stack == null) {
@ -154,38 +164,43 @@ public abstract class ItemTranslator {
}
ItemMapping bedrockItem = session.getItemMappings().getMapping(stack);
if (bedrockItem == null) {
session.getGeyser().getLogger().debug("No matching ItemMapping for " + stack);
if (bedrockItem == ItemMapping.AIR) {
session.getGeyser().getLogger().debug("ItemMapping returned air: " + stack);
return ItemData.AIR;
}
return translateToBedrock(session, bedrockItem, stack.getAmount(), stack.getNbt())
.build();
}
CompoundTag nbt = stack.getNbt() != null ? stack.getNbt().clone() : null;
@Nonnull
private static ItemData.Builder translateToBedrock(GeyserSession session, ItemMapping mapping, int count, CompoundTag tag) {
CompoundTag nbt = tag != null ? tag.clone() : null;
// This is a fallback for maps with no nbt
if (nbt == null && bedrockItem.getJavaIdentifier().equals("minecraft:filled_map")) {
if (nbt == null && mapping.getJavaIdentifier().equals("minecraft:filled_map")) {
nbt = new CompoundTag("");
nbt.put(new IntTag("map", 0));
}
if (nbt != null) {
for (NbtItemStackTranslator translator : NBT_TRANSLATORS) {
if (translator.acceptItem(bedrockItem)) {
translator.translateToBedrock(session, nbt, bedrockItem);
if (translator.acceptItem(mapping)) {
translator.translateToBedrock(session, nbt, mapping);
}
}
}
nbt = translateDisplayProperties(session, nbt, bedrockItem);
nbt = translateDisplayProperties(session, nbt, mapping);
if (session.isAdvancedTooltips()) {
nbt = addAdvancedTooltips(nbt, bedrockItem, session.locale());
nbt = addAdvancedTooltips(nbt, mapping, session.locale());
}
ItemStack itemStack = new ItemStack(stack.getId(), stack.getAmount(), nbt);
ItemStack itemStack = new ItemStack(mapping.getJavaId(), count, nbt);
ItemTranslator itemStackTranslator = ITEM_STACK_TRANSLATORS.getOrDefault(bedrockItem.getJavaId(), DEFAULT_TRANSLATOR);
ItemData.Builder builder = itemStackTranslator.translateToBedrock(itemStack, bedrockItem, session.getItemMappings());
if (bedrockItem.isBlock()) {
builder.blockDefinition(bedrockItem.getBedrockBlockDefinition());
ItemTranslator itemStackTranslator = ITEM_STACK_TRANSLATORS.getOrDefault(mapping.getJavaId(), DEFAULT_TRANSLATOR);
ItemData.Builder builder = itemStackTranslator.translateToBedrock(itemStack, mapping, session.getItemMappings());
if (mapping.isBlock()) {
builder.blockDefinition(mapping.getBedrockBlockDefinition());
}
if (nbt != null) {
@ -202,7 +217,7 @@ public abstract class ItemTranslator {
}
}
return builder.build();
return builder;
}
private static CompoundTag addAdvancedTooltips(CompoundTag nbt, ItemMapping mapping, String language) {

View File

@ -109,7 +109,7 @@ public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommands
@Override
public void translate(GeyserSession session, ClientboundCommandsPacket packet) {
// Don't send command suggestions if they are disabled
if (!session.getGeyser().getConfig().isCommandSuggestions()) {
if (!session.getGeyser().getConfig().isCommandSuggestions() || true) {
session.getGeyser().getLogger().debug("Not sending translated command suggestions as they are disabled.");
// Send an empty packet so Bedrock doesn't override /help with its own, built-in help command.

View File

@ -301,6 +301,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
// Allocate output buffer
byteBuf = ByteBufAllocator.DEFAULT.buffer(size);
byteBuf.retain();
for (int i = 0; i < sectionCount; i++) {
GeyserChunkSection section = sections[i];
if (section != null) {
@ -349,7 +350,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
levelChunkPacket.setCachingEnabled(false);
levelChunkPacket.setChunkX(packet.getX());
levelChunkPacket.setChunkZ(packet.getZ());
levelChunkPacket.setData(byteBuf);
levelChunkPacket.setData(byteBuf.retain());
session.sendUpstreamPacket(levelChunkPacket);
for (Map.Entry<Vector3i, ItemFrameEntity> entry : session.getItemFrameCache().entrySet()) {

View File

@ -25,17 +25,17 @@
package org.geysermc.geyser.util;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.Unpooled;
import it.unimi.dsi.fastutil.ints.IntLists;
import lombok.experimental.UtilityClass;
import org.cloudburstmc.math.vector.Vector2i;
import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition;
import org.cloudburstmc.protocol.bedrock.packet.LevelChunkPacket;
import org.cloudburstmc.protocol.bedrock.packet.NetworkChunkPublisherUpdatePacket;
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.Unpooled;
import it.unimi.dsi.fastutil.ints.IntLists;
import lombok.experimental.UtilityClass;
import org.geysermc.geyser.entity.type.ItemFrameEntity;
import org.geysermc.geyser.level.BedrockDimension;
import org.geysermc.geyser.level.JavaDimension;
@ -181,18 +181,18 @@ public class ChunkUtils {
}
byteBuf.writeByte(0); // Border blocks - Edu edition only
LevelChunkPacket data = new LevelChunkPacket();
data.setChunkX(chunkX);
data.setChunkZ(chunkZ);
data.setSubChunksLength(0);
data.setData(byteBuf.retain());
data.setCachingEnabled(false);
session.sendUpstreamPacket(data);
} finally {
byteBuf.release();
}
LevelChunkPacket data = new LevelChunkPacket();
data.setChunkX(chunkX);
data.setChunkZ(chunkZ);
data.setSubChunksLength(0);
data.setData(byteBuf);
data.setCachingEnabled(false);
session.sendUpstreamPacket(data);
if (forceUpdate) {
Vector3i pos = Vector3i.from(chunkX << 4, 80, chunkZ << 4);
UpdateBlockPacket blockPacket = new UpdateBlockPacket();

View File

@ -54,7 +54,6 @@ import org.geysermc.geyser.text.ChatColor;
import org.geysermc.geyser.text.GeyserLocale;
import javax.crypto.SecretKey;
import java.io.IOException;
import java.net.URI;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
@ -192,12 +191,13 @@ public class LoginEncryptionUtils {
KeyPair serverKeyPair = generator.generateKeyPair();
byte[] token = EncryptionUtils.generateRandomToken();
SecretKey encryptionKey = EncryptionUtils.getSecretKey(serverKeyPair.getPrivate(), key, token);
session.getUpstream().getSession().enableEncryption(encryptionKey);
ServerToClientHandshakePacket packet = new ServerToClientHandshakePacket();
packet.setJwt(EncryptionUtils.createHandshakeJwt(serverKeyPair, token).serialize());
session.sendUpstreamPacketImmediately(packet);
SecretKey encryptionKey = EncryptionUtils.getSecretKey(serverKeyPair.getPrivate(), key, token);
session.getUpstream().getSession().enableEncryption(encryptionKey);
}
private static void sendEncryptionFailedMessage(GeyserImpl geyser) {