Jump to content

Recommended Posts

Posted

I am trying to add a custom slot to the player inventory.  I've managed to get the container and GUI working and getting the visual to show up in game.  However, I cannot seem to manage to keep the inventory persistent between sessions.  I've been playing with the code in multiple ways, but I cannot seem to find a working solution.  I might be overlooking something major and just not be noticing it.  Any help is appreciated.

 

Custom Player Inventory Capability:

Spoiler

package com.championash5357.custom.capability;

import net.minecraftforge.items.ItemStackHandler;

public class PlayerInventoryHandler extends ItemStackHandler {
    
    public PlayerInventoryHandler() {
        super(42);
    }
}

 

Capability Registry

Spoiler

package com.championash5357.custom.capability;

import java.util.concurrent.Callable;

import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.Capability.IStorage;
import net.minecraftforge.common.capabilities.CapabilityInject;
import net.minecraftforge.common.capabilities.CapabilityManager;

public class CustomCapabilities {
    
    @CapabilityInject(PlayerInventoryHandler.class)
    public static Capability<PlayerInventoryHandler> INVENTORY = null;
    
    public static void register() {
        CapabilityManager.INSTANCE.register(PlayerInventoryHandler.class, new IStorage<PlayerInventoryHandler>() {

            @Override
            public NBTBase writeNBT(Capability<PlayerInventoryHandler> capability, PlayerInventoryHandler instance, EnumFacing side) {
                return instance.serializeNBT();
            }

            @Override
            public void readNBT(Capability<PlayerInventoryHandler> capability, PlayerInventoryHandler instance, EnumFacing side, NBTBase nbt) {
                instance.deserializeNBT((NBTTagCompound) nbt);
            }
        }, new Callable<PlayerInventoryHandler>() {

            @Override
            public PlayerInventoryHandler call() throws Exception {
                return new PlayerInventoryHandler();
            }
        });
    }
}

 

Custom Player Inventory

Spoiler

package com.championash5357.custom.entity.player;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import com.championash5357.custom.capability.CustomCapabilities;
import com.championash5357.custom.capability.PlayerInventoryHandler;

import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.ItemStackHelper;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.NonNullList;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ICapabilitySerializable;

public class InventoryPlayerUpdated extends InventoryPlayer implements ICapabilitySerializable<NBTTagCompound> {
    
    public final NonNullList<ItemStack> backInventory = NonNullList.<ItemStack>withSize(1, ItemStack.EMPTY);
    private final List<NonNullList<ItemStack>> allInventories;
    public PlayerInventoryHandler inventory = new PlayerInventoryHandler();

    public InventoryPlayerUpdated(EntityPlayer playerIn) {
        super(playerIn);
        this.allInventories = Arrays.<NonNullList<ItemStack>>asList(this.mainInventory, this.armorInventory, this.offHandInventory, this.backInventory);
    }
    
    @Override
    public NBTTagList writeToNBT(NBTTagList nbtTagListIn) {
        /*for (int i = 0; i < this.mainInventory.size(); ++i)
        {
            if (!((ItemStack)this.mainInventory.get(i)).isEmpty())
            {
                NBTTagCompound nbttagcompound = new NBTTagCompound();
                nbttagcompound.setByte("Slot", (byte)i);
                ((ItemStack)this.mainInventory.get(i)).writeToNBT(nbttagcompound);
                nbtTagListIn.appendTag(nbttagcompound);
            }
        }

        for (int j = 0; j < this.armorInventory.size(); ++j)
        {
            if (!((ItemStack)this.armorInventory.get(j)).isEmpty())
            {
                NBTTagCompound nbttagcompound1 = new NBTTagCompound();
                nbttagcompound1.setByte("Slot", (byte)(j + 100));
                ((ItemStack)this.armorInventory.get(j)).writeToNBT(nbttagcompound1);
                nbtTagListIn.appendTag(nbttagcompound1);
            }
        }

        for (int k = 0; k < this.offHandInventory.size(); ++k)
        {
            if (!((ItemStack)this.offHandInventory.get(k)).isEmpty())
            {
                NBTTagCompound nbttagcompound2 = new NBTTagCompound();
                nbttagcompound2.setByte("Slot", (byte)(k + 150));
                ((ItemStack)this.offHandInventory.get(k)).writeToNBT(nbttagcompound2);
                nbtTagListIn.appendTag(nbttagcompound2);
            }
        }
        
        for (int l = 0; l < this.backInventory.size(); ++l) {
            if (!((ItemStack)this.backInventory.get(l)).isEmpty()) {
                NBTTagCompound nbttagcompound3 = new NBTTagCompound();
                nbttagcompound3.setByte("Slot", (byte)(l + 175));
                ((ItemStack)this.backInventory.get(l)).writeToNBT(nbttagcompound3);
                nbtTagListIn.appendTag(nbttagcompound3);
            }
        }*/
        for(int i = 0; i < this.inventory.getSlots(); i++) {
            if(i < this.mainInventory.size())
                this.inventory.setStackInSlot(i, this.mainInventory.get(i));
            else if (i < this.mainInventory.size() + this.armorInventory.size())
                this.inventory.setStackInSlot(i, this.armorInventory.get(i - this.mainInventory.size()));
            else if (i < this.mainInventory.size() + this.armorInventory.size() + this.offHandInventory.size())
                this.inventory.setStackInSlot(i, this.offHandInventory.get(i - this.mainInventory.size() - this.armorInventory.size()));
            else
                this.inventory.setStackInSlot(i, this.backInventory.get(i - this.mainInventory.size() - this.armorInventory.size() - this.offHandInventory.size()));
        }
        nbtTagListIn.appendTag(this.inventory.serializeNBT());
        return nbtTagListIn;
    }
    
    @Override
    public void readFromNBT(NBTTagList nbtTagListIn) {
        this.mainInventory.clear();
        this.armorInventory.clear();
        this.offHandInventory.clear();
        this.backInventory.clear();

        /*for (int i = 0; i < nbtTagListIn.tagCount(); ++i)
        {
            NBTTagCompound nbttagcompound = nbtTagListIn.getCompoundTagAt(i);
            int j = nbttagcompound.getByte("Slot") & 255;
            ItemStack itemstack = new ItemStack(nbttagcompound);

            if (!itemstack.isEmpty())
            {
                if (j >= 0 && j < this.mainInventory.size())
                {
                    this.mainInventory.set(j, itemstack);
                }
                else if (j >= 100 && j < this.armorInventory.size() + 100)
                {
                    this.armorInventory.set(j - 100, itemstack);
                }
                else if (j >= 150 && j < this.offHandInventory.size() + 150)
                {
                    this.offHandInventory.set(j - 150, itemstack);
                }
                else if(j >= 175 && j < this.backInventory.size() + 175)
                {
                    this.backInventory.set(j - 175, itemstack);
                }
            }
        }*/
        this.inventory.deserializeNBT(nbtTagListIn.getCompoundTagAt(0));
        for(int i = 0; i < this.inventory.getSlots(); i++) {
            if(i < this.mainInventory.size())
                this.mainInventory.set(i, this.inventory.getStackInSlot(i));
            else if (i < this.mainInventory.size() + this.armorInventory.size())
                this.armorInventory.set(i - this.mainInventory.size(), this.inventory.getStackInSlot(i));
            else if (i < this.mainInventory.size() + this.armorInventory.size() + this.offHandInventory.size())
                this.offHandInventory.set(i - this.mainInventory.size() - this.armorInventory.size(), this.inventory.getStackInSlot(i));
            else
                this.backInventory.set(i - this.mainInventory.size() - this.armorInventory.size() - this.offHandInventory.size(), this.inventory.getStackInSlot(i));
        }
    }

    @Override
    public int getSizeInventory() {
        return this.mainInventory.size() + this.armorInventory.size() + this.offHandInventory.size() + this.backInventory.size();
    }
    
    @Override
    public boolean isEmpty() {
        for (ItemStack itemstack : this.mainInventory)
        {
            if (!itemstack.isEmpty())
            {
                return false;
            }
        }

        for (ItemStack itemstack1 : this.armorInventory)
        {
            if (!itemstack1.isEmpty())
            {
                return false;
            }
        }

        for (ItemStack itemstack2 : this.offHandInventory)
        {
            if (!itemstack2.isEmpty())
            {
                return false;
            }
        }
        
        for (ItemStack itemstack3 : this.backInventory)
        {
            if (!itemstack3.isEmpty())
            {
                return false;
            }
        }
        
        return true;
    }
    
    @Override
    public void setInventorySlotContents(int index, ItemStack stack)
    {
        NonNullList<ItemStack> nonnulllist = null;

        for (NonNullList<ItemStack> nonnulllist1 : this.allInventories)
        {
            if (index < nonnulllist1.size())
            {
                nonnulllist = nonnulllist1;
                break;
            }

            index -= nonnulllist1.size();
        }

        if (nonnulllist != null)
        {
            nonnulllist.set(index, stack);
        }
    }
    
    @Override
    public void decrementAnimations()
    {
        for (NonNullList<ItemStack> nonnulllist : this.allInventories)
        {
            for (int i = 0; i < nonnulllist.size(); ++i)
            {
                if (!((ItemStack)nonnulllist.get(i)).isEmpty())
                {
                    ((ItemStack)nonnulllist.get(i)).updateAnimation(this.player.world, this.player, i, this.currentItem == i);
                }
            }
        }
        for (ItemStack is : armorInventory) // FORGE: Tick armor on animation ticks
        {
            if (!is.isEmpty())
            {
                is.getItem().onArmorTick(player.world, player, is);
            }
        }
    }
    
    @Override
    public ItemStack decrStackSize(int index, int count)
    {
        List<ItemStack> list = null;

        for (NonNullList<ItemStack> nonnulllist : this.allInventories)
        {
            if (index < nonnulllist.size())
            {
                list = nonnulllist;
                break;
            }

            index -= nonnulllist.size();
        }

        return list != null && !((ItemStack)list.get(index)).isEmpty() ? ItemStackHelper.getAndSplit(list, index, count) : ItemStack.EMPTY;
    }
    
    @Override
    public void deleteStack(ItemStack stack)
    {
        for (NonNullList<ItemStack> nonnulllist : this.allInventories)
        {
            for (int i = 0; i < nonnulllist.size(); ++i)
            {
                if (nonnulllist.get(i) == stack)
                {
                    nonnulllist.set(i, ItemStack.EMPTY);
                    break;
                }
            }
        }
    }
    
    @Override
    public ItemStack removeStackFromSlot(int index)
    {
        NonNullList<ItemStack> nonnulllist = null;

        for (NonNullList<ItemStack> nonnulllist1 : this.allInventories)
        {
            if (index < nonnulllist1.size())
            {
                nonnulllist = nonnulllist1;
                break;
            }

            index -= nonnulllist1.size();
        }

        if (nonnulllist != null && !((ItemStack)nonnulllist.get(index)).isEmpty())
        {
            ItemStack itemstack = nonnulllist.get(index);
            nonnulllist.set(index, ItemStack.EMPTY);
            return itemstack;
        }
        else
        {
            return ItemStack.EMPTY;
        }
    }
    
    @Override
    public ItemStack getStackInSlot(int index)
    {
        List<ItemStack> list = null;

        for (NonNullList<ItemStack> nonnulllist : this.allInventories)
        {
            if (index < nonnulllist.size())
            {
                list = nonnulllist;
                break;
            }

            index -= nonnulllist.size();
        }

        return list == null ? ItemStack.EMPTY : (ItemStack)list.get(index);
    }
    
    @Override
    public void dropAllItems()
    {
        for (List<ItemStack> list : this.allInventories)
        {
            for (int i = 0; i < list.size(); ++i)
            {
                ItemStack itemstack = list.get(i);

                if (!itemstack.isEmpty())
                {
                    this.player.dropItem(itemstack, true, false);
                    list.set(i, ItemStack.EMPTY);
                }
            }
        }
    }
    
    @Override
    public boolean hasItemStack(ItemStack itemStackIn)
    {
        label23:

        for (List<ItemStack> list : this.allInventories)
        {
            Iterator iterator = list.iterator();

            while (true)
            {
                if (!iterator.hasNext())
                {
                    continue label23;
                }

                ItemStack itemstack = (ItemStack)iterator.next();

                if (!itemstack.isEmpty() && itemstack.isItemEqual(itemStackIn))
                {
                    break;
                }
            }

            return true;
        }

        return false;
    }
    
    @Override
    public void clear()
    {
        for (List<ItemStack> list : this.allInventories)
        {
            list.clear();
        }
    }

    @Override
    public boolean hasCapability(Capability<?> capability, EnumFacing facing) {
        if(capability == CustomCapabilities.INVENTORY) return true;
        return false;
    }

    @Override
    public <T> T getCapability(Capability<T> capability, EnumFacing facing) {
        if(capability == CustomCapabilities.INVENTORY) return (T) this.inventory;
        return null;
    }

    @Override
    public NBTTagCompound serializeNBT() {
        return this.inventory.serializeNBT();
    }

    @Override
    public void deserializeNBT(NBTTagCompound nbt) {
        this.inventory.deserializeNBT(nbt);
    }
}

 

Event Loading

Spoiler

package com.championash5357.custom.client;

 

import com.championash5357.custom.entity.player.InventoryPlayerUpdated;
import com.championash5357.custom.gui.container.ContainerPlayerInventory;
import com.championash5357.custom.gui.gui.GuiPlayerInventory;

 

import net.minecraft.block.Block;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.inventory.GuiInventory;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.event.GuiOpenEvent;
import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.event.AttachCapabilitiesEvent;
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

@Mod.EventBusSubscriber(modid = Reference.MOD_ID)
public class CustomEvents {
    
    @SubscribeEvent
    public static void onPlayerLoad(AttachCapabilitiesEvent<Entity> event) {
        if(event.getObject() instanceof EntityPlayer) {
            event.addCapability(new ResourceLocation(Reference.MOD_ID, "inventory_updated"), new InventoryPlayerUpdated((EntityPlayer) event.getObject()));
        }
    }
    
    @SideOnly(Side.CLIENT)
    @SubscribeEvent
    public static void onGuiOpen(GuiOpenEvent event) {
        if(event.getGui() instanceof GuiInventory) {
            event.setGui(new GuiPlayerInventory(Minecraft.getMinecraft().player));
        }
    }
    
    @SubscribeEvent
    public static void onEntityJoinWorld(EntityJoinWorldEvent event) {
        if(event.getEntity() instanceof EntityPlayer)
        {
            EntityPlayer player = (EntityPlayer) event.getEntity();
            if(!(player.inventory instanceof InventoryPlayerUpdated))
            {
                player.inventory = new InventoryPlayerUpdated(player);
                player.inventoryContainer = new ContainerPlayerInventory((InventoryPlayerUpdated) player.inventory, !player.world.isRemote, player);
                player.openContainer = player.inventoryContainer;
            }
        }
    }
}

 

Container

Spoiler

package com.championash5357.custom.gui.container;

import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.ContainerPlayer;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;

public class ContainerPlayerInventory extends ContainerPlayer
{

    public ContainerPlayerInventory(InventoryPlayer inventory, boolean localWorld, EntityPlayer playerIn)
    {
        super(inventory, localWorld, playerIn);
        this.addSlotToContainer(new Slot(inventory, 41, 77, 44));
    }
    
    @Override
    public ItemStack transferStackInSlot(EntityPlayer playerIn, int index)
    {
        ItemStack itemstack = ItemStack.EMPTY;
        Slot slot = this.inventorySlots.get(index);

        if (slot != null && slot.getHasStack())
        {
            ItemStack itemstack1 = slot.getStack();
            itemstack = itemstack1.copy();
            EntityEquipmentSlot entityequipmentslot = EntityLiving.getSlotForItemStack(itemstack);

            if (index == 0)
            {
                if (!this.mergeItemStack(itemstack1, 9, 45, true))
                {
                    return ItemStack.EMPTY;
                }

                slot.onSlotChange(itemstack1, itemstack);
            }
            else if (index >= 1 && index < 5)
            {
                if (!this.mergeItemStack(itemstack1, 9, 45, false))
                {
                    return ItemStack.EMPTY;
                }
            }
            else if (index >= 5 && index < 9)
            {
                if (!this.mergeItemStack(itemstack1, 9, 45, false))
                {
                    return ItemStack.EMPTY;
                }
            }
            else if (entityequipmentslot.getSlotType() == EntityEquipmentSlot.Type.ARMOR && !((Slot)this.inventorySlots.get(8 - entityequipmentslot.getIndex())).getHasStack())
            {
                int i = 8 - entityequipmentslot.getIndex();

                if (!this.mergeItemStack(itemstack1, i, i + 1, false))
                {
                    return ItemStack.EMPTY;
                }
            }
            else if (entityequipmentslot == EntityEquipmentSlot.OFFHAND && !((Slot)this.inventorySlots.get(45)).getHasStack())
            {
                if (!this.mergeItemStack(itemstack1, 45, 46, false))
                {
                    return ItemStack.EMPTY;
                }
            }
            else if (index >= 9 && index < 36)
            {
                if (!this.mergeItemStack(itemstack1, 36, 45, false))
                {
                    return ItemStack.EMPTY;
                }
            }
            else if (index >= 36 && index < 45)
            {
                if (!this.mergeItemStack(itemstack1, 9, 36, false))
                {
                    return ItemStack.EMPTY;
                }
            }
            else if (!this.mergeItemStack(itemstack1, 9, 45, false))
            {
                return ItemStack.EMPTY;
            }

            if (itemstack1.isEmpty())
            {
                slot.putStack(ItemStack.EMPTY);
            }
            else
            {
                slot.onSlotChanged();
            }

            if (itemstack1.getCount() == itemstack.getCount())
            {
                return ItemStack.EMPTY;
            }

            ItemStack itemstack2 = slot.onTake(playerIn, itemstack1);

            if (index == 0)
            {
                playerIn.dropItem(itemstack2, false);
            }
        }

        return itemstack;
    }
}

Posted
29 minutes ago, ChampionAsh5357 said:

Any help is appreciated

You need to attach the capability to the Entity, not to the inventory. Also, read this documentation.

 

It is also recommended when adding something to the players inventory gui/container you do it through tabs(the way creative tabs work, keeps intermod compatibility).

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Posted
7 hours ago, Animefan8888 said:

You need to attach the capability to the Entity, not to the inventory.

Ah, that might help.  For some reason I thought that attaching it to the inventory meant that it was going to be attached to the player.  I've fixed that now.  However, now I seem to be getting a NullPointerException when the writeToNBT function is being called.

 

7 hours ago, Animefan8888 said:

Also, read this documentation.

I did, and I know I need to sync the server to the client data.  However, I want to get rid of all the errors first so that it at least saves to server before I start implementing the client syncing.

 

8 hours ago, Animefan8888 said:

It is also recommended when adding something to the players inventory gui/container you do it through tabs(the way creative tabs work, keeps intermod compatibility).

I was going to do that as soon as I finished getting it working properly.

Posted
1 minute ago, ChampionAsh5357 said:

Ah, that might help.  For some reason I thought that attaching it to the inventory meant that it was going to be attached to the player.  I've fixed that now.  However, now I seem to be getting a NullPointerException when the writeToNBT function is being called. 

Post your updated code and your crash report

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Posted

Updated writeToNBT and readToNBT in the InventoryPlayer extended class:

Spoiler

@Override
    public NBTTagList writeToNBT(NBTTagList nbtTagListIn) {
        //super.writeToNBT(nbtTagListIn);
        
        for(int i = 0; i < this.inventory.getSlots(); i++) {
            if(i < this.mainInventory.size())
                this.inventory.setStackInSlot(i, this.mainInventory.get(i));
            else if (i < this.mainInventory.size() + this.armorInventory.size())
                this.inventory.setStackInSlot(i, this.armorInventory.get(i - this.mainInventory.size()));
            else if (i < this.mainInventory.size() + this.armorInventory.size() + this.offHandInventory.size())
                this.inventory.setStackInSlot(i, this.offHandInventory.get(i - this.mainInventory.size() - this.armorInventory.size()));
            else
                this.inventory.setStackInSlot(i, this.backInventory.get(i - this.mainInventory.size() - this.armorInventory.size() - this.offHandInventory.size()));
        }
        
        NBTTagCompound compound = new NBTTagCompound();
        compound.setTag("inventory", inventory.serializeNBT());
        nbtTagListIn.appendTag(nbtTagListIn);
        
        /*for (int l = 0; l < this.backInventory.size(); ++l) {
            if (!((ItemStack)this.backInventory.get(l)).isEmpty()) {
                NBTTagCompound nbttagcompound3 = new NBTTagCompound();
                nbttagcompound3.setByte("Slot", (byte)(l + 175));
                ((ItemStack)this.backInventory.get(l)).writeToNBT(nbttagcompound3);
                nbtTagListIn.appendTag(nbttagcompound3);
            }
        }*/
        return nbtTagListIn;
    }
    
    @Override
    public void readFromNBT(NBTTagList nbtTagListIn) {
        //super.readFromNBT(nbtTagListIn);
        this.mainInventory.clear();
        this.armorInventory.clear();
        this.offHandInventory.clear();
        this.backInventory.clear();
        
        
        this.inventory.deserializeNBT(nbtTagListIn.getCompoundTagAt(0).getCompoundTag("inventory"));
        
        for(int i = 0; i < this.inventory.getSlots(); i++) {
            if(i < this.mainInventory.size())
                this.mainInventory.set(i, this.inventory.getStackInSlot(i));
            else if (i < this.mainInventory.size() + this.armorInventory.size())
                this.armorInventory.set(i - this.mainInventory.size(), this.inventory.getStackInSlot(i));
            else if (i < this.mainInventory.size() + this.armorInventory.size() + this.offHandInventory.size())
                this.offHandInventory.set(i - this.mainInventory.size() - this.armorInventory.size(), this.inventory.getStackInSlot(i));
            else
                this.backInventory.set(i - this.mainInventory.size() - this.armorInventory.size() - this.offHandInventory.size(), this.inventory.getStackInSlot(i));
        }
        
        /*this.mainInventory.clear();
        this.armorInventory.clear();
        this.offHandInventory.clear();
        this.backInventory.clear();

        for (int i = 0; i < nbtTagListIn.tagCount(); ++i)
        {
            NBTTagCompound nbttagcompound = nbtTagListIn.getCompoundTagAt(i);
            int j = nbttagcompound.getByte("Slot") & 255;
            ItemStack itemstack = new ItemStack(nbttagcompound);

            if (!itemstack.isEmpty())
            {
                if (j >= 0 && j < this.mainInventory.size())
                {
                    this.mainInventory.set(j, itemstack);
                }
                else if (j >= 100 && j < this.armorInventory.size() + 100)
                {
                    this.armorInventory.set(j - 100, itemstack);
                }
                else if (j >= 150 && j < this.offHandInventory.size() + 150)
                {
                    this.offHandInventory.set(j - 150, itemstack);
                }
                else if(j >= 175 && j < this.backInventory.size() + 175)
                {
                    this.backInventory.set(j - 175, itemstack);
                }
            }
        }*/
    }

 

Event Registering:

Spoiler

@SubscribeEvent
    public static void onPlayerLoad(AttachCapabilitiesEvent<Entity> event) {
        if(event.getObject() instanceof EntityPlayer) {
            event.addCapability(new ResourceLocation(Reference.MOD_ID, "inventory_updated"), event.getObject());
        }
    }

 

Crash Report:

Spoiler

[09:15:16] [Server thread/INFO]: Saving and pausing game...
[09:15:16] [Server thread/ERROR]: Encountered an unexpected exception
net.minecraft.util.ReportedException: Saving entity NBT
    at net.minecraft.entity.Entity.writeToNBT(Entity.java:1985) ~[Entity.class:?]
    at net.minecraft.server.integrated.IntegratedPlayerList.writePlayerData(IntegratedPlayerList.java:30) ~[IntegratedPlayerList.class:?]
    at net.minecraft.server.management.PlayerList.saveAllPlayerData(PlayerList.java:986) ~[PlayerList.class:?]
    at net.minecraft.server.integrated.IntegratedServer.tick(IntegratedServer.java:176) ~[IntegratedServer.class:?]
    at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:590) [MinecraftServer.class:?]
    at java.lang.Thread.run(Unknown Source) [?:1.8.0_171]
Caused by: java.lang.NullPointerException: Null string not allowed
    at java.util.Objects.requireNonNull(Unknown Source) ~[?:1.8.0_171]
    at net.minecraft.nbt.NBTTagString.<init>(NBTTagString.java:20) ~[NBTTagString.class:?]
    at net.minecraft.nbt.NBTTagCompound.setString(NBTTagCompound.java:171) ~[NBTTagCompound.class:?]
    at net.minecraft.entity.Entity.serializeNBT(Entity.java:3530) ~[Entity.class:?]
    at net.minecraft.entity.Entity.serializeNBT(Entity.java:88) ~[Entity.class:?]
    at net.minecraftforge.common.capabilities.CapabilityDispatcher.serializeNBT(CapabilityDispatcher.java:123) ~[CapabilityDispatcher.class:?]
    at net.minecraft.entity.Entity.writeToNBT(Entity.java:1954) ~[Entity.class:?]
    ... 5 more
[09:15:16] [Server thread/ERROR]: This crash report has been saved to: E:\Minecraft Forge\Custom Ideas Other Versions\1.12.2\run\.\crash-reports\crash-2018-07-12_09.15.16-server.txt
[09:15:16] [Server thread/INFO]: Stopping server
[09:15:16] [Server thread/INFO]: Saving players
[09:15:16] [Server thread/ERROR]: Exception stopping the server
net.minecraft.util.ReportedException: Saving entity NBT
    at net.minecraft.entity.Entity.writeToNBT(Entity.java:1985) ~[Entity.class:?]
    at net.minecraft.server.integrated.IntegratedPlayerList.writePlayerData(IntegratedPlayerList.java:30) ~[IntegratedPlayerList.class:?]
    at net.minecraft.server.management.PlayerList.saveAllPlayerData(PlayerList.java:986) ~[PlayerList.class:?]
    at net.minecraft.server.MinecraftServer.stopServer(MinecraftServer.java:493) ~[MinecraftServer.class:?]
    at net.minecraft.server.integrated.IntegratedServer.stopServer(IntegratedServer.java:413) ~[IntegratedServer.class:?]
    at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:643) [MinecraftServer.class:?]
    at java.lang.Thread.run(Unknown Source) [?:1.8.0_171]
Caused by: java.lang.NullPointerException: Null string not allowed
    at java.util.Objects.requireNonNull(Unknown Source) ~[?:1.8.0_171]
    at net.minecraft.nbt.NBTTagString.<init>(NBTTagString.java:20) ~[NBTTagString.class:?]
    at net.minecraft.nbt.NBTTagCompound.setString(NBTTagCompound.java:171) ~[NBTTagCompound.class:?]
    at net.minecraft.entity.Entity.serializeNBT(Entity.java:3530) ~[Entity.class:?]
    at net.minecraft.entity.Entity.serializeNBT(Entity.java:88) ~[Entity.class:?]
    at net.minecraftforge.common.capabilities.CapabilityDispatcher.serializeNBT(CapabilityDispatcher.java:123) ~[CapabilityDispatcher.class:?]
    at net.minecraft.entity.Entity.writeToNBT(Entity.java:1954) ~[Entity.class:?]
    ... 6 more
[09:15:16] [main/INFO] [STDOUT]: [net.minecraft.init.Bootstrap:printToSYSOUT:629]: ---- Minecraft Crash Report ----
// Don't be sad, have a hug! ❤️

Time: 7/12/18 9:15 AM
Description: Saving entity NBT

java.lang.NullPointerException: Null string not allowed
    at java.util.Objects.requireNonNull(Unknown Source)
    at net.minecraft.nbt.NBTTagString.<init>(NBTTagString.java:20)
    at net.minecraft.nbt.NBTTagCompound.setString(NBTTagCompound.java:171)
    at net.minecraft.entity.Entity.serializeNBT(Entity.java:3530)
    at net.minecraft.entity.Entity.serializeNBT(Entity.java:88)
    at net.minecraftforge.common.capabilities.CapabilityDispatcher.serializeNBT(CapabilityDispatcher.java:123)
    at net.minecraft.entity.Entity.writeToNBT(Entity.java:1954)
    at net.minecraft.server.integrated.IntegratedPlayerList.writePlayerData(IntegratedPlayerList.java:30)
    at net.minecraft.server.management.PlayerList.saveAllPlayerData(PlayerList.java:986)
    at net.minecraft.server.integrated.IntegratedServer.tick(IntegratedServer.java:176)
    at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:590)
    at java.lang.Thread.run(Unknown Source)


A detailed walkthrough of the error, its code path and all known details is as follows:
---------------------------------------------------------------------------------------

-- Head --
Thread: Client thread
Stacktrace:
    at java.util.Objects.requireNonNull(Unknown Source)
    at net.minecraft.nbt.NBTTagString.<init>(NBTTagString.java:20)
    at net.minecraft.nbt.NBTTagCompound.setString(NBTTagCompound.java:171)
    at net.minecraft.entity.Entity.serializeNBT(Entity.java:3530)
    at net.minecraft.entity.Entity.serializeNBT(Entity.java:88)
    at net.minecraftforge.common.capabilities.CapabilityDispatcher.serializeNBT(CapabilityDispatcher.java:123)

-- Entity being saved --
Details:
    Entity Type: null (net.minecraft.entity.player.EntityPlayerMP)
    Entity ID: 2662
    Entity Name: Player259
    Entity's Exact location: 217.50, 68.00, 253.50
    Entity's Block location: World: (217,68,253), Chunk: (at 9,4,13 in 13,15; contains blocks 208,0,240 to 223,255,255), Region: (0,0; contains chunks 0,0 to 31,31, blocks 0,0,0 to 511,255,511)
    Entity's Momentum: 0.00, -0.08, 0.00
    Entity's Passengers: []
    Entity's Vehicle: ~~ERROR~~ NullPointerException: null
