mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-08-14 23:57:35 +00:00
Support for 1.20.10 (#3961)
Co-authored-by: chris <github@onechris.mozmail.com> Co-authored-by: RednedEpic <redned235@gmail.com>
This commit is contained in:
parent
6296d4a97f
commit
3a0c1b788a
11 changed files with 11209 additions and 21 deletions
|
@ -14,7 +14,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.19.80 - 1.20 and Minecraft Java 1.20/1.20.1.
|
||||
### Currently supporting Minecraft Bedrock 1.19.80 - 1.20.10 and Minecraft Java 1.20/1.20.1.
|
||||
|
||||
## Setting Up
|
||||
Take a look [here](https://wiki.geysermc.org/geyser/setup/) for how to set up Geyser.
|
||||
|
|
|
@ -30,6 +30,7 @@ import com.github.steveice10.mc.protocol.codec.PacketCodec;
|
|||
import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec;
|
||||
import org.cloudburstmc.protocol.bedrock.codec.v582.Bedrock_v582;
|
||||
import org.cloudburstmc.protocol.bedrock.codec.v589.Bedrock_v589;
|
||||
import org.cloudburstmc.protocol.bedrock.codec.v594.Bedrock_v594;
|
||||
import org.cloudburstmc.protocol.bedrock.netty.codec.packet.BedrockPacketCodec;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
||||
|
@ -45,7 +46,7 @@ public final class GameProtocol {
|
|||
* Default Bedrock codec that should act as a fallback. Should represent the latest available
|
||||
* release of the game that Geyser supports.
|
||||
*/
|
||||
public static final BedrockCodec DEFAULT_BEDROCK_CODEC = Bedrock_v589.CODEC;
|
||||
public static final BedrockCodec DEFAULT_BEDROCK_CODEC = Bedrock_v594.CODEC;
|
||||
|
||||
/**
|
||||
* A list of all supported Bedrock versions that can join Geyser
|
||||
|
@ -62,6 +63,7 @@ public final class GameProtocol {
|
|||
SUPPORTED_BEDROCK_CODECS.add(Bedrock_v582.CODEC.toBuilder()
|
||||
.minecraftVersion("1.19.80/1.19.81")
|
||||
.build());
|
||||
SUPPORTED_BEDROCK_CODECS.add(Bedrock_v589.CODEC);
|
||||
SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ import it.unimi.dsi.fastutil.objects.*;
|
|||
import org.cloudburstmc.nbt.*;
|
||||
import org.cloudburstmc.protocol.bedrock.codec.v582.Bedrock_v582;
|
||||
import org.cloudburstmc.protocol.bedrock.codec.v589.Bedrock_v589;
|
||||
import org.cloudburstmc.protocol.bedrock.codec.v594.Bedrock_v594;
|
||||
import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
|
@ -69,6 +70,34 @@ public final class BlockRegistryPopulator {
|
|||
private static void registerBedrockBlocks() {
|
||||
BiFunction<String, NbtMapBuilder, String> emptyMapper = (bedrockIdentifier, statesBuilder) -> null;
|
||||
|
||||
// adapt 1.20 mappings to 1.20.10+
|
||||
BiFunction<String, NbtMapBuilder, String> concreteAndShulkerBoxMapper = (bedrockIdentifier, statesBuilder) -> {
|
||||
if (bedrockIdentifier.equals("minecraft:concrete")) {
|
||||
String color = (String) statesBuilder.remove("color");
|
||||
if (color.equals("silver")) {
|
||||
color = "light_gray";
|
||||
}
|
||||
return "minecraft:" + color + "_concrete";
|
||||
}
|
||||
if (bedrockIdentifier.equals("minecraft:shulker_box")) {
|
||||
String color = (String) statesBuilder.remove("color");
|
||||
if (color.equals("silver")) {
|
||||
color = "light_gray";
|
||||
}
|
||||
return "minecraft:" + color + "_shulker_box";
|
||||
}
|
||||
if (bedrockIdentifier.equals("minecraft:observer")) {
|
||||
int direction = (int) statesBuilder.remove("facing_direction");
|
||||
statesBuilder.putString("minecraft:facing_direction", switch (direction) {
|
||||
case 0 -> "east";
|
||||
case 1 -> "south";
|
||||
case 2 -> "north";
|
||||
default -> "west";
|
||||
});
|
||||
}
|
||||
return 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")) {
|
||||
|
@ -115,6 +144,7 @@ public final class BlockRegistryPopulator {
|
|||
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()), legacyMapper)
|
||||
.put(ObjectIntPair.of("1_20_0", Bedrock_v589.CODEC.getProtocolVersion()), emptyMapper)
|
||||
.put(ObjectIntPair.of("1_20_10", Bedrock_v594.CODEC.getProtocolVersion()), concreteAndShulkerBoxMapper)
|
||||
.build();
|
||||
|
||||
// We can keep this strong as nothing should be garbage collected
|
||||
|
@ -242,6 +272,7 @@ public final class BlockRegistryPopulator {
|
|||
BlockRegistries.BLOCKS.register(palette.getKey().valueInt(), builder.blockStateVersion(stateVersion)
|
||||
.bedrockRuntimeMap(bedrockRuntimeMap)
|
||||
.javaToBedrockBlocks(javaToBedrockBlocks)
|
||||
.stateDefinitionMap(blockStateOrderedMap)
|
||||
.itemFrames(itemFrames)
|
||||
.flowerPotBlocks(flowerPotBlocks)
|
||||
.jigsawStates(jigsawDefinitions)
|
||||
|
|
|
@ -26,7 +26,10 @@
|
|||
package org.geysermc.geyser.registry.populator;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectMaps;
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||
import org.cloudburstmc.nbt.NbtUtils;
|
||||
import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
|
||||
|
@ -34,6 +37,7 @@ 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.GeyserBedrockBlock;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
|
@ -99,12 +103,32 @@ public class CreativeItemRegistryPopulator {
|
|||
count = countNode.asInt();
|
||||
}
|
||||
|
||||
GeyserBedrockBlock blockDefinition = null;
|
||||
JsonNode blockRuntimeIdNode = itemNode.get("blockRuntimeId");
|
||||
JsonNode blockStateNode;
|
||||
if (blockRuntimeIdNode != null) {
|
||||
bedrockBlockRuntimeId = blockRuntimeIdNode.asInt();
|
||||
if (bedrockBlockRuntimeId == 0 && !identifier.equals("minecraft:blue_candle")) { // FIXME
|
||||
bedrockBlockRuntimeId = -1;
|
||||
}
|
||||
|
||||
blockDefinition = bedrockBlockRuntimeId == -1 ? null : blockMappings.getDefinition(bedrockBlockRuntimeId);
|
||||
} else if ((blockStateNode = itemNode.get("block_state_b64")) != null) {
|
||||
byte[] bytes = Base64.getDecoder().decode(blockStateNode.asText());
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
|
||||
try {
|
||||
NbtMap stateTag = (NbtMap) NbtUtils.createReaderLE(bais).readTag();
|
||||
|
||||
// We remove these from the state definition map in
|
||||
// BlockMappings, so we need to remove it from here
|
||||
NbtMapBuilder builder = stateTag.toBuilder();
|
||||
builder.remove("name_hash");
|
||||
builder.remove("network_id");
|
||||
|
||||
blockDefinition = blockMappings.getDefinition(builder.build());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
JsonNode nbtNode = itemNode.get("nbt_b64");
|
||||
|
@ -129,6 +153,6 @@ public class CreativeItemRegistryPopulator {
|
|||
.damage(damage)
|
||||
.count(count)
|
||||
.tag(tag)
|
||||
.blockDefinition(bedrockBlockRuntimeId == -1 ? null : blockMappings.getDefinition(bedrockBlockRuntimeId));
|
||||
.blockDefinition(blockDefinition);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,12 +40,13 @@ import org.cloudburstmc.nbt.NbtMapBuilder;
|
|||
import org.cloudburstmc.nbt.NbtType;
|
||||
import org.cloudburstmc.protocol.bedrock.codec.v582.Bedrock_v582;
|
||||
import org.cloudburstmc.protocol.bedrock.codec.v589.Bedrock_v589;
|
||||
import org.cloudburstmc.protocol.bedrock.codec.v594.Bedrock_v594;
|
||||
import org.cloudburstmc.protocol.bedrock.data.SoundEvent;
|
||||
import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition;
|
||||
import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition;
|
||||
import org.cloudburstmc.protocol.bedrock.data.definitions.SimpleItemDefinition;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.ComponentItemData;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
|
||||
import org.cloudburstmc.protocol.bedrock.data.SoundEvent;
|
||||
import org.geysermc.geyser.GeyserBootstrap;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.api.item.custom.CustomItemData;
|
||||
|
@ -82,6 +83,7 @@ public class ItemRegistryPopulator {
|
|||
}
|
||||
|
||||
public static void populate() {
|
||||
// Used for the 1.19.80 item palette
|
||||
Map<Item, String> legacyJavaOnly = new HashMap<>();
|
||||
legacyJavaOnly.put(Items.MUSIC_DISC_RELIC, "minecraft:music_disc_wait");
|
||||
legacyJavaOnly.put(Items.PITCHER_PLANT, "minecraft:chorus_flower");
|
||||
|
@ -90,6 +92,7 @@ public class ItemRegistryPopulator {
|
|||
|
||||
List<PaletteVersion> paletteVersions = new ArrayList<>(2);
|
||||
paletteVersions.add(new PaletteVersion("1_19_80", Bedrock_v582.CODEC.getProtocolVersion(), legacyJavaOnly, (item, mapping) -> {
|
||||
// Backward-map 1.20 mappings to 1.19.80
|
||||
String id = item.javaIdentifier();
|
||||
if (id.endsWith("pottery_sherd")) {
|
||||
return mapping.withBedrockIdentifier(id.replace("sherd", "shard"));
|
||||
|
@ -102,6 +105,17 @@ public class ItemRegistryPopulator {
|
|||
return mapping;
|
||||
}));
|
||||
paletteVersions.add(new PaletteVersion("1_20_0", Bedrock_v589.CODEC.getProtocolVersion()));
|
||||
paletteVersions.add(new PaletteVersion("1_20_10", Bedrock_v594.CODEC.getProtocolVersion(), Collections.emptyMap(), (item, mapping) -> {
|
||||
// Forward-map 1.20 mappings to 1.20.10
|
||||
// 1.20.10+ received parity for concrete and shulker boxes
|
||||
String id = item.javaIdentifier();
|
||||
if (id.endsWith("_concrete") || id.endsWith("_shulker_box")) {
|
||||
// the first underscore in "_shulker_box" accounts for ignoring "minecraft:shulker_box"
|
||||
// which is mapped to "minecraft:undyed_shulker_box"
|
||||
return mapping.withBedrockIdentifier(id);
|
||||
}
|
||||
return mapping;
|
||||
}));
|
||||
|
||||
GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap();
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@ public class BlockMappings implements DefinitionRegistry<GeyserBedrockBlock> {
|
|||
|
||||
GeyserBedrockBlock[] javaToBedrockBlocks;
|
||||
|
||||
Map<NbtMap, GeyserBedrockBlock> stateDefinitionMap;
|
||||
GeyserBedrockBlock[] bedrockRuntimeMap;
|
||||
|
||||
BlockDefinition commandBlock;
|
||||
|
@ -85,6 +86,14 @@ public class BlockMappings implements DefinitionRegistry<GeyserBedrockBlock> {
|
|||
return bedrockRuntimeMap[bedrockId];
|
||||
}
|
||||
|
||||
public GeyserBedrockBlock getDefinition(NbtMap tag) {
|
||||
if (tag == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.stateDefinitionMap.get(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRegistered(GeyserBedrockBlock bedrockBlock) {
|
||||
return getDefinition(bedrockBlock.getRuntimeId()) == bedrockBlock;
|
||||
|
|
|
@ -79,8 +79,8 @@ public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommands
|
|||
if (!a.description().equals(b.description())) return false;
|
||||
if (a.paramData().length != b.paramData().length) return false;
|
||||
for (int i = 0; i < a.paramData().length; i++) {
|
||||
CommandParamData[] a1 = a.paramData()[i];
|
||||
CommandParamData[] b1 = b.paramData()[i];
|
||||
CommandParamData[] a1 = a.paramData()[i].getOverloads();
|
||||
CommandParamData[] b1 = b.paramData()[i].getOverloads();
|
||||
if (a1.length != b1.length) return false;
|
||||
|
||||
for (int j = 0; j < a1.length; j++) {
|
||||
|
@ -141,7 +141,7 @@ public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommands
|
|||
}
|
||||
|
||||
// Get and parse all params
|
||||
CommandParamData[][] params = getParams(session, nodes[nodeIndex], nodes);
|
||||
CommandOverloadData[] params = getParams(session, nodes[nodeIndex], nodes);
|
||||
|
||||
// Insert the alias name into the command list
|
||||
commands.computeIfAbsent(new BedrockCommandInfo(node.getName().toLowerCase(Locale.ROOT), manager.description(node.getName().toLowerCase(Locale.ROOT)), params),
|
||||
|
@ -179,7 +179,7 @@ public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommands
|
|||
CommandEnumData aliases = new CommandEnumData(commandName + "Aliases", values, false);
|
||||
|
||||
// Build the completed command and add it to the final list
|
||||
CommandData data = new CommandData(commandName, entry.getKey().description(), flags, CommandPermission.ANY, aliases, entry.getKey().paramData());
|
||||
CommandData data = new CommandData(commandName, entry.getKey().description(), flags, CommandPermission.ANY, aliases, Collections.emptyList(), entry.getKey().paramData());
|
||||
commandData.add(data);
|
||||
}
|
||||
|
||||
|
@ -201,7 +201,7 @@ public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommands
|
|||
* @param allNodes Every command node
|
||||
* @return An array of parameter option arrays
|
||||
*/
|
||||
private static CommandParamData[][] getParams(GeyserSession session, CommandNode commandNode, CommandNode[] allNodes) {
|
||||
private static CommandOverloadData[] getParams(GeyserSession session, CommandNode commandNode, CommandNode[] allNodes) {
|
||||
// Check if the command is an alias and redirect it
|
||||
if (commandNode.getRedirectIndex().isPresent()) {
|
||||
int redirectIndex = commandNode.getRedirectIndex().getAsInt();
|
||||
|
@ -214,12 +214,12 @@ public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommands
|
|||
ParamInfo rootParam = new ParamInfo(commandNode, null);
|
||||
rootParam.buildChildren(new CommandBuilderContext(session), allNodes);
|
||||
|
||||
List<CommandParamData[]> treeData = rootParam.getTree();
|
||||
List<CommandOverloadData> treeData = rootParam.getTree();
|
||||
|
||||
return treeData.toArray(new CommandParamData[0][]);
|
||||
return treeData.toArray(new CommandOverloadData[0]);
|
||||
}
|
||||
|
||||
return new CommandParamData[0][0];
|
||||
return new CommandOverloadData[0];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -272,7 +272,7 @@ public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommands
|
|||
/**
|
||||
* Stores the command description and parameter data for best optimizing the Bedrock commands packet.
|
||||
*/
|
||||
private record BedrockCommandInfo(String name, String description, CommandParamData[][] paramData) implements
|
||||
private record BedrockCommandInfo(String name, String description, CommandOverloadData[] paramData) implements
|
||||
org.geysermc.geyser.api.event.downstream.ServerDefineCommandsEvent.CommandInfo,
|
||||
ServerDefineCommandsEvent.CommandInfo
|
||||
{
|
||||
|
@ -542,25 +542,26 @@ public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommands
|
|||
*
|
||||
* @return List of parameter options arrays for the command
|
||||
*/
|
||||
public List<CommandParamData[]> getTree() {
|
||||
List<CommandParamData[]> treeParamData = new ArrayList<>();
|
||||
public List<CommandOverloadData> getTree() {
|
||||
List<CommandOverloadData> treeParamData = new ArrayList<>();
|
||||
|
||||
for (ParamInfo child : children) {
|
||||
// Get the tree from the child
|
||||
List<CommandParamData[]> childTree = child.getTree();
|
||||
List<CommandOverloadData> childTree = child.getTree();
|
||||
|
||||
// Un-pack the tree append the child node to it and push into the list
|
||||
for (CommandParamData[] subChild : childTree) {
|
||||
for (CommandOverloadData subChildData : childTree) {
|
||||
CommandParamData[] subChild = subChildData.getOverloads();
|
||||
CommandParamData[] tmpTree = new CommandParamData[subChild.length + 1];
|
||||
tmpTree[0] = child.getParamData();
|
||||
System.arraycopy(subChild, 0, tmpTree, 1, subChild.length);
|
||||
|
||||
treeParamData.add(tmpTree);
|
||||
treeParamData.add(new CommandOverloadData(false, tmpTree));
|
||||
}
|
||||
|
||||
// If we have no more child parameters just the child
|
||||
if (childTree.size() == 0) {
|
||||
treeParamData.add(new CommandParamData[] { child.getParamData() });
|
||||
treeParamData.add(new CommandOverloadData(false, new CommandParamData[] { child.getParamData() }));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
BIN
core/src/main/resources/bedrock/block_palette.1_20_10.nbt
Normal file
BIN
core/src/main/resources/bedrock/block_palette.1_20_10.nbt
Normal file
Binary file not shown.
5793
core/src/main/resources/bedrock/creative_items.1_20_10.json
Normal file
5793
core/src/main/resources/bedrock/creative_items.1_20_10.json
Normal file
File diff suppressed because it is too large
Load diff
5314
core/src/main/resources/bedrock/runtime_item_states.1_20_10.json
Normal file
5314
core/src/main/resources/bedrock/runtime_item_states.1_20_10.json
Normal file
File diff suppressed because it is too large
Load diff
|
@ -9,8 +9,8 @@ netty = "4.1.80.Final"
|
|||
guava = "29.0-jre"
|
||||
gson = "2.3.1" # Provided by Spigot 1.8.8
|
||||
websocket = "1.5.1"
|
||||
protocol = "3.0.0.Beta1-20230627.180522-98"
|
||||
protocol-connection = "3.0.0.Beta1-20230627.180522-97"
|
||||
protocol = "3.0.0.Beta1-20230708.191602-100"
|
||||
protocol-connection = "3.0.0.Beta1-20230708.191602-99"
|
||||
raknet = "1.0.0.CR1-20230703.195238-9"
|
||||
mcauthlib = "d9d773e"
|
||||
mcprotocollib = "1.20-1-20230607.135651-6" # Temporary hack - needs to be updated to release once publishing is fixed
|
||||
|
|
Loading…
Reference in a new issue