diff options
Diffstat (limited to 'src/main/java/gregtech/api')
32 files changed, 2118 insertions, 536 deletions
diff --git a/src/main/java/gregtech/api/enums/GT_Values.java b/src/main/java/gregtech/api/enums/GT_Values.java index a6a7d6d45c..8406018707 100644 --- a/src/main/java/gregtech/api/enums/GT_Values.java +++ b/src/main/java/gregtech/api/enums/GT_Values.java @@ -307,7 +307,7 @@ public class GT_Values { TANK_CAPACITY = "gt.tankcap", // Number TANK_IN = "gt.tank.in.", // FluidStack TANK_OUT = "gt.tank.out.", // FluidStack - TEXTURE = "gt.texture", // String + TEXTURE_FOLDER = "gt.texture.folder", // String INV_INPUT_SIZE = "gt.invsize.in", // Number INV_OUTPUT_SIZE = "gt.invsize.out", // Number INV_INPUT_LIST = "gt.invlist.in", // NBT List @@ -326,22 +326,34 @@ public class GT_Values { TARGET_X = "gt.target.x", // Number TARGET_Y = "gt.target.y", // Number TARGET_Z = "gt.target.z", // Number - LOCKED_INVENTORY = "gt.locked.inventory", // String - LOCKED_INVENTORY_INDEX = "gt.locked.inventory.index", // Number + LOCKED_FLUID = "gt.locked.fluid", // String + LOCKED_INVENTORY = "gt.locked.inv", // String + LOCKED_INVENTORY_INDEX = "gt.locked.inv.index", // Number UPGRADE_INVENTORY_SIZE = "gt.invsize.upg", // String UPGRADE_INVENTORY_UUID = "gt.invuuid.upg", // String UPGRADE_INVENTORY_NAME = "gt.invname.upg", // String UPGRADE_INVENTORIES_INPUT = "gt.invlist.upg.in", // NBT List UPGRADE_INVENTORIES_OUTPUT = "gt.invlist.upg.out", // NBT List + UPGRADE_TANK_CAPACITY = "gt.tank.cap.upg", // Long + UPGRADE_TANK_CAPACITY_MULTIPLIER = "gt.tank.cap.mult.upg", // Long + UPGRADE_TANK_UUID = "gt.tankuuid.upg", // String + UPGRADE_TANK_NAME = "gt.tankname.upg", // String + UPGRADE_TANKS_INPUT = "gt.tanklist.upg.in", // NBT List + UPGRADE_TANKS_OUTPUT = "gt.tanklist.upg.out", // NBT List + UPGRADE_TANKS_COUNT = "gt.tankcount.upg", // Int + UPGRADE_TANKS_PREFIX = "gt.tank.upg", // NBT Tag SEPARATE_INPUTS = "gt.separate.inputs", // Boolean + VOID_EXCESS = "gt.void.excess", // Boolean + BATCH_MODE = "gt.batch.mode", // Boolean + RECIPE_LOCK = "gt.recipe.lock", // Boolean // Logic - POWER_LOGIC = "gt.power.logic", // NBT Tag - POWER_LOGIC_STORED_ENERGY = "gt.power.logic.stored.energy", // Number - POWER_LOGIC_ENERGY_CAPACITY = "gt.power.logic.energy.capacity", // Number - POWER_LOGIC_VOLTAGE = "gt.power.logic.voltage", // Number - POWER_LOGIC_AMPERAGE = "gt.power.logic.voltage", // Number - POWER_LOGIC_TYPE = "gt.power.logic.type", // Number + POWER_LOGIC = "gt.pow.logic", // NBT Tag + POWER_LOGIC_STORED_ENERGY = "gt.pow.energy", // Number + POWER_LOGIC_ENERGY_CAPACITY = "gt.pow.energy.cap", // Number + POWER_LOGIC_VOLTAGE = "gt.pow.volt", // Number + POWER_LOGIC_AMPERAGE = "gt.pow.amp", // Number + POWER_LOGIC_TYPE = "gt.pow.type", // Number empty_ = ""; } @@ -588,6 +600,10 @@ public class GT_Values { + EnumChatFormatting.BOLD + "Weabo"; + public static final String Authorminecraft7771 = "Author: " + EnumChatFormatting.BLUE + + EnumChatFormatting.LIGHT_PURPLE + + "minecraft7771"; + // 7.5F comes from GT_Tool_Turbine_Large#getBaseDamage() given huge turbines are the most efficient now. public static double getMaxPlasmaTurbineEfficiencyFromMaterial(Materials material) { return (5F + (7.5F + material.mToolQuality)) / 10.0; diff --git a/src/main/java/gregtech/api/fluid/FluidTankGT.java b/src/main/java/gregtech/api/fluid/FluidTankGT.java index 801354ac86..2102f725ae 100644 --- a/src/main/java/gregtech/api/fluid/FluidTankGT.java +++ b/src/main/java/gregtech/api/fluid/FluidTankGT.java @@ -2,6 +2,8 @@ package gregtech.api.fluid; import static com.google.common.primitives.Ints.saturatedCast; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import net.minecraft.nbt.NBTTagCompound; @@ -446,8 +448,25 @@ public class FluidTankGT implements IFluidTank { return saturatedCast(capacity()); } + public long getCapacityMultiplier() { + return mAdjustableMultiplier; + } + @Override public FluidTankInfo getInfo() { return new FluidTankInfo(isEmpty() ? null : mFluid.copy(), saturatedCast(capacity())); } + + public static FluidStack[] getFluidsFromTanks(FluidTankGT[] tanks) { + if (tanks == null) { + return null; + } + List<FluidStack> fluidStacks = new ArrayList<>(); + for (FluidTankGT tank : tanks) { + if (tank.getFluid() != null) { + fluidStacks.add(tank.getFluid()); + } + } + return fluidStacks.toArray(new FluidStack[0]); + } } diff --git a/src/main/java/gregtech/api/interfaces/tileentity/IEnergyConnected.java b/src/main/java/gregtech/api/interfaces/tileentity/IEnergyConnected.java index 14ead4e4ee..55de2db088 100644 --- a/src/main/java/gregtech/api/interfaces/tileentity/IEnergyConnected.java +++ b/src/main/java/gregtech/api/interfaces/tileentity/IEnergyConnected.java @@ -73,7 +73,7 @@ public interface IEnergyConnected extends IColoredTileEntity { final TileEntity tTileEntity = emitterTile.getTileEntityAtSide(i); if (tTileEntity instanceof PowerLogicHost host) { - PowerLogic logic = host.getPowerLogic(j); + PowerLogic logic = host.getPowerLogic(ForgeDirection.getOrientation(j)); if (logic == null || logic.isEnergyReceiver()) { continue; } diff --git a/src/main/java/gregtech/api/logic/ComplexParallelProcessingLogic.java b/src/main/java/gregtech/api/logic/ComplexParallelProcessingLogic.java new file mode 100644 index 0000000000..d38a3d98fd --- /dev/null +++ b/src/main/java/gregtech/api/logic/ComplexParallelProcessingLogic.java @@ -0,0 +1,183 @@ +package gregtech.api.logic; + +import java.util.stream.LongStream; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.FluidStack; + +import gregtech.api.multitileentity.multiblock.base.Controller; +import gregtech.api.util.GT_OverclockCalculator; +import gregtech.api.util.GT_ParallelHelper; +import gregtech.api.util.GT_Recipe; + +public class ComplexParallelProcessingLogic { + + protected Controller<?> tileEntity; + protected GT_Recipe.GT_Recipe_Map recipeMap; + protected boolean hasPerfectOverclock; + protected final int maxComplexParallels; + protected final ItemStack[][] outputItems; + protected final ItemStack[][] inputItems; + protected final FluidStack[][] inputFluids; + protected final FluidStack[][] outputFluids; + protected final long[] availableEut; + protected final long[] eut; + protected final long[] durations; + protected boolean[] isVoidProtected; + + public ComplexParallelProcessingLogic(int maxComplexParallels) { + this(null, maxComplexParallels); + } + + public ComplexParallelProcessingLogic(GT_Recipe.GT_Recipe_Map recipeMap, int maxComplexParallels) { + this.maxComplexParallels = maxComplexParallels; + this.recipeMap = recipeMap; + inputItems = new ItemStack[maxComplexParallels][]; + outputItems = new ItemStack[maxComplexParallels][]; + inputFluids = new FluidStack[maxComplexParallels][]; + outputFluids = new FluidStack[maxComplexParallels][]; + eut = new long[maxComplexParallels]; + availableEut = new long[maxComplexParallels]; + durations = new long[maxComplexParallels]; + isVoidProtected = new boolean[maxComplexParallels]; + } + + public ComplexParallelProcessingLogic setRecipeMap(GT_Recipe.GT_Recipe_Map recipeMap) { + this.recipeMap = recipeMap; + return this; + } + + public ComplexParallelProcessingLogic setInputItems(int index, ItemStack... itemInputs) { + if (index >= 0 && index < maxComplexParallels) { + inputItems[index] = itemInputs; + } + return this; + } + + public ComplexParallelProcessingLogic setInputFluids(int index, FluidStack... inputFluids) { + if (index >= 0 && index < maxComplexParallels) { + this.inputFluids[index] = inputFluids; + } + return this; + } + + public ComplexParallelProcessingLogic setTileEntity(Controller<?> tileEntity) { + this.tileEntity = tileEntity; + return this; + } + + public ComplexParallelProcessingLogic setEut(int index, long eut) { + if (index >= 0 && index < maxComplexParallels) { + availableEut[index] = eut; + } + return this; + } + + public ComplexParallelProcessingLogic setVoidProtection(int index, boolean shouldVoidProtect) { + if (index >= 0 && index < maxComplexParallels) { + isVoidProtected[index] = shouldVoidProtect; + } + return this; + } + + public ComplexParallelProcessingLogic setPerfectOverclock(boolean shouldOverclockPerfectly) { + this.hasPerfectOverclock = shouldOverclockPerfectly; + return this; + } + + public ComplexParallelProcessingLogic clear() { + for (int i = 0; i < maxComplexParallels; i++) { + outputItems[i] = null; + outputFluids[i] = null; + durations[i] = 0; + eut[i] = 0; + } + return this; + } + + public ComplexParallelProcessingLogic clear(int index) { + if (index >= 0 && index < maxComplexParallels) { + inputItems[index] = null; + inputFluids[index] = null; + outputItems[index] = null; + outputFluids[index] = null; + durations[index] = 0; + availableEut[index] = 0; + eut[index] = 0; + } + return this; + } + + public boolean process(int index) { + if (recipeMap == null) { + return false; + } + GT_Recipe recipe = recipeMap + .findRecipe(tileEntity, false, false, availableEut[index], inputFluids[index], inputItems[index]); + if (recipe == null) { + return false; + } + + GT_ParallelHelper helper = new GT_ParallelHelper().setRecipe(recipe) + .setItemInputs(inputItems[index]) + .setFluidInputs(inputFluids[index]) + .setAvailableEUt(availableEut[index]) + .enableConsumption() + .enableOutputCalculation(); + + if (isVoidProtected[index]) { + helper.enableVoidProtection(tileEntity); + } + + helper.build(); + + if (helper.getCurrentParallel() <= 0) { + return false; + } + + GT_OverclockCalculator calculator = new GT_OverclockCalculator().setRecipeEUt(recipe.mEUt) + .setDuration(recipe.mDuration) + .setEUt(availableEut[index]); + + if (hasPerfectOverclock) { + calculator.enablePerfectOC(); + } + + if (calculator.getConsumption() == Long.MAX_VALUE - 1 || calculator.getDuration() == Integer.MAX_VALUE - 1) { + return false; + } + + durations[index] = calculator.getDuration(); + eut[index] = calculator.getConsumption(); + outputItems[index] = helper.getItemOutputs(); + outputFluids[index] = helper.getFluidOutputs(); + + return true; + } + + public long getDuration(int index) { + if (index >= 0 && index < maxComplexParallels) { + return durations[index]; + } + return 0; + } + + public long getTotalEU() { + return LongStream.of(eut) + .sum(); + } + + public ItemStack[] getOutputItems(int index) { + if (index >= 0 && index < maxComplexParallels) { + return outputItems[index]; + } + return null; + } + + public FluidStack[] getOutputFluids(int index) { + if (index >= 0 && index < maxComplexParallels) { + return outputFluids[index]; + } + return null; + } +} diff --git a/src/main/java/gregtech/api/logic/ModelRenderLogic.java b/src/main/java/gregtech/api/logic/ModelRenderLogic.java new file mode 100644 index 0000000000..d9f2fdcf27 --- /dev/null +++ b/src/main/java/gregtech/api/logic/ModelRenderLogic.java @@ -0,0 +1,5 @@ +package gregtech.api.logic; + +public abstract class ModelRenderLogic { + +} diff --git a/src/main/java/gregtech/api/logic/PowerLogic.java b/src/main/java/gregtech/api/logic/PowerLogic.java index 8044a2f979..ac12ef8917 100644 --- a/src/main/java/gregtech/api/logic/PowerLogic.java +++ b/src/main/java/gregtech/api/logic/PowerLogic.java @@ -15,6 +15,7 @@ public class PowerLogic { private long voltage = 0; private long amperage = 0; private int type = 0; + private boolean canUseLaser = false; public PowerLogic() {} @@ -38,6 +39,16 @@ public class PowerLogic { return this; } + public PowerLogic disableLaser() { + canUseLaser = false; + return this; + } + + public PowerLogic enableLaser() { + canUseLaser = true; + return this; + } + public boolean addEnergyUnsafe(long totalEUAdded) { if (storedEnergy + totalEUAdded >= energyCapacity) { return false; @@ -127,4 +138,8 @@ public class PowerLogic { voltage = powerLogic.getLong(NBT.POWER_LOGIC_VOLTAGE); type = powerLogic.getInteger(NBT.POWER_LOGIC_TYPE); } + + public boolean canUseLaser() { + return canUseLaser; + } } diff --git a/src/main/java/gregtech/api/logic/interfaces/ModelRenderLogicHost.java b/src/main/java/gregtech/api/logic/interfaces/ModelRenderLogicHost.java new file mode 100644 index 0000000000..9a0afaa539 --- /dev/null +++ b/src/main/java/gregtech/api/logic/interfaces/ModelRenderLogicHost.java @@ -0,0 +1,10 @@ +package gregtech.api.logic.interfaces; + +import gregtech.api.logic.ModelRenderLogic; + +public interface ModelRenderLogicHost { + + ModelRenderLogic getRenderLogic(); + + boolean shouldRenderModel(); +} diff --git a/src/main/java/gregtech/api/logic/interfaces/PowerLogicHost.java b/src/main/java/gregtech/api/logic/interfaces/PowerLogicHost.java index 8e504674aa..1a66e5fe83 100644 --- a/src/main/java/gregtech/api/logic/interfaces/PowerLogicHost.java +++ b/src/main/java/gregtech/api/logic/interfaces/PowerLogicHost.java @@ -1,10 +1,12 @@ package gregtech.api.logic.interfaces; +import net.minecraftforge.common.util.ForgeDirection; + import gregtech.api.logic.PowerLogic; public interface PowerLogicHost { - PowerLogic getPowerLogic(byte side); + PowerLogic getPowerLogic(ForgeDirection facing); default boolean isEnergyReceiver() { return false; diff --git a/src/main/java/gregtech/api/metatileentity/BaseTileEntity.java b/src/main/java/gregtech/api/metatileentity/BaseTileEntity.java index a73481d89f..2b9894a616 100644 --- a/src/main/java/gregtech/api/metatileentity/BaseTileEntity.java +++ b/src/main/java/gregtech/api/metatileentity/BaseTileEntity.java @@ -172,6 +172,9 @@ public abstract class BaseTileEntity extends TileEntity implements IHasWorldObje @Override public final boolean isServerSide() { + if (worldObj == null) { + return false; + } return !worldObj.isRemote; } diff --git a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Cable.java b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Cable.java index 132c48e77d..122a5f5128 100644 --- a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Cable.java +++ b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Cable.java @@ -35,6 +35,7 @@ import gregtech.api.interfaces.metatileentity.IMetaTileEntityCable; import gregtech.api.interfaces.tileentity.ICoverable; import gregtech.api.interfaces.tileentity.IEnergyConnected; import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import gregtech.api.logic.interfaces.PowerLogicHost; import gregtech.api.metatileentity.BaseMetaPipeEntity; import gregtech.api.metatileentity.MetaPipeEntity; import gregtech.api.objects.GT_Cover_None; @@ -336,8 +337,12 @@ public class GT_MetaPipeEntity_Cable extends MetaPipeEntity implements IMetaTile final ForgeDirection tDir = ForgeDirection.getOrientation(tSide); // GT Machine handling - if ((tTileEntity instanceof IEnergyConnected) && (((IEnergyConnected) tTileEntity).inputEnergyFrom(tSide, false) - || ((IEnergyConnected) tTileEntity).outputsEnergyTo(tSide, false))) return true; + if ((tTileEntity instanceof PowerLogicHost + && ((PowerLogicHost) tTileEntity).getPowerLogic(ForgeDirection.getOrientation(aSide)) != null) + || ((tTileEntity instanceof IEnergyConnected) + && (((IEnergyConnected) tTileEntity).inputEnergyFrom(tSide, false) + || ((IEnergyConnected) tTileEntity).outputsEnergyTo(tSide, false)))) + return true; // Solar Panel Compat if (coverBehavior instanceof GT_Cover_SolarPanel) return true; diff --git a/src/main/java/gregtech/api/multitileentity/MultiTileEntityBlock.java b/src/main/java/gregtech/api/multitileentity/MultiTileEntityBlock.java index 55edf332bd..b81961af95 100644 --- a/src/main/java/gregtech/api/multitileentity/MultiTileEntityBlock.java +++ b/src/main/java/gregtech/api/multitileentity/MultiTileEntityBlock.java @@ -50,7 +50,6 @@ import gregtech.api.enums.GT_Values; import gregtech.api.enums.ItemList; import gregtech.api.enums.Textures; import gregtech.api.interfaces.IDebugableBlock; -import gregtech.api.interfaces.ITexture; import gregtech.api.interfaces.tileentity.IDebugableTileEntity; import gregtech.api.metatileentity.BaseTileEntity; import gregtech.api.metatileentity.CoverableTileEntity; @@ -69,15 +68,13 @@ import gregtech.api.util.GT_Log; import gregtech.api.util.GT_Util; import gregtech.api.util.GT_Utility; import gregtech.common.covers.CoverInfo; -import gregtech.common.render.GT_Renderer_Block; -import gregtech.common.render.IRenderedBlock; +import gregtech.common.render.GT_MultiTile_Renderer; /* * MultiTileEntityBlock ported from GT6 */ @Optional.Interface(iface = "com.cricketcraft.chisel.api.IFacade", modid = "ChiselAPI") -public class MultiTileEntityBlock extends Block - implements IDebugableBlock, ITileEntityProvider, IRenderedBlock, IFacade { +public class MultiTileEntityBlock extends Block implements IDebugableBlock, ITileEntityProvider, IFacade { protected static final Map<String, MultiTileEntityBlock> MULTI_BLOCK_MAP = new HashMap<>(); private static boolean LOCK = false; @@ -219,7 +216,8 @@ public class MultiTileEntityBlock extends Block @Override public int getRenderType() { - return GT_Renderer_Block.INSTANCE == null ? super.getRenderType() : GT_Renderer_Block.INSTANCE.mRenderID; + return GT_MultiTile_Renderer.INSTANCE == null ? super.getRenderType() + : GT_MultiTile_Renderer.INSTANCE.getRenderId(); } @Override @@ -387,43 +385,6 @@ public class MultiTileEntityBlock extends Block } @Override - public ITexture[] getTexture(Block aBlock, byte aSide, int aRenderPass, boolean[] aShouldSideBeRendered) { - return null; - } - - @Override - public ITexture[] getTexture(Block aBlock, byte aSide, boolean isActive, int aRenderPass) { - // TODO: MTE(Texture) - return null; - } - - @Override - public int getRenderPasses(Block aBlock) { - return 0; - } - - @Override - public boolean usesRenderPass(int aRenderPass) { - return true; - } - - @Override - public boolean setBlockBounds(Block aBlock, int aRenderPass) { - return false; - } - - @Override - public IRenderedBlock passRenderingToObject(ItemStack aStack) { - return null; - } - - @Override - public IRenderedBlock passRenderingToObject(IBlockAccess aWorld, int aX, int aY, int aZ) { - final TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ); - return tTileEntity instanceof IRenderedBlock ? (IRenderedBlock) tTileEntity : null; - } - - @Override public final boolean shouldSideBeRendered(IBlockAccess aWorld, int aX, int aY, int aZ, int aSide) { final TileEntity aTileEntity = aWorld.getTileEntity(aX - OFFX[aSide], aY - OFFY[aSide], aZ - OFFZ[aSide]); return aTileEntity instanceof IMultiTileEntity diff --git a/src/main/java/gregtech/api/multitileentity/MultiTileEntityBlockInternal.java b/src/main/java/gregtech/api/multitileentity/MultiTileEntityBlockInternal.java index ec24654a1c..a3637e4626 100644 --- a/src/main/java/gregtech/api/multitileentity/MultiTileEntityBlockInternal.java +++ b/src/main/java/gregtech/api/multitileentity/MultiTileEntityBlockInternal.java @@ -7,21 +7,16 @@ import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.client.renderer.texture.IIconRegister; import net.minecraft.init.Blocks; -import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.tileentity.TileEntity; import net.minecraft.util.StatCollector; -import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; import gregtech.api.GregTech_API; -import gregtech.api.interfaces.ITexture; import gregtech.api.multitileentity.interfaces.IMultiTileEntity; import gregtech.api.multitileentity.interfaces.IMultiTileEntity.IMTE_HasMultiBlockMachineRelevantData; -import gregtech.common.render.GT_Renderer_Block; -import gregtech.common.render.IRenderedBlock; +import gregtech.common.render.GT_MultiTile_Renderer; -public class MultiTileEntityBlockInternal extends Block implements IRenderedBlock { +public class MultiTileEntityBlockInternal extends Block { public MultiTileEntityRegistry mMultiTileEntityRegistry; @@ -36,7 +31,8 @@ public class MultiTileEntityBlockInternal extends Block implements IRenderedBloc @Override public int getRenderType() { - return GT_Renderer_Block.INSTANCE == null ? super.getRenderType() : GT_Renderer_Block.INSTANCE.mRenderID; + return GT_MultiTile_Renderer.INSTANCE == null ? super.getRenderType() + : GT_MultiTile_Renderer.INSTANCE.getRenderId(); } @Override @@ -115,40 +111,7 @@ public class MultiTileEntityBlockInternal extends Block implements IRenderedBloc return true; } - @Override - public ITexture[] getTexture(Block aBlock, byte aSide, int aRenderPass, boolean[] aShouldSideBeRendered) { - return null; - } - - @Override - public ITexture[] getTexture(Block aBlock, byte aSide, boolean isActive, int aRenderPass) { - // TODO: MTE(Texture) - return null; - } - - @Override - public int getRenderPasses(Block aBlock) { - return 0; - } - - @Override - public boolean usesRenderPass(int aRenderPass) { - return true; - } - - @Override - public boolean setBlockBounds(Block aBlock, int aRenderPass) { - return false; - } - - @Override - public IRenderedBlock passRenderingToObject(ItemStack aStack) { - final TileEntity tTileEntity = mMultiTileEntityRegistry.getNewTileEntity(aStack); - return tTileEntity instanceof IRenderedBlock ? (IRenderedBlock) tTileEntity : null; - } - - @Override - public IRenderedBlock passRenderingToObject(IBlockAccess aWorld, int aX, int aY, int aZ) { - return null; + public MultiTileEntityRegistry getRegistry() { + return mMultiTileEntityRegistry; } } diff --git a/src/main/java/gregtech/api/multitileentity/MultiTileEntityClassContainer.java b/src/main/java/gregtech/api/multitileentity/MultiTileEntityClassContainer.java index 4e4be793b1..3eae75f934 100644 --- a/src/main/java/gregtech/api/multitileentity/MultiTileEntityClassContainer.java +++ b/src/main/java/gregtech/api/multitileentity/MultiTileEntityClassContainer.java @@ -12,7 +12,7 @@ import gregtech.api.multitileentity.base.MultiTileEntity; import gregtech.api.multitileentity.multiblock.casing.FunctionalCasing; import gregtech.api.multitileentity.multiblock.casing.UpgradeCasing; import gregtech.api.util.GT_Util; -import gregtech.common.tileentities.casings.upgrade.InventoryUpgrade; +import gregtech.common.tileentities.casings.upgrade.Inventory; public class MultiTileEntityClassContainer { @@ -94,25 +94,25 @@ public class MultiTileEntityClassContainer { // Need a base texture for the MTE machine, and then a separate texture set for the machine/active overlays - public MultiTileEntityClassContainer material(Materials aMaterial) { + public MultiTileEntityClassContainer material(Materials material) { // Sets the material, and the color from the material, if not already set - mParameters.setString(NBT.MATERIAL, aMaterial.toString()); - if (!mParameters.hasKey(NBT.COLOR)) mParameters.setInteger(NBT.COLOR, GT_Util.getRGBInt(aMaterial.getRGBA())); + mParameters.setString(NBT.MATERIAL, material.toString()); + if (!mParameters.hasKey(NBT.COLOR)) mParameters.setInteger(NBT.COLOR, GT_Util.getRGBInt(material.getRGBA())); return this; } - public MultiTileEntityClassContainer color(int aRPG) { - mParameters.setInteger(NBT.COLOR, aRPG); + public MultiTileEntityClassContainer color(int rbg) { + mParameters.setInteger(NBT.COLOR, rbg); return this; } - public MultiTileEntityClassContainer color(short[] aRPGA) { - mParameters.setInteger(NBT.COLOR, GT_Util.getRGBInt(aRPGA)); + public MultiTileEntityClassContainer color(short[] rgba) { + mParameters.setInteger(NBT.COLOR, GT_Util.getRGBInt(rgba)); return this; } - public MultiTileEntityClassContainer texture(String aTexture) { - mParameters.setString(NBT.TEXTURE, aTexture); + public MultiTileEntityClassContainer textureFolder(String texture) { + mParameters.setString(NBT.TEXTURE_FOLDER, texture); return this; } @@ -138,7 +138,7 @@ public class MultiTileEntityClassContainer { } public MultiTileEntityClassContainer upgradeInventorySize(int aSize) { - verifyDescendentOf(InventoryUpgrade.class); + verifyDescendentOf(Inventory.class); mParameters.setInteger(NBT.UPGRADE_INVENTORY_SIZE, aSize); return this; @@ -174,10 +174,8 @@ public class MultiTileEntityClassContainer { if (!onlyOne) { verifyDescendentOf(cls); atLeastOne = true; - } else { - if (cls.isAssignableFrom(mClass)) { - atLeastOne = true; - } + } else if (cls.isAssignableFrom(mClass)) { + atLeastOne = true; } } diff --git a/src/main/java/gregtech/api/multitileentity/base/MultiTileEntity.java b/src/main/java/gregtech/api/multitileentity/base/MultiTileEntity.java index 2ef1042a01..4312f99ce7 100644 --- a/src/main/java/gregtech/api/multitileentity/base/MultiTileEntity.java +++ b/src/main/java/gregtech/api/multitileentity/base/MultiTileEntity.java @@ -1,12 +1,10 @@ package gregtech.api.multitileentity.base; import static gregtech.GT_Mod.GT_FML_LOGGER; -import static gregtech.api.enums.GT_Values.NBT; import static gregtech.api.enums.GT_Values.OPOS; -import static gregtech.api.enums.GT_Values.SIDE_WEST; import static gregtech.api.enums.GT_Values.VALID_SIDES; -import static gregtech.api.enums.GT_Values.emptyIconContainerArray; +import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.UUID; @@ -15,7 +13,7 @@ import mcp.mobius.waila.api.IWailaConfigHandler; import mcp.mobius.waila.api.IWailaDataAccessor; import net.minecraft.block.Block; -import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.client.Minecraft; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; @@ -29,8 +27,8 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.MovingObjectPosition; +import net.minecraft.util.ResourceLocation; import net.minecraft.world.Explosion; -import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; import net.minecraftforge.fluids.Fluid; @@ -38,16 +36,14 @@ import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidTankInfo; import net.minecraftforge.fluids.IFluidTank; +import com.gtnewhorizons.modularui.common.internal.network.NetworkUtils; + import cpw.mods.fml.common.registry.GameRegistry; -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; import gregtech.api.GregTech_API; -import gregtech.api.enums.GT_Values; -import gregtech.api.enums.Materials; -import gregtech.api.enums.SoundResource; -import gregtech.api.enums.Textures; +import gregtech.api.enums.*; +import gregtech.api.enums.GT_Values.NBT; +import gregtech.api.enums.Textures.BlockIcons.CustomIcon; import gregtech.api.gui.modularui.GT_UIInfos; -import gregtech.api.interfaces.IIconContainer; import gregtech.api.interfaces.ITexture; import gregtech.api.metatileentity.CoverableTileEntity; import gregtech.api.metatileentity.GregTechTileClientEvents; @@ -64,13 +60,18 @@ import gregtech.api.util.GT_Log; import gregtech.api.util.GT_ModHandler; import gregtech.api.util.GT_Util; import gregtech.api.util.GT_Utility; -import gregtech.common.render.GT_MultiTexture; -import gregtech.common.render.IRenderedBlock; +import gregtech.common.render.MultiTileBasicRender; -public abstract class MultiTileEntity extends CoverableTileEntity implements IMultiTileEntity, IRenderedBlock { +public abstract class MultiTileEntity extends CoverableTileEntity + implements IMultiTileEntity.IMTE_BreakBlock, MultiTileBasicRender { - public IIconContainer[] textures = emptyIconContainerArray; - // public IIconContainer[] mTexturesFront = emptyIconContainerArray; + private ITexture baseTexture = null; + private ITexture topOverlayTexture = null; + private ITexture bottomOverlayTexture = null; + private ITexture leftOverlayTexture = null; + private ITexture rightOverlayTexture = null; + private ITexture backOverlayTexture = null; + private ITexture frontOverlayTexture = null; // Makes a Bounding Box without having to constantly specify the Offset Coordinates. protected static final float[] PX_BOX = { 0, 0, 0, 1, 1, 1 }; @@ -87,7 +88,8 @@ public abstract class MultiTileEntity extends CoverableTileEntity implements IMu protected boolean needsUpdate = false; protected boolean hasInventoryChanged = false; protected boolean isPainted = false; - protected byte facing = SIDE_WEST; // Default to WEST, so it renders facing Left in the inventory + protected ForgeDirection facing = ForgeDirection.WEST; // Default to WEST, so it renders facing Left in the + // inventory protected byte color; protected int rgba = GT_Values.UNCOLORED; private short mteID = GT_Values.W, mteRegistry = GT_Values.W; @@ -117,6 +119,9 @@ public abstract class MultiTileEntity extends CoverableTileEntity implements IMu @Override public void initFromNBT(NBTTagCompound nbt, short mteID, short mteRegistry) { + if (this.mteID == mteID && this.mteRegistry == mteRegistry) { + return; + } // Set ID and Registry ID. this.mteID = mteID; this.mteRegistry = mteRegistry; @@ -125,13 +130,31 @@ public abstract class MultiTileEntity extends CoverableTileEntity implements IMu } @Override - public void loadTextureNBT(NBTTagCompound nbt) { + public void loadTextures(String folder) { // Loading the registry - final String textureName = nbt.getString(NBT.TEXTURE); - textures = new IIconContainer[] { - new Textures.BlockIcons.CustomIcon("multitileentity/base/" + textureName + "/bottom"), - new Textures.BlockIcons.CustomIcon("multitileentity/base/" + textureName + "/top"), - new Textures.BlockIcons.CustomIcon("multitileentity/base/" + textureName + "/side"), }; + for (SidedTextureNames textureName : SidedTextureNames.TEXTURES) { + ITexture texture; + try { + Minecraft.getMinecraft() + .getResourceManager() + .getResource( + new ResourceLocation( + Mods.GregTech.ID, + "textures/blocks/multitileentity/" + folder + "/" + textureName.getName() + ".png")); + texture = TextureFactory.of(new CustomIcon("multitileentity/" + folder + "/" + textureName.getName())); + } catch (IOException ignored) { + texture = TextureFactory.of(Textures.BlockIcons.VOID); + } + switch (textureName) { + case Top -> topOverlayTexture = texture; + case Bottom -> bottomOverlayTexture = texture; + case Back -> backOverlayTexture = texture; + case Front -> frontOverlayTexture = texture; + case Left -> leftOverlayTexture = texture; + case Right -> rightOverlayTexture = texture; + case Base -> baseTexture = texture; + } + } } @Override @@ -139,8 +162,48 @@ public abstract class MultiTileEntity extends CoverableTileEntity implements IMu // Loading an instance final TileEntity tCanonicalTileEntity = MultiTileEntityRegistry .getCanonicalTileEntity(getMultiTileEntityRegistryID(), getMultiTileEntityID()); - if (tCanonicalTileEntity instanceof MultiTileEntity) - textures = ((MultiTileEntity) tCanonicalTileEntity).textures; + if (!(tCanonicalTileEntity instanceof MultiTileEntity)) { + return; + } + final MultiTileEntity canonicalEntity = (MultiTileEntity) tCanonicalTileEntity; + baseTexture = canonicalEntity.baseTexture; + topOverlayTexture = canonicalEntity.topOverlayTexture; + bottomOverlayTexture = canonicalEntity.bottomOverlayTexture; + leftOverlayTexture = canonicalEntity.leftOverlayTexture; + rightOverlayTexture = canonicalEntity.rightOverlayTexture; + backOverlayTexture = canonicalEntity.backOverlayTexture; + frontOverlayTexture = canonicalEntity.frontOverlayTexture; + } + + @Override + public ITexture getTexture(ForgeDirection side) { + if (facing == side) { + return TextureFactory.of(baseTexture, frontOverlayTexture); + } + + if (facing.getOpposite() == side) { + return TextureFactory.of(baseTexture, backOverlayTexture); + } + + if (side == ForgeDirection.UP) { + return TextureFactory.of(baseTexture, topOverlayTexture); + } + + if (side == ForgeDirection.DOWN) { + return TextureFactory.of(baseTexture, bottomOverlayTexture); + } + + if (facing.getRotation(ForgeDirection.DOWN) == side) { + return TextureFactory.of(baseTexture, rightOverlayTexture); + } else { + return TextureFactory.of(baseTexture, leftOverlayTexture); + } + } + + @Override + public ITexture[] getTexture(Block ignoredBlock, byte ignoredSide) { + // We are not going to be using this + return null; } @Override @@ -181,15 +244,17 @@ public abstract class MultiTileEntity extends CoverableTileEntity implements IMu ownerUUID = null; } if (nbt.hasKey(NBT.LOCK_UPGRADE)) lockUpgrade = nbt.getBoolean(NBT.LOCK_UPGRADE); - if (nbt.hasKey(NBT.FACING)) facing = nbt.getByte(NBT.FACING); + if (nbt.hasKey(NBT.FACING)) facing = ForgeDirection.getOrientation(nbt.getInteger(NBT.FACING)); readCoverNBT(nbt); readMultiTileNBT(nbt); - if (GregTech_API.sBlockIcons == null && nbt.hasKey(NBT.TEXTURE)) { - loadTextureNBT(nbt); - } else { - copyTextures(); + if (NetworkUtils.isDedicatedClient()) { + if (GregTech_API.sBlockIcons == null && nbt.hasKey(NBT.TEXTURE_FOLDER)) { + loadTextures(nbt.getString(NBT.TEXTURE_FOLDER)); + } else { + copyTextures(); + } } if (mSidedRedstone.length != 6) mSidedRedstone = new byte[] { 15, 15, 15, 15, 15, 15 }; @@ -228,7 +293,7 @@ public abstract class MultiTileEntity extends CoverableTileEntity implements IMu aNBT.setString(NBT.OWNER, ownerName); aNBT.setString(NBT.OWNER_UUID, ownerUUID == null ? "" : ownerUUID.toString()); aNBT.setBoolean(NBT.LOCK_UPGRADE, lockUpgrade); - aNBT.setByte(NBT.FACING, facing); + aNBT.setInteger(NBT.FACING, facing.ordinal()); writeCoverNBT(aNBT, false); writeMultiTileNBT(aNBT); @@ -244,10 +309,16 @@ public abstract class MultiTileEntity extends CoverableTileEntity implements IMu @Override public NBTTagCompound writeItemNBT(NBTTagCompound aNBT) { writeCoverNBT(aNBT, true); - + if (shouldSaveNBTToItemStack()) { + writeMultiTileNBT(aNBT); + } return aNBT; } + protected boolean shouldSaveNBTToItemStack() { + return false; + } + @Override public boolean useModularUI() { return false; @@ -322,69 +393,6 @@ public abstract class MultiTileEntity extends CoverableTileEntity implements IMu } @Override - @SideOnly(Side.CLIENT) - public final IRenderedBlock passRenderingToObject(ItemStack aStack) { - return this; - } - - @Override - @SideOnly(Side.CLIENT) - public final IRenderedBlock passRenderingToObject(IBlockAccess aWorld, int aX, int aY, int aZ) { - return this; - } - - @Override - public int getRenderPasses(Block aBlock) { - return 1; - } - - @Override - public boolean usesRenderPass(int aRenderPass) { - return true; - } - - @Override - public boolean setBlockBounds(Block aBlock, int aRenderPass) { - return false; - } - - @Override - public boolean renderItem(Block aBlock, RenderBlocks aRenderer) { - return false; - } - - @Override - public boolean renderBlock(Block aBlock, RenderBlocks aRenderer, IBlockAccess aWorld, int aX, int aY, int aZ) { - return false; - } - - @Override - public ITexture[] getTexture(Block aBlock, byte aSide) { - return getTexture(aBlock, aSide, 1, VALID_SIDES); - } - - @Override - public final ITexture[] getTexture(Block aBlock, byte aSide, int aRenderPass, boolean[] aShouldSideBeRendered) { - if (!aShouldSideBeRendered[aSide]) return null; - - final ITexture coverTexture = getCoverTexture(aSide); - final ITexture[] textureUncovered = getTexture(aBlock, aSide, true, aRenderPass); - - if (coverTexture != null) { - return new ITexture[] { GT_MultiTexture.get(textureUncovered), coverTexture }; - } else { - return textureUncovered; - } - } - - @Override - public ITexture[] getTexture(Block aBlock, byte aSide, boolean isActive, int aRenderPass) { - // Top, bottom or side - aSide = (byte) Math.min(aSide, 2); - return new ITexture[] { TextureFactory.of(textures[aSide], GT_Util.getRGBaArray(rgba)) }; - } - - @Override public void setCustomName(String aName) { customName = aName; } @@ -428,18 +436,18 @@ public abstract class MultiTileEntity extends CoverableTileEntity implements IMu @Override public byte getFrontFacing() { - return facing; + return (byte) facing.ordinal(); } /** * Sets the main facing to {aSide} and update as appropriately - * + * * @return Whether the facing was changed */ @Override public boolean setMainFacing(byte aSide) { if (!isValidFacing(aSide)) return false; - facing = aSide; + facing = ForgeDirection.getOrientation(aSide); issueClientUpdate(); issueBlockUpdate(); @@ -464,7 +472,8 @@ public abstract class MultiTileEntity extends CoverableTileEntity implements IMu @Override public byte getBackFacing() { - return GT_Utility.getOppositeSide(facing); + return (byte) facing.getOpposite() + .ordinal(); } @Override @@ -700,7 +709,8 @@ public abstract class MultiTileEntity extends CoverableTileEntity implements IMu @Override public boolean onPlaced(ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX, int aY, int aZ, byte aSide, float aHitX, float aHitY, float aHitZ) { - facing = getSideForPlayerPlacing(aPlayer, facing, getValidFacings()); + facing = ForgeDirection + .getOrientation(getSideForPlayerPlacing(aPlayer, (byte) facing.ordinal(), getValidFacings())); onFacingChange(); return true; } @@ -922,9 +932,14 @@ public abstract class MultiTileEntity extends CoverableTileEntity implements IMu final ArrayList<ItemStack> rList = new ArrayList<>(); final MultiTileEntityRegistry tRegistry = MultiTileEntityRegistry.getRegistry(getMultiTileEntityRegistryID()); if (tRegistry != null) rList.add(tRegistry.getItem(getMultiTileEntityID(), writeItemNBT(new NBTTagCompound()))); + return rList; + } + @Override + public boolean breakBlock() { + isDead = true; onBaseTEDestroyed(); - return rList; + return false; } @Override @@ -975,7 +990,7 @@ public abstract class MultiTileEntity extends CoverableTileEntity implements IMu zCoord, getMultiTileEntityRegistryID(), getMultiTileEntityID(), - (byte) ((facing & 7) | (mRedstone ? 16 : 0)), + (byte) ((facing.ordinal() & 7) | (mRedstone ? 16 : 0)), color); packet.setCoverData( @@ -1014,7 +1029,7 @@ public abstract class MultiTileEntity extends CoverableTileEntity implements IMu issueTextureUpdate(); switch (aEventID) { case GregTechTileClientEvents.CHANGE_COMMON_DATA: - facing = (byte) (aValue & 7); + facing = ForgeDirection.getOrientation(aValue & 7); // mActive = ((aValue & 8) != 0); mRedstone = ((aValue & 16) != 0); // mLockUpgrade = ((aValue&32) != 0); @@ -1096,9 +1111,6 @@ public abstract class MultiTileEntity extends CoverableTileEntity implements IMu + mteID + EnumChatFormatting.RESET); } - if (joinedIc2Enet) tList.add("Joined IC2 ENet"); - - tList.add("Energy: " + getUniversalEnergyStored() + "/" + getUniversalEnergyCapacity()); addDebugInfo(aPlayer, aLogLevel, tList); @@ -1395,4 +1407,51 @@ public abstract class MultiTileEntity extends CoverableTileEntity implements IMu public ItemStack getStackForm(long aAmount) { return new ItemStack(Item.getItemById(getMultiTileEntityRegistryID()), (int) aAmount, getMultiTileEntityID()); } + + protected enum SidedTextureNames { + + Base("base"), + Left("left"), + Right("right"), + Top("top"), + Bottom("bottom"), + Back("back"), + Front("front"); + + private final String name; + public static final SidedTextureNames[] TEXTURES = { Base, Left, Right, Top, Bottom, Back, Front }; + + SidedTextureNames(String name) { + this.name = name; + } + + public String getName() { + return name; + } + } + + protected enum StatusTextures { + + Active("active", false), + ActiveWithGlow("active_glow", true), + Inactive("inactive", false), + InactiveWithGlow("inactive_glow", true); + + private final String name; + private final boolean hasGlow; + public static final StatusTextures[] TEXTURES = { Active, ActiveWithGlow, Inactive, InactiveWithGlow }; + + StatusTextures(String name, boolean hasGlow) { + this.name = name; + this.hasGlow = hasGlow; + } + + public String getName() { + return name; + } + + public boolean hasGlow() { + return hasGlow; + } + } } diff --git a/src/main/java/gregtech/api/multitileentity/base/TickableMultiTileEntity.java b/src/main/java/gregtech/api/multitileentity/base/TickableMultiTileEntity.java index 25a9edd9ac..4fa06ff6b4 100644 --- a/src/main/java/gregtech/api/multitileentity/base/TickableMultiTileEntity.java +++ b/src/main/java/gregtech/api/multitileentity/base/TickableMultiTileEntity.java @@ -39,7 +39,6 @@ public abstract class TickableMultiTileEntity extends MultiTileEntity implements return; } onPreTick(timer, isServerSide); - timer++; super.updateEntity(); if (!isServerSide && needsUpdate) { worldObj.markBlockForUpdate(xCoord, yCoord, zCoord); @@ -67,7 +66,7 @@ public abstract class TickableMultiTileEntity extends MultiTileEntity implements @Override public void sendClientData(EntityPlayerMP aPlayer) { if (sendClientData) { - GT_FML_LOGGER.info("Sending client data"); + // GT_FML_LOGGER.info("Sending client data"); super.sendClientData(aPlayer); sendClientData = false; } diff --git a/src/main/java/gregtech/api/multitileentity/enums/GT_MultiTileCasing.java b/src/main/java/gregtech/api/multitileentity/enums/GT_MultiTileCasing.java index be74ca3ef2..baa235ccf1 100644 --- a/src/main/java/gregtech/api/multitileentity/enums/GT_MultiTileCasing.java +++ b/src/main/java/gregtech/api/multitileentity/enums/GT_MultiTileCasing.java @@ -5,15 +5,16 @@ import gregtech.api.enums.GT_Values; public enum GT_MultiTileCasing { CokeOven(0), + Chemical(1), NONE(GT_Values.W); - private final short meta; + private final int meta; GT_MultiTileCasing(int meta) { - this.meta = (short) meta; + this.meta = meta; } - public short getId() { + public int getId() { return meta; } } diff --git a/src/main/java/gregtech/api/multitileentity/enums/GT_MultiTileComponentCasing.java b/src/main/java/gregtech/api/multitileentity/enums/GT_MultiTileComponentCasing.java new file mode 100644 index 0000000000..e062ecc705 --- /dev/null +++ b/src/main/java/gregtech/api/multitileentity/enums/GT_MultiTileComponentCasing.java @@ -0,0 +1,130 @@ +package gregtech.api.multitileentity.enums; + +import gregtech.api.enums.GT_Values; + +public enum GT_MultiTileComponentCasing { + + LV_Motor(0), + MV_Motor(1), + HV_Motor(2), + EV_Motor(3), + IV_Motor(4), + LuV_Motor(5), + ZPM_Motor(6), + UV_Motor(7), + UHV_Motor(8), + UEV_Motor(9), + UIV_Motor(10), + UMV_Motor(11), + UXV_Motor(12), + MAX_Motor(13), + LV_Pump(14), + MV_Pump(15), + HV_Pump(16), + EV_Pump(17), + IV_Pump(18), + LuV_Pump(19), + ZPM_Pump(20), + UV_Pump(21), + UHV_Pump(22), + UEV_Pump(23), + UIV_Pump(24), + UMV_Pump(25), + UXV_Pump(26), + MAX_Pump(27), + LV_Conveyor(28), + MV_Conveyor(29), + HV_Conveyor(30), + EV_Conveyor(31), + IV_Conveyor(32), + LuV_Conveyor(33), + ZPM_Conveyor(34), + UV_Conveyor(35), + UHV_Conveyor(36), + UEV_Conveyor(37), + UIV_Conveyor(38), + UMV_Conveyor(39), + UXV_Conveyor(40), + MAX_Conveyor(41), + LV_Piston(42), + MV_Piston(43), + HV_Piston(44), + EV_Piston(45), + IV_Piston(46), + LuV_Piston(47), + ZPM_Piston(48), + UV_Piston(49), + UHV_Piston(50), + UEV_Piston(51), + UIV_Piston(52), + UMV_Piston(53), + UXV_Piston(54), + MAX_Piston(55), + LV_RobotArm(56), + MV_RobotArm(57), + HV_RobotArm(58), + EV_RobotArm(59), + IV_RobotArm(60), + LuV_RobotArm(61), + ZPM_RobotArm(62), + UV_RobotArm(63), + UHV_RobotArm(64), + UEV_RobotArm(65), + UIV_RobotArm(66), + UMV_RobotArm(67), + UXV_RobotArm(68), + MAX_RobotArm(69), + LV_Emitter(70), + MV_Emitter(71), + HV_Emitter(72), + EV_Emitter(73), + IV_Emitter(74), + LuV_Emitter(75), + ZPM_Emitter(76), + UV_Emitter(77), + UHV_Emitter(78), + UEV_Emitter(79), + UIV_Emitter(80), + UMV_Emitter(81), + UXV_Emitter(82), + MAX_Emitter(83), + LV_Sensor(84), + MV_Sensor(85), + HV_Sensor(86), + EV_Sensor(87), + IV_Sensor(88), + LuV_Sensor(89), + ZPM_Sensor(90), + UV_Sensor(91), + UHV_Sensor(92), + UEV_Sensor(93), + UIV_Sensor(94), + UMV_Sensor(95), + UXV_Sensor(96), + MAX_Sensor(97), + LV_FieldGenerator(98), + MV_FieldGenerator(99), + HV_FieldGenerator(100), + EV_FieldGenerator(101), + IV_FieldGenerator(102), + LuV_FieldGenerator(103), + ZPM_FieldGenerator(104), + UV_FieldGenerator(105), + UHV_FieldGenerator(106), + UEV_FieldGenerator(107), + UIV_FieldGenerator(108), + UMV_FieldGenerator(109), + UXV_FieldGenerator(110), + MAX_FieldGenerator(111), + NONE(GT_Values.W); + + private final int meta; + + GT_MultiTileComponentCasing(int meta) { + this.meta = meta; + } + + public int getId() { + return meta; + } +} diff --git a/src/main/java/gregtech/api/multitileentity/enums/GT_MultiTileMachine.java b/src/main/java/gregtech/api/multitileentity/enums/GT_MultiTileMachine.java index 0fc8f3dafd..7cdde78986 100644 --- a/src/main/java/gregtech/api/multitileentity/enums/GT_MultiTileMachine.java +++ b/src/main/java/gregtech/api/multitileentity/enums/GT_MultiTileMachine.java @@ -7,13 +7,13 @@ public enum GT_MultiTileMachine { CokeOven(0), NONE(GT_Values.W); - private final short meta; + private final int meta; GT_MultiTileMachine(int meta) { - this.meta = (short) meta; + this.meta = meta; } - public short getId() { + public int getId() { return meta; } } diff --git a/src/main/java/gregtech/api/multitileentity/interfaces/IMultiBlockController.java b/src/main/java/gregtech/api/multitileentity/interfaces/IMultiBlockController.java index 21e1328d27..1168f8e7ce 100644 --- a/src/main/java/gregtech/api/multitileentity/interfaces/IMultiBlockController.java +++ b/src/main/java/gregtech/api/multitileentity/interfaces/IMultiBlockController.java @@ -1,8 +1,12 @@ package gregtech.api.multitileentity.interfaces; import net.minecraft.util.ChunkCoordinates; +import net.minecraftforge.common.util.ForgeDirection; +import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; +import com.gtnewhorizons.modularui.api.screen.ModularWindow; +import com.gtnewhorizons.modularui.api.screen.UIBuildContext; import gregtech.api.logic.PowerLogic; public interface IMultiBlockController extends IMultiTileEntity, IMultiBlockFluidHandler, IMultiBlockInventory { @@ -17,6 +21,8 @@ public interface IMultiBlockController extends IMultiTileEntity, IMultiBlockFlui FluidStack getDrainableFluid(byte aSide); + FluidStack getDrainableFluid(byte aSide, Fluid fluid); + boolean isLiquidInput(byte aSide); boolean isLiquidOutput(byte aSide); @@ -31,5 +37,7 @@ public interface IMultiBlockController extends IMultiTileEntity, IMultiBlockFlui void changeInventoryName(String aName, String aID, int aType); - PowerLogic getPowerLogic(IMultiBlockPart part, byte side); + PowerLogic getPowerLogic(IMultiBlockPart part, ForgeDirection side); + + ModularWindow createWindowGUI(UIBuildContext buildContext); } diff --git a/src/main/java/gregtech/api/multitileentity/interfaces/IMultiBlockFluidHandler.java b/src/main/java/gregtech/api/multitileentity/interfaces/IMultiBlockFluidHandler.java index 045a173e94..b513f51324 100644 --- a/src/main/java/gregtech/api/multitileentity/interfaces/IMultiBlockFluidHandler.java +++ b/src/main/java/gregtech/api/multitileentity/interfaces/IMultiBlockFluidHandler.java @@ -1,5 +1,7 @@ package gregtech.api.multitileentity.interfaces; +import java.util.List; + import net.minecraftforge.common.util.ForgeDirection; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; @@ -23,4 +25,8 @@ public interface IMultiBlockFluidHandler { FluidTankInfo[] getTankInfo(MultiBlockPart aPart, ForgeDirection aDirection); IFluidTank[] getFluidTanksForGUI(MultiBlockPart aPart); + + List<String> getTankArrayNames(MultiBlockPart aPart); + + List<String> getTankArrayIDs(MultiBlockPart aPart); } diff --git a/src/main/java/gregtech/api/multitileentity/interfaces/IMultiTileEntity.java b/src/main/java/gregtech/api/multitileentity/interfaces/IMultiTileEntity.java index b42aa35195..cafde57de5 100644 --- a/src/main/java/gregtech/api/multitileentity/interfaces/IMultiTileEntity.java +++ b/src/main/java/gregtech/api/multitileentity/interfaces/IMultiTileEntity.java @@ -71,7 +71,7 @@ public interface IMultiTileEntity @Override boolean isDead(); - void loadTextureNBT(NBTTagCompound aNBT); + void loadTextures(String folder); void copyTextures(); diff --git a/src/main/java/gregtech/api/multitileentity/machine/MultiTileBasicMachine.java b/src/main/java/gregtech/api/multitileentity/machine/MultiTileBasicMachine.java index e50236c93b..f3cc00692c 100644 --- a/src/main/java/gregtech/api/multitileentity/machine/MultiTileBasicMachine.java +++ b/src/main/java/gregtech/api/multitileentity/machine/MultiTileBasicMachine.java @@ -1,12 +1,12 @@ package gregtech.api.multitileentity.machine; import static com.google.common.primitives.Ints.saturatedCast; -import static gregtech.api.enums.GT_Values.B; -import static gregtech.api.enums.GT_Values.emptyIconContainerArray; +import static gregtech.api.enums.GT_Values.*; +import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; -import net.minecraft.block.Block; import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; @@ -16,6 +16,8 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntityFurnace; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.ResourceLocation; +import net.minecraft.util.StatCollector; +import net.minecraftforge.common.util.ForgeDirection; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.IFluidTank; @@ -24,13 +26,10 @@ import com.gtnewhorizons.modularui.api.forge.ItemStackHandler; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import gregtech.api.enums.GT_Values; +import gregtech.api.enums.*; import gregtech.api.enums.GT_Values.NBT; -import gregtech.api.enums.SoundResource; -import gregtech.api.enums.Textures; -import gregtech.api.enums.TickTime; +import gregtech.api.enums.Textures.BlockIcons.CustomIcon; import gregtech.api.fluid.FluidTankGT; -import gregtech.api.interfaces.IIconContainer; import gregtech.api.interfaces.ITexture; import gregtech.api.logic.PollutionLogic; import gregtech.api.logic.PowerLogic; @@ -44,7 +43,6 @@ import gregtech.api.multitileentity.base.TickableMultiTileEntity; import gregtech.api.multitileentity.interfaces.IMultiTileMachine; import gregtech.api.net.GT_Packet_MultiTileEntity; import gregtech.api.render.TextureFactory; -import gregtech.api.util.GT_Util; import gregtech.api.util.GT_Utility; import gregtech.client.GT_SoundLoop; import gregtech.common.GT_Pollution; @@ -59,9 +57,10 @@ public abstract class MultiTileBasicMachine extends TickableMultiTileEntity impl protected static final IItemHandlerModifiable EMPTY_INVENTORY = new ItemStackHandler(0); - private static final String TEXTURE_LOCATION = "multitileentity/machines/"; - public IIconContainer[] texturesInactive = emptyIconContainerArray; - public IIconContainer[] texturesActive = emptyIconContainerArray; + public ITexture activeOverlayTexture = null; + public ITexture activeOverlayGlowTexture = null; + public ITexture inactiveOverlayTexture = null; + public ITexture inactiveOverlayGlowTexture = null; protected int maxParallel = 1; protected boolean active = false; @@ -82,15 +81,15 @@ public abstract class MultiTileBasicMachine extends TickableMultiTileEntity impl protected IItemHandlerModifiable inputInventory = EMPTY_INVENTORY; protected IItemHandlerModifiable outputInventory = EMPTY_INVENTORY; protected boolean outputInventoryChanged = false; - private boolean powerShutDown = false; - private boolean wasEnabled = false; - private boolean canWork = true; - private boolean isElectric = true; - private boolean isSteam = false; - private boolean acceptsFuel = false; - private boolean isWireless = false; - private byte soundEvent = 0; - private int soundEventValue = 0; + protected boolean powerShutDown = false; + protected boolean wasEnabled = false; + protected boolean canWork = true; + protected boolean isElectric = true; + protected boolean isSteam = false; + protected boolean acceptsFuel = false; + protected boolean isWireless = false; + protected byte soundEvent = 0; + protected int soundEventValue = 0; @SideOnly(Side.CLIENT) protected GT_SoundLoop activitySoundLoop; @@ -221,7 +220,8 @@ public abstract class MultiTileBasicMachine extends TickableMultiTileEntity impl .readFromNBT(nbt, NBT.TANK_IN + i); } for (int i = 0; i < outputTanks.length; i++) { - outputTanks[i] = new FluidTankGT().readFromNBT(nbt, NBT.TANK_OUT + i); + outputTanks[i] = new FluidTankGT(capacity).setCapacityMultiplier(maxParallel * 2L) + .readFromNBT(nbt, NBT.TANK_OUT + i); } for (int i = 0; i < fluidsToOutput.length; i++) { @@ -258,56 +258,67 @@ public abstract class MultiTileBasicMachine extends TickableMultiTileEntity impl } @Override - public void loadTextureNBT(NBTTagCompound aNBT) { - // Loading the registry - final String textureName = aNBT.getString(NBT.TEXTURE); - textures = new IIconContainer[] { - new Textures.BlockIcons.CustomIcon(TEXTURE_LOCATION + textureName + "/bottom"), - new Textures.BlockIcons.CustomIcon(TEXTURE_LOCATION + textureName + "/top"), - new Textures.BlockIcons.CustomIcon(TEXTURE_LOCATION + textureName + "/left"), - new Textures.BlockIcons.CustomIcon(TEXTURE_LOCATION + textureName + "/front"), - new Textures.BlockIcons.CustomIcon(TEXTURE_LOCATION + textureName + "/right"), - new Textures.BlockIcons.CustomIcon(TEXTURE_LOCATION + textureName + "/side") }; - texturesInactive = new IIconContainer[] { - new Textures.BlockIcons.CustomIcon(TEXTURE_LOCATION + textureName + "/overlay/inactive/bottom"), - new Textures.BlockIcons.CustomIcon(TEXTURE_LOCATION + textureName + "/overlay/inactive/top"), - new Textures.BlockIcons.CustomIcon(TEXTURE_LOCATION + textureName + "/overlay/inactive/left"), - new Textures.BlockIcons.CustomIcon(TEXTURE_LOCATION + textureName + "/overlay/inactive/front"), - new Textures.BlockIcons.CustomIcon(TEXTURE_LOCATION + textureName + "/overlay/inactive/right"), - new Textures.BlockIcons.CustomIcon(TEXTURE_LOCATION + textureName + "/overlay/inactive/back") }; - texturesActive = new IIconContainer[] { - new Textures.BlockIcons.CustomIcon(TEXTURE_LOCATION + textureName + "/overlay/active/bottom"), - new Textures.BlockIcons.CustomIcon(TEXTURE_LOCATION + textureName + "/overlay/active/top"), - new Textures.BlockIcons.CustomIcon(TEXTURE_LOCATION + textureName + "/overlay/active/left"), - new Textures.BlockIcons.CustomIcon(TEXTURE_LOCATION + textureName + "/overlay/active/front"), - new Textures.BlockIcons.CustomIcon(TEXTURE_LOCATION + textureName + "/overlay/active/right"), - new Textures.BlockIcons.CustomIcon(TEXTURE_LOCATION + textureName + "/overlay/active/back") }; + public void loadTextures(String folder) { + super.loadTextures(folder); + for (StatusTextures textureName : StatusTextures.TEXTURES) { + ITexture texture = null; + try { + Minecraft.getMinecraft() + .getResourceManager() + .getResource( + new ResourceLocation( + Mods.GregTech.ID, + "textures/blocks/multitileentity/" + folder + "/" + textureName.getName() + ".png")); + } catch (IOException ignored) { + texture = TextureFactory.of(Textures.BlockIcons.VOID); + } + if (texture == null) { + if (textureName.hasGlow()) { + texture = TextureFactory.builder() + .addIcon(new CustomIcon("multitileentity/" + folder + "/" + textureName.getName())) + .glow() + .build(); + } else { + texture = TextureFactory + .of(new CustomIcon("multitileentity/" + folder + "/" + textureName.getName())); + } + } + switch (textureName) { + case Active -> activeOverlayTexture = texture; + case ActiveWithGlow -> activeOverlayGlowTexture = texture; + case Inactive -> inactiveOverlayTexture = texture; + case InactiveWithGlow -> inactiveOverlayGlowTexture = texture; + } + } } @Override public void copyTextures() { - // Loading an instance + super.copyTextures(); final TileEntity tCanonicalTileEntity = MultiTileEntityRegistry .getCanonicalTileEntity(getMultiTileEntityRegistryID(), getMultiTileEntityID()); - if (tCanonicalTileEntity instanceof MultiTileBasicMachine) { - textures = ((MultiTileBasicMachine) tCanonicalTileEntity).textures; - texturesInactive = ((MultiTileBasicMachine) tCanonicalTileEntity).texturesInactive; - texturesActive = ((MultiTileBasicMachine) tCanonicalTileEntity).texturesActive; - } else { - textures = texturesInactive = texturesActive = emptyIconContainerArray; + if (!(tCanonicalTileEntity instanceof MultiTileBasicMachine)) { + return; } + final MultiTileBasicMachine canonicalEntity = (MultiTileBasicMachine) tCanonicalTileEntity; + activeOverlayTexture = canonicalEntity.activeOverlayTexture; + activeOverlayGlowTexture = canonicalEntity.activeOverlayGlowTexture; + inactiveOverlayTexture = canonicalEntity.inactiveOverlayTexture; + inactiveOverlayGlowTexture = canonicalEntity.inactiveOverlayGlowTexture; } @Override - public ITexture[] getTexture(Block aBlock, byte aSide, boolean isActive, int aRenderPass) { - if (aSide != facing) { - return new ITexture[] { - TextureFactory.of(textures[GT_Values.FACING_ROTATIONS[facing][aSide]], GT_Util.getRGBaArray(rgba)) }; + public ITexture getTexture(ForgeDirection side) { + ITexture texture = super.getTexture(side); + if (side == facing) { + if (isActive()) { + return TextureFactory.of(texture, activeOverlayTexture, activeOverlayGlowTexture); + } + + return TextureFactory.of(texture, inactiveOverlayTexture, inactiveOverlayGlowTexture); } - return new ITexture[] { - TextureFactory.of(textures[GT_Values.FACING_ROTATIONS[facing][aSide]], GT_Util.getRGBaArray(rgba)), - TextureFactory - .of((active ? texturesActive : texturesInactive)[GT_Values.FACING_ROTATIONS[facing][aSide]]) }; + + return TextureFactory.of(texture, getCoverTexture((byte) side.ordinal())); } @Override @@ -358,12 +369,12 @@ public abstract class MultiTileBasicMachine extends TickableMultiTileEntity impl @Override public boolean isLiquidInput(byte aSide) { - return aSide != facing; + return facing.compareTo(ForgeDirection.getOrientation(aSide)) != 0; } @Override public boolean isLiquidOutput(byte aSide) { - return aSide != facing; + return facing.compareTo(ForgeDirection.getOrientation(aSide)) != 0; } @Override @@ -386,8 +397,13 @@ public abstract class MultiTileBasicMachine extends TickableMultiTileEntity impl @Override public IFluidTank getFluidTankFillable(byte aSide, FluidStack aFluidToFill) { - if (!isLiquidInput(aSide)) return null; - for (FluidTankGT tankGT : inputTanks) if (tankGT.contains(aFluidToFill)) return tankGT; + return getFluidTankFillable((byte) facing.ordinal(), aSide, aFluidToFill); + } + + public IFluidTank getFluidTankFillable(byte sideSource, byte sideDestination, FluidStack fluidToFill) { + if (ForgeDirection.getOrientation(sideSource) + .compareTo(ForgeDirection.getOrientation(sideDestination)) != 0) return null; + for (FluidTankGT tankGT : inputTanks) if (tankGT.contains(fluidToFill)) return tankGT; // if (!mRecipes.containsInput(aFluidToFill, this, slot(mRecipes.mInputItemsCount + // mRecipes.mOutputItemsCount))) return null; for (FluidTankGT fluidTankGT : inputTanks) if (fluidTankGT.isEmpty()) return fluidTankGT; @@ -396,9 +412,14 @@ public abstract class MultiTileBasicMachine extends TickableMultiTileEntity impl @Override protected IFluidTank getFluidTankDrainable(byte aSide, FluidStack aFluidToDrain) { - if (!isLiquidOutput(aSide)) return null; + return getFluidTankDrainable((byte) facing.ordinal(), aSide, aFluidToDrain); + } + + protected IFluidTank getFluidTankDrainable(byte sideSource, byte sideDestination, FluidStack fluidToDrain) { + if (ForgeDirection.getOrientation(sideSource) + .compareTo(ForgeDirection.getOrientation(sideDestination)) != 0) return null; for (FluidTankGT fluidTankGT : outputTanks) - if (aFluidToDrain == null ? fluidTankGT.has() : fluidTankGT.contains(aFluidToDrain)) return fluidTankGT; + if (fluidToDrain == null ? fluidTankGT.has() : fluidTankGT.contains(fluidToDrain)) return fluidTankGT; return null; } @@ -428,7 +449,7 @@ public abstract class MultiTileBasicMachine extends TickableMultiTileEntity impl @Override public boolean isItemValidForSlot(int aSlot, ItemStack aStack) { - return false; + return true; } @Override @@ -518,9 +539,8 @@ public abstract class MultiTileBasicMachine extends TickableMultiTileEntity impl } ProcessingLogic logic = ((ProcessingLogicHost) this).getProcessingLogic(); logic.clear(); - boolean result = logic.setInputItems( - inputInventory.getStacks() - .toArray(new ItemStack[0])) + boolean result = logic.setInputItems(getInputItems()) + .setInputFluids(getInputFluids()) .setCurrentOutputItems( outputInventory.getStacks() .toArray(new ItemStack[0])) @@ -554,13 +574,13 @@ public abstract class MultiTileBasicMachine extends TickableMultiTileEntity impl * Runs only on server side */ protected void consumeEnergy() { - PowerLogic logic = ((PowerLogicHost) this).getPowerLogic(GT_Values.SIDE_UNKNOWN); + PowerLogic logic = ((PowerLogicHost) this).getPowerLogic(ForgeDirection.UNKNOWN); if (logic == null) { return; } - if (logic.removeEnergyUnsafe(eut)) { + if (!logic.removeEnergyUnsafe(eut)) { stopMachine(true); } } @@ -591,6 +611,7 @@ public abstract class MultiTileBasicMachine extends TickableMultiTileEntity impl return 100; } + @SideOnly(Side.CLIENT) protected void doActivitySound(ResourceLocation activitySound) { if (isActive() && activitySound != null) { if (activitySoundLoop == null) { @@ -606,36 +627,65 @@ public abstract class MultiTileBasicMachine extends TickableMultiTileEntity impl } } + @SideOnly(Side.CLIENT) protected ResourceLocation getActivitySoundLoop() { return null; } + protected ItemStack[] getInputItems() { + return inputInventory.getStacks() + .toArray(new ItemStack[0]); + } + + protected FluidStack[] getInputFluids() { + return Arrays.stream(inputTanks) + .map(FluidTankGT::get) + .toArray(FluidStack[]::new); + } + protected void outputItems() { - if (itemsToOutput == null) { + outputItems(itemsToOutput); + itemsToOutput = null; + } + + protected void outputItems(ItemStack... itemsToOutput) { + outputItems(outputInventory, itemsToOutput); + } + + protected void outputItems(IItemHandlerModifiable inventory, ItemStack... itemsToOutput) { + if (itemsToOutput == null || inventory == null) { return; } for (ItemStack item : itemsToOutput) { int index = 0; - while (item != null && item.stackSize > 0 && index < outputInventory.getSlots()) { - item = outputInventory.insertItem(index++, item.copy(), false); + while (item != null && item.stackSize > 0 && index < inventory.getSlots()) { + item = inventory.insertItem(index++, item.copy(), false); } } - itemsToOutput = null; } protected void outputFluids() { + outputFluids(fluidsToOutput); + fluidsToOutput = null; + } + + protected void outputFluids(FluidStack... fluidsToOutput) { + outputFluids(outputTanks, fluidsToOutput); + } + + protected void outputFluids(FluidTankGT[] tankArray, FluidStack... fluidsToOutput) { if (fluidsToOutput == null) { return; } for (FluidStack fluid : fluidsToOutput) { - tryToFillTanks(fluid, outputTanks); + tryToFillTanks(fluid, tankArray); } } protected void tryToFillTanks(FluidStack fluid, FluidTankGT... tanks) { for (FluidTankGT tank : tanks) { if (tank.canFillAll(fluid)) { - tank.add(fluid.amount, fluid); + fluid.amount -= tank.add(fluid.amount, fluid); } } } @@ -756,14 +806,77 @@ public abstract class MultiTileBasicMachine extends TickableMultiTileEntity impl @Override protected void addDebugInfo(EntityPlayer player, int logLevel, ArrayList<String> list) { - if (isElectric()) { - list.add( - "Energy: " + EnumChatFormatting.GOLD + getUniversalEnergyStored() + "/" + getUniversalEnergyCapacity()); - } + list.add( + GT_Utility.trans("186", "Owned by: ") + EnumChatFormatting.BLUE + + getOwnerName() + + EnumChatFormatting.RESET + + " (" + + EnumChatFormatting.AQUA + + getOwnerUuid() + + EnumChatFormatting.RESET + + ")"); if (acceptsFuel()) { list.add("Fuel: " + EnumChatFormatting.GOLD + burnTime + "/" + totalBurnTime); } + + if (this instanceof PowerLogicHost powerLogicHost) { + PowerLogic logic = powerLogicHost.getPowerLogic(facing); + if (isElectric) { + list.add( + StatCollector.translateToLocal("GT5U.multiblock.energy") + ": " + + EnumChatFormatting.GREEN + + GT_Utility.formatNumbers(logic.getStoredEnergy()) + + EnumChatFormatting.RESET + + " EU / " + + EnumChatFormatting.YELLOW + + GT_Utility.formatNumbers(logic.getCapacity()) + + EnumChatFormatting.RESET + + " EU"); + list.add( + StatCollector.translateToLocal("GT5U.multiblock.usage") + ": " + + EnumChatFormatting.RED + + GT_Utility.formatNumbers(eut) + + EnumChatFormatting.RESET + + " EU/t"); + list.add( + StatCollector.translateToLocal("GT5U.multiblock.mei") + ": " + + EnumChatFormatting.YELLOW + + GT_Utility.formatNumbers(logic.getVoltage()) + + EnumChatFormatting.RESET + // TODO: Put ampere getter here, once that's variable + + " EU/t(*2A) " + + StatCollector.translateToLocal("GT5U.machines.tier") + + ": " + + EnumChatFormatting.YELLOW + + VN[GT_Utility.getTier(logic.getVoltage())] + + EnumChatFormatting.RESET); + } + } + + addProgressStringToScanner(player, logLevel, list); + + // TODO: Add CPU load calculator + list.add( + "Average CPU load of ~" + GT_Utility.formatNumbers(0) + + "ns over " + + GT_Utility.formatNumbers(0) + + " ticks with worst time of " + + GT_Utility.formatNumbers(0) + + "ns."); + } + + protected void addProgressStringToScanner(EntityPlayer player, int logLevel, ArrayList<String> list) { + list.add( + StatCollector.translateToLocal("GT5U.multiblock.Progress") + ": " + + EnumChatFormatting.GREEN + + GT_Utility.formatNumbers(progressTime > 20 ? progressTime / 20 : progressTime) + + EnumChatFormatting.RESET + + (progressTime > 20 ? " s / " : " ticks / ") + + EnumChatFormatting.YELLOW + + GT_Utility.formatNumbers(maxProgressTime > 20 ? maxProgressTime / 20 : maxProgressTime) + + EnumChatFormatting.RESET + + (maxProgressTime > 20 ? " s" : " ticks")); } protected void stopMachine(boolean powerShutDown) { @@ -783,6 +896,25 @@ public abstract class MultiTileBasicMachine extends TickableMultiTileEntity impl inputInventory.setStackInSlot(i, null); } } + + for (FluidTankGT inputTank : inputTanks) { + if (inputTank == null) { + continue; + } + + if (inputTank.get() != null && inputTank.get().amount <= 0) { + inputTank.setEmpty(); + continue; + } + + FluidStack afterRecipe = inputTank.get(); + FluidStack beforeRecipe = inputTank.get(Integer.MAX_VALUE); + if (afterRecipe == null || beforeRecipe == null) { + continue; + } + int difference = beforeRecipe.amount - afterRecipe.amount; + inputTank.remove(difference); + } } /** @@ -817,6 +949,8 @@ public abstract class MultiTileBasicMachine extends TickableMultiTileEntity impl public void setBooleans(int booleans) { if ((booleans & ACTIVE) == ACTIVE) { setActive(true); + } else { + setActive(false); } } diff --git a/src/main/java/gregtech/api/multitileentity/multiblock/base/ComplexParallelController.java b/src/main/java/gregtech/api/multitileentity/multiblock/base/ComplexParallelController.java new file mode 100644 index 0000000000..ecdeb2294d --- /dev/null +++ b/src/main/java/gregtech/api/multitileentity/multiblock/base/ComplexParallelController.java @@ -0,0 +1,244 @@ +package gregtech.api.multitileentity.multiblock.base; + +import static mcp.mobius.waila.api.SpecialChars.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.LongStream; + +import mcp.mobius.waila.api.IWailaConfigHandler; +import mcp.mobius.waila.api.IWailaDataAccessor; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.StatCollector; +import net.minecraft.world.World; +import net.minecraftforge.fluids.FluidStack; + +import gregtech.api.enums.GT_Values; +import gregtech.api.logic.ComplexParallelProcessingLogic; +import gregtech.api.logic.interfaces.PollutionLogicHost; +import gregtech.api.util.GT_Utility; +import gregtech.api.util.GT_Waila; + +public abstract class ComplexParallelController<T extends ComplexParallelController<T>> extends PowerController<T> { + + protected ComplexParallelProcessingLogic processingLogic; + protected int maxComplexParallels = 0; + protected int currentComplexParallels = 0; + protected long[] maxProgressTimes = new long[0]; + protected long[] progressTimes = new long[0]; + + public ComplexParallelController() { + isSimpleMachine = false; + } + + protected void setMaxComplexParallels(int parallel) { + if (parallel != maxComplexParallels) { + if (maxComplexParallels != 0) { + stopMachine(false); + } + maxProgressTimes = new long[parallel]; + progressTimes = new long[parallel]; + } + maxComplexParallels = parallel; + } + + @Override + protected void runMachine(long tick) { + if (acceptsFuel() && isActive()) { + if (!consumeFuel()) { + stopMachine(true); + return; + } + } + + if (hasThingsToDo()) { + markDirty(); + runningTick(tick); + } + if ((tick % TICKS_BETWEEN_RECIPE_CHECKS == 0 || hasWorkJustBeenEnabled() || hasInventoryBeenModified()) + && maxComplexParallels != currentComplexParallels) { + if (isAllowedToWork() && maxComplexParallels > currentComplexParallels) { + wasEnabled = false; + boolean started = false; + for (int i = 0; i < maxComplexParallels; i++) { + if (maxProgressTimes[i] <= 0 && checkRecipe(i)) { + currentComplexParallels++; + started = true; + } + } + if (started) { + setActive(true); + updateSlots(); + markDirty(); + issueClientUpdate(); + } + } + } + } + + @Override + protected void runningTick(long tick) { + consumeEnergy(); + boolean allStopped = true; + for (int i = 0; i < maxComplexParallels; i++) { + if (maxProgressTimes[i] > 0 && ++progressTimes[i] >= maxProgressTimes[i]) { + progressTimes[i] = 0; + maxProgressTimes[i] = 0; + outputItems(i); + outputFluids(i); + if (isAllowedToWork()) { + if (checkRecipe(i)) { + allStopped = false; + } else { + currentComplexParallels--; + } + } + updateSlots(); + } else if (maxProgressTimes[i] > 0) { + allStopped = false; + } + } + if (allStopped) { + setActive(false); + issueClientUpdate(); + } + + if (this instanceof PollutionLogicHost && tick % POLLUTION_TICK == 0) { + doPollution(); + } + emitEnergy(); + } + + protected boolean checkRecipe(int index) { + ComplexParallelProcessingLogic processingLogic = getComplexProcessingLogic(); + if (processingLogic == null || index < 0 || index >= maxComplexParallels) { + return false; + } + processingLogic.clear(index); + boolean result = processingLogic.setInputItems(index, getInputItems(index)) + .setInputFluids(index, getInputFluids(index)) + .setTileEntity(this) + .setVoidProtection(index, isVoidProtectionEnabled(index)) + .setEut(index, getEutForComplexParallel(index)) + .setPerfectOverclock(hasPerfectOverclock()) + .process(index); + setDuration(index, processingLogic.getDuration(index)); + setEut(processingLogic.getTotalEU()); + return result; + } + + protected void outputItems(int index) { + ComplexParallelProcessingLogic processingLogic = getComplexProcessingLogic(); + if (processingLogic != null && index >= 0 && index < maxComplexParallels) { + outputItems(processingLogic.getOutputItems(index)); + } + } + + protected void outputFluids(int index) { + ComplexParallelProcessingLogic processingLogic = getComplexProcessingLogic(); + if (processingLogic != null && index >= 0 && index < maxComplexParallels) { + outputFluids(processingLogic.getOutputFluids(index)); + } + } + + protected ComplexParallelProcessingLogic getComplexProcessingLogic() { + return processingLogic; + } + + @Override + public boolean hasThingsToDo() { + return LongStream.of(maxProgressTimes) + .sum() > 0; + } + + @Override + protected void stopMachine(boolean powerShutDown) { + super.stopMachine(powerShutDown); + for (int i = 0; i < maxComplexParallels; i++) { + maxProgressTimes[i] = 0; + } + } + + protected void setDuration(int index, long duration) { + if (duration < 0) { + duration = -duration; + } + if (index >= 0 && index < maxComplexParallels) { + maxProgressTimes[index] = duration; + } + } + + protected ItemStack[] getInputItems(int index) { + return getInputItems(); + } + + protected FluidStack[] getInputFluids(int index) { + return getInputFluids(); + } + + protected boolean isVoidProtectionEnabled(int index) { + return !voidExcess; + } + + protected boolean hasPerfectOverclock() { + return false; + } + + protected long getEutForComplexParallel(int index) { + // As default behavior we'll give the parallel all remaining EU we have + return GT_Values.V[tier] - eut; + } + + @Override + protected void addProgressStringToScanner(EntityPlayer player, int logLevel, ArrayList<String> list) { + for (int i = 0; i < maxComplexParallels; i++) { + list.add( + StatCollector.translateToLocal("GT5U.multiblock.Progress") + " " + + (i + 1) + + ": " + + EnumChatFormatting.GREEN + + GT_Utility.formatNumbers(progressTimes[i] > 20 ? progressTimes[i] / 20 : progressTimes[i]) + + EnumChatFormatting.RESET + + (progressTimes[i] > 20 ? " s / " : " ticks / ") + + EnumChatFormatting.YELLOW + + GT_Utility + .formatNumbers(maxProgressTimes[i] > 20 ? maxProgressTimes[i] / 20 : maxProgressTimes[i]) + + EnumChatFormatting.RESET + + (maxProgressTimes[i] > 20 ? " s" : " ticks")); + } + } + + @Override + public void getWailaNBTData(EntityPlayerMP player, TileEntity tile, NBTTagCompound tag, World world, int x, int y, + int z) { + super.getWailaNBTData(player, tile, tag, world, x, y, z); + tag.setInteger("maxComplexParallels", maxComplexParallels); + for (int i = 0; i < maxComplexParallels; i++) { + tag.setLong("maxProgress" + i, maxProgressTimes[i]); + tag.setLong("progress" + i, progressTimes[i]); + } + } + + @Override + public void getWailaBody(ItemStack itemStack, List<String> currentTip, IWailaDataAccessor accessor, + IWailaConfigHandler config) { + super.getWailaBody(itemStack, currentTip, accessor, config); + final NBTTagCompound tag = accessor.getNBTData(); + maxComplexParallels = tag.getInteger("maxComplexParallels"); + for (int i = 0; i < maxComplexParallels; i++) { + long maxProgress = tag.getLong("maxProgress" + i); + long progress = tag.getLong("progress" + i); + currentTip.add( + "Process " + (i + 1) + + ": " + + GT_Waila + .getMachineProgressString(maxProgress > 0 && maxProgress >= progress, maxProgress, progress)); + } + } +} diff --git a/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockController.java b/src/main/java/gregtech/api/multitileentity/multiblock/base/Controller.java index 1355ac13a6..9fdac059da 100644 --- a/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockController.java +++ b/src/main/java/gregtech/api/multitileentity/multiblock/base/Controller.java @@ -1,8 +1,11 @@ package gregtech.api.multitileentity.multiblock.base; +import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofChain; import static gregtech.GT_Mod.GT_FML_LOGGER; import static gregtech.api.enums.GT_Values.ALL_VALID_SIDES; -import static gregtech.api.enums.GT_Values.NBT; +import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.*; +import static gregtech.loaders.preload.GT_Loader_MultiTileEntities.COMPONENT_CASING_REGISTRY; +import static mcp.mobius.waila.api.SpecialChars.*; import java.lang.ref.WeakReference; import java.util.ArrayList; @@ -15,8 +18,12 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; +import mcp.mobius.waila.api.IWailaConfigHandler; +import mcp.mobius.waila.api.IWailaDataAccessor; + import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; @@ -24,6 +31,7 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.IIcon; import net.minecraft.util.StatCollector; import net.minecraft.world.World; +import net.minecraftforge.common.util.Constants; import net.minecraftforge.common.util.ForgeDirection; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; @@ -44,6 +52,7 @@ import com.gtnewhorizon.structurelib.alignment.enumerable.Flip; import com.gtnewhorizon.structurelib.alignment.enumerable.Rotation; import com.gtnewhorizon.structurelib.structure.IStructureDefinition; import com.gtnewhorizon.structurelib.structure.IStructureElement; +import com.gtnewhorizon.structurelib.structure.IStructureElementChain; import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment; import com.gtnewhorizon.structurelib.util.Vec3Impl; import com.gtnewhorizons.modularui.api.ModularUITextures; @@ -92,10 +101,13 @@ import gregtech.api.multitileentity.multiblock.casing.UpgradeCasing; import gregtech.api.objects.GT_ItemStack; import gregtech.api.util.GT_Multiblock_Tooltip_Builder; import gregtech.api.util.GT_Utility; -import gregtech.common.tileentities.casings.upgrade.InventoryUpgrade; +import gregtech.api.util.GT_Waila; +import gregtech.common.tileentities.casings.upgrade.Inventory; + +public abstract class Controller<T extends Controller<T>> extends MultiTileBasicMachine implements IAlignment, + IConstructable, IMultiBlockController, IDescribable, IMTE_AddToolTips, ISurvivalConstructable { -public abstract class MultiBlockController<T extends MultiBlockController<T>> extends MultiTileBasicMachine implements - IAlignment, IConstructable, IMultiBlockController, IDescribable, IMTE_AddToolTips, ISurvivalConstructable { + public static final String ALL_INVENTORIES_NAME = "all"; private static final Map<Integer, GT_Multiblock_Tooltip_Builder> tooltip = new ConcurrentHashMap<>(); private final List<UpgradeCasing> upgradeCasings = new ArrayList<>(); @@ -110,8 +122,8 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex protected Map<String, String> multiBlockInputTankNames = new LinkedHashMap<>(); protected Map<String, String> multiBlockOutputTankNames = new LinkedHashMap<>(); - protected Map<String, FluidTankGT> multiBlockInputTank = new LinkedHashMap<>(); - protected Map<String, FluidTankGT> multiBlockOutputTank = new LinkedHashMap<>(); + protected Map<String, FluidTankGT[]> multiBlockInputTank = new LinkedHashMap<>(); + protected Map<String, FluidTankGT[]> multiBlockOutputTank = new LinkedHashMap<>(); private boolean structureOkay = false, structureChanged = false; private ExtendedFacing extendedFacing = ExtendedFacing.DEFAULT; @@ -122,6 +134,8 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex protected boolean voidExcess = false; protected boolean batchMode = false; protected boolean recipeLock = false; + /** If this is set to true, the machine will get default WAILA behavior */ + protected boolean isSimpleMachine = true; // A list of sides // Each side has a list of parts that have a cover that need to be ticked @@ -137,7 +151,7 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex public abstract short getCasingRegistryID(); /** Meta ID of the required casing */ - public abstract short getCasingMeta(); + public abstract int getCasingMeta(); /** * Create the tooltip for this multi block controller. @@ -164,8 +178,11 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex */ public boolean checkMachine() { double sum = 0; + if (functionalCasings == null || functionalCasings.size() == 0) { + return false; + } for (FunctionalCasing casing : functionalCasings) { - sum += casing.getPartTier(); + sum += casing.getPartTier() * casing.getPartModifier(); } tier = (int) Math.floor(sum / functionalCasings.size()); // Maximum Energy stores will have a cap of 2 minute work time of current voltage @@ -187,6 +204,12 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex .getIndex()); saveUpgradeInventoriesToNBT(nbt); + saveUpgradeTanksToNBT(nbt); + + nbt.setBoolean(NBT.VOID_EXCESS, voidExcess); + nbt.setBoolean(NBT.SEPARATE_INPUTS, separateInputs); + nbt.setBoolean(NBT.RECIPE_LOCK, recipeLock); + nbt.setBoolean(NBT.BATCH_MODE, batchMode); } private void saveUpgradeInventoriesToNBT(NBTTagCompound nbt) { @@ -216,14 +239,54 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex nbt.setTag(NBT.UPGRADE_INVENTORIES_OUTPUT, outputInvList); } + private void saveUpgradeTanksToNBT(NBTTagCompound nbt) { + final NBTTagList inputTankList = new NBTTagList(); + multiBlockInputTank.forEach((id, tanks) -> { + if (!id.equals("controller") && tanks != null && tanks.length > 0) { + final NBTTagCompound tTag = new NBTTagCompound(); + tTag.setString(NBT.UPGRADE_TANK_UUID, id); + tTag.setString(NBT.UPGRADE_TANK_NAME, multiBlockInputTankNames.get(id)); + // We assume all tanks in the tank-array are equally sized + tTag.setLong(NBT.UPGRADE_TANK_CAPACITY, tanks[0].capacity()); + tTag.setLong(NBT.UPGRADE_TANK_CAPACITY_MULTIPLIER, tanks[0].getCapacityMultiplier()); + tTag.setInteger(NBT.UPGRADE_TANKS_COUNT, tanks.length); + for (int i = 0; i < tanks.length; i++) { + tanks[i].writeToNBT(tTag, NBT.UPGRADE_TANKS_PREFIX + i); + } + inputTankList.appendTag(tTag); + } + }); + final NBTTagList outputTankList = new NBTTagList(); + multiBlockOutputTank.forEach((id, tanks) -> { + if (!id.equals("controller") && tanks != null && tanks.length > 0) { + final NBTTagCompound tTag = new NBTTagCompound(); + tTag.setString(NBT.UPGRADE_TANK_UUID, id); + tTag.setString(NBT.UPGRADE_TANK_NAME, multiBlockInputTankNames.get(id)); + // We assume all tanks in the tank-array are equally sized + tTag.setLong(NBT.UPGRADE_TANK_CAPACITY, tanks[0].capacity()); + tTag.setLong(NBT.UPGRADE_TANK_CAPACITY_MULTIPLIER, tanks[0].getCapacityMultiplier()); + tTag.setInteger(NBT.UPGRADE_TANKS_COUNT, tanks.length); + for (int i = 0; i < tanks.length; i++) { + tanks[i].writeToNBT(tTag, NBT.UPGRADE_TANKS_PREFIX + i); + } + outputTankList.appendTag(tTag); + } + }); + nbt.setTag(NBT.UPGRADE_TANKS_INPUT, inputTankList); + nbt.setTag(NBT.UPGRADE_TANKS_OUTPUT, outputTankList); + } + @Override public void readMultiTileNBT(NBTTagCompound nbt) { super.readMultiTileNBT(nbt); // Multiblock inventories are a collection of inventories. The first inventory is the default internal // inventory, and the others are added by inventory extending blocks. - if (inputInventory != null) multiBlockInputInventory.put("controller", inputInventory); - if (outputInventory != null) multiBlockOutputInventory.put("controller", outputInventory); + if (inputInventory != null) registerInventory("controller", "controller", inputInventory, Inventory.INPUT); + if (outputInventory != null) registerInventory("controller", "controller", outputInventory, Inventory.OUTPUT); + + if (inputTanks != null) registerFluidInventory("controller", "controller", inputTanks, Inventory.INPUT); + if (outputTanks != null) registerFluidInventory("controller", "controller", outputTanks, Inventory.OUTPUT); structureOkay = nbt.getBoolean(NBT.STRUCTURE_OK); extendedFacing = ExtendedFacing.of( @@ -232,10 +295,17 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex Flip.byIndex(nbt.getByte(NBT.FLIP))); loadUpgradeInventoriesFromNBT(nbt); + loadUpgradeTanksFromNBT(nbt); + + voidExcess = nbt.getBoolean(NBT.VOID_EXCESS); + separateInputs = nbt.getBoolean(NBT.SEPARATE_INPUTS); + recipeLock = nbt.getBoolean(NBT.RECIPE_LOCK); + batchMode = nbt.getBoolean(NBT.BATCH_MODE); } private void loadUpgradeInventoriesFromNBT(NBTTagCompound nbt) { - final NBTTagList listInputInventories = nbt.getTagList(NBT.UPGRADE_INVENTORIES_INPUT, 10); + final NBTTagList listInputInventories = nbt + .getTagList(NBT.UPGRADE_INVENTORIES_INPUT, Constants.NBT.TAG_COMPOUND); for (int i = 0; i < listInputInventories.tagCount(); i++) { final NBTTagCompound nbtInv = listInputInventories.getCompoundTagAt(i); String invUUID = nbtInv.getString(NBT.UPGRADE_INVENTORY_UUID); @@ -243,11 +313,11 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex int invSize = nbtInv.getInteger(NBT.UPGRADE_INVENTORY_SIZE); IItemHandlerModifiable inv = new ItemStackHandler(invSize); loadInventory(nbtInv, inv, NBT.INV_INPUT_LIST); - multiBlockInputInventory.put(invUUID, inv); - multiBlockInputInventoryNames.put(invUUID, invName); + registerInventory(invName, invUUID, invSize, Inventory.INPUT); } - final NBTTagList listOutputInventories = nbt.getTagList(NBT.UPGRADE_INVENTORIES_OUTPUT, 10); + final NBTTagList listOutputInventories = nbt + .getTagList(NBT.UPGRADE_INVENTORIES_OUTPUT, Constants.NBT.TAG_COMPOUND); for (int i = 0; i < listOutputInventories.tagCount(); i++) { final NBTTagCompound nbtInv = listOutputInventories.getCompoundTagAt(i); String invUUID = nbtInv.getString(NBT.UPGRADE_INVENTORY_UUID); @@ -255,8 +325,41 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex int invSize = nbtInv.getInteger(NBT.UPGRADE_INVENTORY_SIZE); IItemHandlerModifiable inv = new ItemStackHandler(invSize); loadInventory(nbtInv, inv, NBT.INV_OUTPUT_LIST); - multiBlockOutputInventory.put(invUUID, inv); - multiBlockOutputInventoryNames.put(invUUID, invName); + registerInventory(invName, invUUID, invSize, Inventory.OUTPUT); + } + } + + private void loadUpgradeTanksFromNBT(NBTTagCompound nbt) { + final NBTTagList listInputTanks = nbt.getTagList(NBT.UPGRADE_TANKS_INPUT, Constants.NBT.TAG_COMPOUND); + for (int i = 0; i < listInputTanks.tagCount(); i++) { + final NBTTagCompound nbtTank = listInputTanks.getCompoundTagAt(i); + String tankUUID = nbtTank.getString(NBT.UPGRADE_TANK_UUID); + String tankName = nbtTank.getString(NBT.UPGRADE_TANK_NAME); + long capacity = nbtTank.getLong(NBT.UPGRADE_TANK_CAPACITY); + long capacityMultiplier = nbtTank.getLong(NBT.UPGRADE_TANK_CAPACITY_MULTIPLIER); + int count = nbtTank.getInteger(NBT.UPGRADE_TANKS_COUNT); + FluidTankGT[] tanks = new FluidTankGT[count]; + for (int j = 0; j < count; j++) { + tanks[j] = new FluidTankGT(capacity).setCapacityMultiplier(capacityMultiplier) + .readFromNBT(nbtTank, NBT.UPGRADE_TANKS_PREFIX + j); + } + registerFluidInventory(tankName, tankUUID, count, capacity, capacityMultiplier, Inventory.INPUT); + } + + final NBTTagList listOutputTanks = nbt.getTagList(NBT.UPGRADE_TANKS_OUTPUT, Constants.NBT.TAG_COMPOUND); + for (int i = 0; i < listOutputTanks.tagCount(); i++) { + final NBTTagCompound nbtTank = listOutputTanks.getCompoundTagAt(i); + String tankUUID = nbtTank.getString(NBT.UPGRADE_TANK_UUID); + String tankName = nbtTank.getString(NBT.UPGRADE_TANK_NAME); + long capacity = nbtTank.getLong(NBT.UPGRADE_TANK_CAPACITY); + long capacityMultiplier = nbtTank.getLong(NBT.UPGRADE_TANK_CAPACITY_MULTIPLIER); + int count = nbtTank.getInteger(NBT.UPGRADE_TANKS_COUNT); + FluidTankGT[] tanks = new FluidTankGT[count]; + for (int j = 0; j < count; j++) { + tanks[j] = new FluidTankGT(capacity).setCapacityMultiplier(capacityMultiplier) + .readFromNBT(nbtTank, NBT.UPGRADE_TANKS_PREFIX + j); + } + registerFluidInventory(tankName, tankUUID, count, capacity, capacityMultiplier, Inventory.OUTPUT); } } @@ -285,7 +388,12 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex } protected GT_Multiblock_Tooltip_Builder getTooltip() { - return createTooltip(); + GT_Multiblock_Tooltip_Builder builder = tooltip.get(getToolTipID()); + if (builder == null) { + builder = createTooltip(); + tooltip.put(getToolTipID(), builder); + } + return builder; } @Override @@ -306,6 +414,8 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex } public final boolean checkPiece(String piece, Vec3Impl offset) { + functionalCasings.clear(); + upgradeCasings.clear(); return checkPiece(piece, offset.get0(), offset.get1(), offset.get2()); } @@ -390,8 +500,8 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex } @SuppressWarnings("unchecked") - private IStructureDefinition<MultiBlockController<T>> getCastedStructureDefinition() { - return (IStructureDefinition<MultiBlockController<T>>) getStructureDefinition(); + private IStructureDefinition<Controller<T>> getCastedStructureDefinition() { + return (IStructureDefinition<Controller<T>>) getStructureDefinition(); } @Override @@ -501,7 +611,7 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex // Recheck the structure every 30 seconds or so if (!checkStructure(false)) checkStructure(true); } - if (structureOkay) { + if (checkStructure(false)) { runMachine(tick); } else { stopMachine(false); @@ -528,7 +638,7 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex @Override public boolean allowCoverOnSide(byte aSide, GT_ItemStack aCoverID) { - return aSide != facing; + return facing.compareTo(ForgeDirection.getOrientation(aSide)) != 0; } @Override @@ -563,7 +673,14 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex @Override public FluidStack getDrainableFluid(byte aSide) { - final IFluidTank tank = getFluidTankDrainable(aSide, null); + return getDrainableFluid(aSide, null); + } + + @Override + public FluidStack getDrainableFluid(byte aSide, Fluid fluidToDrain) { + final IFluidTank tank = getFluidTankDrainable( + aSide, + fluidToDrain == null ? null : new FluidStack(fluidToDrain, 0)); return tank == null ? null : tank.getFluid(); } @@ -663,11 +780,11 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex return false; final IMultiBlockController tTarget = part.getTarget(false); - if (tTarget != null && tTarget != MultiBlockController.this) return false; + if (tTarget != null && tTarget != t) return false; - part.setTarget(MultiBlockController.this, modes); + part.setTarget((IMultiBlockController) t, modes); - registerSpecialCasings(part); + ((Controller<?>) t).registerSpecialCasings(part); return true; } @@ -703,9 +820,9 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex } if (world.setBlock(x, y, z, tContainer.mBlock, 15 - tContainer.mBlockMetaData, 2)) { tContainer.setMultiTile(world, x, y, z); - ((MultiBlockPart) te).setTarget(MultiBlockController.this, modes); + ((MultiBlockPart) te).setTarget(Controller.this, modes); - registerSpecialCasings((MultiBlockPart) te); + ((Controller<?>) t).registerSpecialCasings((MultiBlockPart) te); } return false; @@ -717,6 +834,150 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex }; } + protected <S> IStructureElementChain<S> addMotorCasings(int modes) { + return ofChain( + addMultiTileCasing(COMPONENT_CASING_REGISTRY, LV_Motor.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, MV_Motor.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, HV_Motor.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, EV_Motor.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, IV_Motor.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, LuV_Motor.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, ZPM_Motor.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UV_Motor.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UHV_Motor.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UEV_Motor.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UIV_Motor.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UMV_Motor.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UXV_Motor.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, MAX_Motor.getId(), modes)); + } + + protected <S> IStructureElementChain<S> addPumpCasings(int modes) { + return ofChain( + addMultiTileCasing(COMPONENT_CASING_REGISTRY, LV_Pump.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, MV_Pump.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, HV_Pump.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, EV_Pump.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, IV_Pump.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, LuV_Pump.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, ZPM_Pump.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UV_Pump.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UHV_Pump.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UEV_Pump.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UIV_Pump.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UMV_Pump.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UXV_Pump.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, MAX_Pump.getId(), modes)); + } + + protected <S> IStructureElementChain<S> addPistonCasings(int modes) { + return ofChain( + addMultiTileCasing(COMPONENT_CASING_REGISTRY, LV_Piston.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, MV_Piston.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, HV_Piston.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, EV_Piston.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, IV_Piston.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, LuV_Piston.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, ZPM_Piston.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UV_Piston.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UHV_Piston.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UEV_Piston.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UIV_Piston.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UMV_Piston.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UXV_Piston.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, MAX_Piston.getId(), modes)); + } + + protected <S> IStructureElementChain<S> addConveyorCasings(int modes) { + return ofChain( + addMultiTileCasing(COMPONENT_CASING_REGISTRY, LV_Conveyor.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, MV_Conveyor.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, HV_Conveyor.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, EV_Conveyor.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, IV_Conveyor.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, LuV_Conveyor.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, ZPM_Conveyor.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UV_Conveyor.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UHV_Conveyor.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UEV_Conveyor.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UIV_Conveyor.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UMV_Conveyor.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UXV_Conveyor.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, MAX_Conveyor.getId(), modes)); + } + + protected <S> IStructureElementChain<S> addRobotArmCasings(int modes) { + return ofChain( + addMultiTileCasing(COMPONENT_CASING_REGISTRY, LV_RobotArm.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, MV_RobotArm.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, HV_RobotArm.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, EV_RobotArm.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, IV_RobotArm.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, LuV_RobotArm.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, ZPM_RobotArm.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UV_RobotArm.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UHV_RobotArm.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UEV_RobotArm.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UIV_RobotArm.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UMV_RobotArm.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UXV_RobotArm.getId(), modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, MAX_RobotArm.getId(), modes)); + } + + protected <S> IStructureElementChain<S> addSensorCasings(int Modes) { + return ofChain( + addMultiTileCasing(COMPONENT_CASING_REGISTRY, LV_Sensor.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, MV_Sensor.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, HV_Sensor.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, EV_Sensor.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, IV_Sensor.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, LuV_Sensor.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, ZPM_Sensor.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UV_Sensor.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UHV_Sensor.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UEV_Sensor.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UIV_Sensor.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UMV_Sensor.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UXV_Sensor.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, MAX_Sensor.getId(), Modes)); + } + + protected <S> IStructureElementChain<S> addEmitterCasings(int Modes) { + return ofChain( + addMultiTileCasing(COMPONENT_CASING_REGISTRY, LV_Emitter.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, MV_Emitter.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, HV_Emitter.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, EV_Emitter.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, IV_Emitter.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, LuV_Emitter.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, ZPM_Emitter.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UV_Emitter.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UHV_Emitter.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UEV_Emitter.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UIV_Emitter.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UMV_Emitter.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UXV_Emitter.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, MAX_Emitter.getId(), Modes)); + } + + protected <S> IStructureElementChain<S> addFieldGeneratorCasings(int Modes) { + return ofChain( + addMultiTileCasing(COMPONENT_CASING_REGISTRY, LV_FieldGenerator.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, MV_FieldGenerator.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, HV_FieldGenerator.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, EV_FieldGenerator.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, IV_FieldGenerator.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, LuV_FieldGenerator.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, ZPM_FieldGenerator.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UV_FieldGenerator.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UHV_FieldGenerator.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UEV_FieldGenerator.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UIV_FieldGenerator.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UMV_FieldGenerator.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, UXV_FieldGenerator.getId(), Modes), + addMultiTileCasing(COMPONENT_CASING_REGISTRY, MAX_FieldGenerator.getId(), Modes)); + } + protected void registerSpecialCasings(MultiBlockPart part) { if (part instanceof UpgradeCasing) { upgradeCasings.add((UpgradeCasing) part); @@ -729,12 +990,76 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex /** * Fluid - MultiBlock related Fluid Tank behaviour. */ + public void registerFluidInventory(String name, String id, int numberOfSlots, long capacity, + long capacityMultiplier, int type) { + if (name == null || name.equals("") + || id == null + || id.equals("") + || numberOfSlots < 0 + || capacity < 0 + || capacityMultiplier < 0) { + return; + } + FluidTankGT[] tanks = new FluidTankGT[numberOfSlots]; + for (int i = 0; i < numberOfSlots; i++) { + tanks[i] = new FluidTankGT(capacity).setCapacityMultiplier(capacityMultiplier); + } + registerFluidInventory(name, id, tanks, type); + } + + public void registerFluidInventory(String name, String id, FluidTankGT[] fluidInventory, int type) { + if (name == null || name.equals("") + || id == null + || id.equals("") + || fluidInventory == null + || fluidInventory.length == 0) { + return; + } + if (type == Inventory.INPUT || type == Inventory.BOTH) { + if (multiBlockInputTank.containsKey(id)) return; + multiBlockInputTank.put(id, fluidInventory); + multiBlockInputTankNames.put(id, name); + } + if (type == Inventory.OUTPUT || type == Inventory.BOTH) { + if (multiBlockOutputTank.containsKey(id)) return; + multiBlockOutputTank.put(id, fluidInventory); + multiBlockOutputTankNames.put(id, name); + } + } + + public void unregisterFluidInventory(String aName, String aID, int aType) { + if ((aType == Inventory.INPUT || aType == Inventory.BOTH) && multiBlockInputTank.containsKey(aID)) { + multiBlockInputTank.remove(aID, multiBlockInputTank.get(aID)); + multiBlockInputTankNames.remove(aID, aName); + } + if ((aType == Inventory.OUTPUT || aType == Inventory.BOTH) && multiBlockOutputTank.containsKey(aID)) { + multiBlockOutputTank.remove(aID, multiBlockOutputTank.get(aID)); + multiBlockOutputTankNames.remove(aID, aName); + } + } + + protected FluidTankGT[] getTanksForInput() { + List<FluidTankGT> tanks = new ArrayList<>(); + for (FluidTankGT[] inputTanks : multiBlockInputTank.values()) { + tanks.addAll(Arrays.asList(inputTanks)); + } + return tanks.toArray(new FluidTankGT[0]); + } + + protected FluidTankGT[] getTanksForOutput() { + List<FluidTankGT> tanks = new ArrayList<>(); + for (FluidTankGT[] outputTanks : multiBlockOutputTank.values()) { + tanks.addAll(Arrays.asList(outputTanks)); + } + return tanks.toArray(new FluidTankGT[0]); + } + protected IFluidTank getFluidTankFillable(MultiBlockPart aPart, byte aSide, FluidStack aFluidToFill) { - return getFluidTankFillable(aSide, aFluidToFill); + return getFluidTankFillable(aPart.getFrontFacing(), aSide, aFluidToFill); } protected IFluidTank getFluidTankDrainable(MultiBlockPart aPart, byte aSide, FluidStack aFluidToDrain) { - return getFluidTankDrainable(aSide, aFluidToDrain); + return getFluidTankDrainable(aPart.getFrontFacing(), aSide, aFluidToDrain); } protected IFluidTank[] getFluidTanks(MultiBlockPart aPart, byte aSide) { @@ -802,19 +1127,27 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex @Override public IFluidTank[] getFluidTanksForGUI(MultiBlockPart aPart) { - if (aPart.modeSelected(MultiBlockPart.FLUID_IN)) return inputTanks; - if (aPart.modeSelected(MultiBlockPart.FLUID_OUT)) return outputTanks; + final String lockedInventory = aPart.getLockedInventory(); + if (lockedInventory == null) { + if (aPart.modeSelected(MultiBlockPart.FLUID_IN)) return getTanksForInput(); + else if (aPart.modeSelected(MultiBlockPart.FLUID_OUT)) return getTanksForOutput(); + } else { + final Map<String, FluidTankGT[]> tankMap = getMultiBlockTankArray(aPart); + if (tankMap == null) return GT_Values.emptyFluidTank; + final FluidTankGT[] tanks = tankMap.get(lockedInventory); + return tanks != null ? tanks : GT_Values.emptyFluidTank; + } return GT_Values.emptyFluidTank; } // #region Energy @Override - public PowerLogic getPowerLogic(IMultiBlockPart part, byte side) { + public PowerLogic getPowerLogic(IMultiBlockPart part, ForgeDirection side) { if (!(this instanceof PowerLogicHost)) { return null; } - if (part.getFrontFacing() != side) { + if (ForgeDirection.getOrientation(part.getFrontFacing()) != side) { return null; } @@ -827,27 +1160,32 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex */ @Override public void registerInventory(String aName, String aID, int aInventorySize, int aType) { - if (aType == InventoryUpgrade.INPUT || aType == InventoryUpgrade.BOTH) { - if (multiBlockInputInventory.containsKey(aID)) return; - multiBlockInputInventory.put(aID, new ItemStackHandler(aInventorySize)); - multiBlockInputInventoryNames.put(aID, aName); + registerInventory(aName, aID, new ItemStackHandler(aInventorySize), aType); + } + + public void registerInventory(String name, String id, IItemHandlerModifiable inventory, int type) { + if (name == null || name.equals("") || id == null || id.equals("") || inventory == null) { + return; } - if (aType == InventoryUpgrade.OUTPUT || aType == InventoryUpgrade.BOTH) { - if (multiBlockOutputInventory.containsKey(aID)) return; - multiBlockOutputInventory.put(aID, new ItemStackHandler(aInventorySize)); - multiBlockOutputInventoryNames.put(aID, aName); + if (type == Inventory.INPUT || type == Inventory.BOTH) { + if (multiBlockInputInventory.containsKey(id)) return; + multiBlockInputInventory.put(id, inventory); + multiBlockInputInventoryNames.put(id, name); + } + if (type == Inventory.OUTPUT || type == Inventory.BOTH) { + if (multiBlockOutputInventory.containsKey(id)) return; + multiBlockOutputInventory.put(id, inventory); + multiBlockOutputInventoryNames.put(id, name); } } @Override public void unregisterInventory(String aName, String aID, int aType) { - if ((aType == InventoryUpgrade.INPUT || aType == InventoryUpgrade.BOTH) - && multiBlockInputInventory.containsKey(aID)) { + if ((aType == Inventory.INPUT || aType == Inventory.BOTH) && multiBlockInputInventory.containsKey(aID)) { multiBlockInputInventory.remove(aID, multiBlockInputInventory.get(aID)); multiBlockInputInventoryNames.remove(aID, aName); } - if ((aType == InventoryUpgrade.OUTPUT || aType == InventoryUpgrade.BOTH) - && multiBlockOutputInventory.containsKey(aID)) { + if ((aType == Inventory.OUTPUT || aType == Inventory.BOTH) && multiBlockOutputInventory.containsKey(aID)) { multiBlockOutputInventory.remove(aID, multiBlockOutputInventory.get(aID)); multiBlockOutputInventoryNames.remove(aID, aName); } @@ -855,12 +1193,10 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex @Override public void changeInventoryName(String aName, String aID, int aType) { - if ((aType == InventoryUpgrade.INPUT || aType == InventoryUpgrade.BOTH) - && multiBlockInputInventoryNames.containsKey(aID)) { + if ((aType == Inventory.INPUT || aType == Inventory.BOTH) && multiBlockInputInventoryNames.containsKey(aID)) { multiBlockInputInventoryNames.put(aID, aName); } - if ((aType == InventoryUpgrade.OUTPUT || aType == InventoryUpgrade.BOTH) - && multiBlockOutputInventoryNames.containsKey(aID)) { + if ((aType == Inventory.OUTPUT || aType == Inventory.BOTH) && multiBlockOutputInventoryNames.containsKey(aID)) { multiBlockOutputInventoryNames.put(aID, aName); } } @@ -879,10 +1215,18 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex } @Override + public void enableWorking() { + super.enableWorking(); + if (!structureOkay) { + checkStructure(true); + } + } + + @Override public IItemHandlerModifiable getInventoryForGUI(MultiBlockPart aPart) { if (isServerSide()) { for (UpgradeCasing tPart : upgradeCasings) { - if (!(tPart instanceof InventoryUpgrade)) continue; + if (!(tPart instanceof Inventory)) continue; tPart.issueClientUpdate(); } } @@ -908,6 +1252,18 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex return false; } + protected Map<String, FluidTankGT[]> getMultiBlockTankArray(MultiBlockPart aPart) { + if (aPart.modeSelected(MultiBlockPart.FLUID_IN)) return multiBlockInputTank; + else if (aPart.modeSelected(MultiBlockPart.FLUID_OUT)) return multiBlockOutputTank; + return null; + } + + protected Map<String, String> getMultiBlockTankArrayNames(MultiBlockPart aPart) { + if (aPart.modeSelected(MultiBlockPart.FLUID_IN)) return multiBlockInputTankNames; + else if (aPart.modeSelected(MultiBlockPart.FLUID_OUT)) return multiBlockOutputTankNames; + return null; + } + protected Map<String, IItemHandlerModifiable> getMultiBlockInventory(MultiBlockPart aPart) { if (aPart.modeSelected(MultiBlockPart.ITEM_IN)) return multiBlockInputInventory; else if (aPart.modeSelected(MultiBlockPart.ITEM_OUT)) return multiBlockOutputInventory; @@ -1058,8 +1414,7 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex @Override public List<String> getInventoryNames(MultiBlockPart aPart) { final List<String> inventoryNames = new ArrayList<>(); - inventoryNames.add("all"); - inventoryNames.add("controller"); + inventoryNames.add(ALL_INVENTORIES_NAME); inventoryNames.addAll(getMultiBlockInventoryNames(aPart).values()); return inventoryNames; } @@ -1067,7 +1422,7 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex @Override public List<String> getInventoryIDs(MultiBlockPart aPart) { final List<String> tInventoryIDs = new ArrayList<>(); - tInventoryIDs.add("all"); + tInventoryIDs.add(ALL_INVENTORIES_NAME); tInventoryIDs.addAll(getMultiBlockInventory(aPart).keySet()); return tInventoryIDs; } @@ -1095,6 +1450,22 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex } @Override + public List<String> getTankArrayNames(MultiBlockPart aPart) { + final List<String> inventoryNames = new ArrayList<>(); + inventoryNames.add(ALL_INVENTORIES_NAME); + inventoryNames.addAll(getMultiBlockTankArrayNames(aPart).values()); + return inventoryNames; + } + + @Override + public List<String> getTankArrayIDs(MultiBlockPart aPart) { + final List<String> inventoryIDs = new ArrayList<>(); + inventoryIDs.add(ALL_INVENTORIES_NAME); + inventoryIDs.addAll(getMultiBlockTankArray(aPart).keySet()); + return inventoryIDs; + } + + @Override public boolean hasCustomInventoryName(MultiBlockPart aPart) { return hasCustomInventoryName(); } @@ -1137,12 +1508,13 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex * Helper Methods For Recipe checking */ - protected ItemStack[] getAllItemInputs() { + @Override + protected ItemStack[] getInputItems() { return getInventoriesForInput().getStacks() .toArray(new ItemStack[0]); } - protected ItemStack[] getAllOutputItems() { + protected ItemStack[] getOutputItems() { return getInventoriesForOutput().getStacks() .toArray(new ItemStack[0]); } @@ -1159,6 +1531,53 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex .collect(Collectors.toList()); } + protected ItemStack[] getItemInputsForInventory(String id) { + IItemHandlerModifiable inventory = multiBlockInputInventory.get(id); + if (inventory != null) { + return inventory.getStacks() + .toArray(new ItemStack[0]); + } + return null; + } + + @Override + protected FluidStack[] getInputFluids() { + List<FluidStack> fluidStacks = new ArrayList<>(); + for (FluidTankGT[] inputTanks : multiBlockInputTank.values()) { + for (FluidTankGT inputTank : inputTanks) { + FluidStack fluidStack = inputTank.get(); + if (fluidStack != null) { + fluidStacks.add(fluidStack); + } + } + } + return fluidStacks.toArray(new FluidStack[0]); + } + + protected FluidStack[] getOutputFluids() { + List<FluidStack> fluidStacks = new ArrayList<>(); + for (FluidTankGT[] inputTanks : multiBlockInputTank.values()) { + for (FluidTankGT inputTank : inputTanks) { + FluidStack fluidStack = inputTank.getFluid(); + if (fluidStack != null) { + fluidStacks.add(fluidStack); + } + } + } + return fluidStacks.toArray(new FluidStack[0]); + } + + protected Iterable<Pair<FluidStack[], String>> getFluidInputsForEachTankArray() { + return multiBlockInputTank.entrySet() + .stream() + .map((entry) -> Pair.of(FluidTankGT.getFluidsFromTanks(entry.getValue()), entry.getKey())) + .collect(Collectors.toList()); + } + + protected FluidStack[] getFluidInputsForTankArray(String id) { + return FluidTankGT.getFluidsFromTanks(multiBlockInputTank.get(id)); + } + protected void setItemOutputs(String inventory, ItemStack... itemOutputs) { itemsToOutput = itemOutputs; inventoryName = inventory; @@ -1208,7 +1627,7 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex return; } - List<FluidTankGT> tanks = new ArrayList<>(multiBlockOutputTank.values()); + List<FluidTankGT> tanks = Arrays.asList(outputTanks); for (FluidStack fluid : fluidsToOutput) { int index = 0; while (fluid != null && fluid.amount > 0 && index < tanks.size()) { @@ -1223,10 +1642,29 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex protected void updateSlots() { IItemHandlerModifiable inv = getInventoriesForInput(); for (int i = 0; i < inv.getSlots(); i++) { - if (inv.getStackInSlot(i).stackSize <= 0) { + if (inv.getStackInSlot(i) != null && inv.getStackInSlot(i).stackSize <= 0) { inv.setStackInSlot(i, null); } } + + for (FluidTankGT inputTank : getTanksForInput()) { + if (inputTank == null) { + continue; + } + + if (inputTank.get() != null && inputTank.get().amount <= 0) { + inputTank.setEmpty(); + continue; + } + + FluidStack afterRecipe = inputTank.get(); + FluidStack beforeRecipe = inputTank.get(Integer.MAX_VALUE); + if (afterRecipe == null || beforeRecipe == null) { + continue; + } + int difference = beforeRecipe.amount - afterRecipe.amount; + inputTank.remove(difference); + } } @Override @@ -1238,13 +1676,12 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex logic.clear(); boolean result = false; if (isSeparateInputs()) { + // TODO: Add separation with fluids for (Pair<ItemStack[], String> inventory : getItemInputsForEachInventory()) { IItemHandlerModifiable outputInventory = multiBlockOutputInventory .getOrDefault(inventory.getLeft(), null); result = logic.setInputItems(inventory.getLeft()) - .setCurrentOutputItems( - outputInventory != null ? outputInventory.getStacks() - .toArray(new ItemStack[0]) : null) + .setCurrentOutputItems(getOutputItems()) .process(); if (result) { inventoryName = inventory.getRight(); @@ -1253,8 +1690,10 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex logic.clear(); } } else { - result = logic.setInputItems(getAllItemInputs()) - .setCurrentOutputItems(getAllOutputItems()) + result = logic.setInputItems(getInputItems()) + .setCurrentOutputItems(getOutputItems()) + .setInputFluids(getInputFluids()) + .setCurrentOutputFluids(getOutputFluids()) .process(); } setDuration(logic.getDuration()); @@ -1264,6 +1703,14 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex return result; } + public IItemHandlerModifiable getOutputInventory() { + return outputInventory; + } + + public FluidTankGT[] getOutputTanks() { + return outputTanks; + } + /* * GUI Work - Multiblock GUI related methods */ @@ -1314,7 +1761,7 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) { if (isServerSide()) { for (UpgradeCasing tPart : upgradeCasings) { - if (!(tPart instanceof InventoryUpgrade)) continue; + if (!(tPart instanceof Inventory)) continue; tPart.issueClientUpdate(); } } @@ -1340,12 +1787,12 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex new TabButton(page++) .setBackground( false, - ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0, 1f, 0.5f), + ModularUITextures.VANILLA_TAB_TOP_MIDDLE.getSubArea(0, 0, 1f, 0.5f), GT_UITextures.PICTURE_ITEM_IN.withFixedSize(16, 16) .withOffset(2, 4)) .setBackground( true, - ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0.5f, 1f, 1f), + ModularUITextures.VANILLA_TAB_TOP_MIDDLE.getSubArea(0, 0.5f, 1f, 1f), GT_UITextures.PICTURE_ITEM_IN.withFixedSize(16, 16) .withOffset(2, 4)) .setPos(20 * (page - 1), -20)) @@ -1360,12 +1807,12 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex new TabButton(page++) .setBackground( false, - ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0, 1f, 0.5f), + ModularUITextures.VANILLA_TAB_TOP_MIDDLE.getSubArea(0, 0, 1f, 0.5f), GT_UITextures.PICTURE_ITEM_OUT.withFixedSize(16, 16) .withOffset(2, 4)) .setBackground( true, - ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0.5f, 1f, 1f), + ModularUITextures.VANILLA_TAB_TOP_MIDDLE.getSubArea(0, 0.5f, 1f, 1f), GT_UITextures.PICTURE_ITEM_OUT.withFixedSize(16, 16) .withOffset(2, 4)) .setPos(20 * (page - 1), -20)) @@ -1380,12 +1827,12 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex new TabButton(page++) .setBackground( false, - ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0, 1f, 0.5f), + ModularUITextures.VANILLA_TAB_TOP_MIDDLE.getSubArea(0, 0, 1f, 0.5f), GT_UITextures.PICTURE_FLUID_IN.withFixedSize(16, 16) .withOffset(2, 4)) .setBackground( true, - ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0.5f, 1f, 1f), + ModularUITextures.VANILLA_TAB_TOP_MIDDLE.getSubArea(0, 0.5f, 1f, 1f), GT_UITextures.PICTURE_FLUID_IN.withFixedSize(16, 16) .withOffset(2, 4)) .setPos(20 * (page - 1), -20)) @@ -1400,12 +1847,12 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex new TabButton(page++) .setBackground( false, - ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0, 1f, 0.5f), + ModularUITextures.VANILLA_TAB_TOP_MIDDLE.getSubArea(0, 0, 1f, 0.5f), GT_UITextures.PICTURE_FLUID_OUT.withFixedSize(16, 16) .withOffset(2, 4)) .setBackground( true, - ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0.5f, 1f, 1f), + ModularUITextures.VANILLA_TAB_TOP_MIDDLE.getSubArea(0, 0.5f, 1f, 1f), GT_UITextures.PICTURE_FLUID_OUT.withFixedSize(16, 16) .withOffset(2, 4)) .setPos(20 * (page - 1), -20)) @@ -1487,7 +1934,7 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex } protected Widget getFluidInventoryInputGUI() { - final IFluidTank[] tanks = inputTanks; + final IFluidTank[] tanks = getTanksForInput(); final Scrollable scrollable = new Scrollable().setVerticalScroll(); for (int rows = 0; rows * 4 < tanks.length; rows++) { final int columnsToMake = Math.min(tanks.length - rows * 4, 4); @@ -1498,12 +1945,12 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex .setSize(18, 18)); } } - return scrollable.setSize(18 * 4 + 4, 18 * 4) + return scrollable.setSize(18 * 4 + 4, 18 * 5) .setPos(52, 7); } protected Widget getFluidInventoryOutputGUI() { - final IFluidTank[] tanks = outputTanks; + final IFluidTank[] tanks = getTanksForOutput(); final Scrollable scrollable = new Scrollable().setVerticalScroll(); for (int rows = 0; rows * 4 < tanks.length; rows++) { final int columnsToMake = Math.min(tanks.length - rows * 4, 4); @@ -1706,4 +2153,35 @@ public abstract class MultiBlockController<T extends MultiBlockController<T>> ex protected boolean isRecipeLockingEnabled() { return recipeLock; } + + @Override + public ModularWindow createWindowGUI(UIBuildContext buildContext) { + return createWindow(buildContext); + } + + @Override + public void getWailaNBTData(EntityPlayerMP player, TileEntity tile, NBTTagCompound tag, World world, int x, int y, + int z) { + super.getWailaNBTData(player, tile, tag, world, x, y, z); + tag.setLong("progress", progressTime); + tag.setLong("maxProgress", maxProgressTime); + tag.setBoolean("structureOkay", structureOkay); + } + + @Override + public void getWailaBody(ItemStack itemStack, List<String> currentTip, IWailaDataAccessor accessor, + IWailaConfigHandler config) { + super.getWailaBody(itemStack, currentTip, accessor, config); + final NBTTagCompound tag = accessor.getNBTData(); + if (!tag.getBoolean("structureOkay")) { + currentTip.add(RED + "** INCOMPLETE STRUCTURE **" + RESET); + } else { + currentTip.add((GREEN + "Running Fine") + RESET); + } + if (isSimpleMachine) { + boolean isActive = tag.getBoolean("isActive"); + currentTip + .add(GT_Waila.getMachineProgressString(isActive, tag.getLong("maxProgress"), tag.getLong("progress"))); + } + } } diff --git a/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockPart.java b/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockPart.java index 936145daa8..d9d0ef4666 100644 --- a/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockPart.java +++ b/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockPart.java @@ -18,12 +18,12 @@ import static org.apache.commons.lang3.ObjectUtils.firstNonNull; import java.math.RoundingMode; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import mcp.mobius.waila.api.IWailaConfigHandler; import mcp.mobius.waila.api.IWailaDataAccessor; -import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemStack; @@ -40,19 +40,14 @@ import com.gtnewhorizons.modularui.api.forge.IItemHandlerModifiable; import com.gtnewhorizons.modularui.api.screen.ModularWindow; import com.gtnewhorizons.modularui.api.screen.ModularWindow.Builder; import com.gtnewhorizons.modularui.api.screen.UIBuildContext; -import com.gtnewhorizons.modularui.common.widget.DrawableWidget; -import com.gtnewhorizons.modularui.common.widget.DropDownWidget; -import com.gtnewhorizons.modularui.common.widget.FluidSlotWidget; -import com.gtnewhorizons.modularui.common.widget.Scrollable; -import com.gtnewhorizons.modularui.common.widget.SlotWidget; +import com.gtnewhorizons.modularui.common.widget.*; import gregtech.api.enums.GT_Values; -import gregtech.api.enums.Textures; -import gregtech.api.interfaces.IIconContainer; +import gregtech.api.fluid.FluidTankGT; +import gregtech.api.gui.modularui.GT_UITextures; import gregtech.api.interfaces.ITexture; import gregtech.api.logic.PowerLogic; import gregtech.api.logic.interfaces.PowerLogicHost; -import gregtech.api.multitileentity.MultiTileEntityRegistry; import gregtech.api.multitileentity.base.NonTickableMultiTileEntity; import gregtech.api.multitileentity.interfaces.IMultiBlockController; import gregtech.api.multitileentity.interfaces.IMultiBlockPart; @@ -80,6 +75,7 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity protected String mLockedInventory = GT_Values.E; protected int mLockedInventoryIndex = 0; + protected FluidTankGT configurationTank = new FluidTankGT(); /** * What Part Tier is this part? All Basic Casings are Tier 1, and will allow: Energy, Item, Fluid input/output. Some @@ -90,12 +86,22 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity } public String getLockedInventory() { - issueClientUpdate(); + // TODO: Can this cause side-effects? Removed for now because it causes huge network traffic when using covers + // issueClientUpdate(); IMultiBlockController controller = getTarget(false); - if (!getNameOfInventoryFromIndex(controller, mLockedInventoryIndex).equals(mLockedInventory)) { - mLockedInventory = getNameOfInventoryFromIndex(controller, mLockedInventoryIndex); - if (mLockedInventory.equals("all")) { - mLockedInventory = ""; + if (modeSelected(ITEM_IN) || modeSelected(ITEM_OUT)) { + if (!getNameOfInventoryFromIndex(controller, mLockedInventoryIndex).equals(mLockedInventory)) { + mLockedInventory = getNameOfInventoryFromIndex(controller, mLockedInventoryIndex); + if (mLockedInventory.equals(Controller.ALL_INVENTORIES_NAME)) { + mLockedInventory = ""; + } + } + } else { + if (!getNameOfTankArrayFromIndex(controller, mLockedInventoryIndex).equals(mLockedInventory)) { + mLockedInventory = getNameOfTankArrayFromIndex(controller, mLockedInventoryIndex); + if (mLockedInventory.equals(Controller.ALL_INVENTORIES_NAME)) { + mLockedInventory = ""; + } } } return mLockedInventory.equals("") ? null : mLockedInventory; @@ -124,6 +130,17 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity IWailaConfigHandler config) { super.getWailaBody(itemStack, currenttip, accessor, config); currenttip.add(String.format("Mode: %s", getModeName(mMode))); + if (modeSelected(FLUID_OUT)) { + if (configurationTank != null && configurationTank.get() != null) { + currenttip.add( + String.format( + "Locked to: %s", + configurationTank.get() + .getLocalizedName())); + } else { + currenttip.add("Locked to: Nothing"); + } + } } public IMultiBlockController getTarget(boolean aCheckValidity) { @@ -202,6 +219,9 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity if (aNBT.hasKey(NBT.LOCKED_INVENTORY_INDEX)) { mLockedInventoryIndex = aNBT.getInteger(NBT.LOCKED_INVENTORY_INDEX); } + if (aNBT.hasKey(NBT.LOCKED_FLUID)) { + configurationTank.readFromNBT(aNBT, NBT.LOCKED_FLUID); + } } @Override @@ -220,6 +240,7 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity if (mLockedInventoryIndex != 0) { aNBT.setInteger(NBT.LOCKED_INVENTORY_INDEX, mLockedInventoryIndex); } + configurationTank.writeToNBT(aNBT, NBT.LOCKED_FLUID); } @Override @@ -318,46 +339,48 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity } @Override - public void loadTextureNBT(NBTTagCompound aNBT) { - // Loading the registry - final String textureName = aNBT.getString(NBT.TEXTURE); - textures = new IIconContainer[] { - new Textures.BlockIcons.CustomIcon("multitileentity/multiblockparts/" + textureName + "/bottom"), - new Textures.BlockIcons.CustomIcon("multitileentity/multiblockparts/" + textureName + "/top"), - new Textures.BlockIcons.CustomIcon("multitileentity/multiblockparts/" + textureName + "/side"), - new Textures.BlockIcons.CustomIcon("multitileentity/multiblockparts/" + textureName + "/overlay/bottom"), - new Textures.BlockIcons.CustomIcon("multitileentity/multiblockparts/" + textureName + "/overlay/top"), - new Textures.BlockIcons.CustomIcon("multitileentity/multiblockparts/" + textureName + "/overlay/side") }; - } - - @Override - public void copyTextures() { - // Loading an instance - final TileEntity tCanonicalTileEntity = MultiTileEntityRegistry - .getCanonicalTileEntity(getMultiTileEntityRegistryID(), getMultiTileEntityID()); - if (tCanonicalTileEntity instanceof MultiBlockPart) textures = ((MultiBlockPart) tCanonicalTileEntity).textures; - } - - @Override - public ITexture[] getTexture(Block aBlock, byte aSide, boolean isActive, int aRenderPass) { - // For normal parts - texture comes from BaseMTE; overlay based on current mode - // TODO(MTE) - For Advanced parts they might come from somewhere else - final ITexture baseTexture = TextureFactory.of(super.getTexture(aBlock, aSide, isActive, aRenderPass)); - if (mMode != 0 && aSide == facing) { - if (mMode == getModeOrdinal(ITEM_IN)) return new ITexture[] { baseTexture, - TextureFactory.of(OVERLAY_PIPE_IN), TextureFactory.of(ITEM_IN_SIGN) }; - if (mMode == getModeOrdinal(ITEM_OUT)) return new ITexture[] { baseTexture, - TextureFactory.of(OVERLAY_PIPE_OUT), TextureFactory.of(ITEM_OUT_SIGN) }; - if (mMode == getModeOrdinal(FLUID_IN)) return new ITexture[] { baseTexture, - TextureFactory.of(OVERLAY_PIPE_IN), TextureFactory.of(FLUID_IN_SIGN) }; - if (mMode == getModeOrdinal(FLUID_OUT)) return new ITexture[] { baseTexture, - TextureFactory.of(OVERLAY_PIPE_OUT), TextureFactory.of(FLUID_OUT_SIGN) }; - if (mMode == getModeOrdinal(ENERGY_IN)) - return new ITexture[] { baseTexture, TextureFactory.of(OVERLAY_ENERGY_IN_MULTI) }; - if (mMode == getModeOrdinal(ENERGY_OUT)) - return new ITexture[] { baseTexture, TextureFactory.of(OVERLAY_ENERGY_OUT_MULTI) }; + public ITexture getTexture(ForgeDirection side) { + ITexture texture = super.getTexture(side); + if (mMode != 0 && side == facing) { + if (mMode == getModeOrdinal(ITEM_IN)) { + return TextureFactory.of( + texture, + TextureFactory.of(OVERLAY_PIPE_IN), + TextureFactory.of(ITEM_IN_SIGN), + getCoverTexture((byte) side.ordinal())); + } + if (mMode == getModeOrdinal(ITEM_OUT)) { + return TextureFactory.of( + texture, + TextureFactory.of(OVERLAY_PIPE_OUT), + TextureFactory.of(ITEM_OUT_SIGN), + getCoverTexture((byte) side.ordinal())); + } + if (mMode == getModeOrdinal(FLUID_IN)) { + return TextureFactory.of( + texture, + TextureFactory.of(OVERLAY_PIPE_IN), + TextureFactory.of(FLUID_IN_SIGN), + getCoverTexture((byte) side.ordinal())); + } + if (mMode == getModeOrdinal(FLUID_OUT)) { + return TextureFactory.of( + texture, + TextureFactory.of(OVERLAY_PIPE_OUT), + TextureFactory.of(FLUID_OUT_SIGN), + getCoverTexture((byte) side.ordinal())); + } + if (mMode == getModeOrdinal(ENERGY_IN)) { + return TextureFactory + .of(texture, TextureFactory.of(OVERLAY_ENERGY_IN_MULTI), getCoverTexture((byte) side.ordinal())); + } + if (mMode == getModeOrdinal(ENERGY_OUT)) { + return TextureFactory + .of(texture, TextureFactory.of(OVERLAY_ENERGY_OUT_MULTI), getCoverTexture((byte) side.ordinal())); + } } - return new ITexture[] { baseTexture }; + + return TextureFactory.of(texture, getCoverTexture((byte) side.ordinal())); } @Override @@ -398,8 +421,13 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity public boolean onMalletRightClick(EntityPlayer aPlayer, ItemStack tCurrentItem, byte wrenchSide, float aX, float aY, float aZ) { if (mAllowedModes == NOTHING) return true; - + if (mMode == NOTHING) { + facing = ForgeDirection.getOrientation(wrenchSide); + } mMode = getNextAllowedMode(BASIC_MODES); + if (aPlayer.isSneaking()) { + facing = ForgeDirection.getOrientation(wrenchSide); + } GT_Utility.sendChatToPlayer(aPlayer, "Mode set to `" + getModeName(mMode) + "' (" + mMode + ")"); sendClientData((EntityPlayerMP) aPlayer); return true; @@ -430,9 +458,9 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity public int fill(ForgeDirection aDirection, FluidStack aFluidStack, boolean aDoFill) { if (!modeSelected(FLUID_IN)) return 0; final byte aSide = (byte) aDirection.ordinal(); - if (aDirection != ForgeDirection.UNKNOWN - && (aSide != facing || !coverLetsFluidIn(aSide, aFluidStack == null ? null : aFluidStack.getFluid()))) - return 0; + if (aFluidStack == null || isWrongFluid(aFluidStack.getFluid())) return 0; + if (aDirection != ForgeDirection.UNKNOWN && (facing.compareTo(ForgeDirection.getOrientation(aSide)) != 0 + || !coverLetsFluidIn(aSide, aFluidStack.getFluid()))) return 0; final IMultiBlockController controller = getTarget(true); return controller == null ? 0 : controller.fill(this, aDirection, aFluidStack, aDoFill); } @@ -441,9 +469,9 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity public FluidStack drain(ForgeDirection aDirection, FluidStack aFluidStack, boolean aDoDrain) { if (!modeSelected(FLUID_OUT)) return null; final byte aSide = (byte) aDirection.ordinal(); - if (aDirection != ForgeDirection.UNKNOWN - && (aSide != facing || !coverLetsFluidOut(aSide, aFluidStack == null ? null : aFluidStack.getFluid()))) - return null; + if (aFluidStack == null || isWrongFluid(aFluidStack.getFluid())) return null; + if (aDirection != ForgeDirection.UNKNOWN && (facing.compareTo(ForgeDirection.getOrientation(aSide)) != 0 + || !coverLetsFluidOut(aSide, aFluidStack.getFluid()))) return null; final IMultiBlockController controller = getTarget(true); return controller == null ? null : controller.drain(this, aDirection, aFluidStack, aDoDrain); } @@ -454,18 +482,26 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity final byte aSide = (byte) aDirection.ordinal(); final IMultiBlockController controller = getTarget(true); if (controller == null) return null; - final FluidStack aFluidStack = controller.getDrainableFluid(aSide); - if (aDirection != ForgeDirection.UNKNOWN - && (aSide != facing || !coverLetsFluidOut(aSide, aFluidStack == null ? null : aFluidStack.getFluid()))) - return null; - return controller.drain(this, aDirection, aAmountToDrain, aDoDrain); + FluidStack aFluidStack = null; + if (getLockedFluid() != null) { + aFluidStack = controller.getDrainableFluid(aSide, getLockedFluid()); + } else { + aFluidStack = controller.getDrainableFluid(aSide); + } + if (aFluidStack == null || isWrongFluid(aFluidStack.getFluid())) return null; + if (aDirection != ForgeDirection.UNKNOWN && (facing.compareTo(ForgeDirection.getOrientation(aSide)) != 0 + || !coverLetsFluidOut(aSide, aFluidStack.getFluid()))) return null; + return controller.drain(this, aDirection, aFluidStack, aDoDrain); } @Override public boolean canFill(ForgeDirection aDirection, Fluid aFluid) { if (!modeSelected(FLUID_IN)) return false; final byte aSide = (byte) aDirection.ordinal(); - if (aDirection != ForgeDirection.UNKNOWN && (aSide != facing || !coverLetsFluidIn(aSide, aFluid))) return false; + if (aDirection != ForgeDirection.UNKNOWN + && (facing.compareTo(ForgeDirection.getOrientation(aSide)) != 0 || !coverLetsFluidIn(aSide, aFluid))) + return false; + if (isWrongFluid(aFluid)) return false; final IMultiBlockController controller = getTarget(true); return controller != null && controller.canFill(this, aDirection, aFluid); } @@ -474,8 +510,10 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity public boolean canDrain(ForgeDirection aDirection, Fluid aFluid) { if (!modeSelected(FLUID_OUT)) return false; final byte aSide = (byte) aDirection.ordinal(); - if (aDirection != ForgeDirection.UNKNOWN && (aSide != facing || !coverLetsFluidOut(aSide, aFluid))) + if (aDirection != ForgeDirection.UNKNOWN + && (facing.compareTo(ForgeDirection.getOrientation(aSide)) != 0 || !coverLetsFluidOut(aSide, aFluid))) return false; + if (isWrongFluid(aFluid)) return false; final IMultiBlockController controller = getTarget(true); return controller != null && controller.canDrain(this, aDirection, aFluid); } @@ -483,7 +521,8 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity @Override public FluidTankInfo[] getTankInfo(ForgeDirection aDirection) { final byte aSide = (byte) aDirection.ordinal(); - if (!modeSelected(FLUID_IN, FLUID_OUT) || (aSide != SIDE_UNKNOWN && aSide != facing)) + if (!modeSelected(FLUID_IN, FLUID_OUT) + || (aSide != SIDE_UNKNOWN && facing.compareTo(ForgeDirection.getOrientation(aSide)) != 0)) return GT_Values.emptyFluidTankInfo; final IMultiBlockController controller = getTarget(true); if (controller == null) return GT_Values.emptyFluidTankInfo; @@ -500,8 +539,19 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity // #region Energy - Depending on the part type - proxy to the multiblock controller, if we have one @Override - public PowerLogic getPowerLogic(byte side) { + public PowerLogic getPowerLogic(ForgeDirection side) { + if (facing == side) { + return null; + } + + if (!modeSelected(ENERGY_IN, ENERGY_OUT)) { + return null; + } + final IMultiBlockController controller = getTarget(true); + if (controller == null) { + return null; + } return controller.getPowerLogic(this, side); } @@ -548,7 +598,8 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity @Override public int[] getAccessibleSlotsFromSide(int aSide) { - if (!modeSelected(ITEM_IN, ITEM_OUT) || (facing != SIDE_UNKNOWN && facing != aSide)) + if (!modeSelected(ITEM_IN, ITEM_OUT) + || (facing != ForgeDirection.UNKNOWN && facing.compareTo(ForgeDirection.getOrientation(aSide)) != 0)) return GT_Values.emptyIntArray; final IMultiBlockController controller = getTarget(true); return controller != null ? controller.getAccessibleSlotsFromSide(this, (byte) aSide) : GT_Values.emptyIntArray; @@ -556,8 +607,9 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity @Override public boolean canInsertItem(int aSlot, ItemStack aStack, int aSide) { - if (!modeSelected(ITEM_IN, ITEM_OUT) - || (facing != SIDE_UNKNOWN && (facing != aSide || !coverLetsItemsIn((byte) aSide, aSlot)))) return false; + if (!modeSelected(ITEM_IN, ITEM_OUT) || (facing != ForgeDirection.UNKNOWN + && (facing.compareTo(ForgeDirection.getOrientation(aSide)) != 0 || !coverLetsItemsIn((byte) aSide, aSlot)))) + return false; final IMultiBlockController controller = getTarget(true); return (controller != null && controller.canInsertItem(this, aSlot, aStack, (byte) aSide)); } @@ -565,7 +617,9 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity @Override public boolean canExtractItem(int aSlot, ItemStack aStack, int aSide) { if (!modeSelected(ITEM_IN, ITEM_OUT) - || (facing != SIDE_UNKNOWN && (facing != aSide || !coverLetsItemsOut((byte) aSide, aSlot)))) return false; + || (facing != ForgeDirection.UNKNOWN && (facing.compareTo(ForgeDirection.getOrientation(aSide)) != 0 + || !coverLetsItemsOut((byte) aSide, aSlot)))) + return false; final IMultiBlockController controller = getTarget(true); return (controller != null && controller.canExtractItem(this, aSlot, aStack, (byte) aSide)); } @@ -642,10 +696,10 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity @Override public boolean hasGui(byte aSide) { - // UIs only for specific mode(s) - if (modeSelected(ITEM_IN, ITEM_OUT, FLUID_IN, FLUID_OUT)) return true; - - return false; + if (modeSelected(ENERGY_IN, ENERGY_OUT) && facing == ForgeDirection.getOrientation(aSide)) { + return false; + } + return getTarget(true) != null; } protected void addItemInventory(Builder builder, UIBuildContext buildContext) { @@ -670,7 +724,7 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity dropDown.addDropDownItemsSimple( controller.getInventoryNames(this), (buttonWidget, index, label, setSelected) -> buttonWidget.setOnClick((clickData, widget) -> { - if (getNameOfInventoryFromIndex(controller, index).equals("all")) { + if (getNameOfInventoryFromIndex(controller, index).equals(Controller.ALL_INVENTORIES_NAME)) { mLockedInventory = GT_Values.E; mLockedInventoryIndex = 0; } else { @@ -696,11 +750,52 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity return invNames.get(index); } + protected String getNameOfTankArrayFromIndex(final IMultiBlockController controller, int index) { + final List<String> tankNames = controller.getTankArrayIDs(this); + if (index > tankNames.size()) { + return tankNames.get(0); + } + return tankNames.get(index); + } + + protected boolean isWrongFluid(Fluid fluid) { + if (fluid == null) { + return true; + } + Fluid lockedFluid = getLockedFluid(); + if (lockedFluid != null) { + return !fluid.equals(lockedFluid); + } + return false; + } + + protected Fluid getLockedFluid() { + if (configurationTank.get() != null && configurationTank.get() + .getFluid() != null) { + return configurationTank.get() + .getFluid(); + } + return null; + } + protected void addFluidInventory(Builder builder, UIBuildContext buildContext) { final IMultiBlockController controller = getTarget(false); if (controller == null) { return; } + builder.widget( + new DrawableWidget().setDrawable(GT_UITextures.PICTURE_SCREEN_BLACK) + .setPos(7, 4) + .setSize(85, 95)); + if (modeSelected(FLUID_OUT)) { + builder.widget( + new DrawableWidget().setDrawable(GT_UITextures.PICTURE_SCREEN_BLACK) + .setPos(getGUIWidth() - 77, 4) + .setSize(70, 40)) + .widget( + new TextWidget("Locked Fluid").setDefaultColor(COLOR_TEXT_WHITE.get()) + .setPos(getGUIWidth() - 72, 8)); + } final IFluidTank[] tanks = controller.getFluidTanksForGUI(this); final Scrollable scrollable = new Scrollable().setVerticalScroll(); for (int rows = 0; rows * 4 < tanks.length; rows++) { @@ -717,16 +812,47 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity } builder.widget( scrollable.setSize(18 * 4 + 4, 18 * 4) - .setPos(52, 7)); + .setPos(12, 21)); + DropDownWidget dropDown = new DropDownWidget(); + dropDown.addDropDownItemsSimple( + controller.getTankArrayNames(this), + (buttonWidget, index, label, setSelected) -> buttonWidget.setOnClick((clickData, widget) -> { + if (getNameOfTankArrayFromIndex(controller, index).equals(Controller.ALL_INVENTORIES_NAME)) { + mLockedInventory = GT_Values.E; + mLockedInventoryIndex = 0; + } else { + mLockedInventory = getNameOfTankArrayFromIndex(controller, index); + mLockedInventoryIndex = index; + } + setSelected.run(); + }), + true); + builder.widget( + dropDown.setSelected(mLockedInventoryIndex) + .setExpandedMaxHeight(60) + .setDirection(DropDownWidget.Direction.DOWN) + .setPos(13, 8) + .setSize(70, 11)); } @Override public void addUIWidgets(Builder builder, UIBuildContext buildContext) { if (modeSelected(ITEM_IN, ITEM_OUT)) { addItemInventory(builder, buildContext); + return; } if (modeSelected(FLUID_IN, FLUID_OUT)) { addFluidInventory(builder, buildContext); + if (modeSelected(FLUID_OUT)) { + builder.widget( + SlotGroup.ofFluidTanks(Collections.singletonList(configurationTank), 1) + .startFromSlot(0) + .endAtSlot(0) + .phantom(true) + .build() + .setPos(getGUIWidth() - 72, 20)); + } + return; } } @@ -736,15 +862,19 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity issueClientUpdate(); } System.out.println("MultiBlockPart::createWindow"); + if (modeSelected(NOTHING, ENERGY_IN, ENERGY_OUT) || mMode == NOTHING) { + IMultiBlockController controller = getTarget(false); + if (controller == null) { + return super.createWindow(buildContext); + } + return controller.createWindowGUI(buildContext); + } return super.createWindow(buildContext); } @Override protected int getGUIHeight() { - if (modeSelected(ITEM_IN, ITEM_OUT)) { - return super.getGUIHeight() + 11; - } - return super.getGUIHeight(); + return super.getGUIHeight() + 20; } @Override @@ -754,6 +884,11 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity new DrawableWidget().setDrawable(getGUITextureSet().getGregTechLogo()) .setSize(17, 17) .setPos(152, 74)); + } else if (modeSelected(FLUID_IN, FLUID_OUT)) { + builder.widget( + new DrawableWidget().setDrawable(getGUITextureSet().getGregTechLogo()) + .setSize(17, 17) + .setPos(152, 82)); } else { super.addGregTechLogo(builder); } diff --git a/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockPowerController.java b/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockPowerController.java deleted file mode 100644 index 7f202ec5a4..0000000000 --- a/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockPowerController.java +++ /dev/null @@ -1,44 +0,0 @@ -package gregtech.api.multitileentity.multiblock.base; - -import net.minecraft.nbt.NBTTagCompound; - -import gregtech.api.enums.GT_Values; -import gregtech.api.logic.PowerLogic; -import gregtech.api.logic.interfaces.PowerLogicHost; - -public abstract class MultiBlockPowerController<T extends MultiBlockPowerController<T>> extends MultiBlockController<T> - implements PowerLogicHost { - - public MultiBlockPowerController() { - super(); - power = new PowerLogic().setType(PowerLogic.RECEIVER); - } - - protected PowerLogic power; - - @Override - public void writeMultiTileNBT(NBTTagCompound nbt) { - super.writeMultiTileNBT(nbt); - power.writeToNBT(nbt); - } - - @Override - public void readMultiTileNBT(NBTTagCompound nbt) { - super.readMultiTileNBT(nbt); - power.loadFromNBT(nbt); - } - - @Override - public PowerLogic getPowerLogic(byte side) { - return power; - } - - @Override - public boolean checkMachine() { - boolean result = super.checkMachine(); - power.setEnergyCapacity(GT_Values.V[tier] * 2 * 60 * 20); - power.setAmperage(2); - power.setMaxVoltage(GT_Values.V[tier]); - return result; - } -} diff --git a/src/main/java/gregtech/api/multitileentity/multiblock/base/PowerController.java b/src/main/java/gregtech/api/multitileentity/multiblock/base/PowerController.java new file mode 100644 index 0000000000..6d58249740 --- /dev/null +++ b/src/main/java/gregtech/api/multitileentity/multiblock/base/PowerController.java @@ -0,0 +1,89 @@ +package gregtech.api.multitileentity.multiblock.base; + +import java.util.List; + +import mcp.mobius.waila.api.IWailaConfigHandler; +import mcp.mobius.waila.api.IWailaDataAccessor; + +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.StatCollector; +import net.minecraft.world.World; +import net.minecraftforge.common.util.ForgeDirection; + +import gregtech.api.enums.GT_Values; +import gregtech.api.logic.PowerLogic; +import gregtech.api.logic.interfaces.PowerLogicHost; +import gregtech.api.util.GT_Utility; + +public abstract class PowerController<T extends PowerController<T>> extends Controller<T> implements PowerLogicHost { + + public PowerController() { + super(); + power = new PowerLogic().setType(PowerLogic.RECEIVER); + } + + protected PowerLogic power; + + @Override + public void writeMultiTileNBT(NBTTagCompound nbt) { + super.writeMultiTileNBT(nbt); + power.writeToNBT(nbt); + } + + @Override + public void readMultiTileNBT(NBTTagCompound nbt) { + super.readMultiTileNBT(nbt); + power.loadFromNBT(nbt); + } + + @Override + public PowerLogic getPowerLogic(ForgeDirection side) { + return power; + } + + @Override + public boolean checkMachine() { + boolean result = super.checkMachine(); + power.setEnergyCapacity(GT_Values.V[tier] * 2 * 60 * 20); + power.setAmperage(2); + power.setMaxVoltage(GT_Values.V[tier]); + return result; + } + + @Override + public void getWailaNBTData(EntityPlayerMP player, TileEntity tile, NBTTagCompound tag, World world, int x, int y, + int z) { + super.getWailaNBTData(player, tile, tag, world, x, y, z); + tag.setBoolean("isActive", isActive()); + if (isActive()) { + tag.setLong("energyUsage", eut); + } + } + + @Override + public void getWailaBody(ItemStack itemStack, List<String> currentTip, IWailaDataAccessor accessor, + IWailaConfigHandler config) { + super.getWailaBody(itemStack, currentTip, accessor, config); + final NBTTagCompound tag = accessor.getNBTData(); + boolean isActive = tag.getBoolean("isActive"); + if (isActive) { + long actualEnergyUsage = tag.getLong("energyUsage"); + if (actualEnergyUsage > 0) { + currentTip.add( + StatCollector.translateToLocalFormatted( + "GT5U.waila.energy.use", + GT_Utility.formatNumbers(actualEnergyUsage), + GT_Utility.getColoredTierNameFromVoltage(actualEnergyUsage))); + } else if (actualEnergyUsage < 0) { + currentTip.add( + StatCollector.translateToLocalFormatted( + "GT5U.waila.energy.produce", + GT_Utility.formatNumbers(-actualEnergyUsage), + GT_Utility.getColoredTierNameFromVoltage(-actualEnergyUsage))); + } + } + } +} diff --git a/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlock_Stackable.java b/src/main/java/gregtech/api/multitileentity/multiblock/base/StackableController.java index 11d931433f..90a2742290 100644 --- a/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlock_Stackable.java +++ b/src/main/java/gregtech/api/multitileentity/multiblock/base/StackableController.java @@ -4,7 +4,7 @@ import net.minecraft.item.ItemStack; import com.gtnewhorizon.structurelib.util.Vec3Impl; -public abstract class MultiBlock_Stackable<T extends MultiBlock_Stackable<T>> extends MultiBlockPowerController<T> { +public abstract class StackableController<T extends StackableController<T>> extends PowerController<T> { protected static String STACKABLE_TOP = "STACKABLE_TOP"; protected static String STACKABLE_MIDDLE = "STACKABLE_MIDDLE"; diff --git a/src/main/java/gregtech/api/multitileentity/multiblock/casing/FunctionalCasing.java b/src/main/java/gregtech/api/multitileentity/multiblock/casing/FunctionalCasing.java index 718e159d7a..bc3c857fd6 100644 --- a/src/main/java/gregtech/api/multitileentity/multiblock/casing/FunctionalCasing.java +++ b/src/main/java/gregtech/api/multitileentity/multiblock/casing/FunctionalCasing.java @@ -14,6 +14,8 @@ public abstract class FunctionalCasing extends MultiBlockPart { return tier; } + public abstract float getPartModifier(); + @Override public void readMultiTileNBT(NBTTagCompound nbt) { super.readMultiTileNBT(nbt); diff --git a/src/main/java/gregtech/api/net/GT_Packet_MultiTileEntity.java b/src/main/java/gregtech/api/net/GT_Packet_MultiTileEntity.java index 6c67dbe6b7..b9e334d67b 100644 --- a/src/main/java/gregtech/api/net/GT_Packet_MultiTileEntity.java +++ b/src/main/java/gregtech/api/net/GT_Packet_MultiTileEntity.java @@ -15,7 +15,7 @@ import gregtech.api.multitileentity.MultiTileEntityBlock; import gregtech.api.multitileentity.interfaces.IMultiBlockPart; import gregtech.api.multitileentity.interfaces.IMultiTileEntity; import gregtech.api.multitileentity.interfaces.IMultiTileMachine; -import gregtech.common.tileentities.casings.upgrade.InventoryUpgrade; +import gregtech.common.tileentities.casings.upgrade.Inventory; import io.netty.buffer.ByteBuf; public class GT_Packet_MultiTileEntity extends GT_Packet_New { @@ -271,7 +271,7 @@ public class GT_Packet_MultiTileEntity extends GT_Packet_New { mtePart.setLockedInventoryIndex(mLockedInventoryIndex); } - if ((features & INVENTORY_NAME) == INVENTORY_NAME && mte instanceof InventoryUpgrade invUpg) { + if ((features & INVENTORY_NAME) == INVENTORY_NAME && mte instanceof Inventory invUpg) { invUpg.setInventoryName(mInventoryName); } diff --git a/src/main/java/gregtech/api/util/GT_ParallelHelper.java b/src/main/java/gregtech/api/util/GT_ParallelHelper.java index 4ae33cd48d..4e281e976f 100644 --- a/src/main/java/gregtech/api/util/GT_ParallelHelper.java +++ b/src/main/java/gregtech/api/util/GT_ParallelHelper.java @@ -15,10 +15,11 @@ import org.apache.commons.lang3.tuple.MutableTriple; import com.gtnewhorizon.gtnhlib.util.map.ItemStackMap; +import gregtech.api.fluid.FluidTankGT; import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch; import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Output; import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_MultiBlockBase; -import gregtech.api.multitileentity.multiblock.base.MultiBlockController; +import gregtech.api.multitileentity.multiblock.base.Controller; import gregtech.api.objects.XSTR; import gregtech.common.tileentities.machines.GT_MetaTileEntity_Hatch_OutputBus_ME; import gregtech.common.tileentities.machines.GT_MetaTileEntity_Hatch_Output_ME; @@ -32,7 +33,7 @@ public class GT_ParallelHelper { /** * @mMachineMulti a MultiTileEntity Controller */ - private MultiBlockController<?> mMachineMulti; + private Controller<?> mMachineMulti; /** * @mRecipe Recipe used when trying to calculate parallels */ @@ -87,7 +88,7 @@ public class GT_ParallelHelper { /** * Enables void protection on a multitile multiblock. Experimental! Still needs to be worked on */ - public GT_ParallelHelper enableVoidProtection(MultiBlockController<?> aMachineMulti) { + public GT_ParallelHelper enableVoidProtection(Controller<?> aMachineMulti) { mVoidProtection = true; mMachineMulti = aMachineMulti; return this; @@ -265,25 +266,30 @@ public class GT_ParallelHelper { } // Let's look at how many parallels we can get with void protection if (mVoidProtection) { - for (GT_MetaTileEntity_Hatch tHatch : mMachineMeta.mOutputBusses) { - if (tHatch instanceof GT_MetaTileEntity_Hatch_OutputBus_ME) { - tMEOutputBus = true; - break; + if (mMachineMeta != null) { + for (GT_MetaTileEntity_Hatch tHatch : mMachineMeta.mOutputBusses) { + if (tHatch instanceof GT_MetaTileEntity_Hatch_OutputBus_ME) { + tMEOutputBus = true; + break; + } } - } - for (GT_MetaTileEntity_Hatch tHatch : mMachineMeta.mOutputHatches) { - if (tHatch instanceof GT_MetaTileEntity_Hatch_Output_ME) { - tMEOutputHatch = true; - break; + for (GT_MetaTileEntity_Hatch tHatch : mMachineMeta.mOutputHatches) { + if (tHatch instanceof GT_MetaTileEntity_Hatch_Output_ME) { + tMEOutputHatch = true; + break; + } + } + if (!tMEOutputBus) { + mMaxParallel = Math.min(calculateMaxParallelsForBusses(), mMaxParallel); } - } - if (!tMEOutputBus) { - mMaxParallel = Math.min(calculateMaxParallelsForBusses(), mMaxParallel); - } - if (!tMEOutputHatch) { - mMaxParallel = Math.min(calculateMaxParallelsForHatches(), mMaxParallel); + if (!tMEOutputHatch) { + mMaxParallel = Math.min(calculateMaxParallelsForHatches(), mMaxParallel); + } + } else if (mMachineMulti != null) { + mMaxParallel = Math.min(calculateMaxItemParallelsForMuTEs(), mMaxParallel); + mMaxParallel = Math.min(calculateMaxFluidParallelsForMuTEs(), mMaxParallel); } } @@ -346,6 +352,81 @@ public class GT_ParallelHelper { /** * Calculates the max parallel for fluids if void protection is turned on */ + private int calculateMaxFluidParallelsForMuTEs() { + if (mMachineMulti != null && mMachineMulti.getOutputTanks() != null + && mMachineMulti.getOutputTanks().length >= mRecipe.mFluidOutputs.length) { + // A map to hold the items we will be 'inputting' into the output hatches. These fluidstacks are actually + // the + // recipe outputs. + Map<FluidStack, Integer> tFluidOutputMap = new HashMap<>(); + + // Map that keeps track of the number of parallel crafts we can accommodate for each fluid output. + // In the pair, we keep track of number of full crafts plus mb of fluid in a partial craft, to avoid + // issues with floating point math not being completely accurate when summing. + Map<FluidStack, MutablePair<Integer, Integer>> tParallels = new HashMap<>(); + + // Iterate over the outputs, calculating require stack spacing they will require. + for (FluidStack aY : mRecipe.mFluidOutputs) { + if (aY == null) { + continue; + } + tFluidOutputMap.merge(aY, aY.amount, Integer::sum); + tParallels.put(aY, new MutablePair<>(0, 0)); + } + + if (tFluidOutputMap.isEmpty()) { + // nothing to output, bail early + return mMaxParallel; + } + + for (FluidTankGT tHatch : mMachineMulti.getOutputTanks()) { + int tSpaceLeft = tHatch.getCapacity() - tHatch.getFluidAmount(); + + // check if hatch filled + if (tSpaceLeft <= 0) continue; + + // check if hatch is empty and unrestricted + if (tHatch.getFluidAmount() == 0) continue; + + for (Entry<FluidStack, MutablePair<Integer, Integer>> entry : tParallels.entrySet()) { + FluidStack tFluidOutput = entry.getKey(); + // this fluid is not prevented by restrictions on output hatch + if (tHatch.getFluidAmount() == 0 || GT_Utility.areFluidsEqual(tHatch.getFluid(), tFluidOutput)) { + MutablePair<Integer, Integer> tParallel = entry.getValue(); + Integer tCraftSize = tFluidOutputMap.get(tFluidOutput); + tParallel.left += (tParallel.right + tSpaceLeft) / tCraftSize; + tParallel.right = (tParallel.right + tSpaceLeft) % tCraftSize; + } + } + } + // now that all partial/restricted hatches have been counted, create a priority queue for our outputs + // the lowest priority fluid is the number of complete parallel crafts we can support + PriorityQueue<MutableTriple<Integer, Integer, FluidStack>> aParallelQueue = new PriorityQueue<>( + Comparator.comparing(MutableTriple::getLeft)); + for (Entry<FluidStack, MutablePair<Integer, Integer>> entry : tParallels.entrySet()) { + aParallelQueue.add(new MutableTriple<>(entry.getValue().left, entry.getValue().right, entry.getKey())); + } + // add extra parallels for open slots as well + for (FluidTankGT tHatch : mMachineMulti.getOutputTanks()) { + // partially filled or restricted hatch. done in last pass + if (tHatch.getFluidAmount() > 0) continue; + + MutableTriple<Integer, Integer, FluidStack> tParallel = aParallelQueue.poll(); + assert tParallel != null; // will always be true, specifying assert here to avoid IDE/compiler warnings + Integer tCraftSize = tFluidOutputMap.get(tParallel.right); + int tSpaceLeft = tHatch.getCapacity(); + tParallel.left += (tParallel.middle + tSpaceLeft) / tCraftSize; + tParallel.middle = (tParallel.middle + tSpaceLeft) % tCraftSize; + aParallelQueue.add(tParallel); + } + return aParallelQueue.element().left; + } + return 0; + } + + /** + * Calculates the max parallel for fluids if void protection is turned on + */ private int calculateMaxParallelsForHatches() { // For now we are gonna ignore MuTEs existence as there are no recipes for them if (mMachineMeta != null && mMachineMeta.mOutputHatches.size() >= mRecipe.mFluidOutputs.length) { @@ -437,6 +518,82 @@ public class GT_ParallelHelper { /** * Calculates the max parallels one can do with items if void protection is on */ + private int calculateMaxItemParallelsForMuTEs() { + + // A map to hold the items we will be 'inputting' into the output buses. These itemstacks are actually the + // recipe outputs. + Map<ItemStack, Integer> tItemOutputMap = new ItemStackMap<>(); + + // Map that keeps track of the number of parallel crafts we can accommodate for each item output. + // In the pair, we keep track of number of full crafts plus number of items in a partial craft, to avoid + // issues with floating point math not being completely accurate when summing. + Map<ItemStack, MutablePair<Integer, Integer>> tParallels = new ItemStackMap<>(); + int tSlotsFree = 0; + for (ItemStack tItem : mRecipe.mOutputs) { + tItemOutputMap.merge(tItem, tItem.stackSize, Integer::sum); + tParallels.put(tItem, new MutablePair<>(0, 0)); + } + + if (tItemOutputMap.isEmpty()) { + // nothing to output, bail early + return mMaxParallel; + } + + if (mRecipe.mOutputs.length > 0 && mMachineMulti != null + && mMachineMulti.getOutputInventory() != null + && mMachineMulti.getOutputInventory() + .getSlots() > 0) { + for (int i = 0; i < mMachineMulti.getOutputInventory() + .getSlots(); i++) { + ItemStack tBusStack = mMachineMulti.getOutputInventory() + .getStackInSlot(i); + if (tBusStack == null) { + tSlotsFree++; + } else { + // get the real stack size + // we ignore the bus inventory stack limit here as no one set it to anything other than 64 + int tMaxBusStackSize = tBusStack.getMaxStackSize(); + if (tBusStack.stackSize >= tMaxBusStackSize) + // this bus stack is full. no checking + continue; + int tSpaceLeft = tMaxBusStackSize - tBusStack.stackSize; + Integer tCraftSize = tItemOutputMap.get(tBusStack); + if (tCraftSize == null) { + // we don't have a matching stack to output, ignore this bus stack + continue; + } + MutablePair<Integer, Integer> tParallel = tParallels.get(tBusStack); + tParallel.left += (tParallel.right + tSpaceLeft) / tCraftSize; + tParallel.right = (tParallel.right + tSpaceLeft) % tCraftSize; + } + } + // now that all partial stacks have been counted, create a priority queue for our outputs + // the lowest priority item is the number of complete parallel crafts we can support + PriorityQueue<MutableTriple<Integer, Integer, ItemStack>> aParallelQueue = new PriorityQueue<>( + Comparator.comparing(MutableTriple::getLeft)); + for (Entry<ItemStack, MutablePair<Integer, Integer>> entry : tParallels.entrySet()) { + aParallelQueue.add(new MutableTriple<>(entry.getValue().left, entry.getValue().right, entry.getKey())); + } + + while (tSlotsFree > 0) { + MutableTriple<Integer, Integer, ItemStack> tParallel = aParallelQueue.poll(); + assert tParallel != null; // will always be true, specifying assert here to avoid IDE/compiler warnings + Integer tCraftSize = tItemOutputMap.get(tParallel.right); + int tStackSize = tParallel.right.getMaxStackSize(); + tParallel.left += (tParallel.middle + tStackSize) / tCraftSize; + tParallel.middle = (tParallel.middle + tStackSize) % tCraftSize; + aParallelQueue.add(tParallel); + --tSlotsFree; + } + + return aParallelQueue.element().left; + } + return 0; + } + + /** + * Calculates the max parallels one can do with items if void protection is on + */ private int calculateMaxParallelsForBusses() { // Same thing we are gonna ignore MuTEs existence for now. should be in theory the same later diff --git a/src/main/java/gregtech/api/util/GT_Waila.java b/src/main/java/gregtech/api/util/GT_Waila.java index 9ea42a1028..1c5b5301c8 100644 --- a/src/main/java/gregtech/api/util/GT_Waila.java +++ b/src/main/java/gregtech/api/util/GT_Waila.java @@ -3,6 +3,10 @@ package gregtech.api.util; public abstract class GT_Waila { public static String getMachineProgressString(boolean isActive, int maxProgress, int progress) { + return getMachineProgressString(isActive, (long) maxProgress, (long) progress); + } + + public static String getMachineProgressString(boolean isActive, long maxProgress, long progress) { final String result; if (isActive) { |