Stacktrace:
    at net.minecraft.entity.Entity.writeToNBT(Entity.java:1954)
    at net.minecraft.server.integrated.IntegratedPlayerList.writePlayerData(IntegratedPlayerList.java:30)
    at net.minecraft.server.management.PlayerList.saveAllPlayerData(PlayerList.java:986)
    at net.minecraft.server.integrated.IntegratedServer.tick(IntegratedServer.java:176)
    at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:590)
    at java.lang.Thread.run(Unknown Source)

-- System Details --
Details:
    Minecraft Version: 1.12.2
    Operating System: Windows 10 (amd64) version 10.0
    Java Version: 1.8.0_171, Oracle Corporation
    Java VM Version: Java HotSpot(TM) 64-Bit Server VM (mixed mode), Oracle Corporation
    Memory: 606359496 bytes (578 MB) / 1037959168 bytes (989 MB) up to 1037959168 bytes (989 MB)
    JVM Flags: 3 total; -Xincgc -Xmx1024M -Xms1024M
    IntCache: cache: 1, tcache: 1, allocated: 12, tallocated: 94
    FML: MCP 9.42 Powered by Forge 14.23.2.2611 5 mods loaded, 5 mods active
    States: 'U' = Unloaded 'L' = Loaded 'C' = Constructed 'H' = Pre-initialized 'I' = Initialized 'J' = Post-initialized 'A' = Available 'D' = Disabled 'E' = Errored

    | State     | ID        | Version      | Source                           | Signature |
    |:--------- |:--------- |:------------ |:-------------------------------- |:--------- |
    | UCHIJAAAA | minecraft | 1.12.2       | minecraft.jar                    | None      |
    | UCHIJAAAA | mcp       | 9.42         | minecraft.jar                    | None      |
    | UCHIJAAAA | FML       | 8.0.99.99    | forgeSrc-1.12.2-14.23.2.2611.jar | None      |
    | UCHIJAAAA | forge     | 14.23.2.2611 | forgeSrc-1.12.2-14.23.2.2611.jar | None      |
    | UCHIJAAAA | custom    | 1.0.0.1      | bin                              | None      |

    Loaded coremods (and transformers): 
    GL info: ~~ERROR~~ RuntimeException: No OpenGL context found in the current thread.
    Profiler Position: N/A (disabled)
    Player Count: 1 / 8; [EntityPlayerMP['Player259'/2662, l='New World', x=217.50, y=68.00, z=253.50]]
    Type: Integrated Server (map_client.txt)
    Is Modded: Definitely; Client brand changed to 'fml,forge'
[09:15:16] [main/INFO] [STDOUT]: [net.minecraft.init.Bootstrap:printToSYSOUT:629]: #@!@# Game crashed! Crash report saved to: #@!@# .\crash-reports\crash-2018-07-12_09.15.16-server.txt
[09:15:16] [main/INFO] [FML]: Waiting for the server to terminate/save.
[09:15:16] [Server thread/INFO] [FML]: Applying holder lookups
[09:15:16] [Server thread/INFO] [FML]: Holder lookups applied
[09:15:16] [Server thread/INFO] [FML]: The state engine was in incorrect state SERVER_STOPPING and forced into state SERVER_STOPPED. Errors may have been discarded.
[09:15:16] [main/INFO] [FML]: Server terminated.
[09:15:16] [Client Shutdown Thread/INFO]: Stopping server
[09:15:16] [Client Shutdown Thread/INFO]: Saving players
Exception in thread "Client Shutdown Thread" [09:15:16] [Client Shutdown Thread/INFO] [STDERR]: [java.lang.ThreadGroup:uncaughtException:-1]: net.minecraft.util.ReportedException: Saving entity NBT
[09:15:16] [Client Shutdown Thread/INFO] [STDERR]: [java.lang.ThreadGroup:uncaughtException:-1]:     at net.minecraft.entity.Entity.writeToNBT(Entity.java:1985)
[09:15:16] [Client Shutdown Thread/INFO] [STDERR]: [java.lang.ThreadGroup:uncaughtException:-1]:     at net.minecraft.server.integrated.IntegratedPlayerList.writePlayerData(IntegratedPlayerList.java:30)

 

The rest of the code remained exactly the same.  The mod crashes when the player saves its NBT data at any time.

Posted
59 minutes ago, ChampionAsh5357 said:

nbtTagListIn.appendTag(nbtTagListIn);

 

Inserting a list into itself seems like a good plan.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted
57 minutes ago, ChampionAsh5357 said:

The rest of the code remained exactly the same.  The mod crashes when the player saves its NBT data at any time. 

You did not read and understand the forge documentation.

Quote

CapabilityManager.INSTANCE.register(capability interface class, storage, default implementation factory);

 

Also, you are using the deprecated method of registering, use the factory version.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Posted
On 7/12/2018 at 10:29 AM, Animefan8888 said:

You did not read and understand the forge documentation.

I did read the forge documentation.  Understanding it, maybe.  From my understanding, I do not see why I can't create the inventory with an implementation of ICapabilitySerializable (which is what I did originally) and then just attach the capability via that to the player.  As far as I know through NBT checking, the player inventory does save on the server side and I can see it.  The problem I actually have is with loading it to the client which is actually what I didn't do when I made this thread.  However, I do not really know what event or tick handler I should notify to sync the data already stored in the NBT to the client.  I tried a couple of ways using EntityJoinWorldEvent and PlayerEvent.StartTracking, but I could not manage to get them to work.  So that would actually be the actual issue I'm having as of this moment.  I will repost my inventory and network handler along with the event class.  If you have any recommendation on how I would do that, I would be interested to hear.

 

Custom Inventory

Spoiler

package com.championash5357.custom.entity.player;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import javax.swing.text.html.HTML.Tag;

import com.championash5357.custom.capability.CustomCapabilities;
import com.championash5357.custom.capability.PlayerInventoryHandler;
import com.championash5357.custom.network.PacketHandler;
import com.championash5357.custom.network.PacketHandler.PacketUpdatePlayerInventory;

import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.ItemStackHelper;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.NonNullList;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ICapabilitySerializable;

public class InventoryPlayerUpdated extends InventoryPlayer implements ICapabilitySerializable<NBTTagCompound>{
    
    public final NonNullList<ItemStack> backInventory = NonNullList.<ItemStack>withSize(1, ItemStack.EMPTY);
    private final List<NonNullList<ItemStack>> allInventories;
    public PlayerInventoryHandler inventory = new PlayerInventoryHandler();
    private NBTTagList nbtinventory = new NBTTagList();

    public InventoryPlayerUpdated(EntityPlayer playerIn) {
        super(playerIn);
        this.allInventories = Arrays.<NonNullList<ItemStack>>asList(this.mainInventory, this.armorInventory, this.offHandInventory, this.backInventory);
    }
    
    @Override
    public NBTTagList writeToNBT(NBTTagList nbtTagListIn) {        
        for(int i = 0; i < this.inventory.getSlots(); i++) {
            if(i < this.mainInventory.size())
                this.inventory.setStackInSlot(i, this.mainInventory.get(i));
            else if (i < this.mainInventory.size() + this.armorInventory.size())
                this.inventory.setStackInSlot(i, this.armorInventory.get(i - this.mainInventory.size()));
            else if (i < this.mainInventory.size() + this.armorInventory.size() + this.offHandInventory.size())
                this.inventory.setStackInSlot(i, this.offHandInventory.get(i - this.mainInventory.size() - this.armorInventory.size()));
            else
                this.inventory.setStackInSlot(i, this.backInventory.get(i - this.mainInventory.size() - this.armorInventory.size() - this.offHandInventory.size()));
        }
        
        nbtTagListIn.appendTag(this.inventory.serializeNBT());
        return nbtTagListIn;
    }
    
    @Override
    public void readFromNBT(NBTTagList nbtTagListIn) {
        this.mainInventory.clear();
        this.armorInventory.clear();
        this.offHandInventory.clear();
        this.backInventory.clear();
        
        
        this.inventory.deserializeNBT(nbtTagListIn.getCompoundTagAt(0));
        
        for(int i = 0; i < this.inventory.getSlots(); i++) {
            if(i < this.mainInventory.size())
                this.mainInventory.set(i, this.inventory.getStackInSlot(i));
            else if (i < this.mainInventory.size() + this.armorInventory.size())
                this.armorInventory.set(i - this.mainInventory.size(), this.inventory.getStackInSlot(i));
            else if (i < this.mainInventory.size() + this.armorInventory.size() + this.offHandInventory.size())
                this.offHandInventory.set(i - this.mainInventory.size() - this.armorInventory.size(), this.inventory.getStackInSlot(i));
            else
                this.backInventory.set(i - this.mainInventory.size() - this.armorInventory.size() - this.offHandInventory.size(), this.inventory.getStackInSlot(i));
        }
    }

    @Override
    public int getSizeInventory() {
        return this.mainInventory.size() + this.armorInventory.size() + this.offHandInventory.size() + this.backInventory.size();
    }
    
    @Override
    public boolean isEmpty() {
        for (ItemStack itemstack : this.mainInventory)
        {
            if (!itemstack.isEmpty())
            {
                return false;
            }
        }

        for (ItemStack itemstack1 : this.armorInventory)
        {
            if (!itemstack1.isEmpty())
            {
                return false;
            }
        }

        for (ItemStack itemstack2 : this.offHandInventory)
        {
            if (!itemstack2.isEmpty())
            {
                return false;
            }
        }
        
        for (ItemStack itemstack3 : this.backInventory)
        {
            if (!itemstack3.isEmpty())
            {
                return false;
            }
        }
        
        return true;
    }
    
