Skip to content

Commit ded6f6b

Browse files
Fix NPEs caused by custom head blocks from Polymer (#4764)
* Add null checks to fix NPEs caused by custom head blocks from Polymer * Make sure block state is never null, remove now unnecessary null checks * Remove unnecessary default fallback in skull block entity translator
1 parent 2e6cf2f commit ded6f6b

File tree

6 files changed

+15
-13
lines changed

6 files changed

+15
-13
lines changed

core/src/main/java/org/geysermc/geyser/entity/type/player/SkullPlayerEntity.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ public void updateSkull(SkullCache.Skull skull) {
152152
case EAST -> x -= 0.24f;
153153
}
154154
} else {
155-
rotation = (180f + (blockState.getValue(Properties.ROTATION_16) * 22.5f)) % 360;
155+
rotation = (180f + blockState.getValue(Properties.ROTATION_16, 0) * 22.5f) % 360;
156156
}
157157

158158
moveAbsolute(Vector3f.from(x, y, z), rotation, 0, rotation, true, true);

core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
package org.geysermc.geyser.level.block.type;
2727

28+
import org.checkerframework.checker.nullness.qual.NonNull;
2829
import org.checkerframework.checker.nullness.qual.Nullable;
2930
import org.geysermc.geyser.level.block.property.Property;
3031
import org.geysermc.geyser.registry.BlockRegistries;
@@ -184,7 +185,14 @@ private String paramsToString() {
184185
return builder.toString();
185186
}
186187

188+
/**
189+
* Null-safe method that looks up a Java block state ID in the BLOCK_STATES registry, and defaults to air if not found.
190+
*
191+
* @param javaId the Java block state ID to look up.
192+
* @return the corresponding block state, or air if the given ID wasn't registered and returned null.
193+
*/
194+
@NonNull
187195
public static BlockState of(int javaId) {
188-
return BlockRegistries.BLOCK_STATES.get(javaId);
196+
return BlockRegistries.BLOCK_STATES.getOrDefault(javaId, BlockRegistries.BLOCK_STATES.get(Block.JAVA_AIR_ID));
189197
}
190198
}

