EntityItem всегда выдаёт количество "ноль".

Версия Minecraft
1.7.10
API
Forge
210
1
19
Вот код:
Java:
    @SubscribeEvent
    public void ItemPickupEv(ItemPickupEvent e){
        ItemStack itemstack = e.pickedUp.getEntityItem();
        String name = itemstack.getDisplayName();
        int amount = itemstack.stackSize;
        System.out.println("Item=" + name + " & amount=" + amount);        
    }
Кидаю несколько стаков предметов, вот результат:
Код:
[14:15:58] [Server thread/INFO] [STDOUT]: [ru.lao.rha.handlers.ItemPickup:ItemPickupEv:19]: EVENT:cpw.mods.fml.common.gameevent.PlayerEvent$ItemPickupEvent@aaa8ed
[14:15:58] [Server thread/INFO] [STDOUT]: [ru.lao.rha.handlers.ItemPickup:ItemPickupEv:57]: Item=Камень & amount=0
[14:15:58] [Server thread/INFO] [STDOUT]: [ru.lao.rha.handlers.ItemPickup:ItemPickupEv:19]: EVENT:cpw.mods.fml.common.gameevent.PlayerEvent$ItemPickupEvent@38954a
[14:15:58] [Server thread/INFO] [STDOUT]: [ru.lao.rha.handlers.ItemPickup:ItemPickupEv:57]: Item=Дуб & amount=0
[14:15:58] [Server thread/INFO] [STDOUT]: [ru.lao.rha.handlers.ItemPickup:ItemPickupEv:19]: EVENT:cpw.mods.fml.common.gameevent.PlayerEvent$ItemPickupEvent@4e6ac0
[14:15:58] [Server thread/INFO] [STDOUT]: [ru.lao.rha.handlers.ItemPickup:ItemPickupEv:57]: Item=Доски из тёмного дуба & amount=0
[14:15:58] [Server thread/INFO] [STDOUT]: [ru.lao.rha.handlers.ItemPickup:ItemPickupEv:19]: EVENT:cpw.mods.fml.common.gameevent.PlayerEvent$ItemPickupEvent@364c0f
[14:15:58] [Server thread/INFO] [STDOUT]: [ru.lao.rha.handlers.ItemPickup:ItemPickupEv:57]: Item=Доски из акации & amount=0
[14:15:59] [Server thread/INFO] [STDOUT]: [ru.lao.rha.handlers.ItemPickup:ItemPickupEv:19]: EVENT:cpw.mods.fml.common.gameevent.PlayerEvent$ItemPickupEvent@355b2c
[14:15:59] [Server thread/INFO] [STDOUT]: [ru.lao.rha.handlers.ItemPickup:ItemPickupEv:57]: Item=Дуб & amount=0

В чём причина?
 

tox1cozZ

aka Agravaine
8,456
598
2,893
Причина в кривом ивенте форджа. Этот дурак не учитывает новый stackSize после подбора.
Фиксится довольно сложным трансформером.
Java:
private final String ITEM_STACK = isObfuscated() ? "add" : "net/minecraft/item/ItemStack";
private final String STACK_SIZE_NAME = isObfuscated() ? "b" : "stackSize";
private final String STACK_SIZE_DESC = "I";
private final String IS_REMOTE_NAME = isObfuscated() ? "E" : "isRemote";
private final String IS_REMOTE_DESC = "Z";
private final String INVENTORY_PLAYER = isObfuscated() ? "yx" : "net/minecraft/entity/player/InventoryPlayer";
private final String ENTITY_PLAYER = isObfuscated() ? "yz" : "net/minecraft/entity/player/EntityPlayer";
private final String ADD_ITEM_STACK_TO_INVENTORY_NAME = isObfuscated() ? "a" : "addItemStackToInventory";
private final String ADD_ITEM_STACK_TO_INVENTORY_DESC = isObfuscated() ? "(Ladd;)Z" : "(Lnet/minecraft/item/ItemStack;)
private final String ON_ITEM_PICKUP_NAME = isObfuscated() ? "a" : "onItemPickup";
private final String ON_ITEM_PICKUP_DESC = isObfuscated() ? "(Lsa;I)V" : "(Lnet/minecraft/entity/Entity;I)V";
private final String ON_ITEM_PICKUP_HOOK_NAME = "onItemPickedUp";
private final String ON_ITEM_PICKUP_HOOK_DESC = isObfuscated() ? "(Lxk;Lyz;I)V" : "(Lnet/minecraft/entity/item/EntityItem;Lnet/minecraft/entity/player/EntityPlayer;I)V";
private final String ON_COLLIDE_WITH_PLAYER_NAME = isObfuscated() ? "b_" : "onCollideWithPlayer";
private final String ON_COLLIDE_WITH_PLAYER_DESC = isObfuscated() ? "(Lyz;)V" : "(Lnet/minecraft/entity/player/EntityPlayer;)V";

