mirror of
https://github.com/GeyserMC/Geyser.git
synced 2025-01-01 08:56:09 +01:00
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
This commit is contained in:
parent
2e6cf2f4ca
commit
ded6f6bb7c
6 changed files with 15 additions and 13 deletions
|
@ -152,7 +152,7 @@ public class SkullPlayerEntity extends PlayerEntity {
|
||||||
case EAST -> x -= 0.24f;
|
case EAST -> x -= 0.24f;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rotation = (180f + (blockState.getValue(Properties.ROTATION_16) * 22.5f)) % 360;
|
rotation = (180f + blockState.getValue(Properties.ROTATION_16, 0) * 22.5f) % 360;
|
||||||
}
|
}
|
||||||
|
|
||||||
moveAbsolute(Vector3f.from(x, y, z), rotation, 0, rotation, true, true);
|
moveAbsolute(Vector3f.from(x, y, z), rotation, 0, rotation, true, true);
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
package org.geysermc.geyser.level.block.type;
|
package org.geysermc.geyser.level.block.type;
|
||||||
|
|
||||||
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.geysermc.geyser.level.block.property.Property;
|
import org.geysermc.geyser.level.block.property.Property;
|
||||||
import org.geysermc.geyser.registry.BlockRegistries;
|
import org.geysermc.geyser.registry.BlockRegistries;
|
||||||
|
@ -184,7 +185,14 @@ public final class BlockState {
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Null-safe method that looks up a Java block state ID in the BLOCK_STATES registry, and defaults to air if not found.
|
||||||
|
*
|
||||||
|
* @param javaId the Java block state ID to look up.
|
||||||
|
* @return the corresponding block state, or air if the given ID wasn't registered and returned null.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
public static BlockState of(int javaId) {
|
public static BlockState of(int javaId) {
|
||||||
return BlockRegistries.BLOCK_STATES.get(javaId);
|
return BlockRegistries.BLOCK_STATES.getOrDefault(javaId, BlockRegistries.BLOCK_STATES.get(Block.JAVA_AIR_ID));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -160,7 +160,7 @@ public class BedrockActionTranslator extends PacketTranslator<PlayerActionPacket
|
||||||
LevelEventPacket startBreak = new LevelEventPacket();
|
LevelEventPacket startBreak = new LevelEventPacket();
|
||||||
startBreak.setType(LevelEvent.BLOCK_START_BREAK);
|
startBreak.setType(LevelEvent.BLOCK_START_BREAK);
|
||||||
startBreak.setPosition(vector.toFloat());
|
startBreak.setPosition(vector.toFloat());
|
||||||
double breakTime = BlockUtils.getSessionBreakTime(session, BlockRegistries.BLOCK_STATES.getOrDefault(blockState, BlockState.of(Block.JAVA_AIR_ID)).block()) * 20;
|
double breakTime = BlockUtils.getSessionBreakTime(session, BlockState.of(blockState).block()) * 20;
|
||||||
|
|
||||||
// If the block is custom or the breaking item is custom, we must keep track of break time ourselves
|
// If the block is custom or the breaking item is custom, we must keep track of break time ourselves
|
||||||
GeyserItemStack item = session.getPlayerInventory().getItemInHand();
|
GeyserItemStack item = session.getPlayerInventory().getItemInHand();
|
||||||
|
@ -211,7 +211,7 @@ public class BedrockActionTranslator extends PacketTranslator<PlayerActionPacket
|
||||||
LevelEventPacket updateBreak = new LevelEventPacket();
|
LevelEventPacket updateBreak = new LevelEventPacket();
|
||||||
updateBreak.setType(LevelEvent.BLOCK_UPDATE_BREAK);
|
updateBreak.setType(LevelEvent.BLOCK_UPDATE_BREAK);
|
||||||
updateBreak.setPosition(vectorFloat);
|
updateBreak.setPosition(vectorFloat);
|
||||||
double breakTime = BlockUtils.getSessionBreakTime(session, BlockRegistries.BLOCK_STATES.getOrDefault(breakingBlock, BlockState.of(Block.JAVA_AIR_ID)).block()) * 20;
|
double breakTime = BlockUtils.getSessionBreakTime(session, BlockState.of(breakingBlock).block()) * 20;
|
||||||
|
|
||||||
|
|
||||||
// If the block is custom, we must keep track of when it should break ourselves
|
// If the block is custom, we must keep track of when it should break ourselves
|
||||||
|
|
|
@ -27,9 +27,7 @@ package org.geysermc.geyser.translator.protocol.java.level;
|
||||||
|
|
||||||
import org.cloudburstmc.protocol.bedrock.data.LevelEvent;
|
import org.cloudburstmc.protocol.bedrock.data.LevelEvent;
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket;
|
import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket;
|
||||||
import org.geysermc.geyser.level.block.type.Block;
|
|
||||||
import org.geysermc.geyser.level.block.type.BlockState;
|
import org.geysermc.geyser.level.block.type.BlockState;
|
||||||
import org.geysermc.geyser.registry.BlockRegistries;
|
|
||||||
import org.geysermc.geyser.registry.type.ItemMapping;
|
import org.geysermc.geyser.registry.type.ItemMapping;
|
||||||
import org.geysermc.geyser.session.GeyserSession;
|
import org.geysermc.geyser.session.GeyserSession;
|
||||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||||
|
@ -43,7 +41,7 @@ public class JavaBlockDestructionTranslator extends PacketTranslator<Clientbound
|
||||||
@Override
|
@Override
|
||||||
public void translate(GeyserSession session, ClientboundBlockDestructionPacket packet) {
|
public void translate(GeyserSession session, ClientboundBlockDestructionPacket packet) {
|
||||||
int state = session.getGeyser().getWorldManager().getBlockAt(session, packet.getPosition().getX(), packet.getPosition().getY(), packet.getPosition().getZ());
|
int state = session.getGeyser().getWorldManager().getBlockAt(session, packet.getPosition().getX(), packet.getPosition().getY(), packet.getPosition().getZ());
|
||||||
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));
|
int breakTime = (int) (65535 / Math.ceil(BlockUtils.getBreakTime(session, BlockState.of(state).block(), ItemMapping.AIR, null, false) * 20));
|
||||||
LevelEventPacket levelEventPacket = new LevelEventPacket();
|
LevelEventPacket levelEventPacket = new LevelEventPacket();
|
||||||
levelEventPacket.setPosition(packet.getPosition().toFloat());
|
levelEventPacket.setPosition(packet.getPosition().toFloat());
|
||||||
levelEventPacket.setType(LevelEvent.BLOCK_START_BREAK);
|
levelEventPacket.setType(LevelEvent.BLOCK_START_BREAK);
|
||||||
|
|
|
@ -33,9 +33,7 @@ import org.cloudburstmc.protocol.bedrock.data.structure.StructureMirror;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.structure.StructureRotation;
|
import org.cloudburstmc.protocol.bedrock.data.structure.StructureRotation;
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.ContainerOpenPacket;
|
import org.cloudburstmc.protocol.bedrock.packet.ContainerOpenPacket;
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
|
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
|
||||||
import org.geysermc.geyser.level.block.Blocks;
|
|
||||||
import org.geysermc.geyser.level.block.type.BlockState;
|
import org.geysermc.geyser.level.block.type.BlockState;
|
||||||
import org.geysermc.geyser.registry.BlockRegistries;
|
|
||||||
import org.geysermc.geyser.session.GeyserSession;
|
import org.geysermc.geyser.session.GeyserSession;
|
||||||
import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator;
|
import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator;
|
||||||
import org.geysermc.geyser.translator.level.block.entity.SkullBlockEntityTranslator;
|
import org.geysermc.geyser.translator.level.block.entity.SkullBlockEntityTranslator;
|
||||||
|
@ -59,8 +57,7 @@ public class JavaBlockEntityDataTranslator extends PacketTranslator<ClientboundB
|
||||||
BlockEntityTranslator translator = BlockEntityUtils.getBlockEntityTranslator(type);
|
BlockEntityTranslator translator = BlockEntityUtils.getBlockEntityTranslator(type);
|
||||||
// The Java block state is used in BlockEntityTranslator.translateTag() to make up for some inconsistencies
|
// The Java block state is used in BlockEntityTranslator.translateTag() to make up for some inconsistencies
|
||||||
// between Java block states and Bedrock block entity data
|
// between Java block states and Bedrock block entity data
|
||||||
BlockState blockState = BlockRegistries.BLOCK_STATES.getOrDefault(session.getGeyser().getWorldManager().getBlockAt(session, packet.getPosition()),
|
BlockState blockState = session.getGeyser().getWorldManager().blockAt(session, packet.getPosition());
|
||||||
Blocks.AIR.defaultBlockState());
|
|
||||||
|
|
||||||
if (blockState.block().blockEntityType() != type) {
|
if (blockState.block().blockEntityType() != type) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -39,7 +39,6 @@ import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition;
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.LevelChunkPacket;
|
import org.cloudburstmc.protocol.bedrock.packet.LevelChunkPacket;
|
||||||
import org.geysermc.geyser.entity.type.ItemFrameEntity;
|
import org.geysermc.geyser.entity.type.ItemFrameEntity;
|
||||||
import org.geysermc.geyser.level.BedrockDimension;
|
import org.geysermc.geyser.level.BedrockDimension;
|
||||||
import org.geysermc.geyser.level.block.Blocks;
|
|
||||||
import org.geysermc.geyser.level.block.type.Block;
|
import org.geysermc.geyser.level.block.type.Block;
|
||||||
import org.geysermc.geyser.level.block.type.BlockState;
|
import org.geysermc.geyser.level.block.type.BlockState;
|
||||||
import org.geysermc.geyser.level.chunk.BlockStorage;
|
import org.geysermc.geyser.level.chunk.BlockStorage;
|
||||||
|
@ -399,7 +398,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
|
||||||
|
|
||||||
// Get the Java block state ID from block entity position
|
// Get the Java block state ID from block entity position
|
||||||
DataPalette section = javaChunks[(y >> 4) - yOffset];
|
DataPalette section = javaChunks[(y >> 4) - yOffset];
|
||||||
BlockState blockState = BlockRegistries.BLOCK_STATES.getOrDefault(section.get(x, y & 0xF, z), Blocks.AIR.defaultBlockState());
|
BlockState blockState = BlockState.of(section.get(x, y & 0xF, z));
|
||||||
|
|
||||||
// Note that, since 1.20.5, tags can be null, but Bedrock still needs a default tag to render the item
|
// Note that, since 1.20.5, tags can be null, but Bedrock still needs a default tag to render the item
|
||||||
// Also, some properties - like banner base colors - are part of the tag and is processed here.
|
// Also, some properties - like banner base colors - are part of the tag and is processed here.
|
||||||
|
|
Loading…
Reference in a new issue