    @Override
    public void setInventorySlotContents(int index, ItemStack stack)
    {
        NonNullList<ItemStack> nonnulllist = null;

        for (NonNullList<ItemStack> nonnulllist1 : this.allInventories)
        {
            if (index < nonnulllist1.size())
            {
                nonnulllist = nonnulllist1;
                break;
            }

            index -= nonnulllist1.size();
        }

        if (nonnulllist != null)
        {
            nonnulllist.set(index, stack);
        }
    }
    
    @Override
    public void decrementAnimations()
    {
        for (NonNullList<ItemStack> nonnulllist : this.allInventories)
        {
            for (int i = 0; i < nonnulllist.size(); ++i)
            {
                if (!((ItemStack)nonnulllist.get(i)).isEmpty())
                {
                    ((ItemStack)nonnulllist.get(i)).updateAnimation(this.player.world, this.player, i, this.currentItem == i);
                }
            }
        }
        for (ItemStack is : armorInventory) // FORGE: Tick armor on animation ticks
        {
            if (!is.isEmpty())
            {
                is.getItem().onArmorTick(player.world, player, is);
            }
        }
    }
    
    @Override
    public ItemStack decrStackSize(int index, int count)
    {
        List<ItemStack> list = null;

        for (NonNullList<ItemStack> nonnulllist : this.allInventories)
        {
            if (index < nonnulllist.size())
            {
                list = nonnulllist;
                break;
            }

            index -= nonnulllist.size();
        }

        return list != null && !((ItemStack)list.get(index)).isEmpty() ? ItemStackHelper.getAndSplit(list, index, count) : ItemStack.EMPTY;
    }
    
    @Override
    public void deleteStack(ItemStack stack)
    {
        for (NonNullList<ItemStack> nonnulllist : this.allInventories)
        {
            for (int i = 0; i < nonnulllist.size(); ++i)
            {
                if (nonnulllist.get(i) == stack)
                {
                    nonnulllist.set(i, ItemStack.EMPTY);
                    break;
                }
            }
        }
    }
    
    @Override
    public ItemStack removeStackFromSlot(int index)
    {
        NonNullList<ItemStack> nonnulllist = null;

        for (NonNullList<ItemStack> nonnulllist1 : this.allInventories)
        {
            if (index < nonnulllist1.size())
            {
                nonnulllist = nonnulllist1;
                break;
            }

            index -= nonnulllist1.size();
        }

        if (nonnulllist != null && !((ItemStack)nonnulllist.get(index)).isEmpty())
        {
            ItemStack itemstack = nonnulllist.get(index);
            nonnulllist.set(index, ItemStack.EMPTY);
            return itemstack;
        }
        else
        {
            return ItemStack.EMPTY;
        }
    }
    
    @Override
    public ItemStack getStackInSlot(int index)
    {
        List<ItemStack> list = null;

        for (NonNullList<ItemStack> nonnulllist : this.allInventories)
        {
            if (index < nonnulllist.size())
            {
                list = nonnulllist;
                break;
            }

            index -= nonnulllist.size();
        }

        return list == null ? ItemStack.EMPTY : (ItemStack)list.get(index);
    }
    
    @Override
    public void dropAllItems()
    {
        for (List<ItemStack> list : this.allInventories)
        {
            for (int i = 0; i < list.size(); ++i)
            {
                ItemStack itemstack = list.get(i);

                if (!itemstack.isEmpty())
                {
                    this.player.dropItem(itemstack, true, false);
                    list.set(i, ItemStack.EMPTY);
                }
            }
        }
    }
    
    @Override
    public boolean hasItemStack(ItemStack itemStackIn)
    {
        label23:

        for (List<ItemStack> list : this.allInventories)
        {
            Iterator iterator = list.iterator();

            while (true)
            {
                if (!iterator.hasNext())
                {
                    continue label23;
                }

                ItemStack itemstack = (ItemStack)iterator.next();

                if (!itemstack.isEmpty() && itemstack.isItemEqual(itemStackIn))
                {
                    break;
                }
            }

            return true;
        }

        return false;
    }
    
    @Override
    public void clear()
    {
        for (List<ItemStack> list : this.allInventories)
        {
            list.clear();
        }
    }

    @Override
    public boolean hasCapability(Capability<?> capability, EnumFacing facing) {
        return capability == CustomCapabilities.INVENTORY;
    }

    @Override
    public <T> T getCapability(Capability<T> capability, EnumFacing facing) {
        return capability == CustomCapabilities.INVENTORY ? (T) this.inventory : null;
    }

    @Override
    public NBTTagCompound serializeNBT() {
        return (this.writeToNBT(nbtinventory)).getCompoundTagAt(0);
    }

    @Override
    public void deserializeNBT(NBTTagCompound nbt) {
        nbtinventory = new NBTTagList();
        nbtinventory.appendTag(nbt);
        this.readFromNBT(nbtinventory);
    }
}

 

Packet Handler

Spoiler

package com.championash5357.custom.network;

import com.championash5357.custom.entity.player.InventoryPlayerUpdated;
import com.championash5357.custom.tileentity.TileEntitySingleColor;

import io.netty.buffer.ByteBuf;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.fml.common.network.ByteBufUtils;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper;
import net.minecraftforge.fml.relauncher.Side;

public class PacketHandler {
    private static final SimpleNetworkWrapper INSTANCE = NetworkRegistry.INSTANCE.newSimpleChannel("custom");
    
    public static void registerPackets() {
        INSTANCE.registerMessage(PacketUpdatePlayerInventoryHandler.class, PacketUpdatePlayerInventory.class, 1, Side.CLIENT);
    }
    
    public static void sendTo(IMessage message, EntityPlayerMP player) {
        INSTANCE.sendTo(message, player);
    }
    
    public static class PacketUpdateSingleColorHandler implements IMessageHandler<PacketUpdateSingleColor, IMessage> {

        @Override
        public IMessage onMessage(PacketUpdateSingleColor message, MessageContext ctx) {
            
            if(ctx.getServerHandler().player.getServerWorld().isBlockLoaded(new BlockPos(message.x, message.y, message.z))) {
                TileEntitySingleColor color = (TileEntitySingleColor)ctx.getServerHandler().player.getServerWorld().getTileEntity(new BlockPos(message.x, message.y, message.z));
                color.setRgb(message.red, message.green, message.blue);
            }
            
            return null;
        }
    }
    
    public static class PacketUpdatePlayerInventory implements IMessage {
        
        public PacketUpdatePlayerInventory() {}
        
        private NBTTagCompound data;
        
        public PacketUpdatePlayerInventory(InventoryPlayerUpdated inventory) {
            data = inventory.serializeNBT();
        }
        
        @Override
        public void fromBytes(ByteBuf buf) {
            data = ByteBufUtils.readTag(buf);
        }

        @Override
        public void toBytes(ByteBuf buf) {
            ByteBufUtils.writeTag(buf, data);
        }
    }
    
    public static class PacketUpdatePlayerInventoryHandler implements IMessageHandler<PacketUpdatePlayerInventory, IMessage> {

        @Override
        public IMessage onMessage(PacketUpdatePlayerInventory message, MessageContext ctx) {
            
            Minecraft.getMinecraft().addScheduledTask(() -> {
                ((InventoryPlayerUpdated) Minecraft.getMinecraft().player.inventory).deserializeNBT(message.data);
            });
            
            return null;
        }
        
    }
}

 

Event Class

Spoiler

package com.championash5357.custom.client;

import com.championash5357.custom.entity.player.InventoryPlayerUpdated;
import com.championash5357.custom.gui.container.ContainerPlayerInventory;
import com.championash5357.custom.gui.gui.GuiPlayerInventory;
import com.championash5357.custom.init.CustomBlocks.BlockRegistration;
import com.championash5357.custom.init.CustomItems.ItemRegistration;
import com.championash5357.custom.network.PacketHandler;
import com.championash5357.custom.network.PacketHandler.PacketUpdatePlayerInventory;

import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.inventory.GuiInventory;
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityTracker;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.Item;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.WorldServer;
import net.minecraftforge.client.event.GuiOpenEvent;
import net.minecraftforge.client.event.ModelRegistryEvent;
import net.minecraftforge.client.event.RenderPlayerEvent;
import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.event.AttachCapabilitiesEvent;
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

@Mod.EventBusSubscriber(modid = Reference.MOD_ID)
public class CustomEvents {
    
    @SubscribeEvent
    public static void onPlayerLoad(AttachCapabilitiesEvent<Entity> event) {
        if(event.getObject() instanceof EntityPlayer) {
            event.addCapability(new ResourceLocation(Reference.MOD_ID, "inventory_updated"), new InventoryPlayerUpdated((EntityPlayer) event.getObject()));
        }
    }
    
    @SideOnly(Side.CLIENT)
    @SubscribeEvent
    public static void onGuiOpen(GuiOpenEvent event) {
        if(event.getGui() instanceof GuiInventory) {
            event.setGui(new GuiPlayerInventory(Minecraft.getMinecraft().player));
        }
    }
    
    @SubscribeEvent
    public static void onEntityJoinWorld(EntityJoinWorldEvent event) {
        if(event.getEntity() instanceof EntityPlayer) {
            EntityPlayer player = (EntityPlayer) event.getEntity();
            if(!(player.inventory instanceof InventoryPlayerUpdated)) {
                player.inventory = new InventoryPlayerUpdated(player);
                player.inventoryContainer = new ContainerPlayerInventory((InventoryPlayerUpdated) player.inventory, !player.world.isRemote, player);
                player.openContainer = player.inventoryContainer;
            }
        }
    }

}

 

Apologies for the late reply.

Posted (edited)
9 hours ago, ChampionAsh5357 said:

However, I do not really know what event or tick handler I should notify to sync the data already stored in the NBT to the client.

When you open the inventory or the inventory is accessed the contents need to be synced, it is not necessarily an event handler you need to use. Note the container class should automatically sync its contents to the client from Container#detectAndSendChanges

9 hours ago, ChampionAsh5357 said:

I do not see why I can't create the inventory with an implementation of ICapabilitySerializable

You very well could, but you shouldn't extend InventoryPlayer or any IInventory, instead just use an IItemHandler implementation.

9 hours ago, ChampionAsh5357 said:

PlayerEvent.StartTracking

