Capabilities не сохраняется после выхода из игры

Версия Minecraft
1.12.2
API
Forge
16
1
0
Мне говорили что capabilities сохраняется после выхода из игры в определенном мире. НО я сдлеал у себя capabilities, а он не сохранил после выходя из игры данные. Быстрее всего я тупой и что-то неправильно сделал. Но как можно сохранить capabilities привязанную к игроку в мире ?
Вот все классы:

Вот все классы:
Imana:
package com.example.examplemod.capabilities;

public interface IMana {

    public void setMana(int mana);

    public int getMana();
}
Mana:
package com.example.examplemod.capabilities;

public class Mana implements IMana{

    private int mana = 1;

    @Override
    public void setMana(int mana) {
        this.mana = mana;
    }

    @Override
    public int getMana() {
        return this.mana;
    }
}
ManaProvider:
package com.example.examplemod.capabilities;

import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityInject;
import net.minecraftforge.common.capabilities.ICapabilitySerializable;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

public class ManaProvider implements ICapabilitySerializable<NBTTagCompound> {


    @CapabilityInject(IMana.class)
    public static final Capability<IMana> MANA_CAPABILITY = null;
    private final IMana capability = new Mana();

    @Override
    public boolean hasCapability(@Nonnull Capability<?> capability, @Nullable EnumFacing facing) {
        return capability == MANA_CAPABILITY;
    }

    @Nullable
    @Override
    @SuppressWarnings("unchecked")
    public <T> T getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing) {
        if ((MANA_CAPABILITY != null) && (capability == MANA_CAPABILITY)) return (T) this.capability;
        return null;
    }

    @Override
    public NBTTagCompound serializeNBT() {
        return (NBTTagCompound) ManaStorage.INSTANCE.writeNBT(ManaProvider.MANA_CAPABILITY, new Mana(), null);
    }

    @Override
    public void deserializeNBT(NBTTagCompound nbt) {
        ManaStorage.INSTANCE.readNBT(ManaProvider.MANA_CAPABILITY, new Mana(), null, nbt);
    }
}
ManaStorage:
package com.example.examplemod.capabilities;

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 javax.annotation.Nullable;

public class ManaStorage implements IStorage<IMana> {

    public static final ManaStorage INSTANCE = new ManaStorage();

    @Nullable
    @Override
    public NBTBase writeNBT(Capability<IMana> capability, IMana instance, EnumFacing side) {
        NBTTagCompound nbt = new NBTTagCompound();
        nbt.setInteger("maxMana",instance.getMana());
        return null;
    }

    @Override
    public void readNBT(Capability<IMana> capability, IMana instance, EnumFacing side, NBTBase nbt) {
        NBTTagCompound tag = (NBTTagCompound) nbt;
        instance.setMana(tag.getInteger("maxMana"));
    }
}
Handler:
package com.example.examplemod.util.handlers;

import com.example.examplemod.capabilities.ManaProvider;
import com.example.examplemod.util.Reference;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.event.AttachCapabilitiesEvent;

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

import java.util.Locale;


@Mod.EventBusSubscriber
public class Handler {


    @SubscribeEvent
    public static void attachEntity(AttachCapabilitiesEvent<Entity> event) {
        if (event.getObject() instanceof EntityPlayer) {
            ManaProvider manaCap = new ManaProvider();

            event.addCapability(new ResourceLocation(Reference.MODID, "mana_capability"), manaCap);

        }
    }

}
 
Решение
Зачем ты serializeNBT и deserializeNBT делаешь в непонятном instance? Ты должен получить instance через MANA_CAPABILITY. И в нем получить storage, в котором читать и писать nbt.

Нужно изменить

return (NBTTagCompound) ManaStorage.INSTANCE.writeNBT(ManaProvider.MANA_CAPABILITY, new Mana(), null);
на это
return (NBTTagCompound) MANA_CAPABILITY.getStorage().writeNBT(MANA_CAPABILITY, this.instance, null);,

ManaStorage.INSTANCE.readNBT(ManaProvider.MANA_CAPABILITY, new Mana(), null, nbt);
на это
MANA_CAPABILITY.getStorage().readNBT(MANA_CAPABILITY, this.instance,null, nbt);

Добавить это
private final IMana instance = MANA_CAPABILITY.getDefaultInstance();

В getCapability возвращай (T)...
7,099
324
1,510
EnumFacing должен быть определенным(даже если он не важен для твоей задачи)
Поэтому выбери каку-нить сторону и фильтруй все действия в провайдере и сторежэ по выбранной стороне
 
