Container

1,683
2
Как сохранять предметы в контейнере при закрытии и показывать при открытии?
 
Если у тебя обычный контейнер, подобный сундуку или чему-либо, то в Инвентаре/Тайле есть методы writeToNBT и readFromNBT.

Мне, например, нужно было сохранять содержимое контейнера для предмета. Тогда просто скопировать этот метод, но записывать это все в НБТ Предмета.

Еще можно получать НБТ игрока и записывать туда.
 
Делал рюкзак - использовал IExtendedEntityProperties. Там хранил массив итемстаков. Больше ничего. Ну и там была запись и загрузка с НБТ, конечно.
Была одна проблема - в креативе при добавлении новых слотов в инвентарь игрока ломалась функция Pick Block - которая выбирает блок при щелчке средней кнопки мыши. Всё благодаря встроенной кривой формуле подсчёта выбранного слота. В итоге клиент неправильно посылал слот серверу и тот передавал ему предмет вообще в рюкзак, лол. А на клиенте все было как надо - в итоге был десинхрон и всякие баги, вроде того, что блоки ставились только на клиенте, а при обновлении пропадали из мира.
Решил уберкостыльным путём.
 
Я сделал  IInventory и добавил слоты с этим IInv... При открытии я прочитал из нбт,а при закрытии записал.Но не работмет
[merge_posts_bbcode]Добавлено: 04.01.2015 15:16:44[/merge_posts_bbcode]

Решил уберкостыльным путём.
Можно посмотреть на решение
 
Dovakin написал(а):
Я сделал  IInventory и добавил слоты с этим IInv... При открытии я прочитал из нбт,а при закрытии записал.Но не работмет
[merge_posts_bbcode]Добавлено: 04.01.2015 15:16:44[/merge_posts_bbcode]

Решил уберкостыльным путём.
Можно посмотреть на решение

Скидывай сюда контейнер и твой АйИнвентори
 
Код:
package craftz.backpack;

import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;

/**
 * Created by User1 on 12.12.2014.
 */
public class ContainerSmallBackpack extends Container{
    private SmallBackpackInventory sbi=new SmallBackpackInventory();
    public ContainerSmallBackpack(EntityPlayer player){
        for(int i = 0; i < 9; i++) {
            addSlotToContainer(new Slot(player.inventory, i, 31 + i * 18, 105));
        }
        for(int i = 0; i < 3; i++) {
            for (int j = 0; j < 9; j++) {
                addSlotToContainer(new Slot(player.inventory, j + i * 9 + 9, 31 + j * 18, 47 + i * 18));
            }
        }
        for (int i = 0; i < 5; i++) {
            addSlotToContainer(new Slot(sbi,i, 67 +i*18,23));
        }
        sbi.openInventory();
    }
    @Override
    public boolean canInteractWith(EntityPlayer p_75145_1_) {
        return true;
    }

    @Override
    public ItemStack transferStackInSlot(EntityPlayer p_82846_1_, int p_82846_2_) {
        return null;
    }

    @Override
    public void onContainerClosed(EntityPlayer p_75134_1_) {
        sbi.closeInventory();
        super.onContainerClosed(p_75134_1_);
    }
}


Код:
package craftz.backpack;

import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;

/**
 * Created by User1 on 03.01.2015.
 */
public class SmallBackpackInventory implements IInventory{
    private ItemStack[] slots = new ItemStack[5];
    @Override
    public int getSizeInventory() {
        return slots.length;
    }

    @Override
    public ItemStack getStackInSlot(int p_70301_1_) {
        return slots[p_70301_1_];
    }

    @Override
    public ItemStack decrStackSize(int slot, int par2) {
        if (slots[slot] != null) {
            ItemStack itemStack;
            if (slots[slot].stackSize <= par2) {
                itemStack = slots[slot];
                slots[slot] = null;
                return itemStack;
            }else {
                itemStack = slots[slot].splitStack(par2);

                if (slots[slot].stackSize == 0) {
                    slots[slot] = null;
                }

                return itemStack;
            }
        }else {
            return null;
        }
    }

    @Override
    public ItemStack getStackInSlotOnClosing(int slot) {
        if (slots[slot] != null) {
            ItemStack itemStack = slots[slot];
            slots[slot] = null;
            return itemStack;
        }
        else {
            return null;
        }
    }

    @Override
    public void setInventorySlotContents(int slot, ItemStack itemStack) {
        slots[slot] = itemStack;
        if (itemStack != null && itemStack.stackSize > getInventoryStackLimit()) {
            itemStack.stackSize = getInventoryStackLimit();
        }
    }

    @Override
    public String getInventoryName() {
        return "backpack:small";
    }

    @Override
    public boolean hasCustomInventoryName() {
        return false;
    }

    @Override
    public int getInventoryStackLimit() {
        return 64;
    }

    @Override
    public void markDirty() {

    }

    @Override
    public boolean isUseableByPlayer(EntityPlayer p_70300_1_) {
        return false;
    }

    @Override
    public void openInventory() {
        NBTTagCompound nbt=new NBTTagCompound();
        NBTTagList tagList=nbt.getTagList("Items",5);
        slots=new ItemStack[getSizeInventory()];
        for(int k=0;k<tagList.tagCount();k++){
            NBTTagCompound nbt1=tagList.getCompoundTagAt(k);
            byte b=nbt1.getByte("Slot");
            if(b>=0 && b<slots.length){
                slots[b]=ItemStack.loadItemStackFromNBT(nbt);
            }
        }
    }

    @Override
    public void closeInventory() {
        NBTTagList list=new NBTTagList();
        for(int i=0;i<slots.length;i++){
            if(slots[i]!=null){
                NBTTagCompound nbt1=new NBTTagCompound();
                nbt1.setByte("Slot",(byte)i);
                slots[i].writeToNBT(nbt1);
                list.appendTag(nbt1);
            }
        }
    }

    @Override
    public boolean isItemValidForSlot(int p_94041_1_, ItemStack p_94041_2_) {
        return true;
    }
}
 
А теперь поясни нахуа ты записываешь данные в НБТ который живёт пока выполняется код функции сохранения? А ещё ты даже НБТ-лист никуда не сохраняешь.
 
Ну... Во Первых каждый раз, когда ты открываешь контейнер, ты создаешь новый инвентарь.
Лично я регал инвентарь в IExtendedPlayerProperties и удобненько так оттуда доставал. Сделай и ты так.

Во вторых... Ты гениально сохраняешь и достаешь НБТ. Сохраняешь в непонятный Компоунд, считываешь из НОВОГО ПУСТОГО листа. В Инвентаре нельзя записывать НБТ, ибо там этих методов нет, они есть только в Тайле.

За то такие методы есть в IExtendedPlayerProperties. Там два удобненьких метода:

Код:
public void saveNBTData(NBTTagCompound compound) 
{
}

Код:
public void loadNBTData(NBTTagCompound compound) 
{
}

Собсна. Регай IExtendedPlayerProp*, и делай все уже в нем.

И еще вопрос к Oldestkon-у.
У меня такая туфта, скажем, я в креатив моде и у меня в инвентаре куча предметов. Я хочу очистить, нажимаю кнопку очистки - они пропадают. Но.. если перед этим я открою свой инвентарь, то потом, при нажатии на кнопку очистки, ничего не произойдет. А предметы пропадут лишь тогда, когда я закрою инвентарь. :/
 
Я не знаю.Мне один человек код дал(он есть на форуме,не буду его имени называть)
[merge_posts_bbcode]Добавлено: 04.01.2015 16:26:44[/merge_posts_bbcode]

А как регистрировать IExtendedEntityProperty

[merge_posts_bbcode]Добавлено: 04.01.2015 16:27:09[/merge_posts_bbcode]

и как по человечески в нбт записать?
 
В ЭвентХандлере:

Код:
    @SubscribeEvent
    public void onEntityConstructing(EntityConstructing event)
    {
        if (event.entity instanceof EntityPlayer && PlayerExtended.get((EntityPlayer)event.entity) == null)
        {
            PlayerExtended.register((EntityPlayer)event.entity);
        }
    }

Вот мой игрок:

Код:
public class PlayerExtended implements IExtendedEntityProperties
{
    public final EntityPlayer player;
    public final InventoryEx inventory = new InventoryEx(this.player);

    public PlayerExtended(EntityPlayer player)
    {
        this.player = player;
    }

    public static final void register(EntityPlayer player)
    {
        player.registerExtendedProperties("PlayerExtended123321", new PlayerExtended(player));
    }

    public static final PlayerExtended get(EntityPlayer player)
    {
        return (PlayerExtended)player.getExtendedProperties("PlayerExtended123321");
    }
    
    public void init(Entity entity, World world) {}
    
    /** 
     * TODO
     * Сохраняет предметы (Инвентарь).
     */
    public void saveNBTData(NBTTagCompound compound) 
    {
        NBTTagList nbttaglist = new NBTTagList();
        
        for(int i = 0; i < this.inventory.invslots.length; ++i)
        {
            if (this.inventory.invslots[i] != null)
            {
                NBTTagCompound nbttagcompound1 = new NBTTagCompound();
                nbttagcompound1.setByte("Slot", (byte)i);
                this.inventory.invslots[i].writeToNBT(nbttagcompound1);
                nbttaglist.appendTag(nbttagcompound1);
            }
        }
        
        compound.setTag("Items", nbttaglist);
    }

    /** 
     * TODO
     * Загружает предметы (Инвентарь).
     */
    public void loadNBTData(NBTTagCompound compound) 
    {
        NBTTagList nbttaglist = compound.getTagList("Items", 10);
           
        for (int i = 0; i <= nbttaglist.tagCount(); ++i)
        {
            NBTTagCompound nbttagcompound1 = (NBTTagCompound)nbttaglist.getCompoundTagAt(i);
            byte b0 = nbttagcompound1.getByte("Slot");

            if (b0 >= 0 && b0 < this.inventory.invslots.length) 
            {
                this.inventory.invslots[b0] = ItemStack.loadItemStackFromNBT(nbttagcompound1);
            }
        }
    }
}

Разбирай его как хочешь.
 
Нафиг final в методе?
[merge_posts_bbcode]Добавлено: 04.01.2015 16:54:52[/merge_posts_bbcode]

Всё равно не работает.Я записал IExtended... в IInventory

[merge_posts_bbcode]Добавлено: 04.01.2015 17:01:07[/merge_posts_bbcode]

И да,а если у меня много рюкзаков?
 
Nichie написал(а):
И еще вопрос к Oldestkon-у.
У меня такая туфта, скажем, я в креатив моде и у меня в инвентаре куча предметов. Я хочу очистить, нажимаю кнопку очистки - они пропадают. Но.. если перед этим я открою свой инвентарь, то потом, при нажатии на кнопку очистки, ничего не произойдет. А предметы пропадут лишь тогда, когда я закрою инвентарь. :/

Покопался в сурсах:
R2eZBK7.png

В общем ничего такого сильно костыльного не нашёл. Очищается инвентарь игрока как надо. Лукап для слота-корзины идёт по объекту слота и шифту, т.е. тут не косяк формулы подсчёта номера слота.

Я решал свою проблему так: когда у игрока меняелся режим игры, я узнавал на что он сменился, если на креатив - я убирал слоты рюкзака из инвентаря игрока (всё равно контент в IExtEntityProp хранится), когда сурвивал - возвращал слоты обратно. Но у меня была проблема в том, что ваниль считала слоты по формуле последний слот - 9, что-то вроде, и из-за этого всё смещалось на 19 моих слотов.
В чём у тебя проблема, сказать без класса контейнера не смогу. И с ним не факт.
 
А есть какие нибудь моды,с рюкзаками,чтобы я мог узнать как это делать(source)?
 
Forestry - там отдельные рюкзаки, TinkersConstruct - вещи рюкзака сохраняются в игроке. На GitHub так-же есть и другие моды с рюкзачного типа.
 
Ну вот я сделал.А надо куда-нибудь loadNBTData записать?Например при открытии контейнера
 
saveNBTData и loadNBTData, readFromNBT и writeToNBT - это всё методы, для их работы нужны специальные условия. Подобно как заставить работать свои методы, надо знать как, так как их может быть несколько способов.
У меня пока-что зарисоваеться: Типа в TickHandler'е нужно делать проверку, на то что окно закрыто или нет. При закрытии, открытии или каких-либо действий, выполнялись эти методы сохранения или загрузки данных. У меня пока-что не зарисоваеться работа с контейнером.
 
Нахуа? А markDirty зачем нужен, по-вашему?
Не надо всё пихать в тикхандлеры.
 
Oldestkon написал(а):
Nichie написал(а):
И еще вопрос к Oldestkon-у.
У меня такая туфта, скажем, я в креатив моде и у меня в инвентаре куча предметов. Я хочу очистить, нажимаю кнопку очистки - они пропадают. Но.. если перед этим я открою свой инвентарь, то потом, при нажатии на кнопку очистки, ничего не произойдет. А предметы пропадут лишь тогда, когда я закрою инвентарь. :/

Покопался в сурсах:
R2eZBK7.png

В общем ничего такого сильно костыльного не нашёл. Очищается инвентарь игрока как надо. Лукап для слота-корзины идёт по объекту слота и шифту, т.е. тут не косяк формулы подсчёта номера слота.

Я решал свою проблему так: когда у игрока меняелся режим игры, я узнавал на что он сменился, если на креатив - я убирал слоты рюкзака из инвентаря игрока (всё равно контент в IExtEntityProp хранится), когда сурвивал - возвращал слоты обратно. Но у меня была проблема в том, что ваниль считала слоты по формуле последний слот - 9, что-то вроде, и из-за этого всё смещалось на 19 моих слотов.
В чём у тебя проблема, сказать без класса контейнера не смогу. И с ним не факт.

Вот класс контейнера. Меня эта проблема не напрягает, но все-же было бы не плохо избавиться от неё.

Код:
public class ContainerPlayerEx extends Container 
{
   public final EntityPlayer thePlayer;
   public final InventoryEx inventoryEx;
   
   public SlotBackpack slotbp;
   public SlotBelt slotbe;
   
   public ContainerPlayerEx(EntityPlayer player, InventoryPlayer inventoryPlayer, InventoryEx inventoryEx) 
   {
       this.inventoryEx = inventoryEx;
       this.thePlayer = player;
       int i;
       int j;

       for (i = 0; i < 4; ++i)
       {
           this.addSlotToContainer(new SlotArmor(player, inventoryPlayer, inventoryPlayer.getSizeInventory() - 1 - i, 44, 8 + i * 18, i));
       }

       for (i = 0; i < 3; ++i)
       {
           for (j = 0; j < 9; ++j)
           {
               this.addSlotToContainer(new Slot(inventoryPlayer, j + (i + 1) * 9, 8 + j * 18, 84 + i * 18));
           }
       }
       for (i = 0; i < 9; ++i)
       {
           this.addSlotToContainer(new Slot(inventoryPlayer, i, 8 + i * 18, 142));
       }
       
       /** Главные слоты */
       this.addSlotToContainer(slotbp = new SlotBackpack(this, player, inventoryEx, 1, 116, 8));
       this.addSlotToContainer(slotbe = new SlotBelt(this, player, inventoryEx, 2, 116, 26));
       
       /** Остальные слоты */
       this.AddBackpackSlotsUtil(3, 3, 5);
       this.AddBeltSlotsUtil(18, 3, 3);
   }
   
      private void AddBackpackSlotsUtil(int start, int slots, int count)
      {
          int s = 0;
          
          for(int i = 0; i < count; ++i)
          {
              for(int j = 0; j < slots; ++j)
              {
                  addSlotToContainer(new SlotInBackpack(this, thePlayer, inventoryEx, start + s, 183 + 18 * j, 8 + 18 * i));
                  s++;
              }
          }
      }
      
      private void AddBeltSlotsUtil(int start, int slots, int count)
      {
          int s = 0;
          
          for(int i = 0; i < count; ++i)
          {
              for(int j = 0; j < slots; ++j)
              {
                  addSlotToContainer(new SlotInBelt(this, thePlayer, inventoryEx, start + s, 183 + 18 * j, 8 + 18 * i));
                  s++;
              }
          }
      }
   
       public void onContainerClosed(EntityPlayer par1EntityPlayer)
       {
           super.onContainerClosed(par1EntityPlayer);
       }
   
       public boolean canInteractWith(EntityPlayer player) 
       {
           return true;
       }
   
   /** TODO Настроить */
   public ItemStack transferStackInSlot(EntityPlayer par1EntityPlayer, int par2)
   {
       ItemStack itemstack = null;
       Slot slot = (Slot)this.inventorySlots.get(par2);

       if (slot != null && slot.getHasStack())
       {
           ItemStack itemstack1 = slot.getStack();
           itemstack = itemstack1.copy();

           if (par2 == 0)
           {
               if (!this.mergeItemStack(itemstack1, 4, 40, false))
               {
                   return null;
               }

               slot.onSlotChange(itemstack1, itemstack);
           }
           else if(itemstack1.getItem() instanceof ItemArmor && !((Slot)this.inventorySlots.get(((ItemArmor)itemstack.getItem()).armorType)).getHasStack()) 
           {
               int type = ((ItemArmor)itemstack1.getItem()).armorType;
               
               if(!this.mergeItemStack(itemstack1, type, type + 1, false)) 
               {
                  return null;
               }
           }
           //TODO 
           else if(itemstack1.getItem() instanceof ItemBackpack && !((Slot)this.inventorySlots.get(((ItemBackpack)itemstack.getItem()).bagTypeItem)).getHasStack())
           {
               if (!this.mergeItemStack(itemstack1, 40, 41, true))
               {
                   return null;
               }
           }
           else if (par2 >= 4 && par2 < 31)
           {
               if (!this.mergeItemStack(itemstack1, 31, 40, false))
               {
                   return null;
               }
           }
           else if (par2 >= 31 && par2 < 40)
           {
               if (!this.mergeItemStack(itemstack1, 4, 31, false))
               {
                   return null;
               }
           }
           else if (!this.mergeItemStack(itemstack1, 4, 40, false))
           {
               return null;
           }

           if (itemstack1.stackSize == 0)
           {
               slot.putStack((ItemStack)null);
           }
           else
           {
               slot.onSlotChanged();
           }

           if (itemstack1.stackSize == itemstack.stackSize)
           {
               return null;
           }

           slot.onPickupFromSlot(par1EntityPlayer, itemstack1);
       }

       return itemstack;
   }
}
 
Назад
Сверху