Jump to content
  • Home
  • Files
  • Docs
Topics
  • All Content

  • This Topic
  • This Forum

  • Advanced Search
  • Existing user? Sign In  

    Sign In



    • Not recommended on shared computers


    • Forgot your password?

  • Sign Up
  • All Activity
  • Home
  • Mod Developer Central
  • Modder Support
  • [1.12.2] Persisting Player Capability Inventory Data
The update for 1.13 is being worked on - please be patient. (Updated 02/19/19)
1.13 Update Notes for Mod Creators
Sign in to follow this  
Followers 0
ChampionAsh5357

[1.12.2] Persisting Player Capability Inventory Data

Started by ChampionAsh5357, July 12, 2018

23 posts in this topic

ChampionAsh5357    0

ChampionAsh5357

ChampionAsh5357    0

  • Tree Puncher
  • ChampionAsh5357
  • Members
  • 0
  • 23 posts
  • Report post
Posted July 12, 2018

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

Share this post


Link to post
Share on other sites

Animefan8888    491

Animefan8888

Animefan8888    491

  • Reality Controller
  • Animefan8888
  • Forge Modder
  • 491
  • 4324 posts
  • Report post
Posted July 12, 2018
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).

Share this post


Link to post
Share on other sites

ChampionAsh5357    0

ChampionAsh5357

ChampionAsh5357    0

  • Tree Puncher
  • ChampionAsh5357
  • Members
  • 0
  • 23 posts
  • Report post
Posted July 12, 2018
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.

Share this post


Link to post
Share on other sites

Animefan8888    491

Animefan8888

Animefan8888    491

  • Reality Controller
  • Animefan8888
  • Forge Modder
  • 491
  • 4324 posts
  • Report post
Posted July 12, 2018
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

Share this post


Link to post
Share on other sites

ChampionAsh5357    0

ChampionAsh5357

ChampionAsh5357    0

  • Tree Puncher
  • ChampionAsh5357
  • Members
  • 0
  • 23 posts
  • Report post
Posted July 12, 2018

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.

Share this post


Link to post
Share on other sites

Draco18s    1928

Draco18s

Draco18s    1928

  • Reality Controller
  • Draco18s
  • Members
  • 1928
  • 12868 posts
  • Report post
Posted July 12, 2018
59 minutes ago, ChampionAsh5357 said:

nbtTagListIn.appendTag(nbtTagListIn);

 

Inserting a list into itself seems like a good plan.

Share this post


Link to post
Share on other sites

Animefan8888    491

Animefan8888

Animefan8888    491

  • Reality Controller
  • Animefan8888
  • Forge Modder
  • 491
  • 4324 posts
  • Report post
Posted July 12, 2018
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.

Share this post


Link to post
Share on other sites

ChampionAsh5357    0

ChampionAsh5357

ChampionAsh5357    0

  • Tree Puncher
  • ChampionAsh5357
  • Members
  • 0
  • 23 posts
  • Report post
Posted July 18, 2018
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.

Share this post


Link to post
Share on other sites

Animefan8888    491

Animefan8888

Animefan8888    491

  • Reality Controller
  • Animefan8888
  • Forge Modder
  • 491
  • 4324 posts
  • Report post
Posted July 18, 2018 (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 July 18, 2018 by Animefan8888

Share this post


Link to post
Share on other sites

ChampionAsh5357    0

ChampionAsh5357

ChampionAsh5357    0

  • Tree Puncher
  • ChampionAsh5357
  • Members
  • 0
  • 23 posts
  • Report post
Posted July 18, 2018
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.

Share this post


Link to post
Share on other sites

Animefan8888    491

Animefan8888

Animefan8888    491

  • Reality Controller
  • Animefan8888
  • Forge Modder
  • 491
  • 4324 posts
  • Report post
Posted July 18, 2018
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.

Share this post


Link to post
Share on other sites

ChampionAsh5357    0

ChampionAsh5357

ChampionAsh5357    0

  • Tree Puncher
  • ChampionAsh5357
  • Members
  • 0
  • 23 posts
  • Report post
Posted July 18, 2018
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?

Share this post


Link to post
Share on other sites

Animefan8888    491

Animefan8888

Animefan8888    491

  • Reality Controller
  • Animefan8888
  • Forge Modder
  • 491
  • 4324 posts
  • Report post
Posted July 18, 2018
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

Share this post


Link to post
Share on other sites

diesieben07    6114

diesieben07

diesieben07    6114

  • Reality Controller
  • diesieben07
  • Forum Team
  • 6114
  • 40242 posts
  • Report post
Posted July 18, 2018

Only one capability can be registered for each class. So you would need you make your own interface.

Share this post


Link to post
Share on other sites

ChampionAsh5357    0

ChampionAsh5357

ChampionAsh5357    0

  • Tree Puncher
  • ChampionAsh5357
  • Members
  • 0
  • 23 posts
  • Report post
Posted July 19, 2018 (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 July 20, 2018 by ChampionAsh5357
Everything was fixed.

Share this post


Link to post
Share on other sites

ChampionAsh5357    0

ChampionAsh5357

ChampionAsh5357    0

  • Tree Puncher
  • ChampionAsh5357
  • Members
  • 0
  • 23 posts
  • Report post
Posted July 20, 2018
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.

Share this post


Link to post
Share on other sites

Animefan8888    491

Animefan8888

Animefan8888    491

  • Reality Controller
  • Animefan8888
  • Forge Modder
  • 491
  • 4324 posts
  • Report post
Posted July 20, 2018
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.

Share this post


Link to post
Share on other sites

ChampionAsh5357    0

ChampionAsh5357

ChampionAsh5357    0

  • Tree Puncher
  • ChampionAsh5357
  • Members
  • 0
  • 23 posts
  • Report post
Posted July 22, 2018
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);
        }
    }

 

Share this post


Link to post
Share on other sites

Animefan8888    491

Animefan8888

Animefan8888    491

  • Reality Controller
  • Animefan8888
  • Forge Modder
  • 491
  • 4324 posts
  • Report post
Posted July 22, 2018
29 minutes ago, ChampionAsh5357 said:

NullPointerException somehow when I add the scheduled task.

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

 

Share this post


Link to post
Share on other sites

ChampionAsh5357    0

ChampionAsh5357

ChampionAsh5357    0

  • Tree Puncher
  • ChampionAsh5357
  • Members
  • 0
  • 23 posts
  • Report post
Posted July 23, 2018
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.

Share this post


Link to post
Share on other sites

Animefan8888    491

Animefan8888

Animefan8888    491

  • Reality Controller
  • Animefan8888
  • Forge Modder
  • 491
  • 4324 posts
  • Report post
Posted July 23, 2018
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

Share this post


Link to post
Share on other sites

ChampionAsh5357    0

ChampionAsh5357

ChampionAsh5357    0

  • Tree Puncher
  • ChampionAsh5357
  • Members
  • 0
  • 23 posts
  • Report post
Posted July 24, 2018
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.

Share this post


Link to post
Share on other sites

Animefan8888    491

Animefan8888

Animefan8888    491

  • Reality Controller
  • Animefan8888
  • Forge Modder
  • 491
  • 4324 posts
  • Report post
Posted July 24, 2018
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.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  
Followers 0
Go To Topic Listing Modder Support

  • Recently Browsing

    No registered users viewing this page.

  • Posts

    • Pkbldr
      Trouble Updating Forge

      By Pkbldr · Posted 1 minute ago

    • Aloonus
      1.13.2-25.0.45 fails to install

      By Aloonus · Posted 1 minute ago

      I get the exact same error   java.net.preferIPv4Stack=true
      Extracting json
      Extracting json
      Considering minecraft client jar
      Considering minecraft client jar
      Downloading libraries
      Downloading libraries
      Considering library net.minecraftforge:forge:1.13.2-25.0.45
      File exists: Checksum validated. ....... Data  pack.mcmeta
      Output: C:\Users\*****\AppData\Roaming\.minecraft\libraries\net\minecraft\client\1.13.2\client-1.13.2-slim.jar Checksum Validated: 46c94ec3485ec35fe1826ca17ecfd5e10bb17c9c
      Processor failed, invalid outputs:
        C:\Users\*****\AppData\Roaming\.minecraft\libraries\net\minecraft\client\1.13.2\client-1.13.2-extra.jar
          Expected: b04f3ee8f5e43fa3b162981b50bb72fe1acabb33
          Actual:   938487f223e08b48c7b40dc7aa40a34b9dea2520   Before running the installer I have tried:   a) Updated the launcher to the latest version   b) Ran the latest version of minecraft   c) Checked that I had the latest version of Java installed, which I do, apparently   d) Deleting 1.12 version in the launcher   e) Deleting 1.13.2 version of optifine from launcher   file I am using is:   forge-1.13.2-25.0.45-installer.jar   Any help would be greatly appreciated   Thanks
    • perigrine3
      Adding Items To Armor Slots???

      By perigrine3 · Posted 5 minutes ago

      Yeah it is, but it works now. I tested it and fixed it. It was funny lol, I tried using the Amulet and the boots appeared floating over my head, the chestplate on my leggings, and the leggings on my chestplate lmao. 
    • Drachenbauer
      error at entity registration

      By Drachenbauer · Posted 7 minutes ago

      Hello my error-log now shows this:   It leads me to this: @SubscribeEvent public static void registerEntities(final RegistryEvent.Register<EntityType<?>> event) { event.getRegistry().register(EntityType.Builder.create(EntityRed.class, EntityRed::new).tracker(32, 1, true).build(Reference.MOD_ID + ".red")); event.getRegistry().register(EntityType.Builder.create(EntityChuck.class, EntityChuck::new).tracker(32, 1, true).build(Reference.MOD_ID + ".chuck")); event.getRegistry().register(EntityType.Builder.create(EntityBlues.class, EntityBlues::new).tracker(32, 1, true).build(Reference.MOD_ID + ".blues")); event.getRegistry().register(EntityType.Builder.create(EntityBomb.class, EntityBomb::new).tracker(32, 1, true).build(Reference.MOD_ID + ".bomb")); event.getRegistry().register(EntityType.Builder.create(EntityMathilda.class, EntityMathilda::new).tracker(32, 1, true).build(Reference.MOD_ID + ".mathilda")); RenderHandler.regigisterEntityRenders(); LOGGER.info("Entities registered."); }   what does it mean, what exactly i have to fix?
    • Pkbldr
      Trouble Updating Forge

      By Pkbldr · Posted 8 minutes ago

      It's not available as I can see.... or am I missing something?
  • Topics

    • Pkbldr
      5
      Trouble Updating Forge

      By Pkbldr
      Started 56 minutes ago

    • CJWilk
      1
      1.13.2-25.0.45 fails to install

      By CJWilk
      Started 4 hours ago

    • perigrine3
      24
      Adding Items To Armor Slots???

      By perigrine3
      Started Saturday at 10:32 PM

    • Drachenbauer
      0
      error at entity registration

      By Drachenbauer
      Started 7 minutes ago

    • WesterlyClown
      3
      I am not able to run the forge installer

      By WesterlyClown
      Started Tuesday at 02:26 AM

  • Who's Online (See full list)

    • Awakened Redstone
    • perigrine3
    • sunsigne
    • Aloonus
    • Pkbldr
    • STEENBRINK
    • Drachenbauer
    • Yoyoness_
    • thedarkcolour
    • HighCrit
    • DaemonUmbra
    • Sprasetemvruce
    • Melonslise
    • Floydman
    • DutchM
  • All Activity
  • Home
  • Mod Developer Central
  • Modder Support
  • [1.12.2] Persisting Player Capability Inventory Data
  • Theme
  • Contact Us

Copyright © 2017 ForgeDevelopment LLC Powered by Invision Community