Изменение кол-ва предметов в слотах

Версия Minecraft
1.12.2

will0376

Токсичная личность
2,075
55
584
Драсте. Пишу мод, который будет обменивать "деньги" на предметы. всё вроде бы готово, да вот затупил над тем, как буду удалять предметы из слотов...
К примеру имеем данную картину: 1561989277481.png
а продаю 2 шт...
вот как-бы правильно удалить?
(голова гудит уже ;\)
 

will0376

Токсичная личность
2,075
55
584
какое-то количество определенного предмета?
1)из инвентаря тайлэнтити.
2)кол-во задаётся вручную, от 1 до 64 :D
Удаляй один из первого, второй из второго
3)удалить сначала из 1 потом из 2ого не выйдет. может выйти так,что и в первом не хватает, и во втором не хватает и т.п.
апд:
я уже попытался реализовать... но чёт не так(изменяются все слоты XD)
Java:
HashMap collect = new HashMap<Integer, Integer>();
            for(int i =0;i<tte.SIZE;i++){
                if(tte.itemStackHandler.getStackInSlot(i).isEmpty()){
                    continue;
                }
                if(tte.itemStackHandler.getStackInSlot(i).getCount() <= Integer.valueOf(tte.Count) && i == 0){
                    continue;
                }
                if(!collect.isEmpty()){
                    int all = collect(collect);
                    if(tte.itemStackHandler.getStackInSlot(i).getCount() < Integer.valueOf(tte.Count)-all) {
                        collect.put(i,tte.itemStackHandler.getStackInSlot(i).getCount());
                    }
                    else{
                        ArrayList<Integer> keys = new ArrayList<Integer>(collect.keySet());
                        for(int tmp : keys)
                            tte.itemStackHandler.setStackInSlot(tmp,ItemStack.EMPTY);
                        break;
                    }
                }
                if(tte.itemStackHandler.getStackInSlot(i).getCount() < Integer.valueOf(tte.Count)){
                    collect.put(i,tte.itemStackHandler.getStackInSlot(i).getCount());
                    continue;
                }
                else
                    tte.itemStackHandler.getStackInSlot(i).setCount(tte.itemStackHandler.getStackInSlot(i).getCount()-Integer.valueOf(tte.Count));
            }

//            if(!collect.isEmpty())
            ItemHandlerHelper.giveItemToPlayer(player,new ItemStack(tte.itemStackHandler.getStackInSlot(0).getItem(),Integer.valueOf(tte.Count),tte.itemStackHandler.getStackInSlot(0).getMetadata()));
При этом по задумке я не хотел бы изменений в 0 слоту...
 

tox1cozZ

aka Agravaine
8,455
598
2,892
При этом по задумке я не хотел бы изменений в 0 слоту...
Тогда совсем просто: пробегаешься по всему инвентарю циклом, сравниваешь stackInSlot.stackSize >= нужное_количество, сохраняешь этот стак в переменную и выходишь из цикла с помощью break.
Потом делаешь savedStack.stackSize -= нужное_количество.
 
7,099
324
1,510
А если юзер сделает так, а другой захочет купить 9?
1561993823386.png
Решение, которое я придумал:
Проходим по все слотам, отображаем их в размеры стаков, после применяем эту функцию:
Scala:
def consume(list: List[Int], requiredSize: Int): Stream[(Int, Int)] = {
  if(list.nonEmpty) {
    val consumed = min(requiredSize, list.head)
    (requiredSize,consumed) #:: consume(list.tail, requiredSize - consumed)
  }else
    Stream.empty
}
Ограничиваем
takeWhule(_._1 > 0)
Отображаем, сохраняя только значения, сколько забрать из каждого слота
map(_._2)

И получаем последовательность ,в которой указано, сколько нужно вычесть предметов из каждого слота
Если сумма элементов последовательности меньше, чем requiredSize, то в инвентаре недостаточно предметов для покупки

Решение хорошо тем, что учитывает пустые слоты в середине и не выполняет итераций больше, чем требуется
 

will0376

Токсичная личность
2,075
55
584
а другой захочет купить 9?
этот контейнер только для владельца) а так пользователи могут нажать на только 1 кнопку "купить 4шт за 10$"(к примеру)
а вообще, я что-то придумал с листом.. но не могу вспомнить. надо отдохнуть немного :D
апд:
пустые я пропускаю
if(tte.itemStackHandler.getStackInSlot(i).isEmpty()){
continue;
}
 
7,099
324
1,510
этот контейнер только для владельца) а так пользователи могут нажать на только 1 кнопку "купить 4шт за 10$"(к примеру)
Это утверждение абсолютно о другом.

Я имел ввиду, что поиск стака, размер которого больше запрошенного кол-ва не покрывает все юзкейсы
 
7,099
324
1,510
А вообще, есть такая штука, почему бы ее в сборку не поставить? Если мани свои, то можно форкнуть и добавить функционал, или посмотреть как там происходит работа с инвентарем и перенести в свой мод
 

will0376

Токсичная личность
2,075
55
584
Кажется,смог решить
Java:
    ArrayList<Integer> list = new ArrayList<>();
    public BuyItem(EntityPlayer player, TestContainerTileEntity tte){
        try{
            if(!tte.infinity) {
                for (int i = 1; i < tte.SIZE; i++) {
                    int Count = Integer.valueOf(tte.Count);
                    ItemStack is = tte.itemStackHandler.getStackInSlot(i);
                    if (tte.itemStackHandler.getStackInSlot(i).isEmpty()) {
                        continue;
                    }
                    int k = is.getCount() + combineAL();
                    if (!list.isEmpty() && (k > Count)) {
                        int e = Count;
                        for (int tmp : list) {
                            int slot = getSlotFromCount(tmp, tte);
                            e -= tmp;
                            tte.itemStackHandler.getStackInSlot(slot).setCount(0);
                        }
                        is.setCount(is.getCount() - e);
                        break;
                    }
                    if (is.getCount() >= Count) {
                        is.setCount(is.getCount() - Count);
                        break;
                    }
                    if (is.getCount() < Count) {
                        list.add(is.getCount());
                        continue;
                    }

                }
            }
            ItemHandlerHelper.giveItemToPlayer(player,new ItemStack(tte.itemStackHandler.getStackInSlot(0).getItem(),Integer.valueOf(tte.Count),tte.itemStackHandler.getStackInSlot(0).getMetadata()));
        }catch (Exception e){e.printStackTrace();}
    }
    private int getSlotFromCount(int count, TestContainerTileEntity tte){
        for(int i = 1;i < tte.SIZE;i++)
            if(tte.itemStackHandler.getStackInSlot(i).getCount() == count)
                return i;
            return -999;
    }
    private int combineAL(){
        int tmp = 0;
        for(int i : list)
            tmp+=i;
        return tmp;
    }
 
1,195
31
183
куча лишнего кода, как и отметил выше hohserg1.
я сделал такую же систему, только с кастом нпс: можно покупать и продавать вещи у торговца за деньги, которые сохраняются в IEEP
и кода там намного меньше (не учитывая уже написанный ноппесом), это не особо сложно)
 
Сверху