Skip to content

Commit 53596d0

Browse files
API 2.9.1: Support 1.21.124, add tint/isotropic method to custom block material, allowing updating entity properties immediately (#5991)
* Prepare for 1.21.124 * Add tint method and isotropic properties to block material instances (#5977) * Add tint method and isotropic properties to block material instances * Check if tint method is null before including it * Lets cover the null check on render method too * Allow updating properties immediately (#5961) --------- Co-authored-by: rtm516 <rtm516@users.noreply.github.com>
1 parent c0c7b51 commit 53596d0

File tree

10 files changed

+117
-40
lines changed

10 files changed

+117
-40
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ The ultimate goal of this project is to allow Minecraft: Bedrock Edition users t
1515
Special thanks to the DragonProxy project for being a trailblazer in protocol translation and for all the team members who have joined us here!
1616

1717
## Supported Versions
18-
Geyser is currently supporting Minecraft Bedrock 1.21.90 - 1.21.120 and Minecraft Java 1.21.9 - 1.21.10. For more information, please see [here](https://geysermc.org/wiki/geyser/supported-versions/).
18+
Geyser is currently supporting Minecraft Bedrock 1.21.90 - 1.21.124 and Minecraft Java 1.21.9 - 1.21.10. For more information, please see [here](https://geysermc.org/wiki/geyser/supported-versions/).
1919

2020
## Setting Up
2121
Take a look [here](https://geysermc.org/wiki/geyser/setup/) for how to set up Geyser.

api/src/main/java/org/geysermc/geyser/api/block/custom/component/MaterialInstance.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
2+
* Copyright (c) 2019-2025 GeyserMC. http://geysermc.org
33
*
44
* Permission is hereby granted, free of charge, to any person obtaining a copy
55
* of this software and associated documentation files (the "Software"), to deal
@@ -46,6 +46,13 @@ public interface MaterialInstance {
4646
*/
4747
@Nullable String renderMethod();
4848

49+
/**
50+
* Gets the tint method of the block
51+
*
52+
* @return The tint method of the block.
53+
*/
54+
@Nullable String tintMethod();
55+
4956
/**
5057
* Gets if the block should be dimmed on certain faces
5158
*
@@ -60,6 +67,13 @@ public interface MaterialInstance {
6067
*/
6168
boolean ambientOcclusion();
6269

70+
/**
71+
* Gets if the block is isotropic
72+
*
73+
* @return If the block is isotropic.
74+
*/
75+
boolean isotropic();
76+
6377
/**
6478
* Creates a builder for MaterialInstance.
6579
*
@@ -74,10 +88,14 @@ interface Builder {
7488

7589
Builder renderMethod(@Nullable String renderMethod);
7690

91+
Builder tintMethod(@Nullable String tintMethod);
92+
7793
Builder faceDimming(boolean faceDimming);
7894

7995
Builder ambientOcclusion(boolean ambientOcclusion);
8096

97+
Builder isotropic(boolean isotropic);
98+
8199
MaterialInstance build();
82100
}
83101
}

api/src/main/java/org/geysermc/geyser/api/entity/type/GeyserEntity.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,23 @@ default <T> void updateProperty(@NonNull GeyserEntityProperty<T> property, @Null
6262
/**
6363
* Updates multiple properties with just one update packet.
6464
* @see BatchPropertyUpdater
65+
*
66+
* @param consumer a batch updater
6567
* @since 2.9.0
6668
*/
67-
void updatePropertiesBatched(Consumer<BatchPropertyUpdater> consumer);
69+
default void updatePropertiesBatched(Consumer<BatchPropertyUpdater> consumer) {
70+
this.updatePropertiesBatched(consumer, false);
71+
}
72+
73+
/**
74+
* Updates multiple properties with just one update packet, which can be sent immediately to the client.
75+
* Usually, sending updates immediately is not required except for specific situations where packet batching
76+
* would result in update order issues.
77+
* @see BatchPropertyUpdater
78+
*
79+
* @param consumer a batch updater
80+
* @param immediate whether this update should be sent immediately
81+
* @since 2.9.1
82+
*/
83+
void updatePropertiesBatched(Consumer<BatchPropertyUpdater> consumer, boolean immediate);
6884
}

core/src/main/java/org/geysermc/geyser/entity/type/Entity.java

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -778,40 +778,44 @@ public final void playEntityEvent(EntityEventType type, int data) {
778778
}
779779

780780
@Override
781-
public void updatePropertiesBatched(Consumer<BatchPropertyUpdater> consumer) {
782-
if (this.propertyManager != null) {
783-
Objects.requireNonNull(consumer);
784-
GeyserEntityProperties propertyDefinitions = definition.registeredProperties();
785-
consumer.accept(new BatchPropertyUpdater() {
786-
@Override
787-
public <T> void update(@NonNull GeyserEntityProperty<T> property, @Nullable T value) {
788-
Objects.requireNonNull(property, "property must not be null!");
789-
if (!(property instanceof PropertyType<T, ? extends EntityProperty> propertyType)) {
790-
throw new IllegalArgumentException("Invalid property implementation! Got: " + property.getClass().getSimpleName());
791-
}
792-
int index = propertyDefinitions.getPropertyIndex(property.identifier().toString());
793-
if (index < 0) {
794-
throw new IllegalArgumentException("No property with the name " + property.identifier() + " has been registered.");
795-
}
796-
797-
var expectedProperty = propertyDefinitions.getProperties().get(index);
798-
if (!expectedProperty.equals(propertyType)) {
799-
throw new IllegalArgumentException("The supplied property was not registered with this entity type!");
800-
}
801-
802-
propertyType.apply(propertyManager, value);
781+
public void updatePropertiesBatched(Consumer<BatchPropertyUpdater> consumer, boolean immediate) {
782+
if (this.propertyManager == null) {
783+
throw new IllegalArgumentException("Given entity has no registered properties!");
784+
}
785+
786+
Objects.requireNonNull(consumer);
787+
GeyserEntityProperties propertyDefinitions = definition.registeredProperties();
788+
consumer.accept(new BatchPropertyUpdater() {
789+
@Override
790+
public <T> void update(@NonNull GeyserEntityProperty<T> property, @Nullable T value) {
791+
Objects.requireNonNull(property, "property must not be null!");
792+
if (!(property instanceof PropertyType<T, ? extends EntityProperty> propertyType)) {
793+
throw new IllegalArgumentException("Invalid property implementation! Got: " + property.getClass().getSimpleName());
794+
}
795+
int index = propertyDefinitions.getPropertyIndex(property.identifier().toString());
796+
if (index < 0) {
797+
throw new IllegalArgumentException("No property with the name " + property.identifier() + " has been registered.");
803798
}
804-
});
805799

806-
if (propertyManager.hasProperties()) {
807-
SetEntityDataPacket packet = new SetEntityDataPacket();
808-
packet.setRuntimeEntityId(getGeyserId());
809-
propertyManager.applyFloatProperties(packet.getProperties().getFloatProperties());
810-
propertyManager.applyIntProperties(packet.getProperties().getIntProperties());
800+
var expectedProperty = propertyDefinitions.getProperties().get(index);
801+
if (!expectedProperty.equals(propertyType)) {
802+
throw new IllegalArgumentException("The supplied property was not registered with this entity type!");
803+
}
804+
805+
propertyType.apply(propertyManager, value);
806+
}
807+
});
808+
809+
if (propertyManager.hasProperties()) {
810+
SetEntityDataPacket packet = new SetEntityDataPacket();
811+
packet.setRuntimeEntityId(getGeyserId());
812+
propertyManager.applyFloatProperties(packet.getProperties().getFloatProperties());
813+
propertyManager.applyIntProperties(packet.getProperties().getIntProperties());
814+
if (immediate) {
815+
session.sendUpstreamPacketImmediately(packet);
816+
} else {
811817
session.sendUpstreamPacket(packet);
812818
}
813-
} else {
814-
throw new IllegalArgumentException("Given entity has no registered properties!");
815819
}
816820
}
817821
}

core/src/main/java/org/geysermc/geyser/level/block/GeyserMaterialInstance.java

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
2+
* Copyright (c) 2019-2025 GeyserMC. http://geysermc.org
33
*
44
* Permission is hereby granted, free of charge, to any person obtaining a copy
55
* of this software and associated documentation files (the "Software"), to deal
@@ -33,14 +33,18 @@
3333
public class GeyserMaterialInstance implements MaterialInstance {
3434
private final String texture;
3535
private final String renderMethod;
36+
private final String tintMethod;
3637
private final boolean faceDimming;
3738
private final boolean ambientOcclusion;
39+
private final boolean isotropic;
3840

3941
GeyserMaterialInstance(Builder builder) {
4042
this.texture = builder.texture;
4143
this.renderMethod = builder.renderMethod;
44+
this.tintMethod = builder.tintMethod;
4245
this.faceDimming = builder.faceDimming;
4346
this.ambientOcclusion = builder.ambientOcclusion;
47+
this.isotropic = builder.isotropic;
4448
}
4549

4650
@Override
@@ -53,6 +57,11 @@ public class GeyserMaterialInstance implements MaterialInstance {
5357
return renderMethod;
5458
}
5559

60+
@Override
61+
public @Nullable String tintMethod() {
62+
return tintMethod;
63+
}
64+
5665
@Override
5766
public boolean faceDimming() {
5867
return faceDimming;
@@ -63,11 +72,18 @@ public boolean ambientOcclusion() {
6372
return ambientOcclusion;
6473
}
6574

75+
@Override
76+
public boolean isotropic() {
77+
return isotropic;
78+
}
79+
6680
public static class Builder implements MaterialInstance.Builder {
6781
private String texture;
6882
private String renderMethod;
83+
private String tintMethod;
6984
private boolean faceDimming;
7085
private boolean ambientOcclusion;
86+
private boolean isotropic;
7187

7288
@Override
7389
public Builder texture(@Nullable String texture) {
@@ -81,6 +97,12 @@ public Builder renderMethod(@Nullable String renderMethod) {
8197
return this;
8298
}
8399

100+
@Override
101+
public Builder tintMethod(@Nullable String tintMethod) {
102+
this.tintMethod = tintMethod;
103+
return this;
104+
}
105+
84106
@Override
85107
public Builder faceDimming(boolean faceDimming) {
86108
this.faceDimming = faceDimming;
@@ -93,6 +115,12 @@ public Builder ambientOcclusion(boolean ambientOcclusion) {
93115
return this;
94116
}
95117

118+
@Override
119+
public MaterialInstance.Builder isotropic(boolean isotropic) {
120+
this.isotropic = isotropic;
121+
return this;
122+
}
123+
96124
@Override
97125
public MaterialInstance build() {
98126
return new GeyserMaterialInstance(this);

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ public final class GameProtocol {
8989
register(Bedrock_v827.CODEC, "1.21.100", "1.21.101");
9090
register(Bedrock_v844.CODEC, "1.21.111", "1.21.112", "1.21.113", "1.21.114");
9191
register(Bedrock_v859.CODEC, "1.21.120", "1.21.121", "1.21.122", "1.21.123");
92+
register(Bedrock_v859.CODEC.toBuilder().protocolVersion(860).minecraftVersion("1.21.124").build());
9293

9394
MinecraftVersion latestBedrock = SUPPORTED_BEDROCK_VERSIONS.get(SUPPORTED_BEDROCK_VERSIONS.size() - 1);
9495
DEFAULT_BEDROCK_VERSION = latestBedrock.versionString();

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
3535
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
3636
import it.unimi.dsi.fastutil.ints.IntArrayList;
37-
import it.unimi.dsi.fastutil.objects.Object2IntMap;
3837
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
3938
import it.unimi.dsi.fastutil.objects.Object2ObjectMaps;
4039
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
@@ -128,7 +127,9 @@ private static void registerBedrockBlocks() {
128127
.put(ObjectIntPair.of("1_21_90", Bedrock_v819.CODEC.getProtocolVersion()), Conversion827_819::remapBlock)
129128
.put(ObjectIntPair.of("1_21_100", Bedrock_v827.CODEC.getProtocolVersion()), Conversion844_827::remapBlock)
130129
.put(ObjectIntPair.of("1_21_110", Bedrock_v844.CODEC.getProtocolVersion()), tag -> tag)
130+
// 1.21.110 -> 1.21.12x doesn't change the block palette
131131
.put(ObjectIntPair.of("1_21_110", Bedrock_v859.CODEC.getProtocolVersion()), tag -> tag)
132+
.put(ObjectIntPair.of("1_21_110", 860), tag -> tag)
132133
.build();
133134

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

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

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019-2024 GeyserMC. http://geysermc.org
2+
* Copyright (c) 2019-2025 GeyserMC. http://geysermc.org
33
*
44
* Permission is hereby granted, free of charge, to any person obtaining a copy
55
* of this software and associated documentation files (the "Software"), to deal
@@ -448,15 +448,23 @@ private static NbtMap convertComponents(CustomBlockComponents components, int pr
448448
for (Map.Entry<String, MaterialInstance> entry : components.materialInstances().entrySet()) {
449449
MaterialInstance materialInstance = entry.getValue();
450450
NbtMapBuilder materialBuilder = NbtMap.builder()
451-
.putString("render_method", materialInstance.renderMethod())
452-
.putBoolean("ambient_occlusion", materialInstance.ambientOcclusion());
451+
.putBoolean("ambient_occlusion", materialInstance.ambientOcclusion())
452+
.putBoolean("isotropic", materialInstance.isotropic());
453453

454454
if (GameProtocol.is1_21_110orHigher(protocolVersion)) {
455455
materialBuilder.putBoolean("packed_bools", materialInstance.faceDimming());
456456
} else {
457457
materialBuilder.putBoolean("face_dimming", materialInstance.faceDimming());
458458
}
459459

460+
if (materialInstance.renderMethod() != null) {
461+
materialBuilder.putString("render_method", materialInstance.renderMethod());
462+
}
463+
464+
if (materialInstance.tintMethod() != null) {
465+
materialBuilder.putString("tint_method", materialInstance.tintMethod());
466+
}
467+
460468
// Texture can be unspecified when blocks.json is used in RP (https://wiki.bedrock.dev/blocks/blocks-stable.html#minecraft-material-instances)
461469
if (materialInstance.texture() != null) {
462470
materialBuilder.putString("texture", materialInstance.texture());

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,12 +194,13 @@ public static void populate() {
194194
Map<Item, Item> eightOneEightFallbacks = new HashMap<>(eightOneNineFallbacks);
195195
eightOneEightFallbacks.put(Items.MUSIC_DISC_LAVA_CHICKEN, Items.MUSIC_DISC_CHIRP);
196196

197-
List<PaletteVersion> paletteVersions = new ArrayList<>(4);
197+
List<PaletteVersion> paletteVersions = new ArrayList<>(6);
198198
paletteVersions.add(new PaletteVersion("1_21_90", Bedrock_v818.CODEC.getProtocolVersion(), eightOneEightFallbacks, Conversion844_827::remapItem));
199199
paletteVersions.add(new PaletteVersion("1_21_93", Bedrock_v819.CODEC.getProtocolVersion(), eightOneNineFallbacks, Conversion844_827::remapItem));
200200
paletteVersions.add(new PaletteVersion("1_21_100", Bedrock_v827.CODEC.getProtocolVersion(), eightTwoSevenFallbacks, Conversion844_827::remapItem));
201201
paletteVersions.add(new PaletteVersion("1_21_110", Bedrock_v844.CODEC.getProtocolVersion()));
202202
paletteVersions.add(new PaletteVersion("1_21_120", Bedrock_v859.CODEC.getProtocolVersion()));
203+
paletteVersions.add(new PaletteVersion("1_21_120", 860));
203204

204205
GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap();
205206

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@ org.gradle.vfs.watch=false
88

99
group=org.geysermc
1010
id=geyser
11-
version=2.9.0-SNAPSHOT
11+
version=2.9.1-SNAPSHOT
1212
description=Allows for players from Minecraft: Bedrock Edition to join Minecraft: Java Edition servers.

0 commit comments

Comments
 (0)