Support for v588 client and mappings

This commit is contained in:
Konicai 2023-05-24 02:33:43 -04:00
parent f712d4dd81
commit a9d64de070
8 changed files with 11871 additions and 19 deletions

View file

@ -29,6 +29,7 @@ import com.github.steveice10.mc.protocol.codec.MinecraftCodec;
import com.github.steveice10.mc.protocol.codec.PacketCodec; import com.github.steveice10.mc.protocol.codec.PacketCodec;
import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec; import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec;
import org.cloudburstmc.protocol.bedrock.codec.v582.Bedrock_v582; import org.cloudburstmc.protocol.bedrock.codec.v582.Bedrock_v582;
import org.cloudburstmc.protocol.bedrock.codec.v588.Bedrock_v588;
import org.cloudburstmc.protocol.bedrock.netty.codec.packet.BedrockPacketCodec; import org.cloudburstmc.protocol.bedrock.netty.codec.packet.BedrockPacketCodec;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
@ -44,9 +45,8 @@ public final class GameProtocol {
* Default Bedrock codec that should act as a fallback. Should represent the latest available * Default Bedrock codec that should act as a fallback. Should represent the latest available
* release of the game that Geyser supports. * release of the game that Geyser supports.
*/ */
public static final BedrockCodec DEFAULT_BEDROCK_CODEC = Bedrock_v582.CODEC.toBuilder() public static final BedrockCodec DEFAULT_BEDROCK_CODEC = Bedrock_v588.CODEC;
.minecraftVersion("1.19.81")
.build();
/** /**
* A list of all supported Bedrock versions that can join Geyser * A list of all supported Bedrock versions that can join Geyser
*/ */
@ -59,9 +59,10 @@ public final class GameProtocol {
private static final PacketCodec DEFAULT_JAVA_CODEC = MinecraftCodec.CODEC; private static final PacketCodec DEFAULT_JAVA_CODEC = MinecraftCodec.CODEC;
static { static {
SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC.toBuilder() SUPPORTED_BEDROCK_CODECS.add(Bedrock_v582.CODEC.toBuilder()
.minecraftVersion("1.19.80/1.19.81") .minecraftVersion("1.19.80/1.19.81")
.build()); .build());
SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC);
} }
/** /**
@ -81,7 +82,7 @@ public final class GameProtocol {
/* Bedrock convenience methods to gatekeep features and easily remove the check on version removal */ /* Bedrock convenience methods to gatekeep features and easily remove the check on version removal */
public static boolean isPre1_20(GeyserSession session) { public static boolean isPre1_20(GeyserSession session) {
return session.getUpstream().getProtocolVersion() >= Bedrock_v582.CODEC.getProtocolVersion(); return session.getUpstream().getProtocolVersion() < Bedrock_v588.CODEC.getProtocolVersion();
} }
/** /**

View file

@ -33,6 +33,7 @@ import com.google.common.collect.Interners;
import it.unimi.dsi.fastutil.objects.*; import it.unimi.dsi.fastutil.objects.*;
import org.cloudburstmc.nbt.*; import org.cloudburstmc.nbt.*;
import org.cloudburstmc.protocol.bedrock.codec.v582.Bedrock_v582; import org.cloudburstmc.protocol.bedrock.codec.v582.Bedrock_v582;
import org.cloudburstmc.protocol.bedrock.codec.v588.Bedrock_v588;
import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition;
import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.block.BlockStateValues;
@ -67,8 +68,53 @@ public final class BlockRegistryPopulator {
private static void registerBedrockBlocks() { private static void registerBedrockBlocks() {
BiFunction<String, NbtMapBuilder, String> emptyMapper = (bedrockIdentifier, statesBuilder) -> null; BiFunction<String, NbtMapBuilder, String> emptyMapper = (bedrockIdentifier, statesBuilder) -> null;
// We are using mappings that directly support 1.20, so this maps it back to 1.19.80
BiFunction<String, NbtMapBuilder, String> legacyMapper = (bedrockIdentifier, statesBuilder) -> {
if (bedrockIdentifier.endsWith("pumpkin")) {
String direction = statesBuilder.remove("minecraft:cardinal_direction").toString();
statesBuilder.putInt("direction", switch (direction) {
case "north" -> 2;
case "east" -> 3;
case "west" -> 1;
default -> 0; // south
});
} else if (bedrockIdentifier.endsWith("carpet") && !bedrockIdentifier.startsWith("minecraft:moss")) {
String color = bedrockIdentifier.replace("minecraft:", "").replace("_carpet", "");
if (color.equals("light_gray")) {
color = "silver";
}
statesBuilder.putString("color", color);
return "minecraft:carpet";
} else if (bedrockIdentifier.equals("minecraft:sniffer_egg")) {
statesBuilder.remove("cracked_state");
return "minecraft:dragon_egg";
} else if (bedrockIdentifier.endsWith("coral")) {
statesBuilder.putString("coral_color", "blue"); // all blue
statesBuilder.putBoolean("dead_bit", bedrockIdentifier.startsWith("minecraft:dead"));
return "minecraft:coral";
} else if (bedrockIdentifier.endsWith("sculk_sensor")) {
int phase = (int) statesBuilder.remove("sculk_sensor_phase");
statesBuilder.putBoolean("powered_bit", phase != 0);
} else if (bedrockIdentifier.endsWith("pitcher_plant")) {
statesBuilder.putString("double_plant_type", "sunflower");
return "minecraft:double_plant";
} else if (bedrockIdentifier.endsWith("pitcher_crop")) {
statesBuilder.remove("growth");
if (((byte) statesBuilder.remove("upper_block_bit")) == 1){
statesBuilder.putString("flower_type", "orchid");
return "minecraft:red_flower"; // top
}
statesBuilder.putBoolean("update_bit", false);
return "minecraft:flower_pot"; // bottom
}
return null;
};
ImmutableMap<ObjectIntPair<String>, BiFunction<String, NbtMapBuilder, String>> blockMappers = ImmutableMap.<ObjectIntPair<String>, BiFunction<String, NbtMapBuilder, String>>builder() ImmutableMap<ObjectIntPair<String>, BiFunction<String, NbtMapBuilder, String>> blockMappers = ImmutableMap.<ObjectIntPair<String>, BiFunction<String, NbtMapBuilder, String>>builder()
.put(ObjectIntPair.of("1_19_80", Bedrock_v582.CODEC.getProtocolVersion()), emptyMapper) .put(ObjectIntPair.of("1_19_80", Bedrock_v582.CODEC.getProtocolVersion()), legacyMapper)
.put(ObjectIntPair.of("1_20_0", Bedrock_v588.CODEC.getProtocolVersion()), emptyMapper)
.build(); .build();
// We can keep this strong as nothing should be garbage collected // We can keep this strong as nothing should be garbage collected
@ -131,8 +177,8 @@ public final class BlockRegistryPopulator {
GeyserBedrockBlock bedrockDefinition = blockStateOrderedMap.get(buildBedrockState(entry.getValue(), stateVersion, stateMapper)); GeyserBedrockBlock bedrockDefinition = blockStateOrderedMap.get(buildBedrockState(entry.getValue(), stateVersion, stateMapper));
if (bedrockDefinition == null) { if (bedrockDefinition == null) {
throw new RuntimeException("Unable to find " + javaId + " Bedrock BlockDefinition! Built NBT tag: \n" + throw new RuntimeException("Unable to find " + javaId + " Bedrock BlockDefinition on version "
buildBedrockState(entry.getValue(), stateVersion, stateMapper)); + palette.getKey().key() + "! Built NBT tag: \n" + buildBedrockState(entry.getValue(), stateVersion, stateMapper));
} }
switch (javaId) { switch (javaId) {

View file

@ -34,10 +34,12 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet; import it.unimi.dsi.fastutil.ints.IntSet;
import it.unimi.dsi.fastutil.objects.*; import it.unimi.dsi.fastutil.objects.*;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.nbt.NbtType; import org.cloudburstmc.nbt.NbtType;
import org.cloudburstmc.protocol.bedrock.codec.v582.Bedrock_v582; import org.cloudburstmc.protocol.bedrock.codec.v582.Bedrock_v582;
import org.cloudburstmc.protocol.bedrock.codec.v588.Bedrock_v588;
import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition;
import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.definitions.SimpleItemDefinition; import org.cloudburstmc.protocol.bedrock.data.definitions.SimpleItemDefinition;
@ -66,12 +68,40 @@ import java.util.concurrent.atomic.AtomicInteger;
*/ */
public class ItemRegistryPopulator { public class ItemRegistryPopulator {
record PaletteVersion(int protocolVersion, Map<Item, String> additionalTranslatedItems) { record PaletteVersion(int protocolVersion, Map<Item, String> javaOnlyItems, Remapper remapper) {
public PaletteVersion(int protocolVersion) {
this(protocolVersion, Collections.emptyMap(), (item, mapping) -> mapping);
}
}
@FunctionalInterface
interface Remapper {
@NonNull
GeyserMappingItem remap(Item item, GeyserMappingItem mapping);
} }
public static void populate() { public static void populate() {
Map<Item, String> legacyJavaOnly = new HashMap<>();
legacyJavaOnly.put(Items.MUSIC_DISC_RELIC, "minecraft:music_disc_wait");
legacyJavaOnly.put(Items.PITCHER_PLANT, "minecraft:chorus_flower");
legacyJavaOnly.put(Items.PITCHER_POD, "minecraft:beetroot");
legacyJavaOnly.put(Items.SNIFFER_EGG, "minecraft:sniffer_spawn_egg"); // the BlockItem of the sniffer egg block
Map<String, PaletteVersion> paletteVersions = new Object2ObjectOpenHashMap<>(); Map<String, PaletteVersion> paletteVersions = new Object2ObjectOpenHashMap<>();
paletteVersions.put("1_19_80", new PaletteVersion(Bedrock_v582.CODEC.getProtocolVersion(), Collections.emptyMap())); paletteVersions.put("1_19_80", new PaletteVersion(Bedrock_v582.CODEC.getProtocolVersion(), legacyJavaOnly, (item, mapping) -> {
String id = item.javaIdentifier();
if (id.endsWith("pottery_sherd")) {
return mapping.withBedrockIdentifier(id.replace("sherd", "shard"));
} else if (id.endsWith("carpet") && !id.startsWith("minecraft:moss")) {
return mapping.withBedrockIdentifier("minecraft:carpet");
} else if (id.endsWith("coral")) {
return mapping.withBedrockIdentifier("minecraft:coral");
}
return mapping;
}));
paletteVersions.put("1_20_0", new PaletteVersion(Bedrock_v588.CODEC.getProtocolVersion()));
GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap(); GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap();
@ -168,12 +198,11 @@ public class ItemRegistryPopulator {
Set<Item> javaOnlyItems = new ObjectOpenHashSet<>(); Set<Item> javaOnlyItems = new ObjectOpenHashSet<>();
Collections.addAll(javaOnlyItems, Items.SPECTRAL_ARROW, Items.DEBUG_STICK, Collections.addAll(javaOnlyItems, Items.SPECTRAL_ARROW, Items.DEBUG_STICK,
Items.KNOWLEDGE_BOOK, Items.TIPPED_ARROW, Items.BUNDLE); Items.KNOWLEDGE_BOOK, Items.TIPPED_ARROW, Items.BUNDLE);
javaOnlyItems.add(Items.DECORATED_POT);
if (!customItemsAllowed) { if (!customItemsAllowed) {
javaOnlyItems.add(Items.FURNACE_MINECART); javaOnlyItems.add(Items.FURNACE_MINECART);
} }
// Java-only items for this version // Java-only items for this version
javaOnlyItems.addAll(palette.getValue().additionalTranslatedItems().keySet()); javaOnlyItems.addAll(palette.getValue().javaOnlyItems().keySet());
Int2ObjectMap<String> customIdMappings = new Int2ObjectOpenHashMap<>(); Int2ObjectMap<String> customIdMappings = new Int2ObjectOpenHashMap<>();
Set<String> registeredItemNames = new ObjectOpenHashSet<>(); // This is used to check for duplicate item names Set<String> registeredItemNames = new ObjectOpenHashSet<>(); // This is used to check for duplicate item names
@ -184,12 +213,12 @@ public class ItemRegistryPopulator {
throw new RuntimeException("Extra item in mappings? " + entry.getKey()); throw new RuntimeException("Extra item in mappings? " + entry.getKey());
} }
GeyserMappingItem mappingItem; GeyserMappingItem mappingItem;
String replacementItem = palette.getValue().additionalTranslatedItems().get(javaItem); String replacementItem = palette.getValue().javaOnlyItems().get(javaItem);
if (replacementItem != null) { if (replacementItem != null) {
mappingItem = items.get(replacementItem); mappingItem = items.get(replacementItem); // java only item, a java id fallback has been provided
} else { } else {
// This items has a mapping specifically for this version of the game // check if any mapping changes need to be made on this version
mappingItem = entry.getValue(); mappingItem = palette.getValue().remapper().remap(javaItem, entry.getValue());
} }
if (customItemsAllowed && javaItem == Items.FURNACE_MINECART) { if (customItemsAllowed && javaItem == Items.FURNACE_MINECART) {
@ -201,7 +230,7 @@ public class ItemRegistryPopulator {
String bedrockIdentifier = mappingItem.getBedrockIdentifier(); String bedrockIdentifier = mappingItem.getBedrockIdentifier();
ItemDefinition definition = definitions.get(bedrockIdentifier); ItemDefinition definition = definitions.get(bedrockIdentifier);
if (definition == null) { if (definition == null) {
throw new RuntimeException("Missing Bedrock ItemDefinition in mappings: " + bedrockIdentifier); throw new RuntimeException("Missing Bedrock ItemDefinition in version " + palette.getKey() + " for mapping: " + mappingItem);
} }
BlockDefinition bedrockBlock = null; BlockDefinition bedrockBlock = null;

View file

@ -26,12 +26,22 @@
package org.geysermc.geyser.registry.type; package org.geysermc.geyser.registry.type;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data; import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.With;
/** /**
* Represents Geyser's own serialized item information before being processed per-version * Represents Geyser's own serialized item information before being processed per-version
*/ */
@Data @ToString
@EqualsAndHashCode
@Getter
@With
@NoArgsConstructor
@AllArgsConstructor
public class GeyserMappingItem { public class GeyserMappingItem {
@JsonProperty("bedrock_identifier") String bedrockIdentifier; @JsonProperty("bedrock_identifier") String bedrockIdentifier;
@JsonProperty("bedrock_data") int bedrockData; @JsonProperty("bedrock_data") int bedrockData;

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff