Jump to content

[1.16.5] Register Container NullPointerException


StarsPath

Recommended Posts

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;
    }

 

 

Link to comment
Share on other sites

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());
    }
}

 

Link to comment
Share on other sites

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:

  1. removed implement INamedContainerProvider
  2. 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);
    }

 


 

Link to comment
Share on other sites

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.