16
1
0
Сделал как ты и сказал. Поставил EnumFacing.NORTH и проверки на side. Все равно не сохраняет. Вот код:

ManaStorage:
package com.example.examplemod.capabilities;

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 ManaStorage implements IStorage<IMana> {

    public static final ManaStorage INSTANCE = new ManaStorage();


    @Override
    public NBTBase writeNBT(Capability<IMana> capability, IMana instance, EnumFacing side) {
        if (side != EnumFacing.NORTH) {return null;}
        NBTTagCompound nbt = new NBTTagCompound();
        nbt.setInteger("Mana", instance.getMana());
        return nbt;
    }


    @Override
    public void readNBT(Capability<IMana> capability, IMana instance, EnumFacing side, NBTBase nbt) {
        if (side != EnumFacing.NORTH) {
            NBTTagCompound tag = (NBTTagCompound) nbt;
            instance.setMana(tag.getInteger("Mana"));
        }
    }
}
ManaProvider:
package com.example.examplemod.capabilities;

import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityInject;
import net.minecraftforge.common.capabilities.ICapabilitySerializable;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

public class ManaProvider implements ICapabilitySerializable<NBTTagCompound> {


    @CapabilityInject(IMana.class)
    public static final Capability<IMana> MANA_CAPABILITY = null;
    private final IMana capability = new Mana();

    @Override
    public boolean hasCapability(@Nonnull Capability<?> capability, @Nullable EnumFacing facing) {
        return (capability == MANA_CAPABILITY)  && (facing == EnumFacing.NORTH);
    }

    @Nullable
    @Override
    @SuppressWarnings("unchecked")
    public <T> T getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing) {
        if ((MANA_CAPABILITY != null) && (capability == MANA_CAPABILITY) && (facing == EnumFacing.NORTH)) return (T) this.capability;
        return null;
    }

    @Override
    public NBTTagCompound serializeNBT() {
        return (NBTTagCompound) ManaStorage.INSTANCE.writeNBT(ManaProvider.MANA_CAPABILITY, new Mana(), EnumFacing.NORTH);
    }

    @Override
    public void deserializeNBT(NBTTagCompound nbt) {
        ManaStorage.INSTANCE.readNBT(ManaProvider.MANA_CAPABILITY, new Mana(), EnumFacing.NORTH, nbt);
    }
}
Java:
 public EnumActionResult onItemUse(EntityPlayer player, World worldIn, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) {
        assert false;
        System.out.println(player.getCapability(ManaProvider.MANA_CAPABILITY, EnumFacing.NORTH).getMana());
        player.getCapability(ManaProvider.MANA_CAPABILITY, EnumFacing.NORTH).setMana(player.getCapability(ManaProvider.MANA_CAPABILITY, EnumFacing.NORTH).getMana() + 1);
        return super.onItemUse(player, worldIn, pos, hand, facing, hitX, hitY, hitZ);
    }
 
7,099
324
1,510
if (side != EnumFacing.NORTH) {
Тут ошибка. Почему для всех ,кроме выбранной стороны? Нужно наоборот
if (side != EnumFacing.NORTH) {return null;}
Нужно возвращать не null, а пустой тэг
Оно никогда не может быть null, потому что forge вставляет нужное значение в поле
 
16
1
0
Исправил, но все равно не работает. Не сохраняет когда выходишь из мира. Вот код:

ManaStorage:
package com.example.examplemod.capabilities;

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 ManaStorage implements IStorage<IMana> {

    public static final ManaStorage INSTANCE = new ManaStorage();


    @Override
    public NBTBase writeNBT(Capability<IMana> capability, IMana instance, EnumFacing side) {
        NBTTagCompound nbt = new NBTTagCompound();
        if (side != EnumFacing.NORTH) {return nbt;}
        nbt.setInteger("Mana", instance.getMana());
        return nbt;
    }


    @Override
    public void readNBT(Capability<IMana> capability, IMana instance, EnumFacing side, NBTBase nbt) {
        if (side == EnumFacing.NORTH) {
            NBTTagCompound tag = (NBTTagCompound) nbt;
            instance.setMana(tag.getInteger("Mana"));
        }
    }
}
ManaProvider:
package com.example.examplemod.capabilities;

import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityInject;
import net.minecraftforge.common.capabilities.ICapabilitySerializable;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

public class ManaProvider implements ICapabilitySerializable<NBTTagCompound> {


    @CapabilityInject(IMana.class)
    public static final Capability<IMana> MANA_CAPABILITY = null;
    private final IMana capability = new Mana();

    @Override
    public boolean hasCapability(@Nonnull Capability<?> capability, @Nullable EnumFacing facing) {
        return (capability == MANA_CAPABILITY)  && (facing == EnumFacing.NORTH);
    }

    @Nullable
    @Override
    @SuppressWarnings("unchecked")
    public <T> T getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing) {
        if ((capability == MANA_CAPABILITY) && (facing == EnumFacing.NORTH)) return (T) this.capability;
        return null;
    }

    @Override
    public NBTTagCompound serializeNBT() {
        return (NBTTagCompound) ManaStorage.INSTANCE.writeNBT(ManaProvider.MANA_CAPABILITY, new Mana(), EnumFacing.NORTH);
    }

    @Override
    public void deserializeNBT(NBTTagCompound nbt) {
        ManaStorage.INSTANCE.readNBT(ManaProvider.MANA_CAPABILITY, new Mana(), EnumFacing.NORTH, nbt);
    }
}
 
