Railcraft

Railcraft

34M Downloads

NullPointerException with OutfittedTrackModel getQuads

TimTinkers opened this issue ยท 9 comments

commented

Description of the Bug
I am writing a mod which seeks to export an average pixel color for the top surface of all blocks.

To Reproduce
My code is as follows:

			// Find the texture of each block and write to file.
			for (Block block : ForgeRegistries.BLOCKS) {
				for (IBlockState blockState : block.getBlockState().getValidStates()) {
					String variantName = blockState.toString();
					TextureAtlasSprite sprite = null;

					// If a block is liquid, get its texture from the fluid registry.
					if (block instanceof IFluidBlock || block instanceof BlockLiquid) {
						Fluid fluid = FluidRegistry.lookupFluidForBlock(block);
						if (fluid == null) {
							sender.sendMessage(new TextComponentString(
									TextFormatting.RED + "Unable to find fluid sprite for '" + variantName + "'!"));
						} else {
							ResourceLocation fluidTexture = fluid.getStill();
							sprite = Minecraft.getMinecraft().getTextureMapBlocks()
									.getAtlasSprite(fluidTexture.toString());
						}

						// Retrieve the top quad of the solid block.
					} else {
						IBakedModel bakedModel = Minecraft.getMinecraft().getBlockRendererDispatcher()
								.getBlockModelShapes().getModelForState(blockState);
						if (bakedModel == null) {
							sender.sendMessage(new TextComponentString(TextFormatting.RED
									+ "Unable to find baked model sprite for '" + variantName + "'!"));
						} else {
							List<BakedQuad> quadList = bakedModel.getQuads(blockState, EnumFacing.UP, 0L);
							sprite = quadList.isEmpty() ? bakedModel.getParticleTexture() : quadList.get(0).getSprite();
						}
					}
...

with the specific line List<BakedQuad> quadList = bakedModel.getQuads(blockState, EnumFacing.UP, 0L); causing the following crash.

Expected behavior
I expect to be able to retrieve the TextureAtlasSprite for the top surface of your block the same way I can with vanilla blocks.

Logs & Environment
Here is my full crash log. https://pastebin.com/72c3f9j5

Additional context
I am working on 1.12.2 and this is using my mod as a compiled jar running on a server.

commented

My bad; the mod is present on the server and the client and I am executing this command from the client.

It does not crash until I execute the command that runs the above code. I have no idea how it happens either, but it definitely does. This same NPE seems to have cropped up from time to time in other issues as well.

This is running in a tick event, but don't worry. Not present in the code I shared is logic that ensures this only happens on the very first tick. The plan is to spread this out across the remainder of some other ticks to keep processing running in a longer operation that I don't want to cause noticeable lag by cramming full a single tick.

commented

I am working on 1.12.2 and this is using my mod as a compiled jar running on a server.

Well, the log says you are on the client.

Moreover, does it crash immediately when you join a world on the client side? I don't see how an NPE can happen on this line

kitState = ((IExtendedBlockState) state).getValue(BlockTrackOutfitted.STATE);

Moreover, you seem to be collecting all the pixel color each tick. I suggest you do it only once in some other event like load complete event.

commented

The NPE occurs when getValue checks the value of the state, which is null (Optional.empty) for all the states returned by getValidStates. For rendering the model in the world, Forge calls getExtendedState on the Block to get a state before passing it to getQuads. I'll investigate further and see if the issue is in getValidStates, getQuads, or because getExtendedState always needs to be called to render blocks.

commented

I think the issue is caused by setDefaultState for BlockTrackOutfitted

setDefaultState(getDefaultState().withProperty(TICKING, false));

not setting the unlisted properties - so the model believes it can get the properties from the IExtendedBlockState but it cannot, as the properties are null.

commented

I'll probably revert this because setting the default state has broken rendering of the track for some reason.

I think you may have to call getExtendedState().

commented

Reverted

commented

It crashes on this line:

kitState = ((IExtendedBlockState) state).getValue(BlockTrackOutfitted.STATE);

The reason it crashes is because getValue() returned null. If a value was present, it would return an Integer object. Note, an Integer, not an int. It would then perform auto-unboxing to convert it to an int. But the auto-unboxing fails because it is null.

commented

See #1072

commented

Awesome, thanks for getting around to clearing this one. :)