private byte[] patchEntityItem(byte[] bytes){
        ClassNode classNode = new ClassNode();
        ClassReader classReader = new ClassReader(bytes);
        classReader.accept(classNode, 0);

        MethodNode onCollideWithPlayer = findMethod(classNode, ON_COLLIDE_WITH_PLAYER_NAME, ON_COLLIDE_WITH_PLAYER_DESC).orElseThrow(() -> new RuntimeException("Can not find target method 'onCollideWithPlayer' in class 'net.minecraft.entity.item.EntityItem'"));

        InsnList instructions = onCollideWithPlayer.instructions;

        // Добавляем проверку в if
        AbstractInsnNode hookAnchor = null;
        ListIterator<AbstractInsnNode> iterator = instructions.iterator();
        while(iterator.hasNext()){
            AbstractInsnNode node = iterator.next();
            if(node.getOpcode() == INVOKEVIRTUAL){
                MethodInsnNode methodNode = (MethodInsnNode)node;
                if(methodNode.owner.equals(INVENTORY_PLAYER) && methodNode.name.equals(ADD_ITEM_STACK_TO_INVENTORY_NAME) && methodNode.desc.equals(ADD_ITEM_STACK_TO_INVENTORY_DESC)){
                    JumpInsnNode ifLastNode = (JumpInsnNode)findInsnsWithOpcode(instructions.getFirst(), IFNE, false).stream().filter(insn -> {
                        if(insn.getPrevious().getOpcode() == GETFIELD){
                            FieldInsnNode field = (FieldInsnNode)insn.getPrevious();
                            return field.owner.equals(WORLD) && field.name.equals(IS_REMOTE_NAME) && field.desc.equals(IS_REMOTE_DESC);
                        }
                        return false;
                    }).findFirst().orElseThrow(() -> new RuntimeException("Can not find target label instructions"));

                    AbstractInsnNode ifNode = findInsnsWithOpcode(instructions.getFirst(), GETSTATIC, false).stream().filter(insn -> ((FieldInsnNode)insn).name.equals("ALLOW")).findFirst().orElseThrow(() -> new RuntimeException("Can not find target label instructions"));

                    JumpInsnNode ifAddItem = (JumpInsnNode)methodNode.getNext();
                    ifAddItem.setOpcode(IFNE);
                    ifAddItem.label = ((JumpInsnNode)ifNode.getNext()).label;

                    InsnList list = new InsnList();
                    list.add(new VarInsnNode(ILOAD, 4));
                    list.add(new VarInsnNode(ALOAD, 3));
                    list.add(new FieldInsnNode(GETFIELD, ITEM_STACK, STACK_SIZE_NAME, STACK_SIZE_DESC));
                    list.add(new JumpInsnNode(IF_ICMPLE, ifLastNode.label));
                    instructions.insert(methodNode.getNext(), list);

                    hookAnchor = methodNode;
                    break;
                }
            }
        }

        // Вызываем хук
        AbstractInsnNode hookPos = findInsnsWith(hookAnchor, insn -> insn instanceof FrameNode && ((FrameNode)insn).type == F_SAME, false).stream().findFirst().orElseThrow(() -> new RuntimeException("Can not find target hook instructions"));
        InsnList hookList = new InsnList();
        hookList.add(new VarInsnNode(ALOAD, 0));
        hookList.add(new VarInsnNode(ALOAD, 1));
        hookList.add(new VarInsnNode(ILOAD, 4));
        hookList.add(new VarInsnNode(ALOAD, 3));
        hookList.add(new FieldInsnNode(GETFIELD, ITEM_STACK, STACK_SIZE_NAME, STACK_SIZE_DESC));
        hookList.add(new InsnNode(ISUB));
        hookList.add(new MethodInsnNode(INVOKESTATIC, HOOKS, ON_ITEM_PICKUP_HOOK_NAME, ON_ITEM_PICKUP_HOOK_DESC, false));
        instructions.insert(hookPos, hookList);

        // Перемещаем вызов EntityPlayer#onItemPickup в условие itemstack.stackSize <= 0 чтобы вызывался только когда весь предмет был подобран
        AbstractInsnNode onItemPickupAnchor = findInsnsWith(instructions.getFirst(), insn -> {
            if(insn.getOpcode() == INVOKEVIRTUAL){
                MethodInsnNode methodNode = (MethodInsnNode)insn;
                return methodNode.owner.equals(ENTITY_PLAYER) && methodNode.name.equals(ON_ITEM_PICKUP_NAME) && methodNode.desc.equals(ON_ITEM_PICKUP_DESC);
            }
            return false;
        }, false).stream().findFirst().orElseThrow(() -> new RuntimeException("Can not find target onItemPickup call position"));

        InsnList onItemPickupList = new InsnList();
        onItemPickupList.add(new VarInsnNode(ALOAD, 1));
        onItemPickupList.add(new VarInsnNode(ALOAD, 0));
        onItemPickupList.add(new VarInsnNode(ILOAD, 4));
        onItemPickupList.add(new MethodInsnNode(INVOKEVIRTUAL, ENTITY_PLAYER, ON_ITEM_PICKUP_NAME, ON_ITEM_PICKUP_DESC, false));
        AbstractInsnNode onItemPickupNewCallPos = findInsnsWith(onItemPickupAnchor, insn -> {
            if(insn.getOpcode() == GETFIELD){
                FieldInsnNode field = (FieldInsnNode)insn;
                return field.owner.equals(ITEM_STACK) && field.name.equals(STACK_SIZE_NAME) && field.desc.equals(STACK_SIZE_DESC);
            }
            return false;
        }, false).stream().findFirst().orElseThrow(() -> new RuntimeException("Can not find target new onItemPickup call position"));
        instructions.insert(onItemPickupNewCallPos.getNext(), onItemPickupList);

        for(int i = 0; i < 3; i++){
            instructions.remove(onItemPickupAnchor.getPrevious());
        }
        instructions.remove(onItemPickupAnchor);

        ClassWriter classWriter = new SafeClassWriter(classMetadataReader, 0);
        classNode.accept(classWriter);
        return classWriter.toByteArray();
    }

    private static List<AbstractInsnNode> findInsnsWithOpcode(@NonNull AbstractInsnNode firstToCheck, int opcode, boolean reverseDirection){
        return findInsnsWith(firstToCheck, insn -> insn.getOpcode() == opcode, reverseDirection);
    }

    private static List<AbstractInsnNode> findInsnsWith(@NonNull AbstractInsnNode firstToCheck, Predicate<AbstractInsnNode> predicate, boolean reverseDirection){
        List<AbstractInsnNode> list = Lists.newArrayList();
        AbstractInsnNode insn = firstToCheck;
        while(insn != null){
            if(predicate.test(insn)){
                list.add(insn);
            }
            insn = reverseDirection ? insn.getPrevious() : insn.getNext();
        }
        return list;
    }

    private static Optional<MethodNode> findMethod(ClassNode classNode, String name, String desc){
        return classNode.methods.stream().filter(method -> method.name.equals(name) && method.desc.equals(desc)).findFirst();
    }