7,099
324
1,510
Очень странно. Покажи регистрацию капы, чтоли.

У мя тут есть работающая реализация "маны" в игроке
Если очистить от всего предметно-ориентированного, то код точно такой же
Хотя там еще в сторажэ нету проверки сторон(а вообще-то должна быть, или я че-то забыл)
~~~
Посмотрел в том же моде капу чанка, которая тоже сохраняемая, там тоже нет проверк в сторажэ. Возможно, она там не нужна, попробуй убрать из ManaStorage строчки
if (side != EnumFacing.NORTH) {return nbt;}
и
if (side == EnumFacing.NORTH)
 
16
1
0
Не работает. Вот весь код:

ManaProvider:
package com.example.examplemod.capabilities;

import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityInject;
import net.minecraftforge.common.capabilities.ICapabilitySerializable;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

public class ManaProvider implements ICapabilitySerializable<NBTTagCompound> {


    @CapabilityInject(IMana.class)
    public static final Capability<IMana> MANA_CAPABILITY = null;
    private final IMana capability = new Mana();

    @Override
    public boolean hasCapability(@Nonnull Capability<?> capability, @Nullable EnumFacing facing) {
        return (capability == MANA_CAPABILITY)  && (facing == EnumFacing.NORTH);
    }

    @Nullable
    @Override
    @SuppressWarnings("unchecked")
    public <T> T getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing) {
        if ((capability == MANA_CAPABILITY) && (facing == EnumFacing.NORTH)) return (T) this.capability;
        return null;
    }

    @Override
    public NBTTagCompound serializeNBT() {
        return (NBTTagCompound) ManaStorage.INSTANCE.writeNBT(ManaProvider.MANA_CAPABILITY, new Mana(), EnumFacing.NORTH);
    }

    @Override
    public void deserializeNBT(NBTTagCompound nbt) {
        ManaStorage.INSTANCE.readNBT(ManaProvider.MANA_CAPABILITY, new Mana(), EnumFacing.NORTH, nbt);
    }
}
ManaStorage:
package com.example.examplemod.capabilities;

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 ManaStorage implements IStorage<IMana> {

    public static final ManaStorage INSTANCE = new ManaStorage();


    @Override
    public NBTBase writeNBT(Capability<IMana> capability, IMana instance, EnumFacing side) {
        NBTTagCompound nbt = new NBTTagCompound();
        nbt.setInteger("Mana", instance.getMana());
        return nbt;
    }


    @Override
    public void readNBT(Capability<IMana> capability, IMana instance, EnumFacing side, NBTBase nbt) {
        NBTTagCompound tag = (NBTTagCompound) nbt;
        instance.setMana(tag.getInteger("Mana"));
    }
}
CapaItem:
package com.example.examplemod.object.item;

import com.example.examplemod.capabilities.ManaProvider;
import com.example.examplemod.init.ItemInit;
import com.example.examplemod.proxy.ClientProxy;
import com.example.examplemod.util.IHasModel;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;

public class CapaItem extends Item implements IHasModel {


    public CapaItem() {
//        setUnlocalizedName("CapaItem");
        setRegistryName("CapaItem");
        setCreativeTab(CreativeTabs.FOOD);
        ItemInit.ITEMS.add(this);
    }

    @Override
    public void registryItemRender() {
        ClientProxy.registryItemRender(this,0,"inventory");
    }


    @Override
    public EnumActionResult onItemUse(EntityPlayer player, World worldIn, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) {
        assert false;
        System.out.println(player.getCapability(ManaProvider.MANA_CAPABILITY, EnumFacing.NORTH).getMana());
        player.getCapability(ManaProvider.MANA_CAPABILITY, EnumFacing.NORTH).setMana(player.getCapability(ManaProvider.MANA_CAPABILITY, EnumFacing.NORTH).getMana() + 1);
        return super.onItemUse(player, worldIn, pos, hand, facing, hitX, hitY, hitZ);
    }
}
ServerProxy:
package com.example.examplemod.proxy;


import com.example.examplemod.capabilities.IMana;
import com.example.examplemod.capabilities.Mana;
import com.example.examplemod.capabilities.ManaStorage;
import net.minecraftforge.common.capabilities.CapabilityManager;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;

public class ServerProxy {

    public void preInit(FMLPreInitializationEvent event) {

        CapabilityManager.INSTANCE.register(IMana.class, new ManaStorage(), Mana::new);
    }


}
ExampleMod:
package com.example.examplemod;


import com.example.examplemod.proxy.ServerProxy;
import com.example.examplemod.util.Reference;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.SidedProxy;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;

@Mod(modid = Reference.MODID, name = Reference.NAME, version = Reference.VERSION)
public class ExampleMod {

    @SidedProxy(clientSide = Reference.CLIENT, serverSide = Reference.SERVER)
    public static ServerProxy proxy;

    @EventHandler
    public void preInit(FMLPreInitializationEvent event) {
        proxy.preInit(event);
    }

    @EventHandler
    public void Init(FMLInitializationEvent event) {
    }

    @EventHandler
    public void postInit(FMLPostInitializationEvent event) {

    }
}
 
7,099
324
1,510
Залей весь воркспейс на гитхаб, поковыряю на досуге у себя локально
 
60
3
5
Зачем ты serializeNBT и deserializeNBT делаешь в непонятном instance? Ты должен получить instance через MANA_CAPABILITY. И в нем получить storage, в котором читать и писать nbt.

Нужно изменить

return (NBTTagCompound) ManaStorage.INSTANCE.writeNBT(ManaProvider.MANA_CAPABILITY, new Mana(), null);
на это
return (NBTTagCompound) MANA_CAPABILITY.getStorage().writeNBT(MANA_CAPABILITY, this.instance, null);,

ManaStorage.INSTANCE.readNBT(ManaProvider.MANA_CAPABILITY, new Mana(), null, nbt);
на это
MANA_CAPABILITY.getStorage().readNBT(MANA_CAPABILITY, this.instance,null, nbt);

Добавить это
private final IMana instance = MANA_CAPABILITY.getDefaultInstance();

В getCapability возвращай (T) this.instance

А ещё для красоты измени
public static final Capability<IMana> MANA_CAPABILITY = null;
на это
public static Capability<IMana> MANA_CAPABILITY;
Forge сам подставит нужный данные.
 
16
1
0
Ееее сработало. Спасибо тебе. Спасибо и тебе hohserg1. Все получилось. Вот код:
ManaProvider:
package com.example.examplemod.capabilities;

import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityInject;
import net.minecraftforge.common.capabilities.ICapabilitySerializable;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

public class ManaProvider implements ICapabilitySerializable<NBTTagCompound> {


    @CapabilityInject(IMana.class)
    public static Capability<IMana> MANA_CAPABILITY;
    private final IMana instance = MANA_CAPABILITY.getDefaultInstance();

    @Override
    public boolean hasCapability(@Nonnull Capability<?> capability, @Nullable EnumFacing facing) {
        return capability == MANA_CAPABILITY;
    }

    @Nullable
    @Override
    @SuppressWarnings("unchecked")
    public <T> T getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing) {
        if (capability == MANA_CAPABILITY) return  (T) this.instance;
        return null;
    }

    @Override
    public NBTTagCompound serializeNBT() {
        return (NBTTagCompound) MANA_CAPABILITY.getStorage().writeNBT(MANA_CAPABILITY, this.instance, null);
    }

    @Override
    public void deserializeNBT(NBTTagCompound nbt) {
       MANA_CAPABILITY.getStorage().readNBT(MANA_CAPABILITY, this.instance,null, nbt);
    }
}
ManaStorage:
package com.example.examplemod.capabilities;

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 ManaStorage implements IStorage<IMana> {


    @Override
    public NBTBase writeNBT(Capability<IMana> capability, IMana instance, EnumFacing side) {
        NBTTagCompound nbt = new NBTTagCompound();
        nbt.setInteger("Mana", instance.getMana());
        return nbt;
    }


    @Override
    public void readNBT(Capability<IMana> capability, IMana instance, EnumFacing side, NBTBase nbt) {
        NBTTagCompound tag = (NBTTagCompound) nbt;
        instance.setMana(tag.getInteger("Mana"));
    }
}
 
Сверху