Jump to content
Search In
  • More options...
Find results that contain...
Find results in...

[SOLVED] Struggles With Creating Capabilities


Ghost20000
 Share

Recommended Posts

There seems to be a lot of conflicting information out there on creating capabilities. On what classes/interfaces you need, what needs to implement what, whether serializeNBT should call writeNBT or the other way around, etc. I understand there's probably a lot of ways to create a capability, but I just want the simplest possible thing.

I have a capability which I only want 1 item to use. It'll be able to store an EntityType, and serialize it into a String or deserialize it from a String when needed. Right now I have 2 classes, Pet and PetCapability:

public class Pet implements INBTSerializable<CompoundNBT> {
  private EntityType<?> entityType;

  public Pet() {
    this.entityType = null;
  }

  @Override
  public CompoundNBT serializeNBT() {
    CompoundNBT result = new CompoundNBT();

    String entityTypeString = EntityType.getKey(this.entityType).toString();
    result.putString("entityType", entityTypeString);

    return result;
  }

  @Override
  public void deserializeNBT(CompoundNBT nbt) {
    if (nbt.contains("entityType")) {
      String entityTypeString = nbt.getString("entityType");
      this.entityType = EntityType.byKey(entityTypeString).get();
    }
  }
}
public class PetCapability {
  @CapabilityInject(Pet.class)
  public static Capability<Pet> CAPABILITY_PET = null;

  public static void register() {
    CapabilityManager.INSTANCE.register(Pet.class, new PetStorage(), () -> new Pet());
  }

  public static class PetStorage implements IStorage<Pet> {
    @Override
    public void readNBT(Capability<Pet> capability, Pet instance, Direction side, INBT nbt) {
      instance.deserializeNBT((CompoundNBT) nbt);
    }

    @Override
    public INBT writeNBT(Capability<Pet> capability, Pet instance, Direction side) {
      return instance.serializeNBT();
    }
  }
}

Where do I go from here? I need a provider to attach to capability to the item right? Are my classes ok? Am I doing something where I shouldn't be doing it?

Thanks!

Edited by Ghost20000
Link to comment
Share on other sites

You need an interface to make a capability, I'd say you should call it IPet, Pet should implement it and you should pass in IPet in @CapabilityInject and the first parameter of register. The interface should look something like this with what you're currently doing: 

public interface IExample {
    EntityType<?> getEntityType();

    void setEntityType(EntityType<?> type);
}

strongly recommend you use generics instead if you can, something like this:

public interface IExample {
    <T extends Entity> EntityType<T> getEntityType();

    <T extends Entity> void setEntityType(EntityType<T> type);
}

Ping me or something next post, I'll help you out if I can.

Edit: Oh come on, solved as I was posting.

Edited by Novârch

It's sad how much time mods spend saying "x is no longer supported on this forum. Please update to a modern version of Minecraft to receive support".

Link to comment
Share on other sites

I ended up solving this with some help from the MinecraftByExample repo.

public class Pet {
  private EntityType<?> entityType;

  public Pet() {
    this.entityType = null;
  }

  public String getEntityTypeString() {
    if (this.entityType == null) {
      return null;
    }

    return EntityType.getKey(this.entityType).toString();
  }

  public EntityType<?> getEntityType() {
    return this.entityType;
  }

  public void setEntityType(String entityType) {
    this.entityType = EntityType.byKey(entityType).get();
  }

  public void setEntityType(EntityType<?> entityType) {
    this.entityType = entityType;
  }
}
public class PetCapability {
  @CapabilityInject(Pet.class)
  public static Capability<Pet> CAPABILITY_PET = null;

  public static void register() {
    CapabilityManager.INSTANCE.register(Pet.class, new PetStorage(), () -> new Pet());
  }

  public static class PetStorage implements IStorage<Pet> {
    @Override
    public void readNBT(Capability<Pet> capability, Pet instance, Direction side, INBT nbt) {
      if (nbt instanceof CompoundNBT && ((CompoundNBT) nbt).contains("type")) {
        String entityType = ((CompoundNBT) nbt).getString("type");
        instance.setEntityType(entityType);
      }
    }

    @Override
    public INBT writeNBT(Capability<Pet> capability, Pet instance, Direction side) {
      CompoundNBT result = new CompoundNBT();

      String entityTypeString = instance.getEntityTypeString();
      if (entityTypeString != null) {
        result.putString("type", entityTypeString);
      }

      return result;
    }
  }
}
public class PetCapabilityProvider implements ICapabilitySerializable<INBT> {
  private Pet pet = new Pet();

  @Override
  public <T> LazyOptional<T> getCapability(Capability<T> cap, Direction side) {
    if (cap == PetCapability.CAPABILITY_PET) {
      return (LazyOptional<T>) LazyOptional.of(() -> pet);
    }

    return LazyOptional.empty();
  }

  @Override
  public INBT serializeNBT() {
    return PetCapability.CAPABILITY_PET.writeNBT(pet, null);
  }

  @Override
  public void deserializeNBT(INBT nbt) {
    PetCapability.CAPABILITY_PET.readNBT(pet, null, nbt);
  }

}

Then register in the FMLCommonSetupEvent in your mod event subscriber and in your item class add the following function:

@Override
public ICapabilityProvider initCapabilities(ItemStack stack, CompoundNBT nbt) {
  return new PetCapabilityProvider();
}

Whenever you want to access the capability, just get the ItemStack and call GetCapability on it. If it's null, something went wrong, but if it's an instance of Pet, you can access 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
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.

 Share



×
×
  • Create New...

Important Information

By using this site, you agree to our Privacy Policy.