Mass Storage AE2 compat

This commit is contained in:
abel1502 2025-06-20 01:26:23 +03:00
parent 381ef334b2
commit 9b08adc314
No known key found for this signature in database
GPG Key ID: 076926596A536338
6 changed files with 264 additions and 0 deletions

View File

@ -79,6 +79,18 @@ repositories {
// name = "CurseForge"
// url = "https://minecraft.curseforge.com/api/maven/"
//}
maven {
name = "Jitpack"
url = "https://jitpack.io"
}
maven {
name = "CurseMaven"
url = "https://cursemaven.com"
}
maven {
name = "OpenComputers"
url = "https://maven.cil.li/"
}
}
dependencies {
@ -94,6 +106,9 @@ dependencies {
compileOnly "inventorytweaks:InventoryTweaks:1.59-dev:deobf"
implementation "li.cil.oc:OpenComputers:MC1.7.10-1.5.+:api"
implementation "com.github.GTNewHorizons:Applied-Energistics-2-Unofficial:rv3-beta.56-GTNH:dev"
compileOnly "com.github.GTNewHorizons:Applied-Energistics-2-Unofficial:rv3-beta.56-GTNH:sources"
}
processResources {

View File

@ -0,0 +1,12 @@
package com.hbm.handler.ae2;
import appeng.api.AEApi;
import cpw.mods.fml.common.Loader;
public class AE2CompatHandler {
public static void init() {
if (Loader.isModLoaded("appliedenergistics2")) {
AEApi.instance().registries().externalStorage().addExternalStorageInterface(new MSUExternalStorageHandler());
}
}
}

View File

@ -0,0 +1,44 @@
package com.hbm.handler.ae2;
import com.hbm.tileentity.machine.storage.TileEntityMassStorage;
import com.hbm.util.ItemStackUtil;
import appeng.api.networking.security.BaseActionSource;
import appeng.api.storage.IExternalStorageHandler;
import appeng.api.storage.IMEInventory;
import appeng.api.storage.StorageChannel;
import appeng.api.storage.data.IAEItemStack;
import appeng.me.storage.MEMonitorIInventory;
import appeng.util.inv.IMEAdaptor;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.util.ForgeDirection;
public class MSUExternalStorageHandler implements IExternalStorageHandler {
public MSUExternalStorageHandler() {}
@Override
public boolean canHandle(TileEntity te, ForgeDirection d, StorageChannel channel, BaseActionSource mySrc) {
return channel == StorageChannel.ITEMS && te instanceof TileEntityMassStorage;
}
@Override
public IMEInventory getInventory(TileEntity te, ForgeDirection d, StorageChannel channel, BaseActionSource src) {
if (!canHandle(te, d, channel, src))
return null;
// Note: apparently I need this, though I'm not sure why. Storage drawers does it.
// Here's a relevant discussion, if anyone wants to dive into that rabbit hole:
// https://github.com/AppliedEnergistics/Applied-Energistics-2/issues/418
return new MEMonitorIInventory(new IMEAdaptor(new MassStorageMEInventory((TileEntityMassStorage)te), src)) {
@Override
public boolean isPrioritized(IAEItemStack stack) {
ItemStack type = ((TileEntityMassStorage)te).getType();
return type != null && ItemStackUtil.areStacksCompatible(stack.getItemStack(), type);
}
};
}
}

View File

@ -0,0 +1,84 @@
package com.hbm.handler.ae2;
import static com.hbm.inventory.OreDictManager.I;
import com.hbm.tileentity.machine.storage.TileEntityMassStorage;
import com.hbm.util.ItemStackUtil;
import appeng.api.AEApi;
import appeng.api.config.Actionable;
import appeng.api.networking.security.BaseActionSource;
import appeng.api.storage.IMEInventory;
import appeng.api.storage.StorageChannel;
import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList;
import net.minecraft.item.ItemStack;
public class MassStorageMEInventory implements IMEInventory<IAEItemStack> {
private TileEntityMassStorage tile;
public MassStorageMEInventory(TileEntityMassStorage tile) {
this.tile = tile;
}
@Override
public IAEItemStack injectItems(IAEItemStack input, Actionable type, BaseActionSource src) {
ItemStack typeStack = tile.getType();
if (typeStack == null || !ItemStackUtil.areStacksCompatible(input.getItemStack(), typeStack))
return input;
// If you're working with amounts greater than MAX_INT, you shouldn't use MSUs in the first place
int remaining = tile.increaseTotalStockpile((int)input.getStackSize(), type == Actionable.MODULATE);
if (remaining == 0) {
return null;
}
return AEApi.instance().storage()
.createItemStack(typeStack)
.setStackSize(remaining);
}
@Override
public IAEItemStack extractItems(IAEItemStack request, Actionable mode, BaseActionSource src) {
ItemStack typeStack = tile.getType();
if (typeStack == null || !ItemStackUtil.areStacksCompatible(request.getItemStack(), typeStack))
return null;
// If you're working with amounts greater than MAX_INT, you shouldn't use MSUs in the first place
int missing = tile.decreaseTotalStockpile((int)request.getStackSize(), mode == Actionable.MODULATE);
long fulfilled = request.getStackSize() - missing;
if (fulfilled == 0) {
return null;
}
return AEApi.instance().storage()
.createItemStack(typeStack)
.setStackSize(fulfilled);
}
@Override
public IItemList<IAEItemStack> getAvailableItems(IItemList<IAEItemStack> out) {
ItemStack typeStack = tile.getType();
if (typeStack != null) {
out.add(
AEApi.instance().storage()
.createItemStack(typeStack)
.setStackSize(tile.getTotalStockpile())
);
}
return out;
}
@Override
public StorageChannel getChannel() {
return StorageChannel.ITEMS;
}
}

View File

@ -13,6 +13,7 @@ import com.hbm.entity.grenade.*;
import com.hbm.entity.logic.IChunkLoader;
import com.hbm.entity.mob.siege.SiegeTier;
import com.hbm.handler.*;
import com.hbm.handler.ae2.AE2CompatHandler;
import com.hbm.handler.imc.IMCBlastFurnace;
import com.hbm.handler.imc.IMCCentrifuge;
import com.hbm.handler.imc.IMCCrystallizer;
@ -881,6 +882,9 @@ public class MainRegistry {
// Load compatibility for OC.
CompatHandler.init();
// Load compatibility for AE2.
AE2CompatHandler.init();
//expand for the largest entity we have (currently Quackos who is 17.5m in diameter, that's one fat duck)
World.MAX_ENTITY_RADIUS = Math.max(World.MAX_ENTITY_RADIUS, 8.75);

View File

@ -7,6 +7,7 @@ import com.hbm.tileentity.IBufPacketReceiver;
import com.hbm.tileentity.IControlReceiverFilter;
import com.hbm.util.BufferUtil;
import com.hbm.util.ItemStackUtil;
import api.hbm.redstoneoverradio.IRORInteractive;
import api.hbm.redstoneoverradio.IRORValueProvider;
@ -15,6 +16,7 @@ import cpw.mods.fml.relauncher.SideOnly;
import io.netty.buffer.ByteBuf;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.Container;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.Vec3;
@ -133,6 +135,109 @@ public class TileEntityMassStorage extends TileEntityCrateBase implements IBufPa
return result;
}
// Note: the following three methods are used for AE2 integration, and aren't meant to be called in any other context by default
public int getTotalStockpile() {
ItemStack type = getType();
if (type == null)
return 0;
int result = getStockpile();
ItemStack inStack = slots[0];
if (inStack != null && ItemStackUtil.areStacksCompatible(type, inStack)) {
result += inStack.stackSize;
}
ItemStack outStack = slots[2];
if (outStack != null && ItemStackUtil.areStacksCompatible(type, outStack)) {
result += outStack.stackSize;
}
return result;
}
// Returns the remainder that didn't fit.
// If `actually` is false, only predicts the outcome, but doesn't change the state
public int increaseTotalStockpile(int amount, boolean actually) {
return changeTotalStockpile(amount, actually, +1);
}
// Returns the remainder that couldn't be extracted.
// If `actually` is false, only predicts the outcome, but doesn't change the state
public int decreaseTotalStockpile(int amount, boolean actually) {
return changeTotalStockpile(amount, actually, -1);
}
private int changeTotalStockpile(int amount, boolean actually, int sign) {
ItemStack type = getType();
if (type == null)
return amount;
int stockpileAvail = sign > 0 ? getCapacity() - getStockpile() : getStockpile();
if (amount > 0 && stockpileAvail > 0) {
int depositStockpile = Math.min(amount, stockpileAvail);
if (actually) {
this.stack += sign * depositStockpile;
}
amount -= depositStockpile;
}
int inputAvail = 0;
ItemStack inStack = slots[0];
if (inStack != null && ItemStackUtil.areStacksCompatible(type, inStack)) {
inputAvail = sign > 0 ? inStack.getMaxStackSize() - inStack.stackSize : inStack.stackSize;
} else if (inStack == null) {
inputAvail = sign > 0 ? type.getMaxStackSize() : 0;
}
if (amount > 0 && inputAvail > 0) {
int depositInput = Math.min(amount, inputAvail);
if (actually) {
if (slots[0] == null) { // Only possible with sign == +1
slots[0] = slots[1].copy();
slots[0].stackSize = 0;
}
slots[0].stackSize += sign * depositInput;
if (slots[0].stackSize == 0) {
slots[0] = null;
}
}
amount -= depositInput;
}
int outputAvail = 0;
ItemStack outStack = slots[2];
if (outStack != null && ItemStackUtil.areStacksCompatible(type, outStack)) {
outputAvail = sign > 0 ? outStack.getMaxStackSize() - outStack.stackSize : outStack.stackSize;
} else if (outStack == null) {
outputAvail = sign > 0 ? type.getMaxStackSize() : 0;
}
if (amount > 0 && outputAvail > 0) {
int depositOutput = Math.min(amount, outputAvail);
if (actually) {
if (slots[2] == null) { // Only possible with sign == +1
slots[2] = slots[1].copy();
slots[2].stackSize = 0;
}
slots[2].stackSize += sign * depositOutput;
if (slots[2].stackSize == 0) {
slots[2] = null;
}
}
amount -= depositOutput;
}
if (actually) {
this.markDirty();
}
return amount;
}
@Override
public void serialize(ByteBuf buf) {
buf.writeInt(this.stack);