Jump to content

Recommended Posts

Posted (edited)

I created a capability for player to write a custom inventory for each player. But I do not really understant how to get the data stored in the capability.
Heres some classes:

The IStorage

  Reveal hidden contents

The default capability:

  Reveal hidden contents

The CapabilitySerializable:

  Reveal hidden contents

The tile entity:

  Reveal hidden contents

And the container's class:

  Reveal hidden contents

 

Edited by LuccaPossamai
Posted

Why do you have a tile entity? isn't the capability for the player entity?

What's  the purpose of IStorageInstance? and what's the difference between AltarCapability and DefaultAltarCapability?

I think you're under some fundamental misconception over the capability system. Here's what you need:

1. A capability, and a capability is just a class which holds any arbitrary data you need. Since what you want is an "inventory", forge provides an implementation for that, the ItemStackHandler. If you don't require any custom logic on top of just a holder of ItemStacks, you don't even need to extend it, just use the ItemStackHandler capability.

2. A capability provider, which will manage the capabilities for your player. in it you'll handle serialization, and on the getCapability method, you'll check if the requested capability matches your capability, and if it does, return the lazy capability

3. you'll register the capabilities, and attach them on the proper event handler

4. if you want the inventory to be displayed, and interacted with by the player, you'll need the container and a container screen (not a tile entity, those are for blocks).

Posted

The tile entity in this context just serves to open the container that allows the player to have acess to this inventory. I change for the ItemStackHandler and I works. But, when I enter the world the capability resets.

Posted
  On 5/27/2021 at 7:31 PM, LuccaPossamai said:

The tile entity in this context just serves to open the container that allows the player to have acess to this inventory.

Expand  

yeah, that's not what tile entities are for. Tile entities are for blocks.

what you need to open the container, is an INamedContainerProvider

  On 5/27/2021 at 7:31 PM, LuccaPossamai said:

I change for the ItemStackHandler and I works. But, when I enter the world the capability resets.

Expand  

then you're not properly serializing your data, make sure you properly overrode the serializeNBT and deserializeNBT methods in your Capability Provider.

and post your new code if you're still with some issues

Posted

I use this tile entity for a block, and this block the player use to open the inventory(like an ender chest). I changed the capability to an ItemStackHandler. But every time I enter in the game the inventory resets.

The class for ItemStackHandler cap: 

  Reveal hidden contents

The Capability.IStorage:

  Reveal hidden contents

The instance of the capability:

  Reveal hidden contents

I'm using this to load the items, a add them to an inventory:

  Reveal hidden contents

And using this, to save the items of the container in the cap:

  Reveal hidden contents

 

Posted (edited)
  On 5/28/2021 at 4:19 AM, LuccaPossamai said:

I use this tile entity for a block, and this block the player use to open the inventory(like an ender chest).

Expand  

that doesn't mean you need a tile entity, the data is being stored in the player's capability, not the block

 

  On 5/28/2021 at 4:19 AM, LuccaPossamai said:

The class for ItemStackHandler cap: 


public class DefaultAltarCapability extends ItemStackHandler {

    public DefaultAltarCapability(){
        super(9);
    }
    
}

 

Expand  

There's no need to extends the ItemStackHandler, just instantiate it

 

  On 5/28/2021 at 4:19 AM, LuccaPossamai said:

The Capability.IStorage:



public class IStorageInstance implements Capability.IStorage<DefaultAltarCapability> {

    @Nullable
    @Override
    public INBT writeNBT(Capability<DefaultAltarCapability> capability, DefaultAltarCapability instance, Direction side) {
        ListNBT listnbt = new ListNBT();

        for(int i = 0; i < instance.getSlots(); ++i) {
            ItemStack itemstack = instance.getStackInSlot(i);
            CompoundNBT compoundnbt = new CompoundNBT();
            compoundnbt.putInt("Slot", i);
            itemstack.save(compoundnbt);
            listnbt.add(compoundnbt);

        }
        CompoundNBT nbt = new CompoundNBT();
        nbt.put("Items",listnbt);
        nbt.putInt("Size",listnbt.size());

        return listnbt;
    }

    @Override
    public void readNBT(Capability<DefaultAltarCapability> capability, DefaultAltarCapability instance, Direction side, INBT nbt) {
        if(nbt instanceof  CompoundNBT) {
            System.out.println("É tag");
            CompoundNBT compoundNBT = (CompoundNBT) nbt;
            ListNBT tagList = compoundNBT.getList("Items", Constants.NBT.TAG_COMPOUND);

            for (int i = 0; i < tagList.size(); ++i) {
                instance.insertItem(i, ItemStack.of(tagList.getCompound(i)), false);
            }
        }
    }

}

 

Expand  

You don't need to use IStorage, plus they're being removed in the next versions. just do the serialization in the provider

 

  On 5/28/2021 at 4:19 AM, LuccaPossamai said:

The instance of the capability:



public class CapabilityInstance  {

    @CapabilityInject(DefaultAltarCapability.class)
    public static Capability<DefaultAltarCapability> ALTAR_CAPABILITY = null;

    public static void register(){
        CapabilityManager.INSTANCE.register(DefaultAltarCapability.class, new IStorageInstance(), DefaultAltarCapability::new );
    }


}

 

Expand  

and when your CapabilityInstance.register called?

 

  On 5/28/2021 at 4:19 AM, LuccaPossamai said:

I'm using this to load the items, a add them to an inventory:



private Inventory loadItems(PlayerEntity player){
        Inventory inventory = new Inventory(9);
        player.getCapability(CapabilityInstance.ALTAR_CAPABILITY).ifPresent(inv ->{
            for(int i = 0; i < inv.getSlots(); i++){
                inventory.setItem(i, inv.getStackInSlot(i));
            }
        });

        return inventory;
    }

And using this, to save the items of the container in the cap:



@SubscribeEvent
    public static void saveAltarItems(PlayerContainerEvent.Close event){
        PlayerEntity jogador = event.getPlayer();
        if(event.getContainer() instanceof ModAltarContainer) {
            NonNullList<ItemStack> lista = NonNullList.withSize(9, ItemStack.EMPTY);
            Container cont = event.getContainer();
            jogador.getCapability(CapabilityInstance.ALTAR_CAPABILITY).ifPresent( inv ->{
                for(int i = 0 ; i < inv.getSlots() ; i++){
                    inv.setStackInSlot(i, cont.getItems().get(i));
                    inv.deserializeNBT(inv.serializeNBT());
                }
            });
            //PlayerEvolution.setStats(lista, jogador);
        }
    }

 

Expand  

What are these for? why are you converting the ItemStackHandler to an Inventory, to use the ItemStackHandler

 

And you didn't show the CapabilityProvider.

You're over complicating this, I've already explained what it is that you need:

  On 5/27/2021 at 2:58 AM, kiou.23 said:

1. A capability, and a capability is just a class which holds any arbitrary data you need. Since what you want is an "inventory", forge provides an implementation for that, the ItemStackHandler. If you don't require any custom logic on top of just a holder of ItemStacks, you don't even need to extend it, just use the ItemStackHandler capability.

2. A capability provider, which will manage the capabilities for your player. in it you'll handle serialization, and on the getCapability method, you'll check if the requested capability matches your capability, and if it does, return the lazy capability

3. you'll register the capabilities, and attach them on the proper event handler

4. if you want the inventory to be displayed, and interacted with by the player, you'll need the container and a container screen (not a tile entity, those are for blocks).

Expand  

your Capability Provider will provide an ItemStackHandler, in this case, handle serialization in the Provider's serialize and deserialize methods

and you don't need a TE, at least not for this. the TE is meant to store additional data for blocks, since the data you're storing isn't kept in a block, but in the player, you don't need a Tile entity. to open the container you just need an INamedContainerProvider, which passes any data that the Container needs, to the container. and you'll get this data from the Capability

Edited by kiou.23
Posted

Ok, I changed some things. But the inventory still resets. I'm calling the registration of the capability in the setup, maybe this is causing the reset.
The attachEvent:

  Reveal hidden contents

And the Provider/Serializable:

  Reveal hidden contents

 

Posted (edited)
  On 5/28/2021 at 11:40 PM, LuccaPossamai said:

Ok, I changed some things. But the inventory still resets. I'm calling the registration of the capability in the setup, maybe this is causing the reset.
The attachEvent:

  Reveal hidden contents

And the Provider/Serializable:

  Reveal hidden contents

 

Expand  

in the provider's serializeNBT you call the IStorage's writeNBT, but in the IStorage's writeNBT you call the provider's serializeNBT. You never actually serialize your data.

 

1. You don't need an IStorage, just do the serialization in the provider itself.

2. your lazy altar isn't actually lazy. google the concept up. don't initialize the the field on instantiation, instead wait until the capability is requested to initialize it, then cache it.

3. no need to implement ICapabilityProvider, only ICapabilitySerializable, also, you should define the generic parameter of the interface.

4. don't put your capability instance on the capability provider class. that's separation of concerns 101

5. on your getCapability, make sure that the capability being requested is the one you're providing!

Hold on, I have a mod with a private repo that uses capabilities. I'll make it public to share it here so you can see some examples

 

EDIT: here's some examples https://github.com/jvcmarcenes/skbackpacks

EDIT2: I had forgot, for serializing ItemStackHandlers you can use of CapabilityItemHandler.ITEM_HANDLER_CAPABILITY write/read method

Edited by kiou.23
Posted

Ok, with an example the things just get so many clear now. Thanks btw. But, I'm confused. How do I register this Capability. I mean, I tried but, with the serialization, there is no IStorage. I looked in your code, and do not find a field that you register the cap. 

Posted
  On 5/29/2021 at 6:06 AM, LuccaPossamai said:

Ok, with an example the things just get so many clear now. Thanks btw. But, I'm confused. How do I register this Capability. I mean, I tried but, with the serialization, there is no IStorage. I looked in your code, and do not find a field that you register the cap. 

Expand  

since that's just using an ItemStackHandler, I used the ITEM_HANDLER capability that already exists in CapabilityItemHandler

Bur for registration you just create a field, in a class like ModCapabilities, of type Capability<Your Capability class>, and use @CapabilityInject()

and I didn't have to use an attach event because I'm using the capability in a custom Item. but for attaching it's the same thing, just listen to the proper event, and call event.addCapabicall, then give it the cap ID and an instance of the cap provider

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

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

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

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

×   Your previous content has been restored.   Clear editor

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

Announcements



×
×
  • Create New...

Important Information

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