diff --git a/src/main/java/com/imbgt/kineticbridge/KineticBridge.java b/src/main/java/com/imbgt/kineticbridge/KineticBridge.java index 2f7b003..d8f1fcc 100644 --- a/src/main/java/com/imbgt/kineticbridge/KineticBridge.java +++ b/src/main/java/com/imbgt/kineticbridge/KineticBridge.java @@ -9,6 +9,7 @@ import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import com.imbgt.kineticbridge.compat.create.KineticBridgeCreateCompat; import com.mojang.logging.LogUtils; import org.slf4j.Logger; @@ -23,6 +24,7 @@ public class KineticBridge { IEventBus modBus = FMLJavaModLoadingContext.get().getModEventBus(); REGISTRATE.registerRegistrate(); + KineticBridgeCreateCompat.init(modBus); modBus.addGenericListener(MachineDefinition.class, this::registerMachines); } diff --git a/src/main/java/com/imbgt/kineticbridge/compat/create/KineticBridgeCreateCompat.java b/src/main/java/com/imbgt/kineticbridge/compat/create/KineticBridgeCreateCompat.java new file mode 100644 index 0000000..508d69a --- /dev/null +++ b/src/main/java/com/imbgt/kineticbridge/compat/create/KineticBridgeCreateCompat.java @@ -0,0 +1,25 @@ +package com.imbgt.kineticbridge.compat.create; + +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.registries.DeferredRegister; +import net.minecraftforge.registries.RegistryObject; + +import com.imbgt.kineticbridge.KineticBridge; +import com.imbgt.kineticbridge.compat.create.arm.MetaMachineArmInteractionPointType; +import com.simibubi.create.api.registry.CreateRegistries; +import com.simibubi.create.content.kinetics.mechanicalArm.ArmInteractionPointType; + +public final class KineticBridgeCreateCompat { + + private static final DeferredRegister ARM_POINTS = DeferredRegister + .create(CreateRegistries.ARM_INTERACTION_POINT_TYPE, KineticBridge.MOD_ID); + + public static final RegistryObject META_MACHINE_POINT = ARM_POINTS.register("meta_machine", + MetaMachineArmInteractionPointType::new); + + private KineticBridgeCreateCompat() {} + + public static void init(IEventBus modBus) { + ARM_POINTS.register(modBus); + } +} diff --git a/src/main/java/com/imbgt/kineticbridge/compat/create/arm/MetaMachineArmInteractionPoint.java b/src/main/java/com/imbgt/kineticbridge/compat/create/arm/MetaMachineArmInteractionPoint.java new file mode 100644 index 0000000..2424af9 --- /dev/null +++ b/src/main/java/com/imbgt/kineticbridge/compat/create/arm/MetaMachineArmInteractionPoint.java @@ -0,0 +1,197 @@ +package com.imbgt.kineticbridge.compat.create.arm; + +import com.gregtechceu.gtceu.api.blockentity.MetaMachineBlockEntity; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.capabilities.ForgeCapabilities; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemHandlerHelper; + +import com.simibubi.create.content.kinetics.mechanicalArm.ArmInteractionPoint; +import com.simibubi.create.content.kinetics.mechanicalArm.ArmInteractionPointType; + +import java.util.ArrayList; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; + +public class MetaMachineArmInteractionPoint extends ArmInteractionPoint { + + public MetaMachineArmInteractionPoint(ArmInteractionPointType type, Level level, + BlockPos pos, BlockState state) { + super(type, level, pos, state); + } + + @Override + public ItemStack insert(ItemStack stack, boolean simulate) { + if (mode != Mode.DEPOSIT) { + return stack; + } + IItemHandler handler = getHandler(); + if (handler == null) { + return stack; + } + return ItemHandlerHelper.insertItem(handler, stack, simulate); + } + + @Override + public ItemStack extract(int slot, int amount, boolean simulate) { + if (mode != Mode.TAKE) { + return ItemStack.EMPTY; + } + IItemHandler handler = getHandler(); + if (handler == null) { + return ItemStack.EMPTY; + } + return handler.extractItem(slot, amount, simulate); + } + + @Override + public int getSlotCount() { + if (mode != Mode.TAKE) { + return 0; + } + IItemHandler handler = getHandler(); + return handler == null ? 0 : handler.getSlots(); + } + + @Override + protected IItemHandler getHandler() { + if (!cachedHandler.isPresent()) { + var be = level.getBlockEntity(pos); + if (!(be instanceof MetaMachineBlockEntity metaMachine)) { + cachedHandler = LazyOptional.empty(); + return null; + } + + List handlers = new ArrayList<>(); + List> dependencies = new ArrayList<>(); + Map seen = new IdentityHashMap<>(); + + for (Direction direction : Direction.values()) { + LazyOptional sideCapability = metaMachine.getCapability(ForgeCapabilities.ITEM_HANDLER, + direction); + sideCapability.ifPresent(handler -> { + if (handler.getSlots() > 0 && !seen.containsKey(handler)) { + handlers.add(handler); + dependencies.add(sideCapability); + seen.put(handler, Boolean.TRUE); + } + }); + } + + if (handlers.isEmpty()) { + cachedHandler = metaMachine.getCapability(ForgeCapabilities.ITEM_HANDLER, null); + } else if (handlers.size() == 1) { + IItemHandler handler = handlers.get(0); + LazyOptional aggregated = LazyOptional.of(() -> handler); + dependencies.forEach(opt -> opt.addListener(l -> aggregated.invalidate())); + cachedHandler = aggregated; + } else { + AggregatedItemHandler aggregatedHandler = new AggregatedItemHandler(handlers); + LazyOptional aggregated = LazyOptional.of(() -> aggregatedHandler); + dependencies.forEach(opt -> opt.addListener(l -> aggregated.invalidate())); + cachedHandler = aggregated; + } + } + return cachedHandler.orElse(null); + } + + @Override + public void updateCachedState() { + var previous = cachedState; + super.updateCachedState(); + if (!previous.equals(cachedState) && cachedHandler.isPresent()) { + cachedHandler.invalidate(); + cachedHandler = LazyOptional.empty(); + } + } + + private static class AggregatedItemHandler implements IItemHandler { + + private final List delegates; + + private AggregatedItemHandler(List delegates) { + this.delegates = List.copyOf(delegates); + } + + @Override + public int getSlots() { + int total = 0; + for (IItemHandler handler : delegates) { + total += handler.getSlots(); + } + return total; + } + + @Override + public ItemStack getStackInSlot(int slot) { + int index = slot; + for (IItemHandler handler : delegates) { + int size = handler.getSlots(); + if (index < size) { + return handler.getStackInSlot(index); + } + index -= size; + } + return ItemStack.EMPTY; + } + + @Override + public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) { + int index = slot; + for (IItemHandler handler : delegates) { + int size = handler.getSlots(); + if (index < size) { + return handler.insertItem(index, stack, simulate); + } + index -= size; + } + return stack; + } + + @Override + public ItemStack extractItem(int slot, int amount, boolean simulate) { + int index = slot; + for (IItemHandler handler : delegates) { + int size = handler.getSlots(); + if (index < size) { + return handler.extractItem(index, amount, simulate); + } + index -= size; + } + return ItemStack.EMPTY; + } + + @Override + public int getSlotLimit(int slot) { + int index = slot; + for (IItemHandler handler : delegates) { + int size = handler.getSlots(); + if (index < size) { + return handler.getSlotLimit(index); + } + index -= size; + } + return 0; + } + + @Override + public boolean isItemValid(int slot, ItemStack stack) { + int index = slot; + for (IItemHandler handler : delegates) { + int size = handler.getSlots(); + if (index < size) { + return handler.isItemValid(index, stack); + } + index -= size; + } + return false; + } + } +} diff --git a/src/main/java/com/imbgt/kineticbridge/compat/create/arm/MetaMachineArmInteractionPointType.java b/src/main/java/com/imbgt/kineticbridge/compat/create/arm/MetaMachineArmInteractionPointType.java new file mode 100644 index 0000000..da60aed --- /dev/null +++ b/src/main/java/com/imbgt/kineticbridge/compat/create/arm/MetaMachineArmInteractionPointType.java @@ -0,0 +1,38 @@ +package com.imbgt.kineticbridge.compat.create.arm; + +import com.gregtechceu.gtceu.api.block.MetaMachineBlock; +import com.gregtechceu.gtceu.api.blockentity.MetaMachineBlockEntity; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.capabilities.ForgeCapabilities; + +import com.simibubi.create.content.kinetics.mechanicalArm.ArmInteractionPoint; +import com.simibubi.create.content.kinetics.mechanicalArm.ArmInteractionPointType; + +public class MetaMachineArmInteractionPointType extends ArmInteractionPointType { + + @Override + public boolean canCreatePoint(Level level, BlockPos pos, BlockState state) { + if (!(state.getBlock() instanceof MetaMachineBlock)) { + return false; + } + var be = level.getBlockEntity(pos); + if (!(be instanceof MetaMachineBlockEntity metaMachine)) { + return false; + } + for (Direction direction : Direction.values()) { + if (metaMachine.getCapability(ForgeCapabilities.ITEM_HANDLER, direction).isPresent()) { + return true; + } + } + return metaMachine.getCapability(ForgeCapabilities.ITEM_HANDLER, null).isPresent(); + } + + @Override + public ArmInteractionPoint createPoint(Level level, BlockPos pos, BlockState state) { + return new MetaMachineArmInteractionPoint(this, level, pos, state); + } +}