mirror of
https://github.com/GeyserMC/Geyser.git
synced 2025-12-19 06:49:28 +00:00
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>
This commit is contained in:
@@ -15,7 +15,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!
|
||||
|
||||
## Supported Versions
|
||||
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/).
|
||||
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/).
|
||||
|
||||
## Setting Up
|
||||
Take a look [here](https://geysermc.org/wiki/geyser/setup/) for how to set up Geyser.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2025 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -46,6 +46,13 @@ public interface MaterialInstance {
|
||||
*/
|
||||
@Nullable String renderMethod();
|
||||
|
||||
/**
|
||||
* Gets the tint method of the block
|
||||
*
|
||||
* @return The tint method of the block.
|
||||
*/
|
||||
@Nullable String tintMethod();
|
||||
|
||||
/**
|
||||
* Gets if the block should be dimmed on certain faces
|
||||
*
|
||||
@@ -60,6 +67,13 @@ public interface MaterialInstance {
|
||||
*/
|
||||
boolean ambientOcclusion();
|
||||
|
||||
/**
|
||||
* Gets if the block is isotropic
|
||||
*
|
||||
* @return If the block is isotropic.
|
||||
*/
|
||||
boolean isotropic();
|
||||
|
||||
/**
|
||||
* Creates a builder for MaterialInstance.
|
||||
*
|
||||
@@ -74,10 +88,14 @@ public interface MaterialInstance {
|
||||
|
||||
Builder renderMethod(@Nullable String renderMethod);
|
||||
|
||||
Builder tintMethod(@Nullable String tintMethod);
|
||||
|
||||
Builder faceDimming(boolean faceDimming);
|
||||
|
||||
Builder ambientOcclusion(boolean ambientOcclusion);
|
||||
|
||||
Builder isotropic(boolean isotropic);
|
||||
|
||||
MaterialInstance build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,23 @@ public interface GeyserEntity {
|
||||
/**
|
||||
* Updates multiple properties with just one update packet.
|
||||
* @see BatchPropertyUpdater
|
||||
*
|
||||
* @param consumer a batch updater
|
||||
* @since 2.9.0
|
||||
*/
|
||||
void updatePropertiesBatched(Consumer<BatchPropertyUpdater> consumer);
|
||||
default void updatePropertiesBatched(Consumer<BatchPropertyUpdater> consumer) {
|
||||
this.updatePropertiesBatched(consumer, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates multiple properties with just one update packet, which can be sent immediately to the client.
|
||||
* Usually, sending updates immediately is not required except for specific situations where packet batching
|
||||
* would result in update order issues.
|
||||
* @see BatchPropertyUpdater
|
||||
*
|
||||
* @param consumer a batch updater
|
||||
* @param immediate whether this update should be sent immediately
|
||||
* @since 2.9.1
|
||||
*/
|
||||
void updatePropertiesBatched(Consumer<BatchPropertyUpdater> consumer, boolean immediate);
|
||||
}
|
||||
|
||||
@@ -778,40 +778,44 @@ public class Entity implements GeyserEntity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updatePropertiesBatched(Consumer<BatchPropertyUpdater> consumer) {
|
||||
if (this.propertyManager != null) {
|
||||
Objects.requireNonNull(consumer);
|
||||
GeyserEntityProperties propertyDefinitions = definition.registeredProperties();
|
||||
consumer.accept(new BatchPropertyUpdater() {
|
||||
@Override
|
||||
public <T> void update(@NonNull GeyserEntityProperty<T> property, @Nullable T value) {
|
||||
Objects.requireNonNull(property, "property must not be null!");
|
||||
if (!(property instanceof PropertyType<T, ? extends EntityProperty> propertyType)) {
|
||||
throw new IllegalArgumentException("Invalid property implementation! Got: " + property.getClass().getSimpleName());
|
||||
}
|
||||
int index = propertyDefinitions.getPropertyIndex(property.identifier().toString());
|
||||
if (index < 0) {
|
||||
throw new IllegalArgumentException("No property with the name " + property.identifier() + " has been registered.");
|
||||
}
|
||||
public void updatePropertiesBatched(Consumer<BatchPropertyUpdater> consumer, boolean immediate) {
|
||||
if (this.propertyManager == null) {
|
||||
throw new IllegalArgumentException("Given entity has no registered properties!");
|
||||
}
|
||||
|
||||
var expectedProperty = propertyDefinitions.getProperties().get(index);
|
||||
if (!expectedProperty.equals(propertyType)) {
|
||||
throw new IllegalArgumentException("The supplied property was not registered with this entity type!");
|
||||
}
|
||||
|
||||
propertyType.apply(propertyManager, value);
|
||||
Objects.requireNonNull(consumer);
|
||||
GeyserEntityProperties propertyDefinitions = definition.registeredProperties();
|
||||
consumer.accept(new BatchPropertyUpdater() {
|
||||
@Override
|
||||
public <T> void update(@NonNull GeyserEntityProperty<T> property, @Nullable T value) {
|
||||
Objects.requireNonNull(property, "property must not be null!");
|
||||
if (!(property instanceof PropertyType<T, ? extends EntityProperty> propertyType)) {
|
||||
throw new IllegalArgumentException("Invalid property implementation! Got: " + property.getClass().getSimpleName());
|
||||
}
|
||||
int index = propertyDefinitions.getPropertyIndex(property.identifier().toString());
|
||||
if (index < 0) {
|
||||
throw new IllegalArgumentException("No property with the name " + property.identifier() + " has been registered.");
|
||||
}
|
||||
});
|
||||
|
||||
if (propertyManager.hasProperties()) {
|
||||
SetEntityDataPacket packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(getGeyserId());
|
||||
propertyManager.applyFloatProperties(packet.getProperties().getFloatProperties());
|
||||
propertyManager.applyIntProperties(packet.getProperties().getIntProperties());
|
||||
var expectedProperty = propertyDefinitions.getProperties().get(index);
|
||||
if (!expectedProperty.equals(propertyType)) {
|
||||
throw new IllegalArgumentException("The supplied property was not registered with this entity type!");
|
||||
}
|
||||
|
||||
propertyType.apply(propertyManager, value);
|
||||
}
|
||||
});
|
||||
|
||||
if (propertyManager.hasProperties()) {
|
||||
SetEntityDataPacket packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(getGeyserId());
|
||||
propertyManager.applyFloatProperties(packet.getProperties().getFloatProperties());
|
||||
propertyManager.applyIntProperties(packet.getProperties().getIntProperties());
|
||||
if (immediate) {
|
||||
session.sendUpstreamPacketImmediately(packet);
|
||||
} else {
|
||||
session.sendUpstreamPacket(packet);
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException("Given entity has no registered properties!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2025 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -33,14 +33,18 @@ import org.geysermc.geyser.api.block.custom.component.MaterialInstance;
|
||||
public class GeyserMaterialInstance implements MaterialInstance {
|
||||
private final String texture;
|
||||
private final String renderMethod;
|
||||
private final String tintMethod;
|
||||
private final boolean faceDimming;
|
||||
private final boolean ambientOcclusion;
|
||||
private final boolean isotropic;
|
||||
|
||||
GeyserMaterialInstance(Builder builder) {
|
||||
this.texture = builder.texture;
|
||||
this.renderMethod = builder.renderMethod;
|
||||
this.tintMethod = builder.tintMethod;
|
||||
this.faceDimming = builder.faceDimming;
|
||||
this.ambientOcclusion = builder.ambientOcclusion;
|
||||
this.isotropic = builder.isotropic;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -53,6 +57,11 @@ public class GeyserMaterialInstance implements MaterialInstance {
|
||||
return renderMethod;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String tintMethod() {
|
||||
return tintMethod;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean faceDimming() {
|
||||
return faceDimming;
|
||||
@@ -63,11 +72,18 @@ public class GeyserMaterialInstance implements MaterialInstance {
|
||||
return ambientOcclusion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isotropic() {
|
||||
return isotropic;
|
||||
}
|
||||
|
||||
public static class Builder implements MaterialInstance.Builder {
|
||||
private String texture;
|
||||
private String renderMethod;
|
||||
private String tintMethod;
|
||||
private boolean faceDimming;
|
||||
private boolean ambientOcclusion;
|
||||
private boolean isotropic;
|
||||
|
||||
@Override
|
||||
public Builder texture(@Nullable String texture) {
|
||||
@@ -81,6 +97,12 @@ public class GeyserMaterialInstance implements MaterialInstance {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder tintMethod(@Nullable String tintMethod) {
|
||||
this.tintMethod = tintMethod;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder faceDimming(boolean faceDimming) {
|
||||
this.faceDimming = faceDimming;
|
||||
@@ -93,6 +115,12 @@ public class GeyserMaterialInstance implements MaterialInstance {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MaterialInstance.Builder isotropic(boolean isotropic) {
|
||||
this.isotropic = isotropic;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MaterialInstance build() {
|
||||
return new GeyserMaterialInstance(this);
|
||||
|
||||
@@ -89,6 +89,7 @@ public final class GameProtocol {
|
||||
register(Bedrock_v827.CODEC, "1.21.100", "1.21.101");
|
||||
register(Bedrock_v844.CODEC, "1.21.111", "1.21.112", "1.21.113", "1.21.114");
|
||||
register(Bedrock_v859.CODEC, "1.21.120", "1.21.121", "1.21.122", "1.21.123");
|
||||
register(Bedrock_v859.CODEC.toBuilder().protocolVersion(860).minecraftVersion("1.21.124").build());
|
||||
|
||||
MinecraftVersion latestBedrock = SUPPORTED_BEDROCK_VERSIONS.get(SUPPORTED_BEDROCK_VERSIONS.size() - 1);
|
||||
DEFAULT_BEDROCK_VERSION = latestBedrock.versionString();
|
||||
|
||||
@@ -34,7 +34,6 @@ import com.google.gson.JsonObject;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectMaps;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
@@ -128,7 +127,9 @@ public final class BlockRegistryPopulator {
|
||||
.put(ObjectIntPair.of("1_21_90", Bedrock_v819.CODEC.getProtocolVersion()), Conversion827_819::remapBlock)
|
||||
.put(ObjectIntPair.of("1_21_100", Bedrock_v827.CODEC.getProtocolVersion()), Conversion844_827::remapBlock)
|
||||
.put(ObjectIntPair.of("1_21_110", Bedrock_v844.CODEC.getProtocolVersion()), tag -> tag)
|
||||
// 1.21.110 -> 1.21.12x doesn't change the block palette
|
||||
.put(ObjectIntPair.of("1_21_110", Bedrock_v859.CODEC.getProtocolVersion()), tag -> tag)
|
||||
.put(ObjectIntPair.of("1_21_110", 860), tag -> tag)
|
||||
.build();
|
||||
|
||||
// We can keep this strong as nothing should be garbage collected
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2024 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2025 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -448,8 +448,8 @@ public class CustomBlockRegistryPopulator {
|
||||
for (Map.Entry<String, MaterialInstance> entry : components.materialInstances().entrySet()) {
|
||||
MaterialInstance materialInstance = entry.getValue();
|
||||
NbtMapBuilder materialBuilder = NbtMap.builder()
|
||||
.putString("render_method", materialInstance.renderMethod())
|
||||
.putBoolean("ambient_occlusion", materialInstance.ambientOcclusion());
|
||||
.putBoolean("ambient_occlusion", materialInstance.ambientOcclusion())
|
||||
.putBoolean("isotropic", materialInstance.isotropic());
|
||||
|
||||
if (GameProtocol.is1_21_110orHigher(protocolVersion)) {
|
||||
materialBuilder.putBoolean("packed_bools", materialInstance.faceDimming());
|
||||
@@ -457,6 +457,14 @@ public class CustomBlockRegistryPopulator {
|
||||
materialBuilder.putBoolean("face_dimming", materialInstance.faceDimming());
|
||||
}
|
||||
|
||||
if (materialInstance.renderMethod() != null) {
|
||||
materialBuilder.putString("render_method", materialInstance.renderMethod());
|
||||
}
|
||||
|
||||
if (materialInstance.tintMethod() != null) {
|
||||
materialBuilder.putString("tint_method", materialInstance.tintMethod());
|
||||
}
|
||||
|
||||
// Texture can be unspecified when blocks.json is used in RP (https://wiki.bedrock.dev/blocks/blocks-stable.html#minecraft-material-instances)
|
||||
if (materialInstance.texture() != null) {
|
||||
materialBuilder.putString("texture", materialInstance.texture());
|
||||
|
||||
@@ -194,12 +194,13 @@ public class ItemRegistryPopulator {
|
||||
Map<Item, Item> eightOneEightFallbacks = new HashMap<>(eightOneNineFallbacks);
|
||||
eightOneEightFallbacks.put(Items.MUSIC_DISC_LAVA_CHICKEN, Items.MUSIC_DISC_CHIRP);
|
||||
|
||||
List<PaletteVersion> paletteVersions = new ArrayList<>(4);
|
||||
List<PaletteVersion> paletteVersions = new ArrayList<>(6);
|
||||
paletteVersions.add(new PaletteVersion("1_21_90", Bedrock_v818.CODEC.getProtocolVersion(), eightOneEightFallbacks, Conversion844_827::remapItem));
|
||||
paletteVersions.add(new PaletteVersion("1_21_93", Bedrock_v819.CODEC.getProtocolVersion(), eightOneNineFallbacks, Conversion844_827::remapItem));
|
||||
paletteVersions.add(new PaletteVersion("1_21_100", Bedrock_v827.CODEC.getProtocolVersion(), eightTwoSevenFallbacks, Conversion844_827::remapItem));
|
||||
paletteVersions.add(new PaletteVersion("1_21_110", Bedrock_v844.CODEC.getProtocolVersion()));
|
||||
paletteVersions.add(new PaletteVersion("1_21_120", Bedrock_v859.CODEC.getProtocolVersion()));
|
||||
paletteVersions.add(new PaletteVersion("1_21_120", 860));
|
||||
|
||||
GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap();
|
||||
|
||||
|
||||
@@ -8,5 +8,5 @@ org.gradle.vfs.watch=false
|
||||
|
||||
group=org.geysermc
|
||||
id=geyser
|
||||
version=2.9.0-SNAPSHOT
|
||||
version=2.9.1-SNAPSHOT
|
||||
description=Allows for players from Minecraft: Bedrock Edition to join Minecraft: Java Edition servers.
|
||||
|
||||
Reference in New Issue
Block a user