For future reference please read the javadoc above things before you use them.

Quote

Fired when an Entity is started to be "tracked" by this player (the player receives updates about this entity, e.g. motion).

 

Edited by Animefan8888

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Posted
9 hours ago, Animefan8888 said:

When you open the inventory or the inventory is accessed the contents need to be synced, it is not necessarily an event handler you need to use. Note the container class should automatically sync its contents to the client from Container#detectAndSendChanges

Ok. I think I'm going to rewrite everything so that it takes out the IInventory use and just add it on as a tab instead of just putting it off.  That way it should get everything working properly and stick with the conventions. Do I need to create a class extended from ItemStackHandler then, or can I just call IItemHandler?  I think I only need to store the slot I'm adding if the player inventory does it manually.

 

9 hours ago, Animefan8888 said:

For future reference please read the javadoc above things before you use them.

I was reading the documentation of the deprecated IEntityExtenedProperties to see if that could potentially work with what I had before.

Posted
4 minutes ago, ChampionAsh5357 said:

Do I need to create a class extended from ItemStackHandler then, or can I just call IItemHandler?

IItemHandler is an interface that ItemStackHandler implements. An instance of ItemStackHandler should work fine for this case.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Posted
11 minutes ago, Animefan8888 said:

IItemHandler is an interface that ItemStackHandler implements. An instance of ItemStackHandler should work fine for this case.

So, just to make sure I understand everything correctly.  Use an instance of ItemStackHandler to attach to the player to hold the inventory information.  Then when creating the container and gui use that same instance to store the custom slots added to the player. Then to call that instance from the gui handler I would just use player.getCapability(<? extends ItemStackHandler>, null); for calling it?

Posted
Just now, ChampionAsh5357 said:

So, just to make sure I understand everything correctly.  Use an instance of ItemStackHandler to attach to the player to hold the inventory information.  Then when creating the container and gui use that same instance to store the custom slots added to the player. Then to call that instance from the gui handler I would just use player.getCapability(<? extends ItemStackHandler>, null); for calling it?

No, you cannot attach an CapabilityItemHandler.ITEM_HANDLER_CAPABILITY to the player as there is already one, but you can make your own capability that uses IItemHandler as its data(I believe. someone will correct me if I am wrong). And then attach this capability in AttachCapabilityEvent<Entity> to the player. Then reference it by EntityPlayer#getCapability

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Posted (edited)

I tried using getSlotTexture to create a back image for the slot similar to the offhand slot and it comes up with a null texture even though the texture is defined at the place I set it to.  Also, when I try to give the player an item, it only detects that once the extended inventory has been opened.

 

Extended Inventory Container

Spoiler

package com.championash5357.custom.gui.container;

import javax.annotation.Nullable;

import com.championash5357.custom.capability.IExtendedInventory;
import com.championash5357.custom.gui.slot.SlotExtendedInventory;

import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemArmor;
import net.minecraft.item.ItemBow;
import net.minecraft.item.ItemElytra;
import net.minecraft.item.ItemShield;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemSword;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

public class ContainerExtendedInventory extends Container {
    
    private static final EntityEquipmentSlot[] VALID_EQUIPMENT_SLOTS = new EntityEquipmentSlot[] {EntityEquipmentSlot.HEAD, EntityEquipmentSlot.CHEST, EntityEquipmentSlot.LEGS, EntityEquipmentSlot.FEET};

    public ContainerExtendedInventory(EntityPlayer player, IExtendedInventory extended) {
        InventoryPlayer playerInventory = player.inventory;
        
        for (int k = 0; k < 4; ++k) {
            final EntityEquipmentSlot entityequipmentslot = VALID_EQUIPMENT_SLOTS[k];
            this.addSlotToContainer(new Slot(playerInventory, 36 + (3 - k), 8, 8 + k * 18) {
                
                public int getSlotStackLimit() {
                    return 1;
                }
                
                public boolean isItemValid(ItemStack stack) {
                    return stack.getItem().isValidArmor(stack, entityequipmentslot, player);
                }

                public boolean canTakeStack(EntityPlayer player) {
                    ItemStack itemstack = this.getStack();
                    return !itemstack.isEmpty() && !player.isCreative() && EnchantmentHelper.hasBindingCurse(itemstack) ? false : super.canTakeStack(player);
                }
                
                @Nullable
                @SideOnly(Side.CLIENT)
                public String getSlotTexture() {
                    return ItemArmor.EMPTY_SLOT_NAMES[entityequipmentslot.getIndex()];
                }
            });
        }

        for (int l = 0; l < 3; ++l)
            for (int j1 = 0; j1 < 9; ++j1)
                this.addSlotToContainer(new Slot(playerInventory, j1 + (l + 1) * 9, 8 + j1 * 18, 84 + l * 18));

        for (int i1 = 0; i1 < 9; ++i1)
            this.addSlotToContainer(new Slot(playerInventory, i1, 8 + i1 * 18, 142));

        this.addSlotToContainer(new Slot(playerInventory, 40, 77, 62)
        {
            @Nullable
            @SideOnly(Side.CLIENT)
            public String getSlotTexture() {
                return "minecraft:items/empty_armor_slot_shield";
            }
        });
        
        this.addSlotToContainer(new SlotExtendedInventory(extended, 0, 77, 44) {
            
            @Override
            public boolean isItemValid(ItemStack stack) {
                return stack.getItem() instanceof ItemSword ? true : (stack.getItem() instanceof ItemBow ? true : (stack.getItem() instanceof ItemShield ? true : (stack .getItem() instanceof ItemElytra ? true : false)));
            }
            
            @Nullable
            @SideOnly(Side.CLIENT)
            @Override
            public String getSlotTexture() {
                return "custom:items/empty_back_slot";
            }
        });
    }
    
    @Override
    public ItemStack transferStackInSlot(EntityPlayer player, int index) {
        ItemStack itemstack = ItemStack.EMPTY;
        Slot slot = this.inventorySlots.get(index);

        if (slot != null && slot.getHasStack()) {
            ItemStack itemstack1 = slot.getStack();
            itemstack = itemstack1.copy();
            EntityEquipmentSlot entityequipmentslot = EntityLiving.getSlotForItemStack(itemstack);

            if (index >= 0 && index < 4)
                if (!this.mergeItemStack(itemstack1, 4, 40, false))
                    return ItemStack.EMPTY;
            else if (entityequipmentslot.getSlotType() == EntityEquipmentSlot.Type.ARMOR && !((Slot)this.inventorySlots.get(3 - entityequipmentslot.getIndex())).getHasStack()) {
                int i = 3 - entityequipmentslot.getIndex();
                if (!this.mergeItemStack(itemstack1, i, i + 1, false))
                    return ItemStack.EMPTY;
            }
            else if (entityequipmentslot == EntityEquipmentSlot.OFFHAND && !((Slot)this.inventorySlots.get(40)).getHasStack())
                if (!this.mergeItemStack(itemstack1, 40, 41, false))
                    return ItemStack.EMPTY;
            else if (index >= 4 && index < 31)
                if (!this.mergeItemStack(itemstack1, 31, 40, false))
                    return ItemStack.EMPTY;
            else if (index >= 31 && index < 40)
                if (!this.mergeItemStack(itemstack1, 4, 31, false))
                    return ItemStack.EMPTY;
            else if (!this.mergeItemStack(itemstack1, 4, 40, false))
                return ItemStack.EMPTY;

            if (itemstack1.isEmpty())
                slot.putStack(ItemStack.EMPTY);       
            else
                slot.onSlotChanged();

            if (itemstack1.getCount() == itemstack.getCount())
                return ItemStack.EMPTY;

            ItemStack itemstack2 = slot.onTake(player, itemstack1);
        }

        return itemstack;
    }

    @Override
    public boolean canInteractWith(EntityPlayer player) {
        return true;
    }
}

 

Gui Extended Inventory

Spoiler

package com.championash5357.custom.gui.gui;

import com.championash5357.custom.capability.IExtendedInventory;
import com.championash5357.custom.client.Reference;
import com.championash5357.custom.gui.container.ContainerExtendedInventory;

import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.InventoryEffectRenderer;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

@SideOnly(Side.CLIENT)
public class GuiExtendedInventory extends InventoryEffectRenderer {
    
    private float oldMouseX;
    private float oldMouseY;
    private static final ResourceLocation INVENTORY_BACKGROUND = new ResourceLocation(Reference.MOD_ID, "textures/gui/container/extended_inventory.png");

    public GuiExtendedInventory(EntityPlayer player, IExtendedInventory extended) {
        super(new ContainerExtendedInventory(player, extended));
    }

    protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) {
        GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
        this.mc.getTextureManager().bindTexture(INVENTORY_BACKGROUND);
        int i = this.guiLeft;
        int j = this.guiTop;
        this.drawTexturedModalRect(i, j, 0, 0, this.xSize, this.ySize);
        drawEntityOnScreen(i + 51, j + 75, 30, (float)(i + 51) - this.oldMouseX, (float)(j + 75 - 50) - this.oldMouseY, this.mc.player);
    }

    public static void drawEntityOnScreen(int posX, int posY, int scale, float mouseX, float mouseY, EntityLivingBase ent) {
        GlStateManager.enableColorMaterial();
        GlStateManager.pushMatrix();
        GlStateManager.translate((float)posX, (float)posY, 50.0F);
        GlStateManager.scale((float)(-scale), (float)scale, (float)scale);
        GlStateManager.rotate(180.0F, 0.0F, 0.0F, 1.0F);
        float f = ent.renderYawOffset;
        float f1 = ent.rotationYaw;
        float f2 = ent.rotationPitch;
        float f3 = ent.prevRotationYawHead;
        float f4 = ent.rotationYawHead;
        GlStateManager.rotate(135.0F, 0.0F, 1.0F, 0.0F);
        RenderHelper.enableStandardItemLighting();
        GlStateManager.rotate(-135.0F, 0.0F, 1.0F, 0.0F);
        GlStateManager.rotate(-((float)Math.atan((double)(mouseY / 40.0F))) * 20.0F, 1.0F, 0.0F, 0.0F);
        ent.renderYawOffset = (float)Math.atan((double)(mouseX / 40.0F)) * 20.0F;
        ent.rotationYaw = (float)Math.atan((double)(mouseX / 40.0F)) * 40.0F;
        ent.rotationPitch = -((float)Math.atan((double)(mouseY / 40.0F))) * 20.0F;
        ent.rotationYawHead = ent.rotationYaw;
        ent.prevRotationYawHead = ent.rotationYaw;
        GlStateManager.translate(0.0F, 0.0F, 0.0F);
        RenderManager rendermanager = Minecraft.getMinecraft().getRenderManager();
        rendermanager.setPlayerViewY(180.0F);
        rendermanager.setRenderShadow(false);
        rendermanager.renderEntity(ent, 0.0D, 0.0D, 0.0D, 0.0F, 1.0F, false);
        rendermanager.setRenderShadow(true);
        ent.renderYawOffset = f;
        ent.rotationYaw = f1;
        ent.rotationPitch = f2;
        ent.prevRotationYawHead = f3;
        ent.rotationYawHead = f4;
        GlStateManager.popMatrix();
        RenderHelper.disableStandardItemLighting();
        GlStateManager.disableRescaleNormal();
        GlStateManager.setActiveTexture(OpenGlHelper.lightmapTexUnit);
        GlStateManager.disableTexture2D();
        GlStateManager.setActiveTexture(OpenGlHelper.defaultTexUnit);
    }
}

 

