Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix item energy bridge #35

Merged
merged 1 commit into from
Apr 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public static void init() {
if (!stack.isEmpty() && !COMPUTING_CAPABILITY_LOCK.get()) {
COMPUTING_CAPABILITY_LOCK.set(true);
EnergyStorage storage = stack.getCapability(ForgeCapabilities.ENERGY, null)
.map(ForgeEnergyStorageHandler::new)
.map(s -> new ForgeEnergyStorageHandler(s, context, stack))
.orElse(null);
COMPUTING_CAPABILITY_LOCK.set(false);
return storage;
Expand All @@ -47,8 +47,7 @@ public static void init() {
});

MinecraftForge.EVENT_BUS.addGenericListener(BlockEntity.class, EnergyBridgeSetup::onAttachBlockEntityCapabilities);
// TODO Fix container item context
// MinecraftForge.EVENT_BUS.addGenericListener(ItemStack.class, EnergyBridgeSetup::onAttachItemStackCapabilities);
MinecraftForge.EVENT_BUS.addGenericListener(ItemStack.class, EnergyBridgeSetup::onAttachItemStackCapabilities);
}

private static void onAttachBlockEntityCapabilities(AttachCapabilitiesEvent<BlockEntity> event) {
Expand Down Expand Up @@ -76,10 +75,11 @@ private static void onAttachItemStackCapabilities(AttachCapabilitiesEvent<ItemSt
public @NotNull <T> LazyOptional<T> getCapability(@NotNull Capability<T> cap, @Nullable Direction side) {
if (cap == ForgeCapabilities.ENERGY && !COMPUTING_CAPABILITY_LOCK.get()) {
COMPUTING_CAPABILITY_LOCK.set(true);
EnergyStorage storage = EnergyStorage.ITEM.find(stack, ContainerItemContext.withConstant(stack));
FabricEnergySlotHandler handler = new FabricEnergySlotHandler(stack);
EnergyStorage storage = EnergyStorage.ITEM.find(stack, ContainerItemContext.ofSingleSlot(handler));
COMPUTING_CAPABILITY_LOCK.set(false);
if (storage != null) {
return CAPS.computeIfAbsent(storage, b -> LazyOptional.of(() -> new FabricEnergyStorageHandler(storage))).cast();
return CAPS.computeIfAbsent(storage, b -> LazyOptional.of(() -> new FabricEnergyStorageHandler(storage, stack, handler))).cast();
}
}
return LazyOptional.empty();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package dev.su5ed.sinytra.connectorextras.energybridge;

import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant;
import net.fabricmc.fabric.api.transfer.v1.storage.base.SingleSlotStorage;
import net.fabricmc.fabric.api.transfer.v1.transaction.TransactionContext;
import net.minecraft.world.item.ItemStack;

public class FabricEnergySlotHandler implements SingleSlotStorage<ItemVariant> {

private ItemStack stack;

public FabricEnergySlotHandler(ItemStack stack) {
this.stack = stack;
}

@Override
public long insert(ItemVariant resource, long maxAmount, TransactionContext transaction) {
this.stack = resource.toStack();
return maxAmount;
}

@Override
public long extract(ItemVariant resource, long maxAmount, TransactionContext transaction) {
this.stack = resource.toStack();
return maxAmount;
}

@Override
public boolean isResourceBlank() {
return getResource().isBlank();
}

@Override
public ItemVariant getResource() {
return ItemVariant.of(stack);
}

public ItemStack getStack() {
return stack;
}

public void setStack(ItemStack stack) {
this.stack = stack;
}

@Override
public long getAmount() {
return stack.getCount();
}

@Override
public long getCapacity() {
return stack.getMaxStackSize();
}

}
Original file line number Diff line number Diff line change
@@ -1,14 +1,25 @@
package dev.su5ed.sinytra.connectorextras.energybridge;

import net.fabricmc.fabric.api.transfer.v1.transaction.Transaction;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.energy.IEnergyStorage;
import team.reborn.energy.api.EnergyStorage;

public class FabricEnergyStorageHandler implements IEnergyStorage {
private final EnergyStorage storage;
private final ItemStack stack;
private final FabricEnergySlotHandler handler;

public FabricEnergyStorageHandler(EnergyStorage storage) {
this.storage = storage;
this.stack = null;
this.handler = null;
}

public FabricEnergyStorageHandler(EnergyStorage storage, ItemStack stack, FabricEnergySlotHandler handler) {
this.storage = storage;
this.stack = stack;
this.handler = handler;
}

@Override
Expand All @@ -18,9 +29,17 @@ public int receiveEnergy(int amount, boolean simulate) {
}
try (Transaction transaction = Transaction.openOuter()) {
long e = EnergyBridge.convertForgeToFabricEnergy(amount);
long originalAmount = this.storage.getAmount();
long inserted = (int) this.storage.insert(e, transaction);
if (!simulate) {
transaction.commit();
if (stack != null) {
stack.setTag(handler.getStack().getTag());
}
} else if (stack != null && originalAmount == (this.storage.getAmount() - inserted)) {
//Some implementations just commit the transaction by themselves, so it must be reverted afterwards
//We can't just extract the energy because the storage could be insert-only
handler.setStack(stack);
}
return EnergyBridge.unConvertForgeToFabricEnergy(inserted);
}
Expand All @@ -36,6 +55,9 @@ public int extractEnergy(int amount, boolean simulate) {
long extracted = (int) this.storage.extract(e, transaction);
if (!simulate) {
transaction.commit();
if (stack != null) {
stack.setTag(handler.getStack().getTag());
}
}
return EnergyBridge.convertFabricToForgeEnergy(extracted);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,28 @@
package dev.su5ed.sinytra.connectorextras.energybridge;

import net.fabricmc.fabric.api.transfer.v1.context.ContainerItemContext;
import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant;
import net.fabricmc.fabric.api.transfer.v1.transaction.Transaction;
import net.fabricmc.fabric.api.transfer.v1.transaction.TransactionContext;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.energy.IEnergyStorage;
import team.reborn.energy.api.EnergyStorage;

public class ForgeEnergyStorageHandler implements EnergyStorage {
private final IEnergyStorage storage;
private final ContainerItemContext context;
private final ItemStack stack;

public ForgeEnergyStorageHandler(IEnergyStorage storage) {
this.storage = storage;
this.context = null;
this.stack = null;
}

public ForgeEnergyStorageHandler(IEnergyStorage storage, ContainerItemContext context, ItemStack stack) {
this.storage = storage;
this.context = context;
this.stack = stack;
}

@Override
Expand All @@ -18,6 +32,7 @@ public long insert(long maxAmount, TransactionContext transaction) {
transaction.addCloseCallback((context, result) -> {
if (result.wasCommitted()) {
this.storage.receiveEnergy(fe, false);
updateStack();
}
});
return EnergyBridge.unConvertFabricToForgeEnergy(inserted);
Expand All @@ -30,11 +45,27 @@ public long extract(long maxAmount, TransactionContext transaction) {
transaction.addCloseCallback((context, result) -> {
if (result.wasCommitted()) {
this.storage.extractEnergy(fe, false);
updateStack();
}
});
return EnergyBridge.convertForgeToFabricEnergy(extracted);
}

private void updateStack() {
if (stack != null) {
//We can't open a new Transaction while one is closing, so we make a new Thread
Thread thread = new Thread(() -> {
try (Transaction t = Transaction.openOuter()) {
//Update the item (NBT).
this.context.extract(this.context.getItemVariant(), 1, t);
this.context.insert(ItemVariant.of(stack), 1, t);
t.commit();
}
});
thread.start();
}
}

@Override
public long getAmount() {
return EnergyBridge.convertForgeToFabricEnergy(this.storage.getEnergyStored());
Expand Down
Loading