Add compat for metamachine and create arm

This commit is contained in:
2025-10-19 10:52:28 +02:00
parent 1856de9307
commit 041b9fa7b2
4 changed files with 262 additions and 0 deletions

View File

@@ -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);
}

View File

@@ -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<ArmInteractionPointType> ARM_POINTS = DeferredRegister
.create(CreateRegistries.ARM_INTERACTION_POINT_TYPE, KineticBridge.MOD_ID);
public static final RegistryObject<ArmInteractionPointType> META_MACHINE_POINT = ARM_POINTS.register("meta_machine",
MetaMachineArmInteractionPointType::new);
private KineticBridgeCreateCompat() {}
public static void init(IEventBus modBus) {
ARM_POINTS.register(modBus);
}
}

View File

@@ -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<IItemHandler> handlers = new ArrayList<>();
List<LazyOptional<IItemHandler>> dependencies = new ArrayList<>();
Map<IItemHandler, Boolean> seen = new IdentityHashMap<>();
for (Direction direction : Direction.values()) {
LazyOptional<IItemHandler> 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<IItemHandler> aggregated = LazyOptional.of(() -> handler);
dependencies.forEach(opt -> opt.addListener(l -> aggregated.invalidate()));
cachedHandler = aggregated;
} else {
AggregatedItemHandler aggregatedHandler = new AggregatedItemHandler(handlers);
LazyOptional<IItemHandler> 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<IItemHandler> delegates;
private AggregatedItemHandler(List<IItemHandler> 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;
}
}
}

View File

@@ -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);
}
}