Сам хук:
Java:
public static void onItemPickedUp(EntityItem entityItem, EntityPlayer player, int stackSize){
        ItemStack itemStack = entityItem.getEntityItem().copy();
        itemStack.stackSize = stackSize;
        // Получаем нормальный ItemStack
    }
 
210
1
19
Фиксится довольно сложным трансформером.
Круто. Других никаких костылей в природе нет? А то такой трансформер без подробной инструкции, что и куда пихать, и где прописывать, я не осилю. Как и вообще любой трансформер...
 
210
1
19
7,099
324
1,510
Причина в кривом ивенте форджа. Этот дурак не учитывает новый stackSize после подбора.
Фиксится довольно сложным трансформером.
Java:
private final String ITEM_STACK = isObfuscated() ? "add" : "net/minecraft/item/ItemStack";
private final String STACK_SIZE_NAME = isObfuscated() ? "b" : "stackSize";
private final String STACK_SIZE_DESC = "I";
private final String IS_REMOTE_NAME = isObfuscated() ? "E" : "isRemote";
private final String IS_REMOTE_DESC = "Z";
private final String INVENTORY_PLAYER = isObfuscated() ? "yx" : "net/minecraft/entity/player/InventoryPlayer";
private final String ENTITY_PLAYER = isObfuscated() ? "yz" : "net/minecraft/entity/player/EntityPlayer";
private final String ADD_ITEM_STACK_TO_INVENTORY_NAME = isObfuscated() ? "a" : "addItemStackToInventory";
private final String ADD_ITEM_STACK_TO_INVENTORY_DESC = isObfuscated() ? "(Ladd;)Z" : "(Lnet/minecraft/item/ItemStack;)
private final String ON_ITEM_PICKUP_NAME = isObfuscated() ? "a" : "onItemPickup";
private final String ON_ITEM_PICKUP_DESC = isObfuscated() ? "(Lsa;I)V" : "(Lnet/minecraft/entity/Entity;I)V";
private final String ON_ITEM_PICKUP_HOOK_NAME = "onItemPickedUp";
private final String ON_ITEM_PICKUP_HOOK_DESC = isObfuscated() ? "(Lxk;Lyz;I)V" : "(Lnet/minecraft/entity/item/EntityItem;Lnet/minecraft/entity/player/EntityPlayer;I)V";
private final String ON_COLLIDE_WITH_PLAYER_NAME = isObfuscated() ? "b_" : "onCollideWithPlayer";
private final String ON_COLLIDE_WITH_PLAYER_DESC = isObfuscated() ? "(Lyz;)V" : "(Lnet/minecraft/entity/player/EntityPlayer;)V";

private byte[] patchEntityItem(byte[] bytes){
        ClassNode classNode = new ClassNode();
        ClassReader classReader = new ClassReader(bytes);
        classReader.accept(classNode, 0);

        MethodNode onCollideWithPlayer = findMethod(classNode, ON_COLLIDE_WITH_PLAYER_NAME, ON_COLLIDE_WITH_PLAYER_DESC).orElseThrow(() -> new RuntimeException("Can not find target method 'onCollideWithPlayer' in class 'net.minecraft.entity.item.EntityItem'"));

        InsnList instructions = onCollideWithPlayer.instructions;

        // Добавляем проверку в if
        AbstractInsnNode hookAnchor = null;
        ListIterator<AbstractInsnNode> iterator = instructions.iterator();
        while(iterator.hasNext()){
            AbstractInsnNode node = iterator.next();
            if(node.getOpcode() == INVOKEVIRTUAL){
                MethodInsnNode methodNode = (MethodInsnNode)node;
                if(methodNode.owner.equals(INVENTORY_PLAYER) && methodNode.name.equals(ADD_ITEM_STACK_TO_INVENTORY_NAME) && methodNode.desc.equals(ADD_ITEM_STACK_TO_INVENTORY_DESC)){
                    JumpInsnNode ifLastNode = (JumpInsnNode)findInsnsWithOpcode(instructions.getFirst(), IFNE, false).stream().filter(insn -> {
                        if(insn.getPrevious().getOpcode() == GETFIELD){
                            FieldInsnNode field = (FieldInsnNode)insn.getPrevious();
                            return field.owner.equals(WORLD) && field.name.equals(IS_REMOTE_NAME) && field.desc.equals(IS_REMOTE_DESC);
                        }
                        return false;
                    }).findFirst().orElseThrow(() -> new RuntimeException("Can not find target label instructions"));

                    AbstractInsnNode ifNode = findInsnsWithOpcode(instructions.getFirst(), GETSTATIC, false).stream().filter(insn -> ((FieldInsnNode)insn).name.equals("ALLOW")).findFirst().orElseThrow(() -> new RuntimeException("Can not find target label instructions"));

                    JumpInsnNode ifAddItem = (JumpInsnNode)methodNode.getNext();
                    ifAddItem.setOpcode(IFNE);
                    ifAddItem.label = ((JumpInsnNode)ifNode.getNext()).label;

                    InsnList list = new InsnList();
                    list.add(new VarInsnNode(ILOAD, 4));
                    list.add(new VarInsnNode(ALOAD, 3));
                    list.add(new FieldInsnNode(GETFIELD, ITEM_STACK, STACK_SIZE_NAME, STACK_SIZE_DESC));
                    list.add(new JumpInsnNode(IF_ICMPLE, ifLastNode.label));
                    instructions.insert(methodNode.getNext(), list);

                    hookAnchor = methodNode;
                    break;
                }
            }
        }

        // Вызываем хук
        AbstractInsnNode hookPos = findInsnsWith(hookAnchor, insn -> insn instanceof FrameNode && ((FrameNode)insn).type == F_SAME, false).stream().findFirst().orElseThrow(() -> new RuntimeException("Can not find target hook instructions"));
        InsnList hookList = new InsnList();
        hookList.add(new VarInsnNode(ALOAD, 0));
        hookList.add(new VarInsnNode(ALOAD, 1));
        hookList.add(new VarInsnNode(ILOAD, 4));
        hookList.add(new VarInsnNode(ALOAD, 3));
        hookList.add(new FieldInsnNode(GETFIELD, ITEM_STACK, STACK_SIZE_NAME, STACK_SIZE_DESC));
        hookList.add(new InsnNode(ISUB));
        hookList.add(new MethodInsnNode(INVOKESTATIC, HOOKS, ON_ITEM_PICKUP_HOOK_NAME, ON_ITEM_PICKUP_HOOK_DESC, false));
        instructions.insert(hookPos, hookList);

        // Перемещаем вызов EntityPlayer#onItemPickup в условие itemstack.stackSize <= 0 чтобы вызывался только когда весь предмет был подобран
        AbstractInsnNode onItemPickupAnchor = findInsnsWith(instructions.getFirst(), insn -> {
            if(insn.getOpcode() == INVOKEVIRTUAL){
                MethodInsnNode methodNode = (MethodInsnNode)insn;
                return methodNode.owner.equals(ENTITY_PLAYER) && methodNode.name.equals(ON_ITEM_PICKUP_NAME) && methodNode.desc.equals(ON_ITEM_PICKUP_DESC);
            }
            return false;
        }, false).stream().findFirst().orElseThrow(() -> new RuntimeException("Can not find target onItemPickup call position"));

        InsnList onItemPickupList = new InsnList();
        onItemPickupList.add(new VarInsnNode(ALOAD, 1));
        onItemPickupList.add(new VarInsnNode(ALOAD, 0));
        onItemPickupList.add(new VarInsnNode(ILOAD, 4));
        onItemPickupList.add(new MethodInsnNode(INVOKEVIRTUAL, ENTITY_PLAYER, ON_ITEM_PICKUP_NAME, ON_ITEM_PICKUP_DESC, false));
        AbstractInsnNode onItemPickupNewCallPos = findInsnsWith(onItemPickupAnchor, insn -> {
            if(insn.getOpcode() == GETFIELD){
                FieldInsnNode field = (FieldInsnNode)insn;
                return field.owner.equals(ITEM_STACK) && field.name.equals(STACK_SIZE_NAME) && field.desc.equals(STACK_SIZE_DESC);
            }
            return false;
        }, false).stream().findFirst().orElseThrow(() -> new RuntimeException("Can not find target new onItemPickup call position"));
        instructions.insert(onItemPickupNewCallPos.getNext(), onItemPickupList);

        for(int i = 0; i < 3; i++){
            instructions.remove(onItemPickupAnchor.getPrevious());
        }
        instructions.remove(onItemPickupAnchor);

        ClassWriter classWriter = new SafeClassWriter(classMetadataReader, 0);
        classNode.accept(classWriter);
        return classWriter.toByteArray();
    }

    private static List<AbstractInsnNode> findInsnsWithOpcode(@NonNull AbstractInsnNode firstToCheck, int opcode, boolean reverseDirection){
        return findInsnsWith(firstToCheck, insn -> insn.getOpcode() == opcode, reverseDirection);
    }

    private static List<AbstractInsnNode> findInsnsWith(@NonNull AbstractInsnNode firstToCheck, Predicate<AbstractInsnNode> predicate, boolean reverseDirection){
        List<AbstractInsnNode> list = Lists.newArrayList();
        AbstractInsnNode insn = firstToCheck;
        while(insn != null){
            if(predicate.test(insn)){
                list.add(insn);
            }
            insn = reverseDirection ? insn.getPrevious() : insn.getNext();
        }
        return list;
    }

    private static Optional<MethodNode> findMethod(ClassNode classNode, String name, String desc){
        return classNode.methods.stream().filter(method -> method.name.equals(name) && method.desc.equals(desc)).findFirst();
    }

Сам хук:
Java:
public static void onItemPickedUp(EntityItem entityItem, EntityPlayer player, int stackSize){
        ItemStack itemStack = entityItem.getEntityItem().copy();
        itemStack.stackSize = stackSize;
        // Получаем нормальный ItemStack
    }
А нельзя это в виде отдельного мода собрать и опубликовать?
 
210
1
19
Этот дурак не учитывает новый stackSize после подбора.

Так у меня получается, что этот дурак не учитывает старый, до подбора. Мне нужно именно знать, сколько поднято.
 
1,083
72
374
Ивент вызывается после подбора предмета игроком, предмет в это время уже стал "невалидным"
В методе net.minecraft.entity.player.InventoryPlayer#addItemStackToInventory происходит обнуление. Можно на этот метод хук повесить.
 

tox1cozZ

aka Agravaine
8,456
598
2,893
А нельзя это в виде отдельного мода собрать и опубликовать?
Да это костыли, ивент-то оно не чинит, а просто добавляет свой хук.

Так у меня получается, что этот дурак не учитывает старый, до подбора. Мне нужно именно знать, сколько поднято.
Да, верно, я неправильно выразился.

В методе net.minecraft.entity.player.InventoryPlayer#addItemStackToInventory происходит обнуление. Можно на этот метод хук повесить.
Можно, тогда сломается вся логика метода, проблем не оберешься.
 
682
20
319
Хукаемся
ttest:
@Hook(returnCondition = ReturnCondition.ALWAYS)
    public static void onCollideWithPlayer(EntityItem obj, EntityPlayer p_70100_1_)
    {
       
        if (!obj.worldObj.isRemote)
        {
            if (obj.delayBeforeCanPickup > 0)
            {
                return;
            }

            EntityItemPickupEvent event = new EntityItemPickupEvent(p_70100_1_, obj);
           
            if (MinecraftForge.EVENT_BUS.post(event))
            {
                return;
            }

            ItemStack itemstack = obj.getEntityItem();
            int i = itemstack.stackSize;

            if (obj.delayBeforeCanPickup <= 0 && (obj.field_145802_g == null || obj.lifespan - obj.age <= 200 || obj.field_145802_g.equals(p_70100_1_.getCommandSenderName())) && (event.getResult() == Result.ALLOW || i <= 0 || p_70100_1_.inventory.addItemStackToInventory(itemstack)))
            {
                if (itemstack.getItem() == Item.getItemFromBlock(Blocks.log))
                {
                    p_70100_1_.triggerAchievement(AchievementList.mineWood);
                }

                if (itemstack.getItem() == Item.getItemFromBlock(Blocks.log2))
                {
                    p_70100_1_.triggerAchievement(AchievementList.mineWood);
                }

                if (itemstack.getItem() == Items.leather)
                {
                    p_70100_1_.triggerAchievement(AchievementList.killCow);
                }

                if (itemstack.getItem() == Items.diamond)
                {
                    p_70100_1_.triggerAchievement(AchievementList.diamonds);
                }

                if (itemstack.getItem() == Items.blaze_rod)
                {
                    p_70100_1_.triggerAchievement(AchievementList.blazeRod);
                }

                if (itemstack.getItem() == Items.diamond && obj.func_145800_j() != null)
                {
                    EntityPlayer entityplayer1 = obj.worldObj.getPlayerEntityByName(obj.func_145800_j());

                    if (entityplayer1 != null && entityplayer1 != p_70100_1_)
                    {
                        entityplayer1.triggerAchievement(AchievementList.field_150966_x);
                    }
                }
                /// берем пеменную i и тут делаем что хотим
                // Пример с моего кода
                Main.network.sendTo(Main.network.createPacket(0, itemstack.copy(), 200, true, i), (EntityPlayerMP) p_70100_1_)
                FMLCommonHandler.instance().firePlayerItemPickupEvent(p_70100_1_, obj);

                obj.worldObj.playSoundAtEntity(p_70100_1_, "random.pop", 0.2F, ((obj.rand.nextFloat() - obj.rand.nextFloat()) * 0.7F + 1.0F) * 2.0F);
                p_70100_1_.onItemPickup(obj, i);

                if (itemstack.stackSize <= 0)
                {
                    obj.setDead();
                }
            }
        }
    }
 

tox1cozZ

aka Agravaine
8,456
598
2,893
Красава тупой токсикоз, уже давно не использую поддержку плагинов
Молодец бро, но не советуй пожалуйста это говно всем. Зачем вообще хуки, если у тебя своё ядро? Мегамозг.

кому надо будет хукнет в строку
А еще ивент неправильно работает и не срабатывает если поднять лишь часть предмета. Пример: у тебя забит инвентарь и ты можешь поднять 16 штук предмета, а на земле лежит 64. Ты передаёшь i (64) будто поднял весь стак, а на деле должно быть (16).
Удачи хукнуть строку :sneaky:
 
682
20
319
Молодец бро, но не советуй пожалуйста это говно всем. Зачем вообще хуки, если у тебя своё ядро? Мегамозг.
Для быстрого удаления лишнего мода


А еще ивент неправильно работает и не срабатывает если поднять лишь часть предмета. Пример: у тебя забит инвентарь и ты можешь поднять 16 штук предмета, а на земле лежит 64. Ты передаёшь i (64) будто поднял весь стак, а на деле должно быть (16).
там нужно свою реализацию addItemStackToInventory добавить
 
210
1
19
Есть такой мод - BackPacks. Я его когда-то модернизировал под свои нужды, поэтому исходники нашлись в загашнике. Так вот, там можно подобрать вещь с пола, минуя инвентарь, сразу в рюкзак. И вроде дюпов и конфликтов с плагинами на этом я не замечал.

Попробуем разобрать?

Итак, первое, класс EventHandlerBackpack:
Java:
    @SubscribeEvent
    public void playerPickup(EntityItemPickupEvent event) {
        BackpackUtil.pickupItem(event.entityPlayer, event.item.getEntityItem());
    }

Смотрим в класс BackpackUtil и видим:
Java:
    public static void pickupItem(EntityPlayer entityPlayer, ItemStack itemStack) {
        PlayerSave playerSave = new PlayerSave(entityPlayer);
        ItemStack backpack = playerSave.getPersonalBackpack();
        if(backpack != null) {
            InventoryPickup inventoryPickup = new InventoryPickup();
            inventoryPickup.setInventoryContent(backpack);

            ContainerPickup container = new ContainerPickup(ItemBackpackBase.getInventory(backpack, entityPlayer), new BackpackSave(backpack));
            boolean hasPickedUp = false;
            for(int i = 0; i < inventoryPickup.getSizeInventory(); i++) {
                ItemStack pickupItemStack = inventoryPickup.getStackInSlot(i);
                if(areStacksEqual(pickupItemStack, itemStack, true)) {
                    hasPickedUp = container.pickupItem(itemStack) || hasPickedUp;
                }
            }
            if(hasPickedUp) {
                container.onContainerClosed(entityPlayer);
            }
        }
    }

Класс ContainerPickup целиком:
Java:
package de.eydamos.backpack.inventory.container;

import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import de.eydamos.backpack.inventory.slot.SlotBackpack;
import de.eydamos.backpack.saves.BackpackSave;

public class ContainerPickup extends ContainerAdvanced {
    public ContainerPickup(IInventory inventoryToSave, BackpackSave save) {
        super(new IInventory[] { inventoryToSave }, save);

        for(int i = 0; i < inventory.getSizeInventory(); i++) {
            addSlotToContainer(new SlotBackpack(inventory, i, 0, 0));
        }
    }

    public boolean pickupItem(ItemStack itemStack) {
        if(mergeItemStack(itemStack, 0, inventorySlots.size(), false)) {
            inventory.markDirty();
            return true;
        }

        return false;
    }

    @Override
    public boolean canInteractWith(EntityPlayer entityplayer) {
        return true;
    }
}

Лично я в чужой код втыкаю фигово. Может кто-то объяснить на пальцах, как тут всё реализовано и можно ли отсюда что-то использовать для обхода косяка с эвентом? Если нужны ещё какие-то классы - скажите, я выложу.
 
7,099
324
1,510
Чем отличается event.item(который используется в бакпаках) от event.pickedUp(который используешь ты)?
Если это не одно и то же под разными маппингами, то первое видимо предмет до подбора игроком или то, что останется после подбора
 
210
1
19
Чем отличается event.item(который используется в бакпаках) от event.pickedUp(который используешь ты)?
Вот по этой причине я никогда не стану программистом - программист должен быть внимательным. :)

Всё заработало.
Эвент нужно было использовать другой - "EntityItemPickupEvent" (я использовал, напомню "ItemPickupEvent").

Вот результат:
1634310408742.png
 
Сверху