filename:
neoforge/src/main/java/rearth/oritech/neoforge/NeoforgeItemApiImpl.java
branch:
1.21
back to repo
package rearth.oritech.neoforge;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
import net.neoforged.neoforge.capabilities.Capabilities;
import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent;
import net.neoforged.neoforge.items.IItemHandler;
import net.neoforged.neoforge.items.IItemHandlerModifiable;
import net.neoforged.neoforge.items.ItemHandlerHelper;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import rearth.oritech.Oritech;
import rearth.oritech.api.item.BlockItemApi;
import rearth.oritech.api.item.ItemApi;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
public class NeoforgeItemApiImpl implements BlockItemApi {
private final List<Supplier<BlockEntityType<?>>> registeredBlockEntities = new ArrayList<>();
@Override
public void registerBlockEntity(Supplier<BlockEntityType<?>> typeSupplier) {
registeredBlockEntities.add(typeSupplier);
}
public void registerEvent(RegisterCapabilitiesEvent event) {
for (var supplied : registeredBlockEntities) {
event.registerBlockEntity(Capabilities.ItemHandler.BLOCK, supplied.get(), (entity, direction) -> ContainerStorageWrapper.of(((ItemApi.BlockProvider) entity).getInventoryStorage(direction)));
}
}
@Override
public ItemApi.InventoryStorage find(World world, BlockPos pos, @Nullable BlockState state, @Nullable BlockEntity entity, @Nullable Direction direction) {
var candidate = world.getCapability(Capabilities.ItemHandler.BLOCK, pos, state, entity, direction);
if (candidate == null) return null;
if (candidate instanceof ContainerStorageWrapper wrapper) return wrapper.container;
return new NeoforgeStoragerWrapper(candidate);
}
@Override
public ItemApi.InventoryStorage find(World world, BlockPos pos, @Nullable Direction direction) {
return find(world, pos, null, null, direction);
}
// used to interact with storages from other mods. Oritech really only uses the insert/extract methods, not the insertToSlot/extractFromSlot variants.
public static class NeoforgeStoragerWrapper implements ItemApi.InventoryStorage {
private final IItemHandler container;
public NeoforgeStoragerWrapper(IItemHandler candidate) {
this.container = candidate;
}
@Override
public int insert(ItemStack inserted, boolean simulate) {
return inserted.getCount() - ItemHandlerHelper.insertItem(container, inserted, simulate).getCount();
}
@Override
public int insertToSlot(ItemStack inserted, int slot, boolean simulate) {
return inserted.getCount() - container.insertItem(slot, inserted, simulate).getCount();
}
@Override
public int extract(ItemStack extracted, boolean simulate) {
var total = 0;
for (int i = 0; i < container.getSlots(); i++) {
var available = container.getStackInSlot(i);
if (ItemStack.areItemsAndComponentsEqual(available, extracted)) {
total += container.extractItem(i, extracted.getCount() - total, simulate).getCount();
}
}
return total;
}
@Override
public int extractFromSlot(ItemStack extracted, int slot, boolean simulate) {
return container.extractItem(slot, extracted.getCount(), simulate).getCount();
}
@Override
public void setStackInSlot(int slot, ItemStack stack) {
if (container instanceof IItemHandlerModifiable handler) {
handler.setStackInSlot(slot, stack);
} else {
Oritech.LOGGER.error("Unable to set stack in slot: {}, stack is: {}", slot, stack);
Oritech.LOGGER.error("This should never happen");
}
}
@Override
public ItemStack getStackInSlot(int slot) {
return container.getStackInSlot(slot);
}
@Override
public int getSlotCount() {
return container.getSlots();
}
@Override
public int getSlotLimit(int slot) {
return container.getSlotLimit(slot);
}
@Override
public void update() {
// nothing to do
}
}
// used by other mods to interact with oritech block / storages
public static class ContainerStorageWrapper implements IItemHandlerModifiable {
public final ItemApi.InventoryStorage container;
public static ContainerStorageWrapper of(ItemApi.InventoryStorage storage) {
if (storage == null) return null;
return new ContainerStorageWrapper(storage);
}
public ContainerStorageWrapper(ItemApi.InventoryStorage container) {
this.container = container;
}
@Override
public int getSlots() {
return container.getSlotCount();
}
@Override
public @NotNull ItemStack getStackInSlot(int slot) {
return container.getStackInSlot(slot);
}
@Override
public @NotNull ItemStack insertItem(int slot, @NotNull ItemStack arg, boolean simulate) {
var inserted = container.insertToSlot(arg, slot, simulate);
if (inserted > 0 && !simulate) {
container.update();
}
// need to return the remainder here
return arg.copyWithCount(arg.getCount() - inserted);
}
@Override
public @NotNull ItemStack extractItem(int slot, int amount, boolean simulate) {
var takenStack = container.getStackInSlot(slot).copyWithCount(amount);
var extracted = container.extractFromSlot(takenStack, slot, simulate);
if (extracted > 0 && !simulate) {
container.update();
}
return takenStack.copyWithCount(extracted);
}
@Override
public int getSlotLimit(int i) {
return container.getSlotLimit(i);
}
@Override
public boolean isItemValid(int i, @NotNull ItemStack arg) {
return container.insertToSlot(arg, i, true) > 0;
}
@Override
public void setStackInSlot(int i, @NotNull ItemStack arg) {
container.setStackInSlot(i, arg);
container.update();
}
}
}