Updated Player Inventory (I know I'm reusing the recipe book texture on the button but its only until I can manage to get it working)

Spoiler

package com.championash5357.custom.gui.gui;

import java.io.IOException;

import com.championash5357.custom.capability.CustomCapabilities;
import com.championash5357.custom.client.CustomKeyBindings;

import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiButtonImage;
import net.minecraft.client.gui.inventory.GuiContainerCreative;
import net.minecraft.client.gui.recipebook.GuiRecipeBook;
import net.minecraft.client.gui.recipebook.IRecipeShownListener;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.InventoryEffectRenderer;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.client.resources.I18n;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.ClickType;
import net.minecraft.inventory.ContainerPlayer;
import net.minecraft.inventory.Slot;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

@SideOnly(Side.CLIENT)
public class GuiUpdatedInventory extends InventoryEffectRenderer implements IRecipeShownListener {
    private float oldMouseX;
    private float oldMouseY;
    private GuiButtonImage recipeButton, extended_inventory;
    private final GuiRecipeBook recipeBookGui = new GuiRecipeBook();
    private boolean widthTooNarrow;
    private boolean buttonClicked;

    public GuiUpdatedInventory(EntityPlayer player) {
        super(player.inventoryContainer);
        this.allowUserInput = true;
    }

    public void updateScreen() {
        if (this.mc.playerController.isInCreativeMode()) this.mc.displayGuiScreen(new GuiContainerCreative(this.mc.player));
        this.recipeBookGui.tick();
    }

    public void initGui() {
        this.buttonList.clear();

        if (this.mc.playerController.isInCreativeMode()) this.mc.displayGuiScreen(new GuiContainerCreative(this.mc.player));
        else super.initGui();

        this.widthTooNarrow = this.width < 379;
        this.recipeBookGui.func_194303_a(this.width, this.height, this.mc, this.widthTooNarrow, ((ContainerPlayer)this.inventorySlots).craftMatrix);
        this.guiLeft = this.recipeBookGui.updateScreenPosition(this.widthTooNarrow, this.width, this.xSize);
        this.recipeButton = new GuiButtonImage(10, this.guiLeft + 104, this.height / 2 - 22, 20, 18, 178, 0, 19, INVENTORY_BACKGROUND);
        this.buttonList.add(this.recipeButton);
        this.extended_inventory = new GuiButtonImage(11, this.guiLeft + 124, this.height / 2 - 22, 20, 18, 178, 0, 19, INVENTORY_BACKGROUND);
        this.buttonList.add(extended_inventory);
    }

    protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {
        this.fontRenderer.drawString(I18n.format("container.crafting"), 97, 8, 4210752);
    }

    public void drawScreen(int mouseX, int mouseY, float partialTicks) {
        this.drawDefaultBackground();
        this.hasActivePotionEffects = !this.recipeBookGui.isVisible();

        if (this.recipeBookGui.isVisible() && this.widthTooNarrow) {
            this.drawGuiContainerBackgroundLayer(partialTicks, mouseX, mouseY);
            this.recipeBookGui.render(mouseX, mouseY, partialTicks);
        } else {
            this.recipeBookGui.render(mouseX, mouseY, partialTicks);
            super.drawScreen(mouseX, mouseY, partialTicks);
            this.recipeBookGui.renderGhostRecipe(this.guiLeft, this.guiTop, false, partialTicks);
        }

        this.renderHoveredToolTip(mouseX, mouseY);
        this.recipeBookGui.renderTooltip(this.guiLeft, this.guiTop, mouseX, mouseY);
        this.oldMouseX = (float)mouseX;
        this.oldMouseY = (float)mouseY;
    }

    protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) {
        GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
        this.mc.getTextureManager().bindTexture(INVENTORY_BACKGROUND);
        int i = this.guiLeft;
        int j = this.guiTop;
        this.drawTexturedModalRect(i, j, 0, 0, this.xSize, this.ySize);
        drawEntityOnScreen(i + 51, j + 75, 30, (float)(i + 51) - this.oldMouseX, (float)(j + 75 - 50) - this.oldMouseY, this.mc.player);
    }

    public static void drawEntityOnScreen(int posX, int posY, int scale, float mouseX, float mouseY, EntityLivingBase ent) {
        GlStateManager.enableColorMaterial();
        GlStateManager.pushMatrix();
        GlStateManager.translate((float)posX, (float)posY, 50.0F);
        GlStateManager.scale((float)(-scale), (float)scale, (float)scale);
        GlStateManager.rotate(180.0F, 0.0F, 0.0F, 1.0F);
        float f = ent.renderYawOffset;
        float f1 = ent.rotationYaw;
        float f2 = ent.rotationPitch;
        float f3 = ent.prevRotationYawHead;
        float f4 = ent.rotationYawHead;
        GlStateManager.rotate(135.0F, 0.0F, 1.0F, 0.0F);
        RenderHelper.enableStandardItemLighting();
        GlStateManager.rotate(-135.0F, 0.0F, 1.0F, 0.0F);
        GlStateManager.rotate(-((float)Math.atan((double)(mouseY / 40.0F))) * 20.0F, 1.0F, 0.0F, 0.0F);
        ent.renderYawOffset = (float)Math.atan((double)(mouseX / 40.0F)) * 20.0F;
        ent.rotationYaw = (float)Math.atan((double)(mouseX / 40.0F)) * 40.0F;
        ent.rotationPitch = -((float)Math.atan((double)(mouseY / 40.0F))) * 20.0F;
        ent.rotationYawHead = ent.rotationYaw;
        ent.prevRotationYawHead = ent.rotationYaw;
        GlStateManager.translate(0.0F, 0.0F, 0.0F);
        RenderManager rendermanager = Minecraft.getMinecraft().getRenderManager();
        rendermanager.setPlayerViewY(180.0F);
        rendermanager.setRenderShadow(false);
        rendermanager.renderEntity(ent, 0.0D, 0.0D, 0.0D, 0.0F, 1.0F, false);
        rendermanager.setRenderShadow(true);
        ent.renderYawOffset = f;
        ent.rotationYaw = f1;
        ent.rotationPitch = f2;
        ent.prevRotationYawHead = f3;
        ent.rotationYawHead = f4;
        GlStateManager.popMatrix();
        RenderHelper.disableStandardItemLighting();
        GlStateManager.disableRescaleNormal();
        GlStateManager.setActiveTexture(OpenGlHelper.lightmapTexUnit);
        GlStateManager.disableTexture2D();
        GlStateManager.setActiveTexture(OpenGlHelper.defaultTexUnit);
    }

    protected boolean isPointInRegion(int rectX, int rectY, int rectWidth, int rectHeight, int pointX, int pointY) {
        return (!this.widthTooNarrow || !this.recipeBookGui.isVisible()) && super.isPointInRegion(rectX, rectY, rectWidth, rectHeight, pointX, pointY);
    }

    protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException {
        if (!this.recipeBookGui.mouseClicked(mouseX, mouseY, mouseButton))
            if (!this.widthTooNarrow || !this.recipeBookGui.isVisible())
                super.mouseClicked(mouseX, mouseY, mouseButton);
    }

    protected void mouseReleased(int mouseX, int mouseY, int state) {
        if (this.buttonClicked) this.buttonClicked = false;
        else super.mouseReleased(mouseX, mouseY, state);
    }

    protected boolean hasClickedOutside(int p_193983_1_, int p_193983_2_, int p_193983_3_, int p_193983_4_) {
        boolean flag = p_193983_1_ < p_193983_3_ || p_193983_2_ < p_193983_4_ || p_193983_1_ >= p_193983_3_ + this.xSize || p_193983_2_ >= p_193983_4_ + this.ySize;
        return this.recipeBookGui.hasClickedOutside(p_193983_1_, p_193983_2_, this.guiLeft, this.guiTop, this.xSize, this.ySize) && flag;
    }

    protected void actionPerformed(GuiButton button) throws IOException {
        if (button.id == 10) {
            this.recipeBookGui.initVisuals(this.widthTooNarrow, ((ContainerPlayer)this.inventorySlots).craftMatrix);
            this.recipeBookGui.toggleVisibility();
            this.guiLeft = this.recipeBookGui.updateScreenPosition(this.widthTooNarrow, this.width, this.xSize);
            this.recipeButton.setPosition(this.guiLeft + 104, this.height / 2 - 22);
            this.buttonClicked = true;
        }
        if(button.id == 11) {
            this.mc.displayGuiScreen(new GuiExtendedInventory(this.mc.player, this.mc.player.getCapability(CustomCapabilities.EXTENDED_INVENTORY, null)));
        }
    }

    protected void keyTyped(char typedChar, int keyCode) throws IOException {
        if (!this.recipeBookGui.keyPressed(typedChar, keyCode)) super.keyTyped(typedChar, keyCode);
    }

    protected void handleMouseClick(Slot slotIn, int slotId, int mouseButton, ClickType type) {
        super.handleMouseClick(slotIn, slotId, mouseButton, type);
        this.recipeBookGui.slotClicked(slotIn);
    }

    public void recipesUpdated() {
        this.recipeBookGui.recipesUpdated();
    }

    public void onGuiClosed() {
        this.recipeBookGui.removed();
        super.onGuiClosed();
    }

    public GuiRecipeBook func_194310_f() {
        return this.recipeBookGui;
    }
}

 

Extended Inventory Slot

Spoiler

package com.championash5357.custom.gui.slot;

import javax.annotation.Nonnull;

import com.championash5357.custom.capability.IExtendedInventory;

import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.InventoryBasic;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;

public class SlotExtendedInventory extends Slot {
    
    private static IInventory emptyInventory = new InventoryBasic("[Null]", true, 0);
    private final IExtendedInventory extended;
    private final int index;
    
    public SlotExtendedInventory(IExtendedInventory extended, int index, int xPosition, int yPosition) {
        super(emptyInventory, index, xPosition, yPosition);
        this.extended = extended;
        this.index = index;
    }
    
    @Override
    public boolean isItemValid(@Nonnull ItemStack stack) {
        if (stack.isEmpty())
            return false;

        IExtendedInventory handler = this.getExtendedInventory();
        ItemStack remainder;
        ItemStack currentStack = handler.getStackInSlot(index);

        handler.setStackInSlot(index, ItemStack.EMPTY);

        remainder = handler.insertItem(index, stack, true);

        handler.setStackInSlot(index, currentStack);
        return remainder.isEmpty() || remainder.getCount() < stack.getCount();
    }

    @Override
    @Nonnull
    public ItemStack getStack() {
        return this.getExtendedInventory().getStackInSlot(index);
    }

    @Override
    public void putStack(@Nonnull ItemStack stack) {
        extended.setStackInSlot(index, stack);
        this.onSlotChanged();
    }

    @Override
    public void onSlotChange(@Nonnull ItemStack p_75220_1_, @Nonnull ItemStack p_75220_2_) {

    }

    @Override
    public int getSlotStackLimit() {
        return this.extended.getSlotLimit(this.index);
    }

    @Override
    public int getItemStackLimit(@Nonnull ItemStack stack)  {
        ItemStack maxAdd = stack.copy();
        int maxInput = stack.getMaxStackSize();
        maxAdd.setCount(maxInput);

        IExtendedInventory handler = this.getExtendedInventory();
        ItemStack currentStack = handler.getStackInSlot(index);
        handler.setStackInSlot(index, ItemStack.EMPTY);
        
        ItemStack remainder = extended.insertItem(index, maxAdd, true);
        handler.setStackInSlot(index, currentStack);

        return maxInput - remainder.getCount();
    }

    @Override
    public boolean canTakeStack(EntityPlayer playerIn) {
        return !this.getExtendedInventory().extractItem(index, 1, true).isEmpty();
    }

    @Override
    @Nonnull
    public ItemStack decrStackSize(int amount) {
        return this.getExtendedInventory().extractItem(index, amount, false);
    }

    public IExtendedInventory getExtendedInventory() {
        return extended;
    }

    @Override
    public boolean isSameInventory(Slot other) {
        return other instanceof SlotExtendedInventory && ((SlotExtendedInventory) other).getExtendedInventory() == this.extended;
    }
    
    public EnumExtendedInventory getTypeFromSlot() {
        switch(this.getSlotIndex()) {
            case 0:
                return EnumExtendedInventory.BACK;
        }
        
        return null;
    }
}

 

Edited by ChampionAsh5357
Everything was fixed.
Posted
On 7/18/2018 at 6:10 PM, Animefan8888 said:

No, you cannot attach an CapabilityItemHandler.ITEM_HANDLER_CAPABILITY to the player as there is already one, but you can make your own capability that uses IItemHandler as its data(I believe. someone will correct me if I am wrong). And then attach this capability in AttachCapabilityEvent<Entity> to the player. Then reference it by EntityPlayer#getCapability

Okay, I created everything so that it works properly.  The only problem I have left is that when I first load up the world, the data in the slot does not get loaded until I open up the tab with it.  Since I created a KeyBinding to change the item with what the player has in hand, the data from the slot has to be loaded by the time the entity joins the world.

Posted
14 minutes ago, ChampionAsh5357 said:

The only problem I have left is that when I first load up the world, the data in the slot does not get loaded until I open up the tab with it. 

Then it is pretty obvious what you have to do if this is an actual problem. Sync it when the player joins the world with a custom packet.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Posted
On 7/20/2018 at 12:24 AM, Animefan8888 said:

Then it is pretty obvious what you have to do if this is an actual problem. Sync it when the player joins the world with a custom packet.

I realized that after posting it.  So I tried with the EntityJoinWorldEvent and I check if the entity joined is the player.  I got the server information and tried to sync it with the client.  However, it only works one time on login and then the packet throws a NullPointerException somehow when I add the scheduled task.  I also tried with PlayerEvent.PlayerLoggedInEvent with the same issue.

 

Packet

Spoiler

public static void registerPackets() {
        INSTANCE.registerMessage(PacketSyncExtendedInventoryHandler.class, PacketSyncExtendedInventory.class, 4, Side.CLIENT);
    }

 

public static class PacketSyncExtendedInventory implements IMessage {
        
        public PacketSyncExtendedInventory() {}
        
        private ItemStack back;
        
        public PacketSyncExtendedInventory(ItemStack back) {
            this.back = back;
        }
        
        @Override
        public void fromBytes(ByteBuf buf) {
            back = ByteBufUtils.readItemStack(buf);
        }

        @Override
        public void toBytes(ByteBuf buf) {
            ByteBufUtils.writeItemStack(buf, back);
        }
    }
    
    public static class PacketSyncExtendedInventoryHandler implements IMessageHandler<PacketSyncExtendedInventory, IMessage> {

        @Override
        public IMessage onMessage(PacketSyncExtendedInventory message, MessageContext ctx) {
            EntityPlayer player = Minecraft.getMinecraft().player;
            
            Minecraft.getMinecraft().addScheduledTask(() -> {
                player.getCapability(CustomCapabilities.EXTENDED_INVENTORY, null).setStackInSlot(0, message.back);
            });
            
            return null;
        }
    }

 

Event

Spoiler

@SubscribeEvent
    public static void onPlayerJoin(EntityJoinWorldEvent event) {
        if(event.getEntity() instanceof EntityPlayer) {
            EntityPlayer player = ((EntityPlayer)event.getEntity());
            player.getCapability(CustomCapabilities.EXTENDED_INVENTORY, null).sync();
        }
    }

 

Inventory Sync Method

Spoiler

@Override
    public void sync() {
        if(this.player.world.isRemote) return;
        
        if(!this.getStackInSlot(0).isEmpty())  {
            PacketHandler.sendTo(new PacketSyncExtendedInventory(this.getStackInSlot(0)), (EntityPlayerMP) player);
        }
    }

 

Posted
18 hours ago, Animefan8888 said:

Can I see the crash, kinda hard to debug without it.

It's not a crash, the packet just throws an exception; the game still runs because the only thing it does it try and load the slot.  If it fails then it's just air until I load it via opening the custom inventory.

 

Spoiler

[10:25:40] [main/FATAL]: Error executing task
java.util.concurrent.ExecutionException: java.lang.NullPointerException
    at java.util.concurrent.FutureTask.report(Unknown Source) ~[?:1.8.0_171]
    at java.util.concurrent.FutureTask.get(Unknown Source) ~[?:1.8.0_171]
    at net.minecraft.util.Util.runTask(Util.java:54) [Util.class:?]
    at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:1176) [Minecraft.class:?]
    at net.minecraft.client.Minecraft.run(Minecraft.java:441) [Minecraft.class:?]
    at net.minecraft.client.main.Main.main(Main.java:118) [Main.class:?]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_171]
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_171]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_171]
    at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_171]
    at net.minecraft.launchwrapper.Launch.launch(Launch.java:135) [launchwrapper-1.12.jar:?]
    at net.minecraft.launchwrapper.Launch.main(Launch.java:28) [launchwrapper-1.12.jar:?]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_171]
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_171]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_171]
    at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_171]
    at net.minecraftforge.gradle.GradleStartCommon.launch(GradleStartCommon.java:97) [start/:?]
    at GradleStart.main(GradleStart.java:25) [start/:?]
Caused by: java.lang.NullPointerException
    at com.championash5357.custom.network.PacketHandler$PacketSyncExtendedInventoryHandler.lambda$0(PacketHandler.java:219) ~[PacketHandler$PacketSyncExtendedInventoryHandler.class:?]
    at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) ~[?:1.8.0_171]
    at java.util.concurrent.FutureTask.run(Unknown Source) ~[?:1.8.0_171]
    at net.minecraft.util.Util.runTask(Util.java:53) ~[Util.class:?]
    ... 15 more

 

The line it is referring to, since I didn't post the entire packet class, is the line where I set the ItemStack in the slot.

Posted
4 hours ago, ChampionAsh5357 said:

The line it is referring to, since I didn't post the entire packet class, is the line where I set the ItemStack in the slot.

Use the debugger and find out what is null

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Posted
9 hours ago, Animefan8888 said:

Use the debugger and find out what is null

The player was returning null because I called it in the beginning of the message.  The player might not have been loaded yet so it couldn't set it. I moved the EntityPlayerSP inside the addScheduledTask and now everything works.  Thank you for taking the time to help me do this.

Posted
1 hour ago, ChampionAsh5357 said:

The player was returning null because I called it in the beginning of the message.  The player might not have been loaded yet so it couldn't set it. I moved the EntityPlayerSP inside the addScheduledTask and now everything works.  Thank you for taking the time to help me do this.

No problem, glad you got it working.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

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.