diff --git a/src/main/java/api/hbm/block/ICrucibleAcceptor.java b/src/main/java/api/hbm/block/ICrucibleAcceptor.java index 2ecfcd1ee..0f140f941 100644 --- a/src/main/java/api/hbm/block/ICrucibleAcceptor.java +++ b/src/main/java/api/hbm/block/ICrucibleAcceptor.java @@ -1,13 +1,7 @@ package api.hbm.block; -import java.util.List; - import com.hbm.inventory.material.Mats.MaterialStack; -import com.hbm.inventory.material.NTMMaterial.SmeltingBehavior; -import net.minecraft.block.Block; -import net.minecraft.util.MovingObjectPosition; -import net.minecraft.util.Vec3; import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; @@ -28,81 +22,4 @@ public interface ICrucibleAcceptor { //public boolean canAcceptFlow(World world, int x, int y, int z, ForgeDirection side, MaterialStack stack); public boolean canAcceptPartialFlow(World world, int x, int y, int z, ForgeDirection side, MaterialStack stack); public MaterialStack flow(World world, int x, int y, int z, ForgeDirection side, MaterialStack stack); - - /** - * Standard pouring, casting a hitscan straight down at the given coordinates with the given range. Returns the materialStack that has been removed. - * The method doesn't make copies of the MaterialStacks in the list, so the materials being subtracted or outright removed will apply to the original list. - */ - public static MaterialStack tryPour(World world, double x, double y, double z, double range, boolean safe, List stacks, int quanta, Vec3 impactPos) { - - if(stacks.isEmpty()) return null; - - Vec3 start = Vec3.createVectorHelper(x, y, z); - Vec3 end = Vec3.createVectorHelper(x, y - range, z); - - MovingObjectPosition mop = world.func_147447_a(start, end, true, true, true); - - //if the pour misses - if(mop == null || mop.typeOfHit != mop.typeOfHit.BLOCK) { - return spill(mop, safe, stacks, quanta, impactPos); - } - - Block b = world.getBlock(mop.blockX, mop.blockY, mop.blockZ); - - if(!(b instanceof ICrucibleAcceptor)) { - return spill(mop, safe, stacks, quanta, impactPos); - } - - ICrucibleAcceptor acc = (ICrucibleAcceptor) b; - Vec3 hit = mop.hitVec; - MaterialStack pouredStack = null; - - for(MaterialStack stack : stacks) { - - if(stack.material.smeltable != SmeltingBehavior.SMELTABLE) { - continue; - } - - if(acc.canAcceptPartialPour(world, mop.blockX, mop.blockY, mop.blockZ, hit.xCoord, hit.yCoord, hit.zCoord, ForgeDirection.getOrientation(mop.sideHit), stack)) { - MaterialStack left = acc.pour(world, mop.blockX, mop.blockY, mop.blockZ, hit.xCoord, hit.yCoord, hit.zCoord, ForgeDirection.getOrientation(mop.sideHit), stack); - if(left == null) { - left = new MaterialStack(stack.material, 0); - } - - pouredStack = new MaterialStack(stack.material, stack.amount - left.amount); - stack.amount -= pouredStack.amount; - impactPos.xCoord = hit.xCoord; - impactPos.yCoord = hit.yCoord; - impactPos.zCoord = hit.zCoord; - - break; - } - } - - return pouredStack; - } - - public static MaterialStack spill(MovingObjectPosition mop, boolean safe, List stacks, int quanta, Vec3 impactPos) { - - //do nothing if safe mode is on - if(safe) { - return null; - } - - //simply use the first available material - MaterialStack top = stacks.get(0); - MaterialStack toWaste = new MaterialStack(top.material, Math.min(top.amount, quanta)); - top.amount -= toWaste.amount; - //remove all stacks with no content - stacks.removeIf(o -> o.amount <= 0); - - //if there is a vec3 reference, set the impact coordinates - if(impactPos != null && mop != null) { - impactPos.xCoord = mop.hitVec.xCoord; - impactPos.yCoord = mop.hitVec.yCoord; - impactPos.zCoord = mop.hitVec.zCoord; - } - - return toWaste; - } } diff --git a/src/main/java/com/hbm/inventory/container/ContainerRBMKStorage.java b/src/main/java/com/hbm/inventory/container/ContainerRBMKStorage.java index 63c0ededf..d20200a80 100644 --- a/src/main/java/com/hbm/inventory/container/ContainerRBMKStorage.java +++ b/src/main/java/com/hbm/inventory/container/ContainerRBMKStorage.java @@ -33,7 +33,7 @@ public class ContainerRBMKStorage extends Container { } @Override - public ItemStack transferStackInSlot(EntityPlayer p_82846_1_, int par2) { + public ItemStack transferStackInSlot(EntityPlayer player, int par2) { ItemStack var3 = null; Slot var4 = (Slot) this.inventorySlots.get(par2); @@ -41,7 +41,7 @@ public class ContainerRBMKStorage extends Container { ItemStack var5 = var4.getStack(); var3 = var5.copy(); - if(par2 == 0) { + if(par2 < 12) { if(!this.mergeItemStack(var5, rbmk.getSizeInventory(), this.inventorySlots.size(), true)) { return null; } diff --git a/src/main/java/com/hbm/tileentity/machine/TileEntityCrucible.java b/src/main/java/com/hbm/tileentity/machine/TileEntityCrucible.java index 0f31dd73c..0bea94db6 100644 --- a/src/main/java/com/hbm/tileentity/machine/TileEntityCrucible.java +++ b/src/main/java/com/hbm/tileentity/machine/TileEntityCrucible.java @@ -15,8 +15,8 @@ import com.hbm.inventory.recipes.CrucibleRecipes.CrucibleRecipe; import com.hbm.items.ModItems; import com.hbm.tileentity.IGUIProvider; import com.hbm.tileentity.TileEntityMachineBase; +import com.hbm.util.CrucibleUtil; -import api.hbm.block.ICrucibleAcceptor; import api.hbm.tile.IHeatSource; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; @@ -98,7 +98,7 @@ public class TileEntityCrucible extends TileEntityMachineBase implements IGUIPro ForgeDirection dir = ForgeDirection.getOrientation(this.getBlockMetadata() - BlockDummyable.offset).getOpposite(); Vec3 impact = Vec3.createVectorHelper(0, 0, 0); - ICrucibleAcceptor.tryPour(worldObj, xCoord + 0.5D + dir.offsetX * 1.875D, yCoord + 0.25D, zCoord + 0.5D + dir.offsetZ * 1.875D, 6, true, this.wasteStack, MaterialShapes.NUGGET.q(1), impact); + CrucibleUtil.pourFullStack(worldObj, xCoord + 0.5D + dir.offsetX * 1.875D, yCoord + 0.25D, zCoord + 0.5D + dir.offsetZ * 1.875D, 6, true, this.wasteStack, MaterialShapes.NUGGET.q(1), impact); } if(!this.recipeStack.isEmpty()) { @@ -123,7 +123,7 @@ public class TileEntityCrucible extends TileEntityMachineBase implements IGUIPro } Vec3 impact = Vec3.createVectorHelper(0, 0, 0); - ICrucibleAcceptor.tryPour(worldObj, xCoord + 0.5D + dir.offsetX * 1.875D, yCoord + 0.25D, zCoord + 0.5D + dir.offsetZ * 1.875D, 6, true, toCast, MaterialShapes.NUGGET.q(1), impact); + CrucibleUtil.pourFullStack(worldObj, xCoord + 0.5D + dir.offsetX * 1.875D, yCoord + 0.25D, zCoord + 0.5D + dir.offsetZ * 1.875D, 6, true, toCast, MaterialShapes.NUGGET.q(1), impact); } this.recipeStack.removeIf(o -> o.amount <= 0); diff --git a/src/main/java/com/hbm/tileentity/machine/TileEntityFoundryOutlet.java b/src/main/java/com/hbm/tileentity/machine/TileEntityFoundryOutlet.java index 8b029c69f..f1e906650 100644 --- a/src/main/java/com/hbm/tileentity/machine/TileEntityFoundryOutlet.java +++ b/src/main/java/com/hbm/tileentity/machine/TileEntityFoundryOutlet.java @@ -2,6 +2,7 @@ package com.hbm.tileentity.machine; import com.hbm.inventory.material.Mats.MaterialStack; +import api.hbm.block.ICrucibleAcceptor; import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; @@ -10,6 +11,16 @@ public class TileEntityFoundryOutlet extends TileEntityFoundryBase { @Override public boolean canAcceptPartialPour(World world, int x, int y, int z, double dX, double dY, double dZ, ForgeDirection side, MaterialStack stack) { return false; } @Override public MaterialStack pour(World world, int x, int y, int z, double dX, double dY, double dZ, ForgeDirection side, MaterialStack stack) { return stack; } + @Override + public boolean canAcceptPartialFlow(World world, int x, int y, int z, ForgeDirection side, MaterialStack stack) { + return this.standardCheck(world, x, y, z, side, stack); + } + + @Override + public MaterialStack flow(World world, int x, int y, int z, ForgeDirection side, MaterialStack stack) { + return standardAdd(world, x, y, z, side, stack); + } + @Override public int getCapacity() { return 0; diff --git a/src/main/java/com/hbm/util/CrucibleUtil.java b/src/main/java/com/hbm/util/CrucibleUtil.java new file mode 100644 index 000000000..7b79b5908 --- /dev/null +++ b/src/main/java/com/hbm/util/CrucibleUtil.java @@ -0,0 +1,166 @@ +package com.hbm.util; + +import java.util.List; + +import com.hbm.inventory.material.Mats.MaterialStack; +import com.hbm.inventory.material.NTMMaterial.SmeltingBehavior; + +import api.hbm.block.ICrucibleAcceptor; +import net.minecraft.block.Block; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.util.Vec3; +import net.minecraft.world.World; +import net.minecraftforge.common.util.ForgeDirection; + +public class CrucibleUtil { + + /** + * Standard pouring, casting a hitscan straight down at the given coordinates with the given range. Returns the leftover material, just like ICrucibleAcceptor's pour. + * The method directly modifies the original stack, so be careful and make a copy beforehand if you don't want that. + * Pass an empty Vec3 instance in order to get the impact position of the stream. + */ + public static MaterialStack pourSingleStack(World world, double x, double y, double z, double range, boolean safe, MaterialStack stack, int quanta, Vec3 impactPosHolder) { + + + Vec3 start = Vec3.createVectorHelper(x, y, z); + Vec3 end = Vec3.createVectorHelper(x, y - range, z); + + MovingObjectPosition[] mopHolder = new MovingObjectPosition[1]; + ICrucibleAcceptor acc = getPouringTarget(world, start, end, mopHolder); + MovingObjectPosition mop = mopHolder[0]; + + if(acc == null) { + spill(mop, safe, stack, quanta, impactPosHolder); + return stack; + } + + MaterialStack ret = tryPourStack(world, acc, mop, stack, impactPosHolder); + + if(ret != null) { + return ret; + } + + spill(mop, safe, stack, quanta, impactPosHolder); + return stack; + } + + /** + * Standard pouring, casting a hitscan straight down at the given coordinates with the given range. Returns the materialStack that has been removed. + * The method doesn't make copies of the MaterialStacks in the list, so the materials being subtracted or outright removed will apply to the original list. + * Pass an empty Vec3 instance in order to get the impact position of the stream. + */ + public static MaterialStack pourFullStack(World world, double x, double y, double z, double range, boolean safe, List stacks, int quanta, Vec3 impactPosHolder) { + + if(stacks.isEmpty()) return null; + + Vec3 start = Vec3.createVectorHelper(x, y, z); + Vec3 end = Vec3.createVectorHelper(x, y - range, z); + + MovingObjectPosition[] mopHolder = new MovingObjectPosition[1]; + ICrucibleAcceptor acc = getPouringTarget(world, start, end, mopHolder); + MovingObjectPosition mop = mopHolder[0]; + + if(acc == null) { + return spill(mop, safe, stacks, quanta, impactPosHolder); + } + + for(MaterialStack stack : stacks) { + + MaterialStack left = tryPourStack(world, acc, mop, stack, impactPosHolder); + + if(left != null) { + return new MaterialStack(stack.material, stack.amount - left.amount); + } + } + + return spill(mop, safe, stacks, quanta, impactPosHolder); + } + + /** + * Tries to pour the stack onto the supplied crucible acceptor instance. Also features our friend the Vec3 dummy, which will be filled with the stream's impact position. + * Returns whatever is left of the stack when successful or null when unsuccessful (potential spillage). + */ + public static MaterialStack tryPourStack(World world, ICrucibleAcceptor acc, MovingObjectPosition mop, MaterialStack stack, Vec3 impactPosHolder) { + Vec3 hit = mop.hitVec; + + if(stack.material.smeltable != SmeltingBehavior.SMELTABLE) { + return null; + } + + if(acc.canAcceptPartialPour(world, mop.blockX, mop.blockY, mop.blockZ, hit.xCoord, hit.yCoord, hit.zCoord, ForgeDirection.getOrientation(mop.sideHit), stack)) { + MaterialStack left = acc.pour(world, mop.blockX, mop.blockY, mop.blockZ, hit.xCoord, hit.yCoord, hit.zCoord, ForgeDirection.getOrientation(mop.sideHit), stack); + if(left == null) { + left = new MaterialStack(stack.material, 0); + } + + impactPosHolder.xCoord = hit.xCoord; + impactPosHolder.yCoord = hit.yCoord; + impactPosHolder.zCoord = hit.zCoord; + + return left; + } + + return null; + } + + /** + * Uses hitscan to find the target of the pour, from start (the top) to end (the bottom). Pass a single cell MOP array to get the reference of the MOP for later use. + * Now we're thinking with reference types. + */ + public static ICrucibleAcceptor getPouringTarget(World world, Vec3 start, Vec3 end, MovingObjectPosition[] mopHolder) { + + MovingObjectPosition mop = world.func_147447_a(start, end, true, true, true); + + if(mopHolder != null) { + mopHolder[0] = mop; + } + + if(mop == null || mop.typeOfHit != mop.typeOfHit.BLOCK) { + return null; + } + + Block b = world.getBlock(mop.blockX, mop.blockY, mop.blockZ); + + if(!(b instanceof ICrucibleAcceptor)) { + return null; + } + + return (ICrucibleAcceptor) b; + } + + /** + * Regular spillage routine but accepts a stack list instead of a stack. simply uses the first available stack from the list. Assumes list is not empty. + */ + public static MaterialStack spill(MovingObjectPosition mop, boolean safe, List stacks, int quanta, Vec3 impactPos) { + //simply use the first available material + MaterialStack top = stacks.get(0); + MaterialStack ret = spill(mop, safe, top, quanta, impactPos); + //remove all stacks with no content + stacks.removeIf(o -> o.amount <= 0); + + return ret; + } + + /** + * The routine used for then there is no valid crucible acceptor found. Will NOP with safe mode on. Returns the MaterialStack that was lost. + */ + public static MaterialStack spill(MovingObjectPosition mop, boolean safe, MaterialStack stack, int quanta, Vec3 impactPos) { + + //do nothing if safe mode is on + if(safe) { + return null; + } + + MaterialStack toWaste = new MaterialStack(stack.material, Math.min(stack.amount, quanta)); + stack.amount -= toWaste.amount; + + //if there is a vec3 reference, set the impact coordinates + if(impactPos != null && mop != null) { + impactPos.xCoord = mop.hitVec.xCoord; + impactPos.yCoord = mop.hitVec.yCoord; + impactPos.zCoord = mop.hitVec.zCoord; + } + + return toWaste; + } +}