Запретить класть предметы в эндер сундук

Версия Minecraft
1.7.10
API
Forge
48
2
9
Собственно, как запретить класть предметы в эндер сундук? Возможно есть какой-то ивент для отслеживания изменения его содержимого?
 
7,099
324
1,510
При открытии контейнера заменить все слоты на свои, у которых нужным образом реализован метод isItemValid
 
48
2
9
При открытии контейнера заменить все слоты на свои, у которых нужным образом реализован метод isItemValid
Как я понял это будет работать на клиентской стороне. А что на счет серверной? Как там можно запретить класти предметы в сундук? И как можно отследить открытие контейнера и понять какому из сундуков он пренадлежит (обычному или эндеру)? Я пробовал через GuiOpenEvent, но там никак тип узнать не получается.
 

necauqua

когда-то был anti344
Администратор
1,216
27
172
это будет работать на клиентской стороне
Нет, контейнер и его слоты существуют на обеих сторонах, а вот GuiOpenEvent как раз только на клиенте, тебе нужен PlayerContainerEvent.Open (если он так называется в 1.7.10 и вообще там есть)
 
48
2
9
тебе нужен PlayerContainerEvent.Open (если он так называется в 1.7.10 и вообще там есть)
В 1.7.10 есть PlayerOpenContainerEvent, но он почему-то срабатывает на каждый тик игрока даже когда я не пытаюсь что-то открыть. Как этот ивент можно применить в даной ситуации?
 

necauqua

когда-то был anti344
Администратор
1,216
27
172
Хм, странно, а если проверять на необходимый тебе контейнер?
Ивент шлётся каждый тик когда контейнер открыт?
Если так, то можно проверять что произошёл переход вида 'левый контейнер -> тот что надо контейнер' и только тогда в том что надо контейнере менять слоты.
У меня 1.7.10 воркспейса нету и вряд-ли будет ¯\_(ツ)_/¯
 
  • Like
Реакции: klas
48
2
9
проверять что произошёл переход вида 'левый контейнер -> тот что надо контейнер'
Получилось следующее
Java:
@SubscribeEvent
public void onContainerOpen(PlayerOpenContainerEvent event) {
    EntityPlayer player = event.entityPlayer;
    if (!(player.openContainer instanceof ContainerChest)) {
        return;
    }
    ContainerChest container = (ContainerChest) player.openContainer;
    if (!Objects.equals(container.lowerChestInventory.getInventoryName(), "container.enderchest")) {
        return;
    }
    player.openContainer = new ContainerTakeOnlyChest(player.inventory, player.getInventoryEnderChest());
}
При открытии контейнера эндер сундука я заменяю его на свой, где есть мои слоты.
И все почти работает как надо. Один только вопрос - в методе слота isItemValid как понять в каком инвентаре находится ItemStack? А то на даный момент я не могу класть ничего в свой инвентарь.
 
7,099
324
1,510
но он почему-то срабатывает на каждый тик игрока даже когда я не пытаюсь что-то открыть.
Скорее всего это связано с контейнером инвентаря игрока, который как бы открыт всегда, если не открыт другой контейнер. Чекай, что за контейнер в ивенте и работай с нужным
 
  • Like
Реакции: klas
7,099
324
1,510
48
2
9
Лучше хукнуться в Slot или Container#slotClick
В общем тот вариант, что я писал выше оказался не до конца рабочим и я решил попробовать заюзать хуки. Раньше я этой либой не пользовался, потому сразу юзать и не хотел. В общем, получились следующие 2 хука чтобы запретить ложить предметы в эндер сундук (1 вызывается при клике на слот, другой при перемещении предмета с помощью shift):
Java:
@Hook(returnCondition = ReturnCondition.ALWAYS)
public static boolean isItemValid(Slot slot, ItemStack itemStack) {
    return slot.inventory instanceof InventoryPlayer;
}

@Hook(returnCondition = ReturnCondition.ON_NULL)
public static ItemStack transferStackInSlot(ContainerChest container, EntityPlayer player, int index) {
    Slot slot = (Slot) container.inventorySlots.get(index);
    return Objects.equals(slot.inventory.getInventoryName(), "container.enderchest") ? slot.getStack() : null;
}
И да, так оказалось действительно в разы проще :sneaky:
Спасибо Фолкену за HookLib
 

necauqua

когда-то был anti344
Администратор
1,216
27
172
Я так и не понял, зачемы ты заменял весь контейнер, но ок, хорошо что "в разы проще" всё получилось
 

tox1cozZ

aka Agravaine
8,455
598
2,892
Хуки у тебя конечно получились максимально кривые и ломающие всё на свете)
Теперь попробуй положить любой предмет в слот брони и офигей 🙃

Java:
@Hook(returnCondition = ReturnCondition.ON_TRUE, booleanReturnConstant = false)
public static boolean isItemValid(Slot slot, ItemStack itemStack) {
    return slot.inventory instanceof InventoryEnderChest;
}

@Hook(returnCondition = ReturnCondition.ON_TRUE, booleanReturnConstant = false)
public static boolean canTakeStack(Slot slot, EntityPlayer player) {
    return slot.inventory instanceof InventoryEnderChest;
}
 
  • Like
Реакции: klas
48
2
9
Теперь попробуй положить любой предмет в слот брони и офигей 🙃
Да, увидел, что слоты везде перестали нормально работать 😅
Но твои хуки у меня тоже не совсем корректно срабатывали (скорее всего из-за того, что slot.inventory типа IInventory). Вот новый вариант, вроде как не сломанный:
Java:
@Hook(returnCondition = ReturnCondition.ON_TRUE, booleanReturnConstant = false)
public static boolean isItemValid(Slot slot, ItemStack itemStack) {
    return Objects.equals(slot.inventory.getInventoryName(), "container.enderchest");
}

@Hook(returnCondition = ReturnCondition.ON_TRUE, returnNull = true)
public static boolean transferStackInSlot(ContainerChest container, EntityPlayer player, int index) {
    Slot slot = (Slot) container.inventorySlots.get(index);
    return Objects.equals(slot.inventory.getInventoryName(), "container.inventory")
        && Objects.equals(container.getLowerChestInventory().getInventoryName(), "container.enderchest");
}
 
Сверху