core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ public void translate(GeyserSession session, PlayerActionPacket packet) {
160160
LevelEventPacket startBreak = new LevelEventPacket();
161161
startBreak.setType(LevelEvent.BLOCK_START_BREAK);
162162
startBreak.setPosition(vector.toFloat());
163-
double breakTime = BlockUtils.getSessionBreakTime(session, BlockRegistries.BLOCK_STATES.getOrDefault(blockState, BlockState.of(Block.JAVA_AIR_ID)).block()) * 20;
163+
double breakTime = BlockUtils.getSessionBreakTime(session, BlockState.of(blockState).block()) * 20;
164164

165165
// If the block is custom or the breaking item is custom, we must keep track of break time ourselves
166166
GeyserItemStack item = session.getPlayerInventory().getItemInHand();
@@ -211,7 +211,7 @@ public void translate(GeyserSession session, PlayerActionPacket packet) {
211211
LevelEventPacket updateBreak = new LevelEventPacket();
212212
updateBreak.setType(LevelEvent.BLOCK_UPDATE_BREAK);
213213
updateBreak.setPosition(vectorFloat);
214-
double breakTime = BlockUtils.getSessionBreakTime(session, BlockRegistries.BLOCK_STATES.getOrDefault(breakingBlock, BlockState.of(Block.JAVA_AIR_ID)).block()) * 20;
214+
double breakTime = BlockUtils.getSessionBreakTime(session, BlockState.of(breakingBlock).block()) * 20;
215215

216216

217217
// If the block is custom, we must keep track of when it should break ourselves

core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockDestructionTranslator.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,7 @@
2727

2828
import org.cloudburstmc.protocol.bedrock.data.LevelEvent;
2929
import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket;
30-
import org.geysermc.geyser.level.block.type.Block;
3130
import org.geysermc.geyser.level.block.type.BlockState;
32-
import org.geysermc.geyser.registry.BlockRegistries;
3331
import org.geysermc.geyser.registry.type.ItemMapping;
3432
import org.geysermc.geyser.session.GeyserSession;
3533
import org.geysermc.geyser.translator.protocol.PacketTranslator;
@@ -43,7 +41,7 @@ public class JavaBlockDestructionTranslator extends PacketTranslator<Clientbound
4341
@Override
4442
public void translate(GeyserSession session, ClientboundBlockDestructionPacket packet) {
4543
int state = session.getGeyser().getWorldManager().getBlockAt(session, packet.getPosition().getX(), packet.getPosition().getY(), packet.getPosition().getZ());
46-
int breakTime = (int) (65535 / Math.ceil(BlockUtils.getBreakTime(session, BlockRegistries.BLOCK_STATES.getOrDefault(state, BlockState.of(Block.JAVA_AIR_ID)).block(), ItemMapping.AIR, null, false) * 20));
44+
int breakTime = (int) (65535 / Math.ceil(BlockUtils.getBreakTime(session, BlockState.of(state).block(), ItemMapping.AIR, null, false) * 20));
4745
LevelEventPacket levelEventPacket = new LevelEventPacket();
4846
levelEventPacket.setPosition(packet.getPosition().toFloat());
4947
levelEventPacket.setType(LevelEvent.BLOCK_START_BREAK);

core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockEntityDataTranslator.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,7 @@
3333
import org.cloudburstmc.protocol.bedrock.data.structure.StructureRotation;
3434
import org.cloudburstmc.protocol.bedrock.packet.ContainerOpenPacket;
3535
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
36-
import org.geysermc.geyser.level.block.Blocks;
3736
import org.geysermc.geyser.level.block.type.BlockState;
38-
import org.geysermc.geyser.registry.BlockRegistries;
3937
import org.geysermc.geyser.session.GeyserSession;
4038
import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator;
4139
import org.geysermc.geyser.translator.level.block.entity.SkullBlockEntityTranslator;
@@ -59,8 +57,7 @@ public void translate(GeyserSession session, ClientboundBlockEntityDataPacket pa
5957
BlockEntityTranslator translator = BlockEntityUtils.getBlockEntityTranslator(type);
6058
// The Java block state is used in BlockEntityTranslator.translateTag() to make up for some inconsistencies
6159
// between Java block states and Bedrock block entity data
62-
BlockState blockState = BlockRegistries.BLOCK_STATES.getOrDefault(session.getGeyser().getWorldManager().getBlockAt(session, packet.getPosition()),
63-
Blocks.AIR.defaultBlockState());
60+
BlockState blockState = session.getGeyser().getWorldManager().blockAt(session, packet.getPosition());
6461

6562
if (blockState.block().blockEntityType() != type) {
6663
return;

core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelChunkWithLightTranslator.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939
import org.cloudburstmc.protocol.bedrock.packet.LevelChunkPacket;
4040
import org.geysermc.geyser.entity.type.ItemFrameEntity;
4141
import org.geysermc.geyser.level.BedrockDimension;
42-
import org.geysermc.geyser.level.block.Blocks;
4342
import org.geysermc.geyser.level.block.type.Block;
4443
import org.geysermc.geyser.level.block.type.BlockState;
4544
import org.geysermc.geyser.level.chunk.BlockStorage;
@@ -399,7 +398,7 @@ public void translate(GeyserSession session, ClientboundLevelChunkWithLightPacke
399398

400399
// Get the Java block state ID from block entity position
401400
DataPalette section = javaChunks[(y >> 4) - yOffset];
402-
BlockState blockState = BlockRegistries.BLOCK_STATES.getOrDefault(section.get(x, y & 0xF, z), Blocks.AIR.defaultBlockState());
401+
BlockState blockState = BlockState.of(section.get(x, y & 0xF, z));
403402

404403
// Note that, since 1.20.5, tags can be null, but Bedrock still needs a default tag to render the item
405404
// Also, some properties - like banner base colors - are part of the tag and is processed here.

0 commit comments

Comments
 (0)