Версия(и) Minecraft
1.14+
Хочу поделиться своим вариантом создания предмета с инвентарём.
Этот вариант создания таких предметов я не видел ещё нигде, по крайней мере, не нашёл на просторах GitHub. Этот вариант использует напрямую IItemHandler, вместо создания нового экземляра IInventory.

ВНИМАНИЕ!
Не спешить добавлять этот код в свой проект, так как в этом коде нету необходимых проверок для исправления некоторых багов и недоработок.

BackpackItem.class:
public class BackpackItem extends Item {
    public BackpackItem(Properties properties) {
        super(properties);
    }

    @Nonnull
    @Override
    public ActionResult<ItemStack> onItemRightClick(@Nonnull World world, @Nonnull PlayerEntity player, @Nonnull Hand hand) {
        ItemStack heldStack = player.getHeldItem(hand);

        if (!world.isRemote) {
            heldStack.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
                    .ifPresent(itemHandler -> {
                        player.openContainer(new SimpleNamedContainerProvider(
                                (id, playerInv, pl) -> new BackpackContainer(id, playerInv, itemHandler),
                                heldStack.getDisplayName()));
                    });
        }

        return ActionResult.resultSuccess(heldStack);
    }

    @Nullable
    @Override
    public ICapabilityProvider initCapabilities(ItemStack stack, @Nullable CompoundNBT nbt) {
        return new BackpackCapability(stack);
    }
}
BackpackCapability.java:
public class BackpackCapability extends ItemStackHandler implements ICapabilityProvider {
    private final LazyOptional<ItemStackHandler> holder = LazyOptional.of(() -> this);
    private final ItemStack stack;

    public BackpackCapability(ItemStack stack) {
        super(27); // размер инвентаря
        this.stack = stack;

        CompoundNBT nbt = stack.getTag();
        if (nbt != null) {
            deserializeNBT(nbt);
        }
    }

    @Override
    protected void onContentsChanged(int slot) {
        CompoundNBT itemsNbt = serializeNBT();
        stack.getOrCreateTag().put("Items", itemsNbt.getList("Items", Constants.NBT.TAG_COMPOUND));
    }

    @Override
    public CompoundNBT serializeNBT() {
        CompoundNBT nbt = new CompoundNBT();
        ItemStackHelper.saveAllItems(nbt, stacks);
        return nbt;
    }

    @Override
    public void deserializeNBT(CompoundNBT nbt) {
        ItemStackHelper.loadAllItems(nbt, stacks);
        onLoad();
    }

    @Nonnull
    @Override
    public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
        return CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.orEmpty(cap, holder.cast());
    }
}
BackpackContainer.java:
public class BackpackContainer extends Container {

    public BackpackContainer(int id, PlayerInventory playerInv, ISlotCreate slotSupplier) {
        super(MyMod.BACKPACK_CONT.get(), id);

        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 9; j++) {
                addSlot(slotSupplier.createSlot(j + i * 9, 8 + j * 18, 18 + i * 18));
            }
        }

        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 9; j++) {
                addSlot(new Slot(playerInv, j + i * 9 + 9, 8 + j * 18, 103 + i * 18 - 18));
            }
        }

        for(int i = 0; i < 9; i++) {
            addSlot(new Slot(playerInv, i, 8 + i * 18, 161 - 18));
        }
    }

    public BackpackContainer(int id, PlayerInventory playerInv, IItemHandler itemHandler) {
        this(id, playerInv, (index, x, y) -> new SlotItemHandler(itemHandler, index, x, y));
    }

    public static BackpackContainer createClientContainer(int id, PlayerInventory playerInv) {
        Inventory inv = new Inventory(27); // размер инвентаря
        return new BackpackContainer(id, playerInv, (index, x, y) -> new Slot(inv, index, x, y));
    }

    @Override
    public boolean canInteractWith(@Nonnull PlayerEntity player) {
        return true;
    }

    public interface ISlotCreate {
        Slot createSlot(int index, int x, int y);
    }
}
BackpackScreen.java:
@OnlyIn(Dist.CLIENT)
public class BackpackScreen extends ContainerScreen<BackpackContainer> {
    private static final ResourceLocation CHEST_GUI_TEXTURE = new ResourceLocation("textures/gui/container/generic_54.png");

    public BackpackScreen(BackpackContainer container, PlayerInventory inv, ITextComponent title) {
        super(container, inv, title);
        ySize = 168;
        playerInventoryTitleY = this.ySize - 94;
    }

    @Override
    public void render(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
        renderBackground(ms);
        super.render(ms, mouseX, mouseY, partialTicks);
        renderHoveredTooltip(ms, mouseX, mouseY);
    }

    @Override
    protected void drawGuiContainerBackgroundLayer(@Nonnull MatrixStack ms, float partialTicks, int x, int y) {
        RenderSystem.color4f(1F, 1F, 1F, 1F);
        getMinecraft().getTextureManager().bindTexture(CHEST_GUI_TEXTURE);
        int i = (width - xSize) / 2;
        int j = (height - ySize) / 2;
        blit(ms, i, j, 0, 0, xSize, 3 * 18 + 17);
        blit(ms, i, j + 3 * 18 + 17, 0, 126, xSize, 96);
    }
}
Где-то в главном классе:
private static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, MODID);
private static final DeferredRegister<ContainerType<?>> CONTAINERS = DeferredRegister.create(ForgeRegistries.CONTAINERS, MODID);

public static final RegistryObject<Item> BACKPACK = regItem("backpack", () -> new BackpackItem(new Item.Properties().maxStackSize(1)));

public static final RegistryObject<ContainerType<BackpackContainer>> BACKPACK_CONT = regCont("backpack", BackpackContainer::createClientContainer);

@OnlyIn(Dist.CLIENT)
public static void onClientSetup(FMLClientSetupEvent event) {
    ScreenManager.registerFactory(BACKPACK_CONT.get(), BackpackScreen::new);
}

private static RegistryObject<Item> regItem(String id, Supplier<Item> item) {
    return ITEMS.register(id, item);
}

private static <T extends Container> RegistryObject<ContainerType<T>> regCont(String id, ContainerType.IFactory<T> factory) {
    return CONTAINERS.register(id, () -> new ContainerType<>(factory));
}
Автор
MaximPixel
Просмотры
1,452
Первый выпуск
Обновление
Оценка
4.00 звёзд 1 оценок

Другие ресурсы пользователя MaximPixel

Сверху