diff --git a/dependencies.gradle b/dependencies.gradle index 26b5a599..01284063 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -10,12 +10,16 @@ dependencies { compileOnly("com.github.GTNewHorizons:BloodMagic:1.8.5") {transitive = false} compileOnly("com.github.GTNewHorizons:CraftTweaker:3.4.2:dev") {transitive = false} compileOnly("com.github.GTNewHorizons:Hodgepodge:2.7.11:dev") {transitive = false} - compileOnly("com.github.GTNewHorizons:GT5-Unofficial:5.09.52.97:dev") {transitive = false} + compileOnly("com.github.GTNewHorizons:GT5-Unofficial:5.09.52.97:dev") { + exclude module: "Avaritia" + } + compileOnly("com.github.GTNewHorizons:ModularUI2:2.3.25-1.7.10:dev") + compileOnly("com.github.GTNewHorizons:GTNHLib:0.9.0:dev") compileOnly("thaumcraft:Thaumcraft:1.7.10-4.2.3.5:dev") {transitive = false} compileOnly("curse.maven:cofh-lib-220333:2388748") {transitive = false} compileOnly("curse.maven:cofh-core-69162:2388751") {transitive = false} compileOnly("curse.maven:witchery-69673:2234410") {transitive = false} - runtimeOnly("com.github.GTNewHorizons:GTNHLib:0.7.7:dev") + runtimeOnly("com.github.GTNewHorizons:GTNHLib:0.9.0:dev") } diff --git a/src/main/java/fox/spiteful/avaritia/Mods.java b/src/main/java/fox/spiteful/avaritia/Mods.java new file mode 100644 index 00000000..77320166 --- /dev/null +++ b/src/main/java/fox/spiteful/avaritia/Mods.java @@ -0,0 +1,78 @@ +package fox.spiteful.avaritia; + +import java.util.Locale; + +import net.minecraft.util.ResourceLocation; + +import org.jetbrains.annotations.NotNull; + +import com.gtnewhorizon.gtnhlib.util.data.IMod; +import com.gtnewhorizon.gtnhmixins.builders.ITargetMod; +import com.gtnewhorizon.gtnhmixins.builders.TargetModBuilder; + +import cpw.mods.fml.common.Loader; + +@SuppressWarnings("unused") +public enum Mods implements IMod, ITargetMod { + + AE2FluidCraft(Names.A_E2_FLUID_CRAFT), + ModularUI2(Names.MODULAR_U_I_2), + + ; + + public static class Names { + + // spotless:off + + public static final String A_E2_FLUID_CRAFT = "ae2fc"; + public static final String MODULAR_U_I_2 = "modularui2"; + + // spotless:on + } + + public final String ID; + public final String resourceDomain; + protected boolean checkedMod, modLoaded; + protected final TargetModBuilder builder; + + Mods(String ID) { + this.ID = ID; + this.resourceDomain = ID.toLowerCase(Locale.ENGLISH); + this.builder = new TargetModBuilder().setModId(getEffectiveModID()); + } + + @Override + public @NotNull TargetModBuilder getBuilder() { + return builder; + } + + @Override + public String getID() { + return ID; + } + + protected String getEffectiveModID() { + return ID; + } + + public boolean isModLoaded() { + if (!checkedMod) { + this.modLoaded = Loader.isModLoaded(getEffectiveModID()); + checkedMod = true; + } + return this.modLoaded; + } + + @Override + public String getResourceLocation() { + return resourceDomain; + } + + public String getResourcePath(String... path) { + return this.getResourceLocation(path).toString(); + } + + public ResourceLocation getResourceLocation(String... path) { + return new ResourceLocation(this.resourceDomain, String.join("/", path)); + } +} diff --git a/src/main/java/fox/spiteful/avaritia/blocks/BlockMatterClusterOpener.java b/src/main/java/fox/spiteful/avaritia/blocks/BlockMatterClusterOpener.java new file mode 100644 index 00000000..790a3670 --- /dev/null +++ b/src/main/java/fox/spiteful/avaritia/blocks/BlockMatterClusterOpener.java @@ -0,0 +1,115 @@ +package fox.spiteful.avaritia.blocks; + +import net.minecraft.block.BlockContainer; +import net.minecraft.block.material.Material; +import net.minecraft.client.renderer.texture.IIconRegister; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.IIcon; +import net.minecraft.util.MathHelper; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; +import net.minecraftforge.common.util.ForgeDirection; + +import com.cleanroommc.modularui.factory.GuiManager; +import com.cleanroommc.modularui.factory.PosGuiData; +import com.cleanroommc.modularui.factory.TileEntityGuiFactory; + +import cpw.mods.fml.common.registry.GameRegistry; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import fox.spiteful.avaritia.items.ItemMatterClusterOpener; +import fox.spiteful.avaritia.tile.TileMatterClusterOpener; + +public class BlockMatterClusterOpener extends BlockContainer { + + public BlockMatterClusterOpener() { + super(Material.iron); + + setBlockName("cluster_opener"); + setHardness(2f); + setResistance(2f); + } + + public static void register() { + LudicrousBlocks.clusterOpener = new BlockMatterClusterOpener(); + GameRegistry.registerBlock(LudicrousBlocks.clusterOpener, ItemMatterClusterOpener.class, "cluster_opener"); + GameRegistry.registerTileEntity(TileMatterClusterOpener.class, "cluster_opener"); + } + + @Override + public TileEntity createNewTileEntity(World worldIn, int meta) { + return new TileMatterClusterOpener(); + } + + @Override + public boolean onBlockActivated(World worldIn, int x, int y, int z, EntityPlayer player, int side, float subX, + float subY, float subZ) { + if (!worldIn.isRemote) { + PosGuiData data = new PosGuiData(player, x, y, z); + GuiManager.open(TileEntityGuiFactory.INSTANCE, data, (EntityPlayerMP) player); + } + + return true; + } + + @Override + public void onBlockPlacedBy(World world, int x, int y, int z, EntityLivingBase player, ItemStack stack) { + int l = MathHelper.floor_double((double) (player.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3; + + world.setBlockMetadataWithNotify(x, y, z, l, 2); + } + + @Override + public void onBlockPreDestroy(World worldIn, int x, int y, int z, int meta) { + super.onBlockPreDestroy(worldIn, x, y, z, meta); + + ((TileMatterClusterOpener) worldIn.getTileEntity(x, y, z)).dropContents(); + } + + @SideOnly(Side.CLIENT) + private IIcon top, side, front; + + @SideOnly(Side.CLIENT) + @Override + public void registerBlockIcons(IIconRegister reg) { + top = reg.registerIcon("avaritia:cluster_opener/top"); + side = reg.registerIcon("avaritia:cluster_opener/side"); + front = reg.registerIcon("avaritia:cluster_opener/front"); + } + + @SideOnly(Side.CLIENT) + @Override + public IIcon getIcon(IBlockAccess worldIn, int x, int y, int z, int side) { + // In-world rendering + ForgeDirection dir = ForgeDirection.getOrientation(side); + + if (dir == ForgeDirection.UP) return top; + if (dir == ForgeDirection.DOWN) return top; + + ForgeDirection front = switch (worldIn.getBlockMetadata(x, y, z)) { + case 0 -> ForgeDirection.NORTH; + case 1 -> ForgeDirection.EAST; + case 2 -> ForgeDirection.SOUTH; + case 3 -> ForgeDirection.WEST; + default -> ForgeDirection.UNKNOWN; + }; + + return dir == front ? this.front : this.side; + } + + @SideOnly(Side.CLIENT) + @Override + public IIcon getIcon(int side, int meta) { + // In-hand rendering + ForgeDirection dir = ForgeDirection.getOrientation(side); + + if (dir == ForgeDirection.UP) return top; + if (dir == ForgeDirection.DOWN) return top; + + return dir == ForgeDirection.SOUTH ? this.front : this.side; + } +} diff --git a/src/main/java/fox/spiteful/avaritia/blocks/LudicrousBlocks.java b/src/main/java/fox/spiteful/avaritia/blocks/LudicrousBlocks.java index f0cf0577..c21753ce 100644 --- a/src/main/java/fox/spiteful/avaritia/blocks/LudicrousBlocks.java +++ b/src/main/java/fox/spiteful/avaritia/blocks/LudicrousBlocks.java @@ -2,6 +2,7 @@ import net.minecraft.block.Block; +import cpw.mods.fml.common.Loader; import cpw.mods.fml.common.registry.GameRegistry; import fox.spiteful.avaritia.Config; import fox.spiteful.avaritia.tile.TileEntityCompressor; @@ -23,6 +24,8 @@ public class LudicrousBlocks { public static Block infinitato; + public static Block clusterOpener; + public static void voxelize() { double_craft = GameRegistry.registerBlock(new BlockDoubleCraft(), "Double_Craft"); triple_craft = GameRegistry.registerBlock(new BlockTripleCraft(), "Triple_Craft"); @@ -37,5 +40,9 @@ public static void voxelize() { GameRegistry.registerTileEntity(TileEntityNeutron.class, "Avaritia_Neutron"); compressor = GameRegistry.registerBlock(new BlockCompressor(), "Neutronium_Compressor"); GameRegistry.registerTileEntity(TileEntityCompressor.class, "Avaritia_Compressor"); + + if (Loader.isModLoaded("gtnhlib") && Loader.isModLoaded("modularui2")) { + BlockMatterClusterOpener.register(); + } } } diff --git a/src/main/java/fox/spiteful/avaritia/crafting/Grinder.java b/src/main/java/fox/spiteful/avaritia/crafting/Grinder.java index 6a7c06bd..e21e45d7 100644 --- a/src/main/java/fox/spiteful/avaritia/crafting/Grinder.java +++ b/src/main/java/fox/spiteful/avaritia/crafting/Grinder.java @@ -483,6 +483,31 @@ public static void artsAndCrafts() { new ItemStack(Blocks.redstone_block, 1), 'O', new ItemStack(LudicrousBlocks.resource_block, 1, 0)); + + if (LudicrousBlocks.clusterOpener != null) { + ExtremeCraftingManager.getInstance().addRecipe( + new ItemStack(LudicrousBlocks.clusterOpener), + "BBBIBIBBB", + "I I", + "E X E", + "IIIIXIIII", + "E X E", + "I I", + "E IXXXI E", + "I I I I", + "BBBHHHBBB", + 'X', + // Crystal matrix ingot + new ItemStack(LudicrousItems.resource, 1, 1), + 'B', + new ItemStack(Blocks.iron_block, 1), + 'I', + new ItemStack(Items.iron_ingot, 1), + 'H', + new ItemStack(Blocks.hopper, 1), + 'E', + new ItemStack(Blocks.emerald_block, 1)); + } } } diff --git a/src/main/java/fox/spiteful/avaritia/items/ItemMatterCluster.java b/src/main/java/fox/spiteful/avaritia/items/ItemMatterCluster.java index 2d95e3d7..5baf4dd7 100644 --- a/src/main/java/fox/spiteful/avaritia/items/ItemMatterCluster.java +++ b/src/main/java/fox/spiteful/avaritia/items/ItemMatterCluster.java @@ -33,7 +33,14 @@ public class ItemMatterCluster extends Item implements ICosmicRenderItem { public static final String COUNTTAG = "count"; public static final String MAINCOUNTTAG = "total"; - public static final int MAX_CAPACITY = 64 * 256; + /// The max number of items a normal cluster will store. Avaritia tools cannot generate clusters bigger than this, + /// and this is the maximum that clusters will automatically combine into. + ///

+ /// It's possible to generate a super-critical (>max capacity) cluster via [#makeCluster(ItemStack)] for situations + /// where this limit is too low, but care should be taken to avoid allowing the player to automate those clusters + /// since they can easily be used for near-infinite item storage. + public static final int MAX_NORMAL_CAPACITY = 64 * 256; + public static final int MAX_SUPER_CRITICAL_CAPACITY = Integer.MAX_VALUE; public IIcon iconFull; public IIcon cosmicIcon; @@ -70,7 +77,9 @@ public void addInformation(ItemStack stack, EntityPlayer player, List to tooltip.add( clustertag.getInteger(MAINCOUNTTAG) + "/" - + Math.max(MAX_CAPACITY, clustertag.getInteger(MAINCOUNTTAG)) + + (clustertag.getInteger(MAINCOUNTTAG) > MAX_SUPER_CRITICAL_CAPACITY + ? MAX_SUPER_CRITICAL_CAPACITY + : MAX_NORMAL_CAPACITY) + " " + StatCollector.translateToLocal("tooltip.matter_cluster.counter")); tooltip.add(""); @@ -113,7 +122,7 @@ public static List makeClusters(List input) { ItemStackWrapper wrap = e.getKey(); int wrapcount = e.getValue(); - int count = Math.min(MAX_CAPACITY - currentTotal, wrapcount); + int count = Math.min(MAX_NORMAL_CAPACITY - currentTotal, wrapcount); if (!currentItems.containsKey(e.getKey())) { currentItems.put(wrap, count); @@ -127,7 +136,7 @@ public static List makeClusters(List input) { itemlist.remove(0); } - if (currentTotal >= MAX_CAPACITY) { + if (currentTotal == MAX_NORMAL_CAPACITY) { ItemStack cluster = makeCluster(currentItems); clusters.add(cluster); @@ -199,7 +208,7 @@ public static int getClusterSize(ItemStack cluster) { } public static boolean isClusterFull(ItemStack cluster) { - return getClusterSize(cluster) >= MAX_CAPACITY; + return getClusterSize(cluster) >= MAX_NORMAL_CAPACITY; } public static void setClusterData(ItemStack stack, Map data, int count) { @@ -225,7 +234,7 @@ public static void mergeClusters(ItemStack donor, ItemStack recipient) { int donorcount = getClusterSize(donor); int recipientcount = getClusterSize(recipient); - if (donorcount == 0 || donorcount >= MAX_CAPACITY || recipientcount >= MAX_CAPACITY) { + if (donorcount == 0 || donorcount >= MAX_NORMAL_CAPACITY || recipientcount >= MAX_NORMAL_CAPACITY) { return; } @@ -233,12 +242,12 @@ public static void mergeClusters(ItemStack donor, ItemStack recipient) { Map recipientdata = getClusterData(recipient); List> datalist = new ArrayList<>(donordata.entrySet()); - while (recipientcount < MAX_CAPACITY && donorcount > 0) { + while (recipientcount < MAX_NORMAL_CAPACITY && donorcount > 0) { Entry e = datalist.get(0); ItemStackWrapper wrap = e.getKey(); int wrapcount = e.getValue(); - int count = Math.min(MAX_CAPACITY - recipientcount, wrapcount); + int count = Math.min(MAX_NORMAL_CAPACITY - recipientcount, wrapcount); if (!recipientdata.containsKey(wrap)) { recipientdata.put(wrap, count); @@ -269,7 +278,7 @@ public static void mergeClusters(ItemStack donor, ItemStack recipient) { @Override public ItemStack onItemRightClick(ItemStack stack, World world, EntityPlayer player) { // Do nothing for super critical clusters - if (getClusterSize(stack) > MAX_CAPACITY) return stack; + if (getClusterSize(stack) > MAX_NORMAL_CAPACITY) return stack; if (!world.isRemote) { List drops = ToolHelper.collateMatterClusterContents(ItemMatterCluster.getClusterData(stack)); @@ -291,7 +300,7 @@ public ItemStack onItemRightClick(ItemStack stack, World world, EntityPlayer pla @Override public IIcon getMaskTexture(ItemStack stack, EntityPlayer player) { int count = getClusterSize(stack); - if (count >= MAX_CAPACITY) { + if (count >= MAX_NORMAL_CAPACITY) { return cosmicIconFull; } return cosmicIcon; @@ -300,13 +309,13 @@ public IIcon getMaskTexture(ItemStack stack, EntityPlayer player) { @Override public float getMaskMultiplier(ItemStack stack, EntityPlayer player) { int count = getClusterSize(stack); - return Math.min(1f, count / (float) MAX_CAPACITY); + return Math.min(1f, count / (float) MAX_NORMAL_CAPACITY); } @Override public IIcon getIcon(ItemStack stack, int pass) { int count = getClusterSize(stack); - if (count >= MAX_CAPACITY) { + if (count >= MAX_NORMAL_CAPACITY) { return iconFull; } return super.getIcon(stack, pass); @@ -320,10 +329,10 @@ public IIcon getIconIndex(ItemStack stack) { @Override public String getUnlocalizedName(ItemStack stack) { int count = getClusterSize(stack); - if (count == MAX_CAPACITY) { + if (count == MAX_NORMAL_CAPACITY) { return super.getUnlocalizedName(stack) + ".full"; } - if (count > MAX_CAPACITY) { + if (count > MAX_NORMAL_CAPACITY) { return super.getUnlocalizedName(stack) + ".veryfull"; } return super.getUnlocalizedName(stack); diff --git a/src/main/java/fox/spiteful/avaritia/items/ItemMatterClusterOpener.java b/src/main/java/fox/spiteful/avaritia/items/ItemMatterClusterOpener.java new file mode 100644 index 00000000..9f5f565e --- /dev/null +++ b/src/main/java/fox/spiteful/avaritia/items/ItemMatterClusterOpener.java @@ -0,0 +1,29 @@ +package fox.spiteful.avaritia.items; + +import java.util.List; + +import net.minecraft.block.Block; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemBlock; +import net.minecraft.item.ItemStack; +import net.minecraft.util.StatCollector; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public class ItemMatterClusterOpener extends ItemBlock { + + public ItemMatterClusterOpener(Block block) { + super(block); + } + + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, EntityPlayer player, List tooltip, boolean advanced) { + super.addInformation(stack, player, tooltip, advanced); + + tooltip.add(StatCollector.translateToLocal("tooltip.matter-cluster-decompressor.line1")); + tooltip.add(StatCollector.translateToLocal("tooltip.matter-cluster-decompressor.line2")); + tooltip.add(StatCollector.translateToLocal("tooltip.matter-cluster-decompressor.line3")); + } +} diff --git a/src/main/java/fox/spiteful/avaritia/tile/TileMatterClusterOpener.java b/src/main/java/fox/spiteful/avaritia/tile/TileMatterClusterOpener.java new file mode 100644 index 00000000..510f913e --- /dev/null +++ b/src/main/java/fox/spiteful/avaritia/tile/TileMatterClusterOpener.java @@ -0,0 +1,401 @@ +package fox.spiteful.avaritia.tile; + +import java.util.Map; + +import net.minecraft.entity.item.EntityItem; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.ISidedInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.util.ForgeDirection; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.FluidTank; +import net.minecraftforge.fluids.FluidTankInfo; +import net.minecraftforge.fluids.IFluidHandler; +import net.minecraftforge.oredict.OreDictionary; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import com.cleanroommc.modularui.api.IGuiHolder; +import com.cleanroommc.modularui.drawable.AdaptableUITexture; +import com.cleanroommc.modularui.drawable.GuiTextures; +import com.cleanroommc.modularui.drawable.UITexture; +import com.cleanroommc.modularui.factory.PosGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.screen.UISettings; +import com.cleanroommc.modularui.utils.Alignment; +import com.cleanroommc.modularui.utils.item.IItemHandlerModifiable; +import com.cleanroommc.modularui.utils.item.InvWrapper; +import com.cleanroommc.modularui.value.sync.PanelSyncManager; +import com.cleanroommc.modularui.widgets.SlotGroupWidget; +import com.cleanroommc.modularui.widgets.TextWidget; +import com.cleanroommc.modularui.widgets.layout.Column; +import com.cleanroommc.modularui.widgets.layout.Row; +import com.cleanroommc.modularui.widgets.slot.FluidSlot; +import com.cleanroommc.modularui.widgets.slot.ItemSlot; +import com.cleanroommc.modularui.widgets.slot.ModularSlot; +import com.glodblock.github.common.item.ItemFluidDrop; +import com.gtnewhorizon.gtnhlib.capability.CapabilityProvider; +import com.gtnewhorizon.gtnhlib.capability.item.ItemSink; +import com.gtnewhorizon.gtnhlib.capability.item.ItemSource; +import com.gtnewhorizon.gtnhlib.item.InventoryItemSink; +import com.gtnewhorizon.gtnhlib.item.InventoryItemSource; +import com.gtnewhorizon.gtnhlib.util.ItemUtil; +import com.gtnewhorizon.gtnhlib.util.data.LazyItem; + +import fox.spiteful.avaritia.Mods; +import fox.spiteful.avaritia.items.ItemMatterCluster; +import fox.spiteful.avaritia.items.ItemStackWrapper; + +public class TileMatterClusterOpener extends TileEntity + implements ISidedInventory, CapabilityProvider, IGuiHolder, IFluidHandler { + + private ItemStack clusterInput, itemOutput; + private final FluidTank fluidOutput = new FluidTank(Integer.MAX_VALUE); + + private static final LazyItem FLUID_DROPS = new LazyItem( + Mods.AE2FluidCraft, + "fluid_drop", + OreDictionary.WILDCARD_VALUE); + + private static final int[] INPUT_SLOTS = { 0 }; + private static final int[] OUTPUT_SLOTS = { 1 }; + + @Override + public void updateEntity() { + super.updateEntity(); + + if (worldObj.isRemote) return; + + if (clusterInput != null && clusterInput.stackSize <= 0) { + clusterInput = null; + markDirty(); + } + + if (itemOutput != null && itemOutput.stackSize <= 0) { + itemOutput = null; + markDirty(); + } + + if (fluidOutput.getFluid() != null && fluidOutput.getFluidAmount() <= 0) { + fluidOutput.setFluid(null); + markDirty(); + } + + if (clusterInput == null) return; + if (itemOutput != null || fluidOutput.getFluid() != null) return; + + Map contents = ItemMatterCluster.getClusterData(clusterInput); + + if (contents.isEmpty()) return; + + var iter = contents.entrySet().iterator(); + + var e = iter.next(); + iter.remove(); + + if (contents.isEmpty()) { + clusterInput = null; + } else { + ItemMatterCluster.setClusterData(clusterInput, contents, contents.values().stream().mapToInt(i -> i).sum()); + } + + itemOutput = ItemUtil.copyAmount(e.getValue(), e.getKey().stack); + + if (FLUID_DROPS.isLoaded() && FLUID_DROPS.matches(itemOutput)) { + fluidOutput.setFluid(ItemFluidDrop.getFluidStack(itemOutput)); + itemOutput = null; + } + + markDirty(); + } + + @Override + public void writeToNBT(NBTTagCompound compound) { + super.writeToNBT(compound); + + if (clusterInput != null) { + compound.setTag("clusterInput", clusterInput.writeToNBT(new NBTTagCompound())); + } + + if (itemOutput != null) { + compound.setTag("itemOutput", itemOutput.writeToNBT(new NBTTagCompound())); + } + + if (fluidOutput.getFluid() != null) { + compound.setTag("fluidOutput", fluidOutput.getFluid().writeToNBT(new NBTTagCompound())); + } + } + + @Override + public void readFromNBT(NBTTagCompound compound) { + super.readFromNBT(compound); + + clusterInput = null; + itemOutput = null; + fluidOutput.setFluid(null); + + if (compound.hasKey("clusterInput")) { + clusterInput = ItemStack.loadItemStackFromNBT(compound.getCompoundTag("clusterInput")); + } + + if (compound.hasKey("itemOutput")) { + itemOutput = ItemStack.loadItemStackFromNBT(compound.getCompoundTag("itemOutput")); + } + + if (compound.hasKey("fluidOutput")) { + fluidOutput.setFluid(FluidStack.loadFluidStackFromNBT(compound.getCompoundTag("fluidOutput"))); + } + } + + public void dropContents() { + if (clusterInput != null) { + EntityItem item = new EntityItem(worldObj, xCoord + 0.5, yCoord + 0.5, zCoord + 0.5, clusterInput); + worldObj.spawnEntityInWorld(item); + clusterInput = null; + } + + if (itemOutput != null) { + ItemStack cluster = ItemMatterCluster.makeCluster(itemOutput); + itemOutput = null; + + EntityItem item = new EntityItem(worldObj, xCoord + 0.5, yCoord + 0.5, zCoord + 0.5, cluster); + worldObj.spawnEntityInWorld(item); + } + + if (FLUID_DROPS.isLoaded() && fluidOutput.getFluidAmount() > 0) { + ItemStack drops = ItemFluidDrop.newStack(fluidOutput.getFluid()); + fluidOutput.setFluid(null); + + assert drops != null; + ItemStack cluster = ItemMatterCluster.makeCluster(drops); + + EntityItem item = new EntityItem(worldObj, xCoord + 0.5, yCoord + 0.5, zCoord + 0.5, cluster); + worldObj.spawnEntityInWorld(item); + } + } + + @Override + public @Nullable T getCapability(@NotNull Class capability, @NotNull ForgeDirection side) { + if (capability == ItemSource.class) { + return capability.cast(new OutputSlotSource()); + } + + if (capability == ItemSink.class) { + return capability.cast(new InventoryItemSink(this, side)); + } + + return null; + } + + private class OutputSlotSource extends InventoryItemSource { + + public OutputSlotSource() { + super(TileMatterClusterOpener.this, ForgeDirection.UNKNOWN); + } + + @Override + protected int[] getSlots() { + return OUTPUT_SLOTS; + } + } + + @Override + public int[] getAccessibleSlotsFromSide(int side) { + return INPUT_SLOTS; + } + + @Override + public boolean canInsertItem(int slotIndex, ItemStack stack, int side) { + return slotIndex == 0; + } + + @Override + public boolean canExtractItem(int slotIndex, ItemStack stack, int side) { + return slotIndex == 0; + } + + @Override + public int getSizeInventory() { + return 2; + } + + @Override + public ItemStack getStackInSlot(int slotIn) { + if (slotIn == 0) return clusterInput; + if (slotIn == 1) return itemOutput; + + return null; + } + + @Override + public ItemStack decrStackSize(int index, int count) { + if (index != 0) return null; + if (clusterInput == null) return null; + + int removable = Math.min(count, clusterInput.stackSize); + + ItemStack out = clusterInput.splitStack(removable); + + if (ItemUtil.isStackEmpty(clusterInput)) clusterInput = null; + + markDirty(); + + return out; + } + + @Override + public ItemStack getStackInSlotOnClosing(int index) { + return decrStackSize(index, Integer.MAX_VALUE); + } + + @Override + public void setInventorySlotContents(int index, ItemStack stack) { + if (index == 0) { + clusterInput = stack; + } + + if (index == 1) { + itemOutput = stack; + } + } + + @Override + public String getInventoryName() { + return getBlockType().getLocalizedName(); + } + + @Override + public boolean hasCustomInventoryName() { + return false; + } + + @Override + public int getInventoryStackLimit() { + return 1; + } + + @Override + public boolean isUseableByPlayer(EntityPlayer player) { + return true; + } + + @Override + public void openInventory() { + + } + + @Override + public void closeInventory() { + + } + + @Override + public boolean isItemValidForSlot(int index, ItemStack stack) { + if (index == 0) { + return stack.getItem() instanceof ItemMatterCluster; + } else if (index == 1) { + return true; + } else { + return false; + } + } + + @Override + public int fill(ForgeDirection from, FluidStack resource, boolean doFill) { + return 0; + } + + @Override + public boolean canFill(ForgeDirection from, Fluid fluid) { + return false; + } + + @Override + public boolean canDrain(ForgeDirection from, Fluid fluid) { + return fluidOutput.getFluid() != null && fluidOutput.getFluid().getFluid() == fluid; + } + + @Override + public FluidStack drain(ForgeDirection from, FluidStack resource, boolean doDrain) { + FluidStack stored = fluidOutput.getFluid(); + + if (stored == null || stored.amount <= 0) return null; + if (stored.getFluid() != resource.getFluid()) return null; + + return drain(from, resource.amount, doDrain); + } + + @Override + public FluidStack drain(ForgeDirection from, int maxDrain, boolean doDrain) { + FluidStack stored = fluidOutput.getFluid(); + + if (stored == null || stored.amount <= 0) return null; + + int removable = Math.min(stored.amount, maxDrain); + + FluidStack out = new FluidStack(stored.getFluid(), removable); + + if (doDrain) { + stored.amount -= removable; + + if (stored.amount <= 0) { + fluidOutput.setFluid(null); + } + + markDirty(); + } + + return out; + } + + @Override + public FluidTankInfo[] getTankInfo(ForgeDirection from) { + return new FluidTankInfo[] { fluidOutput.getInfo() }; + } + + public static final UITexture CLUSTER_SLOT_BACKGROUND = AdaptableUITexture.builder() + .location("avaritia", "gui/slot/cluster_background.png").imageSize(16, 16).build(); + + @Override + public ModularPanel buildUI(PosGuiData data, PanelSyncManager syncManager, UISettings settings) { + IItemHandlerModifiable inv = new InvWrapper(this); + + syncManager.registerSlotGroup("input", 1, 150); + syncManager.registerSlotGroup("output", 1, false); + + // spotless:off + return new ModularPanel("ClusterOpener") + .size(178, 152) + .padding(8) + .child(new Column() + .sizeRel(1) + .expanded() + .child(new TextWidget<>(getInventoryName()).height(16).alignX(0.5f).align(Alignment.TopCenter)) + .child(new Row().widthRel(1) + .alignX(0.5f) + .expanded() + .child(new ItemSlot() + .alignY(0.5f) + .leftRel(0.5f, -18, 0.5f) + .slot(new ModularSlot(inv, 0).slotGroup("input")) + .background(GuiTextures.SLOT_ITEM, CLUSTER_SLOT_BACKGROUND)) + .child(new ItemSlot() + .alignY(0.5f) + .leftRel(0.5f, 18, 0.5f) + .slot(new ModularSlot(inv, 1).slotGroup("output").accessibility(false, false))) + .child(new FluidSlot() + .alignY(0.5f) + .leftRel(0.5f, 36, 0.5f) + .syncHandler(fluidOutput))) + .child(new Row() + .widthRel(1) + .height(76) + .alignX(0.5f) + .child(SlotGroupWidget.playerInventory(false)))); + // spotless:on + } +} diff --git a/src/main/resources/assets/avaritia/lang/en_US.lang b/src/main/resources/assets/avaritia/lang/en_US.lang index 701a6e09..59d9fe5b 100644 --- a/src/main/resources/assets/avaritia/lang/en_US.lang +++ b/src/main/resources/assets/avaritia/lang/en_US.lang @@ -68,6 +68,7 @@ tile.alfheim_deadrock1.name=Deadrock Brick tile.alfheim_deadrock2.name=Mossy Deadrock Brick tile.alfheim_deadrock3.name=Cracked Deadrock Brick tile.alfheim_deadrock4.name=Chiselled Deadrock +tile.cluster_opener.name=Matter Cluster Decompressor # # Tooltips tooltip.armok.desc=Always contains maximum Life Essence @@ -89,6 +90,9 @@ tooltip.matter_cluster.counter=items tooltip.morvinabox.desc=Instant housing tooltip.morvinabox.subdesc=In Canada, Morvy comes in bags. tooltip.claybalance.desc=UNLIMITED BALANCE!!!! +tooltip.matter-cluster-decompressor.line1=Extracts items from Matter Clusters. +tooltip.matter-cluster-decompressor.line2=Only GT and AE can pull items from decompressors. +tooltip.matter-cluster-decompressor.line3=Fluid drops will be converted to fluids automatically. # # Achievements achievement.avaritia:crystal_matrix=The First Seal diff --git a/src/main/resources/assets/avaritia/textures/blocks/cluster_opener/front.png b/src/main/resources/assets/avaritia/textures/blocks/cluster_opener/front.png new file mode 100644 index 00000000..acf2cfcf Binary files /dev/null and b/src/main/resources/assets/avaritia/textures/blocks/cluster_opener/front.png differ diff --git a/src/main/resources/assets/avaritia/textures/blocks/cluster_opener/front.png.mcmeta b/src/main/resources/assets/avaritia/textures/blocks/cluster_opener/front.png.mcmeta new file mode 100644 index 00000000..96c0529b --- /dev/null +++ b/src/main/resources/assets/avaritia/textures/blocks/cluster_opener/front.png.mcmeta @@ -0,0 +1,17 @@ +{ + "animation": { + "frametime": 2, + "frames": [ + 0, + 0, + 1, + 2, + 3, + 3, + 2, + 2, + 1, + 1 + ] + } +} diff --git a/src/main/resources/assets/avaritia/textures/blocks/cluster_opener/side.png b/src/main/resources/assets/avaritia/textures/blocks/cluster_opener/side.png new file mode 100644 index 00000000..2576c387 Binary files /dev/null and b/src/main/resources/assets/avaritia/textures/blocks/cluster_opener/side.png differ diff --git a/src/main/resources/assets/avaritia/textures/blocks/cluster_opener/top.png b/src/main/resources/assets/avaritia/textures/blocks/cluster_opener/top.png new file mode 100644 index 00000000..83c9e094 Binary files /dev/null and b/src/main/resources/assets/avaritia/textures/blocks/cluster_opener/top.png differ diff --git a/src/main/resources/assets/avaritia/textures/gui/slot/cluster_background.png b/src/main/resources/assets/avaritia/textures/gui/slot/cluster_background.png new file mode 100644 index 00000000..85d5503c Binary files /dev/null and b/src/main/resources/assets/avaritia/textures/gui/slot/cluster_background.png differ