Posted May 18, 20223 yr I was trying to create a custom container. Although there was a NullPointerException, I was still able to play the game and have access to the container and containerScreen, no crashes. Specifically, IDE is pointing to the PacketBuffer data in the ContainerRegistry where it says IForgeContainerType.create(((windowId, inv, data) -> { ... data.readBlockPos(); // Error: data is null?? Anyone know what is the cause of this and how can I fix this? Forge Version: forge:1.16.5-36.2.20 Here is the Error: Spoiler java.lang.NullPointerException: null at com.cassiokf.IndustrialRenewal.init.ModContainers.lambda$null$0(ModContainers.java:29) ~[main/:?] {re:classloading} at net.minecraftforge.fml.network.IContainerFactory.create(IContainerFactory.java:34) ~[forge-1.16.5-36.2.20_mapped_official_1.16.5-recomp.jar:?] {re:classloading} at net.minecraft.inventory.container.ContainerType.create(ContainerType.java:47) ~[forge-1.16.5-36.2.20_mapped_official_1.16.5-recomp.jar:?] {re:classloading,pl:accesstransformer:B} at net.minecraft.client.gui.ScreenManager$IScreenFactory.fromPacket(ScreenManager.java:115) ~[forge-1.16.5-36.2.20_mapped_official_1.16.5-recomp.jar:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A} at net.minecraft.client.gui.ScreenManager.lambda$create$0(ScreenManager.java:43) ~[forge-1.16.5-36.2.20_mapped_official_1.16.5-recomp.jar:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A} at java.util.Optional.ifPresent(Optional.java:159) ~[?:1.8.0_241] {} at net.minecraft.client.gui.ScreenManager.create(ScreenManager.java:43) ~[forge-1.16.5-36.2.20_mapped_official_1.16.5-recomp.jar:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A} at net.minecraft.client.network.play.ClientPlayNetHandler.handleOpenScreen(ClientPlayNetHandler.java:1052) ~[forge-1.16.5-36.2.20_mapped_official_1.16.5-recomp.jar:?] {re:classloading,pl:runtimedistcleaner:A} at net.minecraft.network.play.server.SOpenWindowPacket.handle(SOpenWindowPacket.java:41) ~[forge-1.16.5-36.2.20_mapped_official_1.16.5-recomp.jar:?] {re:classloading} at net.minecraft.network.play.server.SOpenWindowPacket.handle(SOpenWindowPacket.java:14) ~[forge-1.16.5-36.2.20_mapped_official_1.16.5-recomp.jar:?] {re:classloading} at net.minecraft.network.PacketThreadUtil.lambda$ensureRunningOnSameThread$0(PacketThreadUtil.java:19) ~[forge-1.16.5-36.2.20_mapped_official_1.16.5-recomp.jar:?] {re:classloading} at net.minecraft.util.concurrent.ThreadTaskExecutor.doRunTask(ThreadTaskExecutor.java:136) ~[forge-1.16.5-36.2.20_mapped_official_1.16.5-recomp.jar:?] {re:classloading,pl:accesstransformer:B} at net.minecraft.util.concurrent.RecursiveEventLoop.doRunTask(RecursiveEventLoop.java:22) ~[forge-1.16.5-36.2.20_mapped_official_1.16.5-recomp.jar:?] {re:classloading} at net.minecraft.util.concurrent.ThreadTaskExecutor.pollTask(ThreadTaskExecutor.java:109) ~[forge-1.16.5-36.2.20_mapped_official_1.16.5-recomp.jar:?] {re:classloading,pl:accesstransformer:B} at net.minecraft.util.concurrent.ThreadTaskExecutor.runAllTasks(ThreadTaskExecutor.java:97) ~[forge-1.16.5-36.2.20_mapped_official_1.16.5-recomp.jar:?] {re:classloading,pl:accesstransformer:B} at net.minecraft.client.Minecraft.runTick(Minecraft.java:948) ~[forge-1.16.5-36.2.20_mapped_official_1.16.5-recomp.jar:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A} at net.minecraft.client.Minecraft.run(Minecraft.java:607) ~[forge-1.16.5-36.2.20_mapped_official_1.16.5-recomp.jar:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A} at net.minecraft.client.main.Main.main(Main.java:184) ~[forge-1.16.5-36.2.20_mapped_official_1.16.5-recomp.jar:?] {re:classloading,pl:runtimedistcleaner:A} at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_241] {} at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_241] {} at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_241] {} at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_241] {} at net.minecraftforge.userdev.FMLUserdevClientLaunchProvider.lambda$launchService$0(FMLUserdevClientLaunchProvider.java:52) ~[forge-1.16.5-36.2.20_mapped_official_1.16.5-recomp.jar:?] {} at cpw.mods.modlauncher.LaunchServiceHandlerDecorator.launch(LaunchServiceHandlerDecorator.java:37) [modlauncher-8.0.9.jar:?] {} at cpw.mods.modlauncher.LaunchServiceHandler.launch(LaunchServiceHandler.java:54) [modlauncher-8.0.9.jar:?] {} at cpw.mods.modlauncher.LaunchServiceHandler.launch(LaunchServiceHandler.java:72) [modlauncher-8.0.9.jar:?] {} at cpw.mods.modlauncher.Launcher.run(Launcher.java:82) [modlauncher-8.0.9.jar:?] {} at cpw.mods.modlauncher.Launcher.main(Launcher.java:66) [modlauncher-8.0.9.jar:?] {} at net.minecraftforge.userdev.LaunchTesting.main(LaunchTesting.java:108) [forge-1.16.5-36.2.20_mapped_official_1.16.5-recomp.jar:?] {} ModContainerRegistry: Spoiler public class ModContainers { public static DeferredRegister<ContainerType<?>> CONTAINERS = DeferredRegister.create(ForgeRegistries.CONTAINERS, References.MODID); public static final RegistryObject<ContainerType<StorageChestContainer>> STORAGE_CHEST_CONTAINER = CONTAINERS.register("storage_chest_container", ()-> IForgeContainerType.create(((windowId, inv, data) -> { // THIS is where the Error occurs, IDE points to data being null BlockPos pos = data.readBlockPos(); TileEntity tileEntity = inv.player.level.getBlockEntity(pos); // getMaster() returns the master tileEntity of the multiblock return new StorageChestContainer(windowId, inv, ((TileEntityStorageChest) Objects.requireNonNull(tileEntity)).getMaster()); }))); public static void register(IEventBus bus){ CONTAINERS.register(bus); } } The use method in ModBlock that opens the gui: Spoiler @Override public ActionResultType use(BlockState state, World world, BlockPos pos, PlayerEntity playerEntity, Hand hand, BlockRayTraceResult rayTraceResult) { if(!world.isClientSide) { // getMaster() returns the master tileEntity of the multiblock TileEntityStorageChest storageChestMaster = ((TileEntityStorageChest) world.getBlockEntity(pos)).getMaster(); BlockPos masterPos = storageChestMaster.getBlockPos(); // openGui() sets some int variable in tileEntity storageChestMaster.openGui(playerEntity, true); NetworkHooks.openGui((ServerPlayerEntity) playerEntity, storageChestMaster, masterPos); } return ActionResultType.SUCCESS; } The Container itself: Spoiler public class StorageChestContainer extends ContainerBase { private final TileEntityStorageChest tileEntity; public StorageChestContainer(int windowId, PlayerInventory playerInventory, TileEntityStorageChest tileEntity){ super(ModContainers.STORAGE_CHEST_CONTAINER.get(), windowId); this.tileEntity = tileEntity; IItemHandler inventory = tileEntity.inventory; int startIndex = tileEntity.currentLine * 11; int numRows = inventory.getSlots() / 11; int limit = 0; int xS = 0; int yS = 0; for (int y = 0; y < numRows; ++y) { for (int x = 0; x < 11; ++x) { int index = x + y * 11; if (index >= startIndex && limit < 66) { limit++; xS = x; this.addSlot(new SlotItemHandler(inventory, index, 8 + xS * 18, 16 + yS * 18)); } else this.addSlot(new SlotItemHandler(inventory, index, Integer.MIN_VALUE, Integer.MIN_VALUE)); } if (xS > 0) yS++; } drawPlayerInv(playerInventory, 45, 18); } @Override public boolean stillValid(PlayerEntity playerEntity) { return stillValid(IWorldPosCallable.create(tileEntity.getLevel(), tileEntity.getBlockPos()), playerEntity, ModBlocks.Storage_CHEST.get()); } public TileEntityStorageChest getTileEntity(){ return tileEntity; }
May 18, 20223 yr Author TileEntityStorageChest: Spoiler package com.cassiokf.IndustrialRenewal.tileentity; import com.cassiokf.IndustrialRenewal.containers.container.StorageChestContainer; import com.cassiokf.IndustrialRenewal.init.ModContainers; import com.cassiokf.IndustrialRenewal.init.ModTileEntities; import com.cassiokf.IndustrialRenewal.tileentity.abstracts.TileEntity3x3x2MachineBase; import com.cassiokf.IndustrialRenewal.util.CustomItemStackHandler; import com.cassiokf.IndustrialRenewal.util.Utils; import net.minecraft.block.BlockState; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.inventory.container.Container; import net.minecraft.inventory.container.INamedContainerProvider; import net.minecraft.nbt.CompoundNBT; import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntityType; import net.minecraft.util.Direction; import net.minecraft.util.text.ITextComponent; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.items.CapabilityItemHandler; import javax.annotation.Nonnull; import javax.annotation.Nullable; public class TileEntityStorageChest extends TileEntity3x3x2MachineBase<TileEntityStorageChest> implements INamedContainerProvider { private static final int slots = 99; public final CustomItemStackHandler inventory = new CustomItemStackHandler(slots){ @Override protected void onContentsChanged(int slot) { TileEntityStorageChest.this.sync(); } }; public int additionalLines; public int currentLine; public String search = ""; public boolean searchActive = true; public LazyOptional<CustomItemStackHandler> inventoryHandler = LazyOptional.of(()->inventory); public TileEntityStorageChest(TileEntityType tileEntityTypeIn) { super(tileEntityTypeIn); } public TileEntityStorageChest(){ super(ModTileEntities.STORAGE_CHEST_TILE.get()); } // Some special interaction to be impelmented public void guiButtonClick(int id, PlayerEntity player) { if (id == 1 && currentLine > 0) { currentLine--; } else if (id == 2 && currentLine < additionalLines) { currentLine++; } openGui(player, false); } // Some special interaction to be impelmented public void openGui(PlayerEntity player, boolean resetLine) { if (this.isRemoved()) return; if (resetLine) { currentLine = 0; search = ""; searchActive = false; } if (!level.isClientSide) { player.openMenu(this); } } @Override public void onMasterBreak() { super.onMasterBreak(); Utils.dropInventoryItems(level, worldPosition, inventory); } @Nonnull @Override public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) { if(cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY){ return inventoryHandler.cast(); } return super.getCapability(cap, side); } @Override public boolean instanceOf(TileEntity tileEntity) { return tileEntity instanceof TileEntityStorageChest; } @Override public CompoundNBT save(CompoundNBT compound) { compound.put("inv", inventory.serializeNBT()); return super.save(compound); } @Override public void load(BlockState state, CompoundNBT compound) { inventory.deserializeNBT(compound.getCompound("inv")); super.load(state, compound); } @Override public ITextComponent getDisplayName() { return ITextComponent.nullToEmpty(""); } @Nullable @Override public Container createMenu(int ID, PlayerInventory inventory, PlayerEntity player) { return new StorageChestContainer(ID, inventory, getMaster()); } }
May 18, 20223 yr Author Yes, that fixed the problem. Thank you so much. Here are the changes incase anyone curious: Spoiler BlockStorageChest: tl;dr: Added createContainerProvider() method to create INamedContainerProvider Used that instead of the TileEntityStorageChest Spoiler @Override public ActionResultType use(BlockState state, World world, BlockPos pos, PlayerEntity playerEntity, Hand hand, BlockRayTraceResult rayTraceResult) { if(!world.isClientSide) { TileEntityStorageChest storageChestMaster = ((TileEntityStorageChest) world.getBlockEntity(pos)).getMaster(); BlockPos masterPos = storageChestMaster.getBlockPos(); INamedContainerProvider containerProvider = createContainerProvider(world, storageChestMaster.getBlockPos()); NetworkHooks.openGui((ServerPlayerEntity) playerEntity, containerProvider, masterPos); } return ActionResultType.SUCCESS; } private INamedContainerProvider createContainerProvider(World world, BlockPos pos) { return new INamedContainerProvider() { @Override public ITextComponent getDisplayName() { return new TranslationTextComponent(""); } @Nullable @Override public Container createMenu(int i, PlayerInventory playerInventory, PlayerEntity playerEntity) { TileEntity te = world.getBlockEntity(pos); TileEntityStorageChest teMaster = te instanceof TileEntityStorageChest? ((TileEntityStorageChest) te).getMaster() : null; return new StorageChestContainer(i, playerInventory, teMaster); } }; } TileEntityStorageChest tl;dr: removed implement INamedContainerProvider removed player.openMenu() and associated methods Spoiler public class TileEntityStorageChest extends TileEntity3x3x2MachineBase<TileEntityStorageChest> { private static final int slots = 99; public final CustomItemStackHandler inventory = new CustomItemStackHandler(slots){ @Override protected void onContentsChanged(int slot) { TileEntityStorageChest.this.sync(); } }; public int additionalLines; public int currentLine; public String search = ""; public boolean searchActive = true; public LazyOptional<CustomItemStackHandler> inventoryHandler = LazyOptional.of(()->inventory); public TileEntityStorageChest(TileEntityType tileEntityTypeIn) { super(tileEntityTypeIn); } public TileEntityStorageChest(){ super(ModTileEntities.STORAGE_CHEST_TILE.get()); } //Some special interaction to be implemented public void guiButtonClick(int id, PlayerEntity player) { if (id == 1 && currentLine > 0) { currentLine--; } else if (id == 2 && currentLine < additionalLines) { currentLine++; } Utils.debug("LINE", currentLine); } @Override public void onMasterBreak() { super.onMasterBreak(); Utils.dropInventoryItems(level, worldPosition, inventory); } @Nonnull @Override public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) { if(cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY){ return inventoryHandler.cast(); } return super.getCapability(cap, side); } @Override public boolean instanceOf(TileEntity tileEntity) { return tileEntity instanceof TileEntityStorageChest; } @Override public CompoundNBT save(CompoundNBT compound) { compound.put("inv", inventory.serializeNBT()); return super.save(compound); } @Override public void load(BlockState state, CompoundNBT compound) { inventory.deserializeNBT(compound.getCompound("inv")); super.load(state, compound); }
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.