Перемещение предметов в инвентаре

Статус
В этой теме нельзя размещать новые ответы.
12
0
Написал тестовую функцию, цель - поместить в ячейку крафта семь предметов, таких же, какие лежат в первой ячейке инвентаря, после помещения, первую ячейку очистить. Визуально все работает, но когда мышкой пытаешься забрать из ячейки крафта предметы, то все возвращается в исходное положение. Примеры смотрел, где ошибаюсь - не понимаю.

проверяю все в 1.8.0

Вот код:
Код:
    public void restoreInventoryOne(boolean b)
    {
        EntityPlayerSP player = Minecraft.getMinecraft().thePlayer;
        if (player != null )
        {
            net.minecraft.inventory.Container container = player.openContainer;
            if (container != null)
                if (container.getClass().getName() == "net.minecraft.inventory.ContainerPlayer")
                {
                    ContainerPlayer conPlayer = (ContainerPlayer)container;
                    InventoryPlayer invPlayer = player.inventory;
                    InventoryCrafting invCraft = conPlayer.craftMatrix;

                    ItemStack playerStack = invPlayer.getStackInSlot(0);
                    Item item = playerStack.getItem();

                    invCraft.setInventorySlotContents(0, new ItemStack(item, 7));
                    invPlayer.setInventorySlotContents(0, null);
                }
        }
    }
 
AlexSocol написал(а):
 А откуда берется этот world. Я вижу его во всех примерах, но не могу понять откуда его брать?

У меня есть вот такой кусок, откуда вызывается предыдущая функция:
Код:
    @SubscribeEvent
    public void tickEvent(TickEvent.PlayerTickEvent event) throws IOException 
    {
        if (event.side == Side.CLIENT)
        {
            if (org.lwjgl.input.Keyboard.isKeyDown(kBindRestoreOne.getKeyCode()))
            {
                if (!kRestoreOneDown)
                {
                    restoreInventoryOne(true);
                }
                kRestoreOneDown = true;
            }
            else
            {
                kRestoreOneDown = false;
            }
        
        }
    }

Вот это "if (event.side == Side.CLIENT)" не аналог разве?
 
world.isRemote - проверка, отдалённый ли мир (если по-русски :D). Если да - то это клиент, если нет - сервер.
"if (!world.isRemote){}" проверяет, сервер ли это, и если да - делает то, что написано в if'е.
"А что тогда делать на сервере, а что - на клиенте?" - спросишь ты. Я отвечу, насколько знаю: "На сервере делать всё, с чем ты взаимодействуешь или что взаимодействует с тобой. Т.е. это спаун сущностей, установка блоков, накладывание эффектов и т.д. А вот текстуры, допустим - чисто клиентская вещь." Вот и вся хитрость =)
 
Agravaine написал(а):
Дружище, ты всё на клиенте делаешь, а надо на сервере.

Ну замена "if (event.side == Side.CLIENT)" на "if (event.side == Side.SERVER)" ничего не меняет. Все по прежнему.
[merge_posts_bbcode]Добавлено: 19.01.2016 08:39:51[/merge_posts_bbcode]

AlexSocol написал(а):
world.isRemote - проверка, отдалённый ли мир (если по-русски :D). Если да - то это клиент, если нет - сервер.
"if (!world.isRemote){}" проверяет, сервер ли это, и если да - делает то, что написано в if'е.
"А что тогда делать на сервере, а что - на клиенте?" - спросишь ты. Я отвечу, насколько знаю: "На сервере делать всё, с чем ты взаимодействуешь или что взаимодействует с тобой. Т.е. это спаун сущностей, установка блоков, накладывание эффектов и т.д. А вот текстуры, допустим - чисто клиентская вещь." Вот и вся хитрость =)

Мне вспомнился анекдот про типичного программиста, где в итоге его ответ был верным, но бесполезным.
Разжую свой вопрос про "world.isRemote": просто копирование этого текста в исходник ни к чему не приводит, точнее приводит к его подчеркиванию красным с ошибкой "world cannot be resolved to a variable". Мой вопрос и заключается в том, что тыкнете меня носом, где его взять (объявить, импортировать и пр.)

[merge_posts_bbcode]Добавлено: 19.01.2016 08:43:46[/merge_posts_bbcode]

Господа, ну серьезно. В других топах вы вопрошающих ругаете за то, что они мозги не включают, доки не читают.

Я в своем вопросе вроде показал и его суть, и свой код привел, и показал что сделал все что мог, а не тупо ленивая сволочь.

Помогите примером кода.

И я читал посты про инвентарь в закрытых вопроса на форуме.
 
На клиентской стороне:
Код:
EntityPlayerSP player = Minecraft.getMinecraft().thePlayer;
и
Код:
org.lwjgl.input.Keyboard.isKeyDown(kBindRestoreOne.getKeyCode())
По этому на серверной стороне не заработает это:
Код:
invCraft.setInventorySlotContents(0, new ItemStack(item, 7));
invPlayer.setInventorySlotContents(0, null);
Скорее всего придётся использовать оправку пакетов, чтобы выполнить это действие.
sevrer написал(а):
Помогите примером кода.
Если будет время.
[merge_posts_bbcode]Добавлено: 19.01.2016 07:56:54[/merge_posts_bbcode]

sevrer написал(а):
AlexSocol написал(а):
А откуда берется этот world. Я вижу его во всех примерах, но не могу понять откуда его брать?
Много откуда, но в данном случаи можно от player.worldObj.
 
Ну, давай подумает, откуда можно достать мир.
Во-первых, клиентский мир можно взять из Minecraft - Minecraft.getMinecraft().theWorld.
Во-вторых, давай логически подумает, где появляется энтити(в данном случае - игрок)? В мире, правильно? Значит в энтити хранится мир, в котором он появился, логично?
Мир у нас есть, окей.
Теперь главная проблема: клиент нажимает на клавиатуре кнопку, но сервер понятия не имеет, что какой-то там клиент клацнул на кнопочку у себя. Собственно, нам нужно это сказать серверу.
Как же это сделать? Правильно, отправить пакет.
В данном случае нам на клиенте нужно проверить, нажата ли клавиша и отправить пакет на сервер.
А на сервере уже делать то что нам хочется. Изменять инвентарь игрока, например.
Туториалов по пакетам много, так что думаю с этим проблем не будет.
Самому когда-то было тяжело понять логику клиент-сервер и сервер-клиент.
 
Agravaine написал(а):
Ну, давай подумает, откуда можно достать мир.
Во-первых, клиентский мир можно взять из Minecraft - Minecraft.getMinecraft().theWorld.
Во-вторых, давай логически подумает, где появляется энтити(в данном случае - игрок)? В мире, правильно? Значит в энтити хранится мир, в котором он появился, логично?
Мир у нас есть, окей.
Теперь главная проблема: клиент нажимает на клавиатуре кнопку, но сервер понятия не имеет, что какой-то там клиент клацнул на кнопочку у себя. Собственно, нам нужно это сказать серверу.
Как же это сделать? Правильно, отправить пакет.
В данном случае нам на клиенте нужно проверить, нажата ли клавиша и отправить пакет на сервер.
А на сервере уже делать то что нам хочется. Изменять инвентарь игрока, например.
Туториалов по пакетам много, так что думаю с этим проблем не будет.
Самому когда-то было тяжело понять логику клиент-сервер и сервер-клиент.

Про Minecraft.getMinecraft().theWorld я писать не стал, думаю что event.side тоже уместен.
Про пакеты мысль пришла, но уже было поздно и пора было спать. Пойду искать туториал по пакетам.
Ну и исходная задача все таки переместить из одного слота в другой, без дюпов, это я уж погорячился в своем примере, нужно создать мод для клиента, но для режима MP. И уж если ванильный клиент может отправлять пакеты о манипуляциях в инвентаре, значит и в модах должна быть такая возможность.

Кстати, ковырял исходники InventoryTweaks, но они реализацию функции move(...) куда-то спрятали.
 
Можно закрывать.
Решил проблему следующим образом:

Код:
    @SubscribeEvent
    public void workPlayerTickeEvent(TickEvent.PlayerTickEvent event) throws IOException 
    {
        Minecraft mc = Minecraft.getMinecraft();
        if (event.side == Side.CLIENT)
        {
            if (mc.gameSettings.isKeyDown(kBindSave))
            {
                if (!kSaveDown)
                {
                    saveInventory(event.player);
                }
                kSaveDown = true;
            }
            else
            {
                kSaveDown = false;
            }
        }
    }    

    
    public void saveInventory(EntityPlayer player)
    {
        Minecraft mc = Minecraft.getMinecraft();
        int srcIdSlot = 10;
        int dstIdSlot = 11;
        mc.playerController.windowClick(player.openContainer.windowId, srcIdSlot, 0, 0, player);
        mc.playerController.windowClick(player.openContainer.windowId, dstIdSlot, 0, 0, player);
    }

Осталось допилить различные проверки по наличию итемов в dstSlot и можно юзать. Работает и мультиплеере.
 
Запустишь такой код вне IDE - сервак тебя пошлёт куда подальше с ClassNotFoundException.
Поставь проверочку на клиент на одну строку повыше и инстанс Minecraft доставай только после проверки.
А заодно повесь над методом аннотацию
Код:
@SideOnly(Side.CLIENT)
 
Статус
В этой теме нельзя размещать новые ответы.
Назад
Сверху