Skip to content

Commit 4180c13

Browse files
Bedrock 1.21.60 support, API 2.6.1
2 parents b96f915 + 04586a4 commit 4180c13

27 files changed

+20701
-208
lines changed

core/src/main/java/org/geysermc/geyser/Constants.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,6 @@ public final class Constants {
3636

3737
public static final String FLOODGATE_DOWNLOAD_LOCATION = "https://geysermc.org/download#floodgate";
3838
public static final String GEYSER_DOWNLOAD_LOCATION = "https://geysermc.org/download";
39-
40-
@Deprecated
41-
static final String SAVED_REFRESH_TOKEN_FILE = "saved-refresh-tokens.json";
4239
static final String SAVED_AUTH_CHAINS_FILE = "saved-auth-chains.json";
4340

4441
public static final String GEYSER_CUSTOM_NAMESPACE = "geyser_custom";

core/src/main/java/org/geysermc/geyser/GeyserImpl.java

Lines changed: 0 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
import com.fasterxml.jackson.core.type.TypeReference;
3030
import com.fasterxml.jackson.databind.DeserializationFeature;
3131
import com.fasterxml.jackson.databind.ObjectMapper;
32-
import com.google.gson.Gson;
3332
import io.netty.channel.epoll.Epoll;
3433
import io.netty.util.NettyRuntime;
3534
import io.netty.util.concurrent.DefaultThreadFactory;
@@ -39,8 +38,6 @@
3938
import lombok.Setter;
4039
import net.kyori.adventure.text.Component;
4140
import net.kyori.adventure.text.format.NamedTextColor;
42-
import net.raphimc.minecraftauth.step.java.session.StepFullJavaSession;
43-
import net.raphimc.minecraftauth.step.msa.StepMsaToken;
4441
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
4542
import org.checkerframework.checker.nullness.qual.NonNull;
4643
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -99,7 +96,6 @@
9996
import org.geysermc.geyser.util.AssetUtils;
10097
import org.geysermc.geyser.util.CooldownUtils;
10198
import org.geysermc.geyser.util.Metrics;
102-
import org.geysermc.geyser.util.MinecraftAuthLogger;
10399
import org.geysermc.geyser.util.NewsHandler;
104100
import org.geysermc.geyser.util.VersionCheckUtils;
105101
import org.geysermc.geyser.util.WebUtils;
@@ -566,53 +562,6 @@ private void startInstance() {
566562
// May be written/read to on multiple threads from each GeyserSession as well as writing the config
567563
savedAuthChains = new ConcurrentHashMap<>();
568564

569-
// TODO Remove after a while - just a migration help
570-
//noinspection deprecation
571-
File refreshTokensFile = bootstrap.getSavedUserLoginsFolder().resolve(Constants.SAVED_REFRESH_TOKEN_FILE).toFile();
572-
if (refreshTokensFile.exists()) {
573-
logger.info("Migrating refresh tokens to auth chains...");
574-
TypeReference<Map<String, String>> type = new TypeReference<>() { };
575-
Map<String, String> refreshTokens = null;
576-
try {
577-
refreshTokens = JSON_MAPPER.readValue(refreshTokensFile, type);
578-
} catch (IOException e) {
579-
// ignored - we'll just delete this file :))
580-
}
581-
582-
if (refreshTokens != null) {
583-
List<String> validUsers = config.getSavedUserLogins();
584-
final Gson gson = new Gson();
585-
for (Map.Entry<String, String> entry : refreshTokens.entrySet()) {
586-
String user = entry.getKey();
587-
if (!validUsers.contains(user)) {
588-
continue;
589-
}
590-
591-
// Migrate refresh tokens to auth chains
592-
try {
593-
StepFullJavaSession javaSession = PendingMicrosoftAuthentication.AUTH_FLOW.apply(false, 10);
594-
StepFullJavaSession.FullJavaSession fullJavaSession = javaSession.getFromInput(
595-
MinecraftAuthLogger.INSTANCE,
596-
PendingMicrosoftAuthentication.AUTH_CLIENT,
597-
new StepMsaToken.RefreshToken(entry.getValue())
598-
);
599-
600-
String authChain = gson.toJson(javaSession.toJson(fullJavaSession));
601-
savedAuthChains.put(user, authChain);
602-
} catch (Exception e) {
603-
GeyserImpl.getInstance().getLogger().warning("Could not migrate " + entry.getKey() + " to an auth chain! " +
604-
"They will need to sign in the next time they join Geyser.");
605-
}
606-
607-
// Ensure the new additions are written to the file
608-
scheduleAuthChainsWrite();
609-
}
610-
}
611-
612-
// Finally: Delete it. Goodbye!
613-
refreshTokensFile.delete();
614-
}
615-
616565
File authChainsFile = bootstrap.getSavedUserLoginsFolder().resolve(Constants.SAVED_AUTH_CHAINS_FILE).toFile();
617566
if (authChainsFile.exists()) {
618567
TypeReference<Map<String, String>> type = new TypeReference<>() { };

core/src/main/java/org/geysermc/geyser/item/GeyserCustomMappingData.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
package org.geysermc.geyser.item;
2727

2828
import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition;
29-
import org.cloudburstmc.protocol.bedrock.data.inventory.ComponentItemData;
3029

31-
public record GeyserCustomMappingData(ComponentItemData componentItemData, ItemDefinition itemDefinition, String stringId, int integerId) {
30+
public record GeyserCustomMappingData(ItemDefinition itemDefinition, String stringId, int integerId) {
3231
}

core/src/main/java/org/geysermc/geyser/network/GameProtocol.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec;
3030
import org.cloudburstmc.protocol.bedrock.codec.v748.Bedrock_v748;
3131
import org.cloudburstmc.protocol.bedrock.codec.v766.Bedrock_v766;
32+
import org.cloudburstmc.protocol.bedrock.codec.v776.Bedrock_v776;
3233
import org.cloudburstmc.protocol.bedrock.netty.codec.packet.BedrockPacketCodec;
3334
import org.geysermc.geyser.session.GeyserSession;
3435
import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodec;
@@ -47,8 +48,8 @@ public final class GameProtocol {
4748
* Default Bedrock codec that should act as a fallback. Should represent the latest available
4849
* release of the game that Geyser supports.
4950
*/
50-
public static final BedrockCodec DEFAULT_BEDROCK_CODEC = CodecProcessor.processCodec(Bedrock_v766.CODEC.toBuilder()
51-
.minecraftVersion("1.21.51")
51+
public static final BedrockCodec DEFAULT_BEDROCK_CODEC = CodecProcessor.processCodec(Bedrock_v776.CODEC.toBuilder()
52+
.minecraftVersion("1.21.60")
5253
.build());
5354

5455
/**
@@ -66,9 +67,10 @@ public final class GameProtocol {
6667
SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v748.CODEC.toBuilder()
6768
.minecraftVersion("1.21.40 - 1.21.44")
6869
.build()));
69-
SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC.toBuilder()
70+
SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v766.CODEC.toBuilder()
7071
.minecraftVersion("1.21.50 - 1.21.51")
71-
.build());
72+
.build()));
73+
SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC);
7274
}
7375

7476
/**
@@ -91,6 +93,10 @@ public static boolean isPreWinterDrop(GeyserSession session) {
9193
return session.getUpstream().getProtocolVersion() == Bedrock_v748.CODEC.getProtocolVersion();
9294
}
9395

96+
public static boolean isPreCreativeInventoryRewrite(int protocolVersion) {
97+
return protocolVersion < 776;
98+
}
99+
94100
/**
95101
* Gets the {@link PacketCodec} for Minecraft: Java Edition.
96102
*

core/src/main/java/org/geysermc/geyser/network/LoggingPacketHandler.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -896,4 +896,14 @@ public PacketSignal handle(ToggleCrafterSlotRequestPacket packet) {
896896
public PacketSignal handle(TrimDataPacket packet) {
897897
return defaultHandler(packet);
898898
}
899-
}
899+
900+
@Override
901+
public PacketSignal handle(MovementPredictionSyncPacket packet) {
902+
return defaultHandler(packet);
903+
}
904+
905+
@Override
906+
public PacketSignal handle(ServerboundDiagnosticsPacket packet) {
907+
return defaultHandler(packet);
908+
}
909+
}

core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
package org.geysermc.geyser.registry;
2727

28+
import org.cloudburstmc.protocol.bedrock.packet.ServerboundDiagnosticsPacket;
2829
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundDelimiterPacket;
2930
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundTabListPacket;
3031
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundChunkBatchStartPacket;
@@ -49,6 +50,7 @@ public class PacketTranslatorRegistry<T> extends AbstractMappedRegistry<Class<?
4950
IGNORED_PACKETS.add(ClientboundDelimiterPacket.class); // Not implemented, spams logs
5051
IGNORED_PACKETS.add(ClientboundLightUpdatePacket.class); // Light is handled on Bedrock for us
5152
IGNORED_PACKETS.add(ClientboundTabListPacket.class); // Cant be implemented in Bedrock
53+
IGNORED_PACKETS.add(ServerboundDiagnosticsPacket.class); // spammy
5254
}
5355

5456
protected PacketTranslatorRegistry() {

core/src/main/java/org/geysermc/geyser/registry/populator/BlockRegistryPopulator.java

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import org.cloudburstmc.nbt.NbtUtils;
4545
import org.cloudburstmc.protocol.bedrock.codec.v748.Bedrock_v748;
4646
import org.cloudburstmc.protocol.bedrock.codec.v766.Bedrock_v766;
47+
import org.cloudburstmc.protocol.bedrock.codec.v776.Bedrock_v776;
4748
import org.cloudburstmc.protocol.bedrock.data.BlockPropertyData;
4849
import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition;
4950
import org.geysermc.geyser.GeyserImpl;
@@ -116,7 +117,40 @@ private static void nullifyBlocksNbt() {
116117
private static void registerBedrockBlocks() {
117118
var blockMappers = ImmutableMap.<ObjectIntPair<String>, Remapper>builder()
118119
.put(ObjectIntPair.of("1_21_40", Bedrock_v748.CODEC.getProtocolVersion()), Conversion766_748::remapBlock)
119-
.put(ObjectIntPair.of("1_21_50", Bedrock_v766.CODEC.getProtocolVersion()), tag -> tag)
120+
.put(ObjectIntPair.of("1_21_50", Bedrock_v766.CODEC.getProtocolVersion()), tag -> tag) // TODO: Finish me
121+
.put(ObjectIntPair.of("1_21_60", Bedrock_v776.CODEC.getProtocolVersion()), tag -> {
122+
final String name = tag.getString("name");
123+
if (name.equals("minecraft:creaking_heart") && tag.getCompound("states").containsKey("active")) {
124+
NbtMapBuilder builder = tag.getCompound("states").toBuilder();
125+
builder.remove("active");
126+
builder.putString("creaking_heart_state", "awake");
127+
NbtMap states = builder.build();
128+
return tag.toBuilder().putCompound("states", states).build();
129+
}
130+
if ((name.endsWith("_door") || name.endsWith("fence_gate")) && tag.getCompound("states").containsKey("direction")) {
131+
NbtMapBuilder builder = tag.getCompound("states").toBuilder();
132+
Integer directionCardinality = (Integer) builder.remove("direction");
133+
switch (directionCardinality) {
134+
case 0:
135+
builder.putString("minecraft:cardinal_direction", "south");
136+
break;
137+
case 1:
138+
builder.putString("minecraft:cardinal_direction", "west");
139+
break;
140+
case 2:
141+
builder.putString( "minecraft:cardinal_direction" , "north");
142+
break;
143+
case 3:
144+
builder.putString("minecraft:cardinal_direction", "east");
145+
break;
146+
default:
147+
throw new AssertionError("Invalid direction: " + directionCardinality);
148+
}
149+
NbtMap states = builder.build();
150+
return tag.toBuilder().putCompound("states", states).build();
151+
}
152+
return tag;
153+
})
120154
.build();
121155

122156
// We can keep this strong as nothing should be garbage collected

core/src/main/java/org/geysermc/geyser/registry/populator/CreativeItemRegistryPopulator.java

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@
3131
import org.cloudburstmc.nbt.NbtMapBuilder;
3232
import org.cloudburstmc.nbt.NbtUtils;
3333
import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition;
34+
import org.cloudburstmc.protocol.bedrock.data.inventory.CreativeItemCategory;
35+
import org.cloudburstmc.protocol.bedrock.data.inventory.CreativeItemData;
36+
import org.cloudburstmc.protocol.bedrock.data.inventory.CreativeItemGroup;
3437
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
3538
import org.geysermc.geyser.GeyserBootstrap;
3639
import org.geysermc.geyser.GeyserImpl;
@@ -42,19 +45,56 @@
4245
import java.io.ByteArrayInputStream;
4346
import java.io.IOException;
4447
import java.io.InputStream;
48+
import java.util.ArrayList;
4549
import java.util.Base64;
4650
import java.util.List;
51+
import java.util.Locale;
4752
import java.util.Map;
53+
import java.util.function.BiConsumer;
4854
import java.util.function.BiPredicate;
49-
import java.util.function.Consumer;
5055

5156
public class CreativeItemRegistryPopulator {
5257
private static final List<BiPredicate<String, Integer>> JAVA_ONLY_ITEM_FILTER = List.of(
5358
// Bedrock-only as its own item
5459
(identifier, data) -> identifier.equals("minecraft:empty_map") && data == 2
5560
);
5661

57-
static void populate(ItemRegistryPopulator.PaletteVersion palette, Map<String, ItemDefinition> definitions, Map<String, GeyserMappingItem> items, Consumer<ItemData.Builder> itemConsumer) {
62+
static List<CreativeItemGroup> readCreativeItemGroups(ItemRegistryPopulator.PaletteVersion palette, List<CreativeItemData> creativeItemData) {
63+
GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap();
64+
65+
JsonNode creativeItemEntries;
66+
try (InputStream stream = bootstrap.getResourceOrThrow(String.format("bedrock/creative_items.%s.json", palette.version()))) {
67+
creativeItemEntries = GeyserImpl.JSON_MAPPER.readTree(stream).get("groups");
68+
} catch (Exception e) {
69+
throw new AssertionError("Unable to load creative item groups", e);
70+
}
71+
72+
List<CreativeItemGroup> creativeItemGroups = new ArrayList<>();
73+
for (JsonNode creativeItemEntry : creativeItemEntries) {
74+
CreativeItemCategory category = CreativeItemCategory.valueOf(creativeItemEntry.get("category").asText().toUpperCase(Locale.ROOT));
75+
String name = creativeItemEntry.get("name").asText();
76+
77+
JsonNode icon = creativeItemEntry.get("icon");
78+
String identifier = icon.get("id").asText();
79+
80+
ItemData itemData;
81+
if (identifier.equals("minecraft:air")) {
82+
itemData = ItemData.AIR;
83+
} else {
84+
itemData = creativeItemData.stream()
85+
.map(CreativeItemData::getItem)
86+
.filter(item -> item.getDefinition().getIdentifier().equals(identifier))
87+
.findFirst()
88+
.orElseThrow();
89+
}
90+
91+
creativeItemGroups.add(new CreativeItemGroup(category, name, itemData));
92+
}
93+
94+
return creativeItemGroups;
95+
}
96+
97+
static void populate(ItemRegistryPopulator.PaletteVersion palette, Map<String, ItemDefinition> definitions, Map<String, GeyserMappingItem> items, BiConsumer<ItemData.Builder, Integer> itemConsumer) {
5898
GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap();
5999

60100
// Load creative items
@@ -72,7 +112,9 @@ static void populate(ItemRegistryPopulator.PaletteVersion palette, Map<String, I
72112
continue;
73113
}
74114

75-
itemConsumer.accept(itemBuilder);
115+
int groupId = itemNode.get("groupId") != null ? itemNode.get("groupId").asInt() : 0;
116+
117+
itemConsumer.accept(itemBuilder, groupId);
76118
}
77119
}
78120

core/src/main/java/org/geysermc/geyser/registry/populator/CustomItemRegistryPopulator.java

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
import org.cloudburstmc.nbt.NbtType;
3434
import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition;
3535
import org.cloudburstmc.protocol.bedrock.data.definitions.SimpleItemDefinition;
36-
import org.cloudburstmc.protocol.bedrock.data.inventory.ComponentItemData;
3736
import org.geysermc.geyser.GeyserImpl;
3837
import org.geysermc.geyser.api.item.custom.CustomItemData;
3938
import org.geysermc.geyser.api.item.custom.CustomRenderOffsets;
@@ -106,12 +105,10 @@ public boolean register(@NonNull NonVanillaCustomItemData customItemData) {
106105
}
107106

108107
public static GeyserCustomMappingData registerCustomItem(String customItemName, Item javaItem, GeyserMappingItem mapping, CustomItemData customItemData, int bedrockId, int protocolVersion) {
109-
ItemDefinition itemDefinition = new SimpleItemDefinition(customItemName, bedrockId, true);
110-
111108
NbtMapBuilder builder = createComponentNbt(customItemData, javaItem, mapping, customItemName, bedrockId, protocolVersion);
112-
ComponentItemData componentItemData = new ComponentItemData(customItemName, builder.build());
109+
ItemDefinition itemDefinition = new SimpleItemDefinition(customItemName, bedrockId, 1, true, builder.build());
113110

114-
return new GeyserCustomMappingData(componentItemData, itemDefinition, customItemName, bedrockId);
111+
return new GeyserCustomMappingData(itemDefinition, customItemName, bedrockId);
115112
}
116113

117114
static boolean initialCheck(String identifier, CustomItemData item, Map<String, GeyserMappingItem> mappings) {
@@ -142,9 +139,11 @@ public static NonVanillaItemRegistration registerCustomItem(NonVanillaCustomItem
142139
Item item = new Item(customIdentifier, Item.builder().components(components));
143140
Items.register(item, customItemData.javaId());
144141

142+
NbtMapBuilder builder = createComponentNbt(customItemData, customItemData.identifier(), customItemId,
143+
customItemData.isHat(), customItemData.displayHandheld(), protocolVersion);
145144
ItemMapping customItemMapping = ItemMapping.builder()
146145
.bedrockIdentifier(customIdentifier)
147-
.bedrockDefinition(new SimpleItemDefinition(customIdentifier, customItemId, true))
146+
.bedrockDefinition(new SimpleItemDefinition(customIdentifier, customItemId, 1, true, builder.build()))
148147
.bedrockData(0)
149148
.bedrockBlockDefinition(null)
150149
.toolType(customItemData.toolType())
@@ -153,11 +152,7 @@ public static NonVanillaItemRegistration registerCustomItem(NonVanillaCustomItem
153152
.javaItem(item)
154153
.build();
155154

156-
NbtMapBuilder builder = createComponentNbt(customItemData, customItemData.identifier(), customItemId,
157-
customItemData.isHat(), customItemData.displayHandheld(), protocolVersion);
158-
ComponentItemData componentItemData = new ComponentItemData(customIdentifier, builder.build());
159-
160-
return new NonVanillaItemRegistration(componentItemData, item, customItemMapping);
155+
return new NonVanillaItemRegistration(item, customItemMapping);
161156
}
162157

163158
private static NbtMapBuilder createComponentNbt(CustomItemData customItemData, Item javaItem, GeyserMappingItem mapping,

0 commit comments

Comments
 (0)