mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-08-14 23:57:35 +00:00
Support for v588 client and mappings
This commit is contained in:
parent
f712d4dd81
commit
a9d64de070
8 changed files with 11871 additions and 19 deletions
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
BIN
core/src/main/resources/bedrock/block_palette.1_20_0.nbt
Normal file
BIN
core/src/main/resources/bedrock/block_palette.1_20_0.nbt
Normal file
Binary file not shown.
6580
core/src/main/resources/bedrock/creative_items.1_20_0.json
Normal file
6580
core/src/main/resources/bedrock/creative_items.1_20_0.json
Normal file
File diff suppressed because it is too large
Load diff
Binary file not shown.
5186
core/src/main/resources/bedrock/runtime_item_states.1_20_0.json
Normal file
5186
core/src/main/resources/bedrock/runtime_item_states.1_20_0.json
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue