Jump to content

[1.9] Having Problem with Capabilities System


PureUnstable

Recommended Posts

I am trying to attach a capability to the player allowing for there to be a point counter listed as destruction points. The capability system I created doesn't seem to work. I made an item called Point Reader that attempts to read the current points the player has, but it keeps returning that the player doesnt have the capability.

 

Here is my code:

 

IDestruction.java

 

package pureunstable.test.tileentity;

 

import net.minecraft.entity.player.EntityPlayer;

import net.minecraft.util.EnumFacing;

import net.minecraftforge.common.capabilities.Capability;

import net.minecraftforge.common.capabilities.ICapabilityProvider;

 

public interface IDestruction {

 

double destructionPoints = 0;

 

double getDestructionPoints();

void setDestructionPoints(double points);

void addDestructionPoints(double points);

void subDestructionPoints(double points);

 

 

}

 

 

 

DefaultImpl.java

 

package pureunstable.test.tileentity;

 

import net.minecraft.entity.player.EntityPlayer;

import net.minecraft.nbt.NBTTagCompound;

import net.minecraft.util.EnumFacing;

import net.minecraftforge.common.capabilities.Capability;

import net.minecraftforge.common.util.INBTSerializable;

import pureunstable.test.TestMod;

import pureunstable.test.tileentity.IDestruction;

 

/*

*  This class is the implementation of IDestruction

*/

 

public class DefaultImpl implements IDestruction{

 

private static double points = 0;

 

public DefaultImpl() {

this.points = this.getDestructionPoints();

}

 

public DefaultImpl(long points) {

this.points = points;

}

 

@Override

public double getDestructionPoints() {

return points;

}

 

@Override

public void setDestructionPoints(double points) {

this.points = points;

}

 

@Override

public void addDestructionPoints(double points) {

if(this.points != getDestructionPoints()) {

this.points = getDestructionPoints();

System.out.println("Slight malfunction...");

}

 

this.points += points;

}

 

@Override

public void subDestructionPoints(double points) {

if(this.points != getDestructionPoints()) {

this.points = getDestructionPoints();

System.out.println("Slight malfunction...");

}

this.points -= points;

}

 

 

}

 

 

 

Storage.java

 

package pureunstable.test.tileentity;

 

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;

 

public class Storage implements IStorage<IDestruction> {

 

public static final Storage destructionPoints = new Storage();

 

@Override

public NBTBase writeNBT(Capability<IDestruction> capability, IDestruction instance, EnumFacing side) {

 

NBTTagCompound nbt = new NBTTagCompound();

nbt.setDouble("dest", instance.getDestructionPoints());

System.out.println("Writing dest points: " + instance.getDestructionPoints());

return nbt;

}

 

@Override

public void readNBT(Capability<IDestruction> capability, IDestruction instance, EnumFacing side, NBTBase nbt) {

 

instance.setDestructionPoints(((NBTTagCompound)nbt).getDouble("dest"));

System.out.println("Reading destruction points: " + ((NBTTagCompound)nbt).getDouble("dest"));

 

}

 

}

 

 

 

EventHandlerCommon.java

 

package pureunstable.test;

 

import net.minecraft.nbt.NBTBase.NBTPrimitive;

import net.minecraft.util.EnumFacing;

import net.minecraft.util.ResourceLocation;

import net.minecraftforge.common.capabilities.Capability;

import net.minecraftforge.common.capabilities.ICapabilitySerializable;

import net.minecraftforge.event.AttachCapabilitiesEvent;

import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;

import pureunstable.test.TestMod;

import pureunstable.test.tileentity.IDestruction;

 

public class EventHandlerCommon {

 

@SubscribeEvent

public void onEntityConstruct(AttachCapabilitiesEvent.Entity evt) {

 

evt.addCapability(new ResourceLocation(Reference.MODID, "IDestruction"), new ICapabilitySerializable<NBTPrimitive>() {

 

IDestruction inst = TestMod.DESTRUCTION_CAP.getDefaultInstance();

 

@Override

public boolean hasCapability(Capability<?> capability, EnumFacing facing) {

return capability == TestMod.DESTRUCTION_CAP;

}

 

@Override

public <T> T getCapability(Capability<T> capability, EnumFacing facing) {

 

return capability == TestMod.DESTRUCTION_CAP ? TestMod.DESTRUCTION_CAP.<T>cast(inst) : null;

}

 

@Override

public NBTPrimitive serializeNBT() {

 

return (NBTPrimitive)TestMod.DESTRUCTION_CAP.getStorage().writeNBT(TestMod.DESTRUCTION_CAP, inst, null);

}

 

@Override

public void deserializeNBT(NBTPrimitive nbt) {

TestMod.DESTRUCTION_CAP.getStorage().readNBT(TestMod.DESTRUCTION_CAP, inst, null, nbt);

 

}

 

});

}

}

 

 

 

CommonProxy.java

 

package pureunstable.test.proxy;

 

import net.minecraftforge.common.MinecraftForge;

import net.minecraftforge.common.capabilities.CapabilityManager;

import net.minecraftforge.fml.common.Mod;

import net.minecraftforge.fml.common.Mod.EventHandler;

import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;

import pureunstable.test.tileentity.IDestruction;

import pureunstable.test.EventHandlerCommon;

import pureunstable.test.tileentity.DefaultImpl;

import pureunstable.test.tileentity.Storage;

 

public class CommonProxy {

 

public void registerRenders() {

 

}

 

@Mod.EventHandler

public void preInit(FMLPreInitializationEvent event){

 

CapabilityManager.INSTANCE.register(IDestruction.class, new Storage(), DefaultImpl.class);

MinecraftForge.EVENT_BUS.register(new EventHandlerCommon());

}

 

}

 

 

 

And I have this in my main mod class:

 

@CapabilityInject(IDestruction.class)

public static final Capability<IDestruction> DESTRUCTION_CAP = null;

 

Link to comment
Share on other sites

public static final Capability<IDestruction> DESTRUCTION_CAP = null;

 

Do you ever make this field not-null?

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

 

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

 

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

Link to comment
Share on other sites

Gotcha.

I haven't quite figured out all the things with capabilities yet.  Definitely haven't done any based on entityConstructing (that is, I've done a custom Cap on a TE of my own design and used the ItemHandler one).

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

 

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

 

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

Link to comment
Share on other sites

I'm not entirely sure why it's not working, but I did notice some errors:

  • The
    IDestruction#destructionPoints

    field doesn't need to exist.

  • The
    DefaultImpl.points

    field shouldn't be static.

  • Your
    IStorage

    expects to work with

    NBTTagCompound

    s, but your

    ICapabilitySerializable

    uses

    NBTPrimitive

    .

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Link to comment
Share on other sites

I just finished fixing those errors. Thank you for pointing them out.

 

I moved my @CapabilityInject to my EventHandlerCommon.java to see if that may solve anything, but it does not seem like it has. The way I am attempting to check if my player has the capability is by right clicking with an item with the following code:

 

 

package pureunstable.test.items;

 

import net.minecraft.entity.player.EntityPlayer;

import net.minecraft.item.Item;

import net.minecraft.item.ItemStack;

import net.minecraft.util.ActionResult;

import net.minecraft.util.EnumHand;

import net.minecraft.util.text.TextComponentString;

import net.minecraft.world.World;

import pureunstable.test.EventHandlerCommon;

import pureunstable.test.TestMod;

import pureunstable.test.tileentity.IDestruction;

 

public class ItemPointReader extends Item {

 

@Override

public ActionResult<ItemStack> onItemRightClick(ItemStack itemStackIn, World worldIn, EntityPlayer playerIn,

EnumHand hand) {

 

if(!worldIn.isRemote) {

 

playerIn.addChatComponentMessage(new TextComponentString(playerIn.getCapability(EventHandlerCommon.DESTRUCTION_CAP, null).getDestructionPoints() + " points"));

 

}

 

return super.onItemRightClick(itemStackIn, worldIn, playerIn, hand);

}

 

 

}

 

 

 

The way I see it, if the player has the DESTRUCTION_CAP capability, then there will be a chat message that shows the points, which is starting at 0 points. I'm instead getting a null pointer exception whenever I right click with this item. Is this a bad way to go about checking if I have the capability?

Link to comment
Share on other sites

The way I am attempting to check if my player has the capability is by right clicking with an item with the following code:

 

 

package pureunstable.test.items;

 

import net.minecraft.entity.player.EntityPlayer;

import net.minecraft.item.Item;

import net.minecraft.item.ItemStack;

import net.minecraft.util.ActionResult;

import net.minecraft.util.EnumHand;

import net.minecraft.util.text.TextComponentString;

import net.minecraft.world.World;

import pureunstable.test.EventHandlerCommon;

import pureunstable.test.TestMod;

import pureunstable.test.tileentity.IDestruction;

 

public class ItemPointReader extends Item {

 

@Override

public ActionResult<ItemStack> onItemRightClick(ItemStack itemStackIn, World worldIn, EntityPlayer playerIn,

EnumHand hand) {

 

if(!worldIn.isRemote) {

 

playerIn.addChatComponentMessage(new TextComponentString(playerIn.getCapability(EventHandlerCommon.DESTRUCTION_CAP, null).getDestructionPoints() + " points"));

 

}

 

return super.onItemRightClick(itemStackIn, worldIn, playerIn, hand);

}

 

 

}

 

 

 

The way I see it, if the player has the DESTRUCTION_CAP capability, then there will be a chat message that shows the points, which is starting at 0 points. I'm instead getting a null pointer exception whenever I right click with this item. Is this a bad way to go about checking if I have the capability?

 

Yes. If the player does not have the capability, getCapability() will return null; since you call a method on the return value, if the player does not have the capability an NPE is thrown. Use hasCapability() to check if the player has a capability.

Link to comment
Share on other sites

I originally had a check in an if statement to see if the player had the capability but it was coming back as false, so i just did a shortcut through the code last night before I went to bed.

 

I just took a look through my code again and realized I had my client proxy class referenced within my main mod class, but not the common proxy class. After fixing that, my capability now works. Thanks everyone for helping me work through it!

Link to comment
Share on other sites

Join the conversation

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

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

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

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

×   Your previous content has been restored.   Clear editor

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

Announcements



×
×
  • Create New...

Important Information

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