From fdde96ab6fef30064b67e28390008ee4ba455655 Mon Sep 17 00:00:00 2001 From: Maxim Date: Sat, 22 Apr 2023 17:38:49 +0200 Subject: MuTE overhaul and ACR (#1883) * complex controller start * Added methods to get input fluids and items * Added logic to complex parallel mute * Added ACR and fixed many, many, many, many bugs * Added void protection setting to checkRecipe * do not init nbt, if mteID and mteRegistry are the same * Improved GUI design * Force structure check when pressing power switch * ACR Textures * Added T1 structure * Added perfect OC * Added WAILA * fix mutes resetting their nbt * Fix ACR GUI * fix npe * Added void protection for MuTEs * Fixed ACR starting recipe while another one is ongoing * nbt saving * maybe fix structure breaking * Fix complex machine disabling on startup * correctly update input tanks * move casings over * Changed logic of casings to change mode and facing in one go by sneaking * Fixed the casing target not resetting * Added side only annotations * don't leave it empty * Added power logic and tiered blocks to ACR * Change facing to wrench side if casing mode is currently none * lasers anyone? * Added ACR item chaining * Remove unncessary item lists * Use HashSet for process whitelists * Optimize list capacities * Fix potential recipe voiding bug * Rename methods for consistancy * Fix NPE * Duct tape fix structure check * allow MuTEs to connect to cables * Added separate tank inventories for input separation (#1887) * Fixed unregistering tank function * Fixed input busses not being automatable * Added fluid chaining * Fixed saving of input tanks * Forbid inventory registering with empty name * Display all input tanks in controller GUI * Fixed fluid hatch GUI height * Reset casing lists when checking the structure * Make inventory GUI size consistant * Make use of the tooltip cache * rename thing clean up * Forgot to put tooltip into map * Added tooltip to ACR * Reset whitelists when one whitelist window was opened * Refined scanner string * Fixed progress times * Fixed MuTE not consuming fluids * Properly register controller inventories * switch to ForgeDirection * switch to new Renderer * Added missing contains check on registerInventory * Fixed output tanks not registering * Fixed upgrade tank loading * fix machines not having active/inactive textures * fix overlays not loading correctly * Don't register controller directly * Remove magic strings all * fix active not setting to inactive * allow glow * item renderer * fix glow * MuTE improved hatch GUI and fluid output locking (#1889) * Allow output hatches to be fluid locked * Reworked hatch GUI * Check target before trying to open GUI * Make ACR GUI easier to look at * fix covers not rendering on mutes * fix covers not displaying above the item/fluid in/out * new folder texture structure * Reduce network traffic caused by covers * Fixed WAILA fluid locking display * Don't save everything to the itemstack NBT * Added possibility to save NBT of MuTE to its itemstack * fix textures, but make sacrifices * mah textures * Removed the need for all textures to be present * Added glow texture for active coke oven * Removed unncesssary upgrade casing textures * shorten nbt tags --------- Co-authored-by: BlueWeabo <76872108+BlueWeabo@users.noreply.github.com> Co-authored-by: Martin Robertz Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- src/main/java/gregtech/api/enums/GT_Values.java | 34 +- src/main/java/gregtech/api/fluid/FluidTankGT.java | 19 + .../interfaces/tileentity/IEnergyConnected.java | 2 +- .../api/logic/ComplexParallelProcessingLogic.java | 183 ++ .../java/gregtech/api/logic/ModelRenderLogic.java | 5 + src/main/java/gregtech/api/logic/PowerLogic.java | 15 + .../api/logic/interfaces/ModelRenderLogicHost.java | 10 + .../api/logic/interfaces/PowerLogicHost.java | 4 +- .../api/metatileentity/BaseTileEntity.java | 3 + .../implementations/GT_MetaPipeEntity_Cable.java | 9 +- .../api/multitileentity/MultiTileEntityBlock.java | 47 +- .../MultiTileEntityBlockInternal.java | 49 +- .../MultiTileEntityClassContainer.java | 28 +- .../api/multitileentity/base/MultiTileEntity.java | 273 ++- .../base/TickableMultiTileEntity.java | 3 +- .../multitileentity/enums/GT_MultiTileCasing.java | 7 +- .../enums/GT_MultiTileComponentCasing.java | 130 ++ .../multitileentity/enums/GT_MultiTileMachine.java | 6 +- .../interfaces/IMultiBlockController.java | 10 +- .../interfaces/IMultiBlockFluidHandler.java | 6 + .../interfaces/IMultiTileEntity.java | 2 +- .../machine/MultiTileBasicMachine.java | 300 ++- .../multiblock/base/ComplexParallelController.java | 244 +++ .../multiblock/base/Controller.java | 2187 ++++++++++++++++++++ .../multiblock/base/MultiBlockController.java | 1709 --------------- .../multiblock/base/MultiBlockPart.java | 301 ++- .../multiblock/base/MultiBlockPowerController.java | 44 - .../multiblock/base/MultiBlock_Stackable.java | 111 - .../multiblock/base/PowerController.java | 89 + .../multiblock/base/StackableController.java | 111 + .../multiblock/casing/FunctionalCasing.java | 2 + .../api/net/GT_Packet_MultiTileEntity.java | 4 +- .../java/gregtech/api/util/GT_ParallelHelper.java | 193 +- src/main/java/gregtech/api/util/GT_Waila.java | 4 + src/main/java/gregtech/common/GT_Client.java | 6 +- .../common/render/GT_MultiTile_Renderer.java | 181 ++ .../gregtech/common/render/GT_Renderer_Block.java | 300 +-- .../common/render/MultiTileBasicRender.java | 10 + .../tileentities/casings/functional/Conveyor.java | 16 + .../tileentities/casings/functional/Emitter.java | 16 + .../casings/functional/FieldGenerator.java | 16 + .../tileentities/casings/functional/Motor.java | 16 + .../casings/functional/MotorCasing.java | 11 - .../tileentities/casings/functional/Piston.java | 16 + .../tileentities/casings/functional/Pump.java | 16 + .../tileentities/casings/functional/RobotArm.java | 16 + .../tileentities/casings/functional/Sensor.java | 16 + .../tileentities/casings/upgrade/Inventory.java | 108 + .../casings/upgrade/InventoryUpgrade.java | 108 - .../machines/multiblock/AdvChemicalReactor.java | 432 ++++ .../tileentities/machines/multiblock/CokeOven.java | 172 ++ .../machines/multiblock/Macerator.java | 175 ++ .../machines/multiblock/MultiBlock_CokeOven.java | 173 -- .../machines/multiblock/MultiBlock_Macerator.java | 216 -- .../preload/GT_Loader_MultiTileEntities.java | 894 +++++++- .../multitileentity/advChemicalReactor/active.png | Bin 0 -> 255 bytes .../advChemicalReactor/active_glow.png | Bin 0 -> 255 bytes .../multitileentity/advChemicalReactor/base.png | Bin 0 -> 333 bytes .../advChemicalReactor/inactive.png | Bin 0 -> 254 bytes .../advChemicalReactor/inactive_glow.png | Bin 0 -> 256 bytes .../multitileentity/base/cokeOven/bottom.png | Bin 453 -> 0 bytes .../blocks/multitileentity/base/cokeOven/side.png | Bin 453 -> 0 bytes .../blocks/multitileentity/base/cokeOven/top.png | Bin 453 -> 0 bytes .../multitileentity/base/metalwall/bottom.png | Bin 443 -> 0 bytes .../blocks/multitileentity/base/metalwall/side.png | Bin 443 -> 0 bytes .../blocks/multitileentity/base/metalwall/top.png | Bin 443 -> 0 bytes .../blocks/multitileentity/cokeOven/active.png | Bin 0 -> 379 bytes .../multitileentity/cokeOven/active_glow.png | Bin 0 -> 306 bytes .../blocks/multitileentity/cokeOven/base.png | Bin 0 -> 453 bytes .../blocks/multitileentity/cokeOven/inactive.png | Bin 0 -> 209 bytes .../blocks/multitileentity/conveyor/base.png | Bin 0 -> 443 bytes .../blocks/multitileentity/emitter/base.png | Bin 0 -> 443 bytes .../blocks/multitileentity/fieldGenerator/base.png | Bin 0 -> 443 bytes .../blocks/multitileentity/macerator/active.png | Bin 0 -> 255 bytes .../multitileentity/macerator/active_glow.png | Bin 0 -> 255 bytes .../blocks/multitileentity/macerator/base.png | Bin 0 -> 443 bytes .../blocks/multitileentity/macerator/inactive.png | Bin 0 -> 254 bytes .../multitileentity/macerator/inactive_glow.png | Bin 0 -> 256 bytes .../multitileentity/machines/cokeOven/bottom.png | Bin 453 -> 0 bytes .../multitileentity/machines/cokeOven/front.png | Bin 453 -> 0 bytes .../multitileentity/machines/cokeOven/left.png | Bin 453 -> 0 bytes .../machines/cokeOven/overlay/active/front.png | Bin 379 -> 0 bytes .../machines/cokeOven/overlay/inactive/front.png | Bin 209 -> 0 bytes .../multitileentity/machines/cokeOven/right.png | Bin 453 -> 0 bytes .../multitileentity/machines/cokeOven/side.png | Bin 453 -> 0 bytes .../multitileentity/machines/cokeOven/top.png | Bin 453 -> 0 bytes .../multitileentity/machines/metalwall/bottom.png | Bin 443 -> 0 bytes .../multitileentity/machines/metalwall/side.png | Bin 443 -> 0 bytes .../multitileentity/machines/metalwall/top.png | Bin 443 -> 0 bytes .../textures/blocks/multitileentity/motor/base.png | Bin 0 -> 443 bytes .../multiblockparts/cokeOven/bottom.png | Bin 453 -> 0 bytes .../multiblockparts/cokeOven/side.png | Bin 453 -> 0 bytes .../multiblockparts/cokeOven/top.png | Bin 453 -> 0 bytes .../multiblockparts/metalwall/bottom.png | Bin 443 -> 0 bytes .../multiblockparts/metalwall/side.png | Bin 443 -> 0 bytes .../multiblockparts/metalwall/top.png | Bin 443 -> 0 bytes .../blocks/multitileentity/piston/base.png | Bin 0 -> 443 bytes .../textures/blocks/multitileentity/pump/base.png | Bin 0 -> 443 bytes .../blocks/multitileentity/robotArm/base.png | Bin 0 -> 443 bytes .../blocks/multitileentity/sensor/base.png | Bin 0 -> 443 bytes 100 files changed, 6007 insertions(+), 3051 deletions(-) create mode 100644 src/main/java/gregtech/api/logic/ComplexParallelProcessingLogic.java create mode 100644 src/main/java/gregtech/api/logic/ModelRenderLogic.java create mode 100644 src/main/java/gregtech/api/logic/interfaces/ModelRenderLogicHost.java create mode 100644 src/main/java/gregtech/api/multitileentity/enums/GT_MultiTileComponentCasing.java create mode 100644 src/main/java/gregtech/api/multitileentity/multiblock/base/ComplexParallelController.java create mode 100644 src/main/java/gregtech/api/multitileentity/multiblock/base/Controller.java delete mode 100644 src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockController.java delete mode 100644 src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockPowerController.java delete mode 100644 src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlock_Stackable.java create mode 100644 src/main/java/gregtech/api/multitileentity/multiblock/base/PowerController.java create mode 100644 src/main/java/gregtech/api/multitileentity/multiblock/base/StackableController.java create mode 100644 src/main/java/gregtech/common/render/GT_MultiTile_Renderer.java create mode 100644 src/main/java/gregtech/common/render/MultiTileBasicRender.java create mode 100644 src/main/java/gregtech/common/tileentities/casings/functional/Conveyor.java create mode 100644 src/main/java/gregtech/common/tileentities/casings/functional/Emitter.java create mode 100644 src/main/java/gregtech/common/tileentities/casings/functional/FieldGenerator.java create mode 100644 src/main/java/gregtech/common/tileentities/casings/functional/Motor.java delete mode 100644 src/main/java/gregtech/common/tileentities/casings/functional/MotorCasing.java create mode 100644 src/main/java/gregtech/common/tileentities/casings/functional/Piston.java create mode 100644 src/main/java/gregtech/common/tileentities/casings/functional/Pump.java create mode 100644 src/main/java/gregtech/common/tileentities/casings/functional/RobotArm.java create mode 100644 src/main/java/gregtech/common/tileentities/casings/functional/Sensor.java create mode 100644 src/main/java/gregtech/common/tileentities/casings/upgrade/Inventory.java delete mode 100644 src/main/java/gregtech/common/tileentities/casings/upgrade/InventoryUpgrade.java create mode 100644 src/main/java/gregtech/common/tileentities/machines/multiblock/AdvChemicalReactor.java create mode 100644 src/main/java/gregtech/common/tileentities/machines/multiblock/CokeOven.java create mode 100644 src/main/java/gregtech/common/tileentities/machines/multiblock/Macerator.java delete mode 100644 src/main/java/gregtech/common/tileentities/machines/multiblock/MultiBlock_CokeOven.java delete mode 100644 src/main/java/gregtech/common/tileentities/machines/multiblock/MultiBlock_Macerator.java create mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalReactor/active.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalReactor/active_glow.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalReactor/base.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalReactor/inactive.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalReactor/inactive_glow.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/base/cokeOven/bottom.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/base/cokeOven/side.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/base/cokeOven/top.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/base/metalwall/bottom.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/base/metalwall/side.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/base/metalwall/top.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/cokeOven/active.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/cokeOven/active_glow.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/cokeOven/base.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/cokeOven/inactive.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/conveyor/base.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/emitter/base.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/fieldGenerator/base.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/macerator/active.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/macerator/active_glow.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/macerator/base.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/macerator/inactive.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/macerator/inactive_glow.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/cokeOven/bottom.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/cokeOven/front.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/cokeOven/left.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/cokeOven/overlay/active/front.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/cokeOven/overlay/inactive/front.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/cokeOven/right.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/cokeOven/side.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/cokeOven/top.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/metalwall/bottom.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/metalwall/side.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/metalwall/top.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/motor/base.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/multiblockparts/cokeOven/bottom.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/multiblockparts/cokeOven/side.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/multiblockparts/cokeOven/top.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/multiblockparts/metalwall/bottom.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/multiblockparts/metalwall/side.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/multiblockparts/metalwall/top.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/piston/base.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/pump/base.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/robotArm/base.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/multitileentity/sensor/base.png (limited to 'src') 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 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 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 @@ -386,43 +384,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]); 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; @@ -321,69 +392,6 @@ public abstract class MultiTileEntity extends CoverableTileEntity implements IMu return true; } - @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 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 getTankArrayNames(MultiBlockPart aPart); + + List 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 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 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> extends PowerController { + + 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 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 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/Controller.java b/src/main/java/gregtech/api/multitileentity/multiblock/base/Controller.java new file mode 100644 index 0000000000..9fdac059da --- /dev/null +++ b/src/main/java/gregtech/api/multitileentity/multiblock/base/Controller.java @@ -0,0 +1,2187 @@ +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.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; +import java.util.Arrays; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +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; +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; +import net.minecraftforge.fluids.FluidTankInfo; +import net.minecraftforge.fluids.IFluidTank; + +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; +import org.lwjgl.input.Keyboard; + +import com.gtnewhorizon.structurelib.StructureLibAPI; +import com.gtnewhorizon.structurelib.alignment.IAlignment; +import com.gtnewhorizon.structurelib.alignment.IAlignmentLimits; +import com.gtnewhorizon.structurelib.alignment.constructable.IConstructable; +import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable; +import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing; +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; +import com.gtnewhorizons.modularui.api.drawable.IDrawable; +import com.gtnewhorizons.modularui.api.drawable.ItemDrawable; +import com.gtnewhorizons.modularui.api.drawable.UITexture; +import com.gtnewhorizons.modularui.api.forge.IItemHandlerModifiable; +import com.gtnewhorizons.modularui.api.forge.ItemStackHandler; +import com.gtnewhorizons.modularui.api.forge.ListItemHandler; +import com.gtnewhorizons.modularui.api.screen.*; +import com.gtnewhorizons.modularui.api.widget.Widget; +import com.gtnewhorizons.modularui.common.widget.ButtonWidget; +import com.gtnewhorizons.modularui.common.widget.DrawableWidget; +import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget; +import com.gtnewhorizons.modularui.common.widget.FluidSlotWidget; +import com.gtnewhorizons.modularui.common.widget.MultiChildWidget; +import com.gtnewhorizons.modularui.common.widget.Scrollable; +import com.gtnewhorizons.modularui.common.widget.SlotWidget; +import com.gtnewhorizons.modularui.common.widget.TabButton; +import com.gtnewhorizons.modularui.common.widget.TabContainer; + +import cpw.mods.fml.common.network.NetworkRegistry; +import gnu.trove.list.TIntList; +import gnu.trove.list.array.TIntArrayList; +import gregtech.api.enums.GT_Values; +import gregtech.api.enums.GT_Values.NBT; +import gregtech.api.enums.OrePrefixes; +import gregtech.api.enums.SoundResource; +import gregtech.api.enums.TextureSet; +import gregtech.api.fluid.FluidTankGT; +import gregtech.api.gui.modularui.GT_UITextures; +import gregtech.api.interfaces.IDescribable; +import gregtech.api.logic.PowerLogic; +import gregtech.api.logic.ProcessingLogic; +import gregtech.api.logic.interfaces.PowerLogicHost; +import gregtech.api.logic.interfaces.ProcessingLogicHost; +import gregtech.api.multitileentity.MultiTileEntityContainer; +import gregtech.api.multitileentity.MultiTileEntityRegistry; +import gregtech.api.multitileentity.interfaces.IMultiBlockController; +import gregtech.api.multitileentity.interfaces.IMultiBlockPart; +import gregtech.api.multitileentity.interfaces.IMultiTileEntity; +import gregtech.api.multitileentity.interfaces.IMultiTileEntity.IMTE_AddToolTips; +import gregtech.api.multitileentity.machine.MultiTileBasicMachine; +import gregtech.api.multitileentity.multiblock.casing.FunctionalCasing; +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.api.util.GT_Waila; +import gregtech.common.tileentities.casings.upgrade.Inventory; + +public abstract class Controller> extends MultiTileBasicMachine implements IAlignment, + IConstructable, IMultiBlockController, IDescribable, IMTE_AddToolTips, ISurvivalConstructable { + + public static final String ALL_INVENTORIES_NAME = "all"; + + private static final Map tooltip = new ConcurrentHashMap<>(); + private final List upgradeCasings = new ArrayList<>(); + private final List functionalCasings = new ArrayList<>(); + protected BuildState buildState = new BuildState(); + + protected Map multiBlockInputInventoryNames = new LinkedHashMap<>(); + protected Map multiBlockOutputInventoryNames = new LinkedHashMap<>(); + protected Map multiBlockInputInventoryToTankLink = new LinkedHashMap<>(); + protected Map multiBlockInputInventory = new LinkedHashMap<>(); + protected Map multiBlockOutputInventory = new LinkedHashMap<>(); + + protected Map multiBlockInputTankNames = new LinkedHashMap<>(); + protected Map multiBlockOutputTankNames = new LinkedHashMap<>(); + protected Map multiBlockInputTank = new LinkedHashMap<>(); + protected Map multiBlockOutputTank = new LinkedHashMap<>(); + + private boolean structureOkay = false, structureChanged = false; + private ExtendedFacing extendedFacing = ExtendedFacing.DEFAULT; + private IAlignmentLimits limits = getInitialAlignmentLimits(); + private String inventoryName; + private String tankName; + protected boolean separateInputs = false; + 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 + protected List>> registeredCoveredParts = Arrays.asList( + new LinkedList<>(), + new LinkedList<>(), + new LinkedList<>(), + new LinkedList<>(), + new LinkedList<>(), + new LinkedList<>()); + + /** Registry ID of the required casing */ + public abstract short getCasingRegistryID(); + + /** Meta ID of the required casing */ + public abstract int getCasingMeta(); + + /** + * Create the tooltip for this multi block controller. + */ + protected abstract GT_Multiblock_Tooltip_Builder createTooltip(); + + /** + * @return The starting offset for the structure builder + */ + public abstract Vec3Impl getStartingStructureOffset(); + + /** + * Due to limitation of Java type system, you might need to do an unchecked cast. HOWEVER, the returned + * IStructureDefinition is expected to be evaluated against current instance only, and should not be used against + * other instances, even for those of the same class. + */ + @Override + public abstract IStructureDefinition getStructureDefinition(); + + /** + * Checks the Machine. + *

+ * NOTE: If using `buildState` be sure to `startBuilding()` and either `endBuilding()` or `failBuilding()` + */ + public boolean checkMachine() { + double sum = 0; + if (functionalCasings == null || functionalCasings.size() == 0) { + return false; + } + for (FunctionalCasing casing : functionalCasings) { + 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 + return tier > 0; + } + + @Override + public void writeMultiTileNBT(NBTTagCompound nbt) { + super.writeMultiTileNBT(nbt); + + nbt.setBoolean(NBT.STRUCTURE_OK, structureOkay); + nbt.setByte( + NBT.ROTATION, + (byte) extendedFacing.getRotation() + .getIndex()); + nbt.setByte( + NBT.FLIP, + (byte) extendedFacing.getFlip() + .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) { + final NBTTagList inputInvList = new NBTTagList(); + multiBlockInputInventory.forEach((id, inv) -> { + if (!id.equals("controller")) { + final NBTTagCompound tTag = new NBTTagCompound(); + tTag.setString(NBT.UPGRADE_INVENTORY_UUID, id); + tTag.setString(NBT.UPGRADE_INVENTORY_NAME, multiBlockInputInventoryNames.get(id)); + tTag.setInteger(NBT.UPGRADE_INVENTORY_SIZE, inv.getSlots()); + writeInventory(tTag, inv, NBT.INV_INPUT_LIST); + inputInvList.appendTag(tTag); + } + }); + final NBTTagList outputInvList = new NBTTagList(); + multiBlockOutputInventory.forEach((id, inv) -> { + if (!id.equals("controller")) { + final NBTTagCompound tTag = new NBTTagCompound(); + tTag.setString(NBT.UPGRADE_INVENTORY_UUID, id); + tTag.setString(NBT.UPGRADE_INVENTORY_NAME, multiBlockOutputInventoryNames.get(id)); + tTag.setInteger(NBT.UPGRADE_INVENTORY_SIZE, inv.getSlots()); + writeInventory(tTag, inv, NBT.INV_OUTPUT_LIST); + outputInvList.appendTag(tTag); + } + }); + nbt.setTag(NBT.UPGRADE_INVENTORIES_INPUT, inputInvList); + 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) 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( + ForgeDirection.getOrientation(getFrontFacing()), + Rotation.byIndex(nbt.getByte(NBT.ROTATION)), + 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, 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); + String invName = nbtInv.getString(NBT.UPGRADE_INVENTORY_NAME); + int invSize = nbtInv.getInteger(NBT.UPGRADE_INVENTORY_SIZE); + IItemHandlerModifiable inv = new ItemStackHandler(invSize); + loadInventory(nbtInv, inv, NBT.INV_INPUT_LIST); + registerInventory(invName, invUUID, invSize, Inventory.INPUT); + } + + 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); + String invName = nbtInv.getString(NBT.UPGRADE_INVENTORY_NAME); + int invSize = nbtInv.getInteger(NBT.UPGRADE_INVENTORY_SIZE); + IItemHandlerModifiable inv = new ItemStackHandler(invSize); + loadInventory(nbtInv, inv, NBT.INV_OUTPUT_LIST); + 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); + } + } + + @Override + public void addToolTips(List aList, ItemStack aStack, boolean aF3_H) { + aList.addAll(Arrays.asList(getDescription())); + } + + @Override + public String[] getDescription() { + if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) { + return getTooltip().getStructureInformation(); + } else { + return getTooltip().getInformation(); + } + } + + @Override + protected void addDebugInfo(EntityPlayer aPlayer, int aLogLevel, ArrayList tList) { + super.addDebugInfo(aPlayer, aLogLevel, tList); + tList.add("Structure ok: " + checkStructure(false)); + } + + protected int getToolTipID() { + return getMultiTileEntityRegistryID() << 16 + getMultiTileEntityID(); + } + + protected GT_Multiblock_Tooltip_Builder getTooltip() { + GT_Multiblock_Tooltip_Builder builder = tooltip.get(getToolTipID()); + if (builder == null) { + builder = createTooltip(); + tooltip.put(getToolTipID(), builder); + } + return builder; + } + + @Override + public boolean checkStructure(boolean aForceReset) { + if (!isServerSide()) return structureOkay; + + // Only trigger an update if forced (from onPostTick, generally), or if the structure has changed + if ((structureChanged || aForceReset)) { + structureOkay = checkMachine(); + } + structureChanged = false; + return structureOkay; + } + + @Override + public void onStructureChange() { + structureChanged = true; + } + + public final boolean checkPiece(String piece, Vec3Impl offset) { + functionalCasings.clear(); + upgradeCasings.clear(); + return checkPiece(piece, offset.get0(), offset.get1(), offset.get2()); + } + + /** + * Explanation of the world coordinate these offset means: + *

+ * Imagine you stand in front of the controller, with controller facing towards you not rotated or flipped. + *

+ * The horizontalOffset would be the number of blocks on the left side of the controller, not counting controller + * itself. The verticalOffset would be the number of blocks on the top side of the controller, not counting + * controller itself. The depthOffset would be the number of blocks between you and controller, not counting + * controller itself. + *

+ * All these offsets can be negative. + */ + protected final boolean checkPiece(String piece, int horizontalOffset, int verticalOffset, int depthOffset) { + return getCastedStructureDefinition().check( + this, + piece, + getWorld(), + getExtendedFacing(), + getXCoord(), + getYCoord(), + getZCoord(), + horizontalOffset, + verticalOffset, + depthOffset, + !structureOkay); + } + + public final boolean buildPiece(String piece, ItemStack trigger, boolean hintsOnly, Vec3Impl offset) { + return buildPiece(piece, trigger, hintsOnly, offset.get0(), offset.get1(), offset.get2()); + } + + protected final boolean buildPiece(String piece, ItemStack trigger, boolean hintOnly, int horizontalOffset, + int verticalOffset, int depthOffset) { + return getCastedStructureDefinition().buildOrHints( + this, + trigger, + piece, + getWorld(), + getExtendedFacing(), + getXCoord(), + getYCoord(), + getZCoord(), + horizontalOffset, + verticalOffset, + depthOffset, + hintOnly); + } + + protected final int survivalBuildPiece(String piece, ItemStack trigger, Vec3Impl offset, int elementBudget, + ISurvivalBuildEnvironment env, boolean check) { + return survivalBuildPiece( + piece, + trigger, + offset.get0(), + offset.get1(), + offset.get2(), + elementBudget, + env, + check); + } + + protected final Integer survivalBuildPiece(String piece, ItemStack trigger, int horizontalOffset, + int verticalOffset, int depthOffset, int elementBudget, ISurvivalBuildEnvironment env, boolean check) { + return getCastedStructureDefinition().survivalBuild( + this, + trigger, + piece, + getWorld(), + getExtendedFacing(), + getXCoord(), + getYCoord(), + getZCoord(), + horizontalOffset, + verticalOffset, + depthOffset, + elementBudget, + env, + check); + } + + @SuppressWarnings("unchecked") + private IStructureDefinition> getCastedStructureDefinition() { + return (IStructureDefinition>) getStructureDefinition(); + } + + @Override + public ExtendedFacing getExtendedFacing() { + return extendedFacing; + } + + @Override + public void setExtendedFacing(ExtendedFacing newExtendedFacing) { + if (extendedFacing != newExtendedFacing) { + onStructureChange(); + if (structureOkay) stopMachine(false); + extendedFacing = newExtendedFacing; + structureOkay = false; + if (isServerSide()) { + StructureLibAPI.sendAlignment( + this, + new NetworkRegistry.TargetPoint( + getWorld().provider.dimensionId, + getXCoord(), + getYCoord(), + getZCoord(), + 512)); + } else { + issueTextureUpdate(); + } + } + } + + @Override + public boolean onWrenchRightClick(EntityPlayer aPlayer, ItemStack tCurrentItem, byte wrenchSide, float aX, float aY, + float aZ) { + if (wrenchSide != getFrontFacing()) + return super.onWrenchRightClick(aPlayer, tCurrentItem, wrenchSide, aX, aY, aZ); + if (aPlayer.isSneaking()) { + // we won't be allowing horizontal flips, as it can be perfectly emulated by rotating twice and flipping + // horizontally allowing an extra round of flip make it hard to draw meaningful flip markers in + // GT_Proxy#drawGrid + toolSetFlip(getFlip().isHorizontallyFlipped() ? Flip.NONE : Flip.HORIZONTAL); + } else { + toolSetRotation(null); + } + return true; + } + + @Override + public void registerCoveredPartOnSide(final int aSide, IMultiBlockPart part) { + if (aSide < 0 || aSide >= 6) return; + + final LinkedList> registeredCovers = registeredCoveredParts.get(aSide); + // TODO: Make sure that we're not already registered on this side + registeredCovers.add(new WeakReference<>(part)); + } + + @Override + public void unregisterCoveredPartOnSide(final int aSide, IMultiBlockPart aPart) { + if (aSide < 0 || aSide >= 6) return; + + final LinkedList> coveredParts = registeredCoveredParts.get(aSide); + final Iterator> it = coveredParts.iterator(); + while (it.hasNext()) { + final IMultiBlockPart part = (it.next()).get(); + if (part == null || part == aPart) it.remove(); + } + } + + @Override + public void onFirstTick(boolean isServerSide) { + super.onFirstTick(isServerSide); + if (isServerSide) { + checkStructure(true); + } else { + StructureLibAPI.queryAlignment(this); + } + } + + private boolean tickCovers() { + for (byte side : ALL_VALID_SIDES) { + // TODO: Tick controller covers, if any + final LinkedList> coveredParts = this.registeredCoveredParts.get(side); + final Iterator> it = coveredParts.iterator(); + while (it.hasNext()) { + final IMultiBlockPart part = (it.next()).get(); + if (part == null) { + it.remove(); + continue; + } + if (!part.tickCoverAtSide(side, mTickTimer)) it.remove(); + } + } + + return true; + } + + @Override + public void onTick(long timer, boolean isServerSide) { + if (!tickCovers()) { + return; + } + } + + @Override + public void onPostTick(long tick, boolean isServerSide) { + if (isServerSide) { + if (tick % 600 == 5) { + clearSpecialLists(); + // Recheck the structure every 30 seconds or so + if (!checkStructure(false)) checkStructure(true); + } + if (checkStructure(false)) { + runMachine(tick); + } else { + stopMachine(false); + } + } else { + doActivitySound(getActivitySoundLoop()); + } + } + + protected void clearSpecialLists() { + upgradeCasings.clear(); + } + + @Override + public final boolean isFacingValid(byte aFacing) { + return canSetToDirectionAny(ForgeDirection.getOrientation(aFacing)); + } + + @Override + public void onFacingChange() { + toolSetDirection(ForgeDirection.getOrientation(getFrontFacing())); + onStructureChange(); + } + + @Override + public boolean allowCoverOnSide(byte aSide, GT_ItemStack aCoverID) { + return facing.compareTo(ForgeDirection.getOrientation(aSide)) != 0; + } + + @Override + public String[] getStructureDescription(ItemStack stackSize) { + return getTooltip().getStructureHint(); + } + + @Override + public IAlignmentLimits getAlignmentLimits() { + return limits; + } + + protected void setAlignmentLimits(IAlignmentLimits mLimits) { + this.limits = mLimits; + } + + // IMachineProgress + @Override + public long getProgress() { + return progressTime; + } + + @Override + public long getMaxProgress() { + return maxProgressTime; + } + + @Override + public boolean increaseProgress(int aProgressAmountInTicks) { + return increaseProgressGetOverflow(aProgressAmountInTicks) != aProgressAmountInTicks; + } + + @Override + public FluidStack getDrainableFluid(byte aSide) { + 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(); + } + + /** + * Increases the Progress, returns the overflown Progress. + */ + public int increaseProgressGetOverflow(int aProgress) { + return 0; + } + + @Override + public boolean hasThingsToDo() { + return getMaxProgress() > 0; + } + + public boolean isSeparateInputs() { + return separateInputs; + } + + public void setSeparateInputs(boolean aSeparateInputs) { + separateInputs = aSeparateInputs; + } + + // End IMachineProgress + + protected IAlignmentLimits getInitialAlignmentLimits() { + return (d, r, f) -> !f.isVerticallyFliped(); + } + + public static class BuildState { + + /** + * Utility class to keep track of the build state of a multiblock + */ + boolean building = false; + + Vec3Impl currentOffset; + + public void startBuilding(Vec3Impl structureOffset) { + if (building) throw new IllegalStateException("Already building!"); + building = true; + setCurrentOffset(structureOffset); + } + + public Vec3Impl setCurrentOffset(Vec3Impl structureOffset) { + verifyBuilding(); + return (currentOffset = structureOffset); + } + + private void verifyBuilding() { + if (!building) throw new IllegalStateException("Not building!"); + } + + public boolean failBuilding() { + building = false; + currentOffset = null; + return false; + } + + public Vec3Impl stopBuilding() { + final Vec3Impl toReturn = getCurrentOffset(); + building = false; + currentOffset = null; + + return toReturn; + } + + public Vec3Impl getCurrentOffset() { + verifyBuilding(); + return currentOffset; + } + + public Vec3Impl addOffset(Vec3Impl offset) { + verifyBuilding(); + return setCurrentOffset(currentOffset.add(offset)); + } + } + + public IStructureElement addMultiTileCasing(String registryName, int meta, int modes) { + MultiTileEntityRegistry registry = MultiTileEntityRegistry.getRegistry(registryName); + int registryID = Block.getIdFromBlock(registry.mBlock); + return addMultiTileCasing(registryID, meta, modes); + } + + public IStructureElement addMultiTileCasing(int registryID, int meta, int modes) { + return new IStructureElement() { + + private final short[] DEFAULT = new short[] { 255, 255, 255, 0 }; + private IIcon[] mIcons = null; + + @Override + public boolean check(S t, World world, int x, int y, int z) { + final TileEntity tileEntity = world.getTileEntity(x, y, z); + if (!(tileEntity instanceof MultiBlockPart part)) return false; + + if (registryID != part.getMultiTileEntityRegistryID() || meta != part.getMultiTileEntityID()) + return false; + + final IMultiBlockController tTarget = part.getTarget(false); + if (tTarget != null && tTarget != t) return false; + + part.setTarget((IMultiBlockController) t, modes); + + ((Controller) t).registerSpecialCasings(part); + return true; + } + + @Override + public boolean spawnHint(S t, World world, int x, int y, int z, ItemStack trigger) { + if (mIcons == null) { + mIcons = new IIcon[6]; + Arrays.fill(mIcons, TextureSet.SET_NONE.mTextures[OrePrefixes.block.mTextureIndex].getIcon()); + // Arrays.fill(mIcons, getTexture(aCasing); + // for (byte i : ALL_VALID_SIDES) { + // mIcons[i] = aCasing.getIcon(i, aMeta); + // } + } + final short[] RGBA = DEFAULT; + StructureLibAPI.hintParticleTinted(world, x, y, z, mIcons, RGBA); + // StructureLibAPI.hintParticle(world, x, y, z, aCasing, aMeta); + return true; + } + + @Override + public boolean placeBlock(S t, World world, int x, int y, int z, ItemStack trigger) { + final MultiTileEntityRegistry tRegistry = MultiTileEntityRegistry.getRegistry(registryID); + final MultiTileEntityContainer tContainer = tRegistry + .getNewTileEntityContainer(world, x, y, z, meta, null); + if (tContainer == null) { + GT_FML_LOGGER.error("NULL CONTAINER"); + return false; + } + final IMultiTileEntity te = ((IMultiTileEntity) tContainer.mTileEntity); + if (!(te instanceof MultiBlockPart)) { + GT_FML_LOGGER.error("Not a multiblock part"); + return false; + } + if (world.setBlock(x, y, z, tContainer.mBlock, 15 - tContainer.mBlockMetaData, 2)) { + tContainer.setMultiTile(world, x, y, z); + ((MultiBlockPart) te).setTarget(Controller.this, modes); + + ((Controller) t).registerSpecialCasings((MultiBlockPart) te); + } + + return false; + } + + public IIcon getTexture(OrePrefixes aBlock) { + return TextureSet.SET_NONE.mTextures[OrePrefixes.block.mTextureIndex].getIcon(); + } + }; + } + + protected IStructureElementChain 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 IStructureElementChain 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 IStructureElementChain 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 IStructureElementChain 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 IStructureElementChain 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 IStructureElementChain 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 IStructureElementChain 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 IStructureElementChain 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); + } + if (part instanceof FunctionalCasing) { + functionalCasings.add((FunctionalCasing) part); + } + } + + /** + * 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 tanks = new ArrayList<>(); + for (FluidTankGT[] inputTanks : multiBlockInputTank.values()) { + tanks.addAll(Arrays.asList(inputTanks)); + } + return tanks.toArray(new FluidTankGT[0]); + } + + protected FluidTankGT[] getTanksForOutput() { + List 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(aPart.getFrontFacing(), aSide, aFluidToFill); + } + + protected IFluidTank getFluidTankDrainable(MultiBlockPart aPart, byte aSide, FluidStack aFluidToDrain) { + return getFluidTankDrainable(aPart.getFrontFacing(), aSide, aFluidToDrain); + } + + protected IFluidTank[] getFluidTanks(MultiBlockPart aPart, byte aSide) { + return getFluidTanks(aSide); + } + + @Override + public int fill(MultiBlockPart aPart, ForgeDirection aDirection, FluidStack aFluid, boolean aDoFill) { + if (aFluid == null || aFluid.amount <= 0) return 0; + final IFluidTank tTank = getFluidTankFillable(aPart, (byte) aDirection.ordinal(), aFluid); + if (tTank == null) return 0; + final int rFilledAmount = tTank.fill(aFluid, aDoFill); + if (rFilledAmount > 0 && aDoFill) hasInventoryChanged = true; + return rFilledAmount; + } + + @Override + public FluidStack drain(MultiBlockPart aPart, ForgeDirection aDirection, FluidStack aFluid, boolean aDoDrain) { + if (aFluid == null || aFluid.amount <= 0) return null; + final IFluidTank tTank = getFluidTankDrainable(aPart, (byte) aDirection.ordinal(), aFluid); + if (tTank == null || tTank.getFluid() == null + || tTank.getFluidAmount() == 0 + || !tTank.getFluid() + .isFluidEqual(aFluid)) + return null; + final FluidStack rDrained = tTank.drain(aFluid.amount, aDoDrain); + if (rDrained != null && aDoDrain) markInventoryBeenModified(); + return rDrained; + } + + @Override + public FluidStack drain(MultiBlockPart aPart, ForgeDirection aDirection, int aAmountToDrain, boolean aDoDrain) { + if (aAmountToDrain <= 0) return null; + final IFluidTank tTank = getFluidTankDrainable(aPart, (byte) aDirection.ordinal(), null); + if (tTank == null || tTank.getFluid() == null || tTank.getFluidAmount() == 0) return null; + final FluidStack rDrained = tTank.drain(aAmountToDrain, aDoDrain); + if (rDrained != null && aDoDrain) markInventoryBeenModified(); + return rDrained; + } + + @Override + public boolean canFill(MultiBlockPart aPart, ForgeDirection aDirection, Fluid aFluid) { + if (aFluid == null) return false; + final IFluidTank tTank = getFluidTankFillable(aPart, (byte) aDirection.ordinal(), new FluidStack(aFluid, 0)); + return tTank != null && (tTank.getFluid() == null || tTank.getFluid() + .getFluid() == aFluid); + } + + @Override + public boolean canDrain(MultiBlockPart aPart, ForgeDirection aDirection, Fluid aFluid) { + if (aFluid == null) return false; + final IFluidTank tTank = getFluidTankDrainable(aPart, (byte) aDirection.ordinal(), new FluidStack(aFluid, 0)); + return tTank != null && (tTank.getFluid() != null && tTank.getFluid() + .getFluid() == aFluid); + } + + @Override + public FluidTankInfo[] getTankInfo(MultiBlockPart aPart, ForgeDirection aDirection) { + final IFluidTank[] tTanks = getFluidTanks(aPart, (byte) aDirection.ordinal()); + if (tTanks == null || tTanks.length <= 0) return GT_Values.emptyFluidTankInfo; + final FluidTankInfo[] rInfo = new FluidTankInfo[tTanks.length]; + for (int i = 0; i < tTanks.length; i++) rInfo[i] = new FluidTankInfo(tTanks[i]); + return rInfo; + } + + @Override + public IFluidTank[] getFluidTanksForGUI(MultiBlockPart aPart) { + 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 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, ForgeDirection side) { + if (!(this instanceof PowerLogicHost)) { + return null; + } + + if (ForgeDirection.getOrientation(part.getFrontFacing()) != side) { + return null; + } + + return ((PowerLogicHost) this).getPowerLogic(side); + } + // #endregion Energy + + /** + * Item - MultiBlock related Item behaviour. + */ + @Override + public void registerInventory(String aName, String aID, int aInventorySize, int aType) { + 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 (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 == Inventory.INPUT || aType == Inventory.BOTH) && multiBlockInputInventory.containsKey(aID)) { + multiBlockInputInventory.remove(aID, multiBlockInputInventory.get(aID)); + multiBlockInputInventoryNames.remove(aID, aName); + } + if ((aType == Inventory.OUTPUT || aType == Inventory.BOTH) && multiBlockOutputInventory.containsKey(aID)) { + multiBlockOutputInventory.remove(aID, multiBlockOutputInventory.get(aID)); + multiBlockOutputInventoryNames.remove(aID, aName); + } + } + + @Override + public void changeInventoryName(String aName, String aID, int aType) { + if ((aType == Inventory.INPUT || aType == Inventory.BOTH) && multiBlockInputInventoryNames.containsKey(aID)) { + multiBlockInputInventoryNames.put(aID, aName); + } + if ((aType == Inventory.OUTPUT || aType == Inventory.BOTH) && multiBlockOutputInventoryNames.containsKey(aID)) { + multiBlockOutputInventoryNames.put(aID, aName); + } + } + + @Override + public boolean hasInventoryBeenModified(MultiBlockPart aPart) { + if (aPart.modeSelected(MultiBlockPart.ITEM_IN)) return hasInventoryBeenModified(); + else if (aPart.modeSelected(MultiBlockPart.ITEM_OUT)) return hasOutputInventoryBeenModified(); + + return false; + } + + @Override + public boolean isValidSlot(MultiBlockPart aPart, int aIndex) { + return false; + } + + @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 Inventory)) continue; + tPart.issueClientUpdate(); + } + } + final Map multiBlockInventory = getMultiBlockInventory(aPart); + if (multiBlockInventory == null) return null; + + final String lockedInventory = aPart.getLockedInventory(); + if (lockedInventory == null) { + return new ListItemHandler(multiBlockInventory.values()); + } else { + final IItemHandlerModifiable inv = multiBlockInventory.get(lockedInventory); + return inv != null ? inv : null; + } + } + + @Override + public boolean addStackToSlot(MultiBlockPart aPart, int aIndex, ItemStack aStack) { + return false; + } + + @Override + public boolean addStackToSlot(MultiBlockPart aPart, int aIndex, ItemStack aStack, int aAmount) { + return false; + } + + protected Map getMultiBlockTankArray(MultiBlockPart aPart) { + if (aPart.modeSelected(MultiBlockPart.FLUID_IN)) return multiBlockInputTank; + else if (aPart.modeSelected(MultiBlockPart.FLUID_OUT)) return multiBlockOutputTank; + return null; + } + + protected Map getMultiBlockTankArrayNames(MultiBlockPart aPart) { + if (aPart.modeSelected(MultiBlockPart.FLUID_IN)) return multiBlockInputTankNames; + else if (aPart.modeSelected(MultiBlockPart.FLUID_OUT)) return multiBlockOutputTankNames; + return null; + } + + protected Map getMultiBlockInventory(MultiBlockPart aPart) { + if (aPart.modeSelected(MultiBlockPart.ITEM_IN)) return multiBlockInputInventory; + else if (aPart.modeSelected(MultiBlockPart.ITEM_OUT)) return multiBlockOutputInventory; + return null; + } + + protected Map getMultiBlockInventoryNames(MultiBlockPart aPart) { + if (aPart.modeSelected(MultiBlockPart.ITEM_IN)) return multiBlockInputInventoryNames; + else if (aPart.modeSelected(MultiBlockPart.ITEM_OUT)) return multiBlockOutputInventoryNames; + return null; + } + + protected Pair getInventory(MultiBlockPart aPart, int aSlot) { + final Map multiBlockInventory = getMultiBlockInventory(aPart); + if (multiBlockInventory == null) return null; + + final String invName = aPart.getLockedInventory(); + if (invName != null && !invName.isEmpty()) return new ImmutablePair<>(multiBlockInventory.get(invName), aSlot); + + int start = 0; + for (IItemHandlerModifiable inv : multiBlockInventory.values()) { + if (aSlot >= start && aSlot < start + inv.getSlots()) { + return new ImmutablePair<>(inv, aSlot - start); + } + start += inv.getSlots(); + } + return null; + } + + @Override + public int[] getAccessibleSlotsFromSide(MultiBlockPart aPart, byte aSide) { + final TIntList tList = new TIntArrayList(); + final Map multiBlockInventory = getMultiBlockInventory(aPart); + if (multiBlockInventory == null) return tList.toArray(); + + final String lockedInventory = aPart.getLockedInventory(); + // Item in --> input inv + // Item out --> output inv + + int start = 0; + if (lockedInventory == null) { + for (IItemHandlerModifiable inv : multiBlockInventory.values()) { + for (int i = start; i < inv.getSlots() + start; i++) tList.add(i); + start += inv.getSlots(); + } + } else { + final IItemHandlerModifiable inv = multiBlockInventory.get(lockedInventory); + final int len = inv != null ? inv.getSlots() : 0; + for (int i = 0; i < len; i++) tList.add(i); + } + return tList.toArray(); + } + + @Override + public boolean canInsertItem(MultiBlockPart aPart, int aSlot, ItemStack aStack, byte aSide) { + final Pair tInv = getInventory(aPart, aSlot); + if (tInv == null) return false; + + final int tSlot = tInv.getRight(); + final IItemHandlerModifiable inv = tInv.getLeft(); + + return inv.getStackInSlot(tSlot) == null || GT_Utility.areStacksEqual(aStack, inv.getStackInSlot(tSlot)); // && + // allowPutStack(getBaseMetaTileEntity(), + // aIndex, + // (byte) + // aSide, + // aStack) + } + + @Override + public boolean canExtractItem(MultiBlockPart aPart, int aSlot, ItemStack aStack, byte aSide) { + final Pair tInv = getInventory(aPart, aSlot); + if (tInv == null) return false; + + final int tSlot = tInv.getRight(); + final IItemHandlerModifiable inv = tInv.getLeft(); + + return inv.getStackInSlot(tSlot) != null; // && allowPullStack(getBaseMetaTileEntity(), aIndex, (byte) aSide, + // aStack); + } + + @Override + public int getSizeInventory(MultiBlockPart aPart) { + final Map multiBlockInventory = getMultiBlockInventory(aPart); + if (multiBlockInventory == null) return 0; + + final String lockedInventory = aPart.getLockedInventory(); + if (lockedInventory == null) { + int len = 0; + for (IItemHandlerModifiable inv : multiBlockInventory.values()) len += inv.getSlots(); + return len; + } else { + final IItemHandlerModifiable inv = multiBlockInventory.get(lockedInventory); + return inv != null ? inv.getSlots() : 0; + } + } + + @Override + public ItemStack getStackInSlot(MultiBlockPart aPart, int aSlot) { + final Pair tInv = getInventory(aPart, aSlot); + if (tInv == null) return null; + + final int tSlot = tInv.getRight(); + final IItemHandlerModifiable inv = tInv.getLeft(); + if (inv == null) return null; + + return inv.getStackInSlot(tSlot); + } + + @Override + public ItemStack decrStackSize(MultiBlockPart aPart, int aSlot, int aDecrement) { + final ItemStack tStack = getStackInSlot(aPart, aSlot); + ItemStack rStack = GT_Utility.copyOrNull(tStack); + if (tStack != null) { + if (tStack.stackSize <= aDecrement) { + setInventorySlotContents(aPart, aSlot, null); + } else { + rStack = tStack.splitStack(aDecrement); + if (tStack.stackSize == 0) setInventorySlotContents(aPart, aSlot, null); + } + } + return rStack; + } + + @Override + public ItemStack getStackInSlotOnClosing(MultiBlockPart aPart, int aSlot) { + final Pair tInv = getInventory(aPart, aSlot); + if (tInv == null) return null; + + final IItemHandlerModifiable inv = tInv.getLeft(); + final int tSlot = tInv.getRight(); + + final ItemStack rStack = inv.getStackInSlot(tSlot); + inv.setStackInSlot(tSlot, null); + return rStack; + } + + @Override + public void setInventorySlotContents(MultiBlockPart aPart, int aSlot, ItemStack aStack) { + final Pair tInv = getInventory(aPart, aSlot); + if (tInv == null) return; + + final IItemHandlerModifiable inv = tInv.getLeft(); + final int tSlot = tInv.getRight(); + inv.setStackInSlot(tSlot, aStack); + } + + @Override + public List getInventoryNames(MultiBlockPart aPart) { + final List inventoryNames = new ArrayList<>(); + inventoryNames.add(ALL_INVENTORIES_NAME); + inventoryNames.addAll(getMultiBlockInventoryNames(aPart).values()); + return inventoryNames; + } + + @Override + public List getInventoryIDs(MultiBlockPart aPart) { + final List tInventoryIDs = new ArrayList<>(); + tInventoryIDs.add(ALL_INVENTORIES_NAME); + tInventoryIDs.addAll(getMultiBlockInventory(aPart).keySet()); + return tInventoryIDs; + } + + @Override + public String getInventoryName(MultiBlockPart aPart) { + final StringBuilder str = new StringBuilder(); + str.append(getInventoryName()); + if (aPart.modeSelected(MultiBlockPart.ITEM_IN)) { + str.append(" Input"); + } else if (aPart.modeSelected(MultiBlockPart.ITEM_OUT)) { + str.append(" Output"); + String a; + } else { + str.append(" Unknown"); + } + final String lockedInventory = aPart.getLockedInventory(); + if (lockedInventory != null && !lockedInventory.equals("")) { + str.append(" [Locked: ") + .append(lockedInventory) + .append("]"); + } + + return str.toString(); + } + + @Override + public List getTankArrayNames(MultiBlockPart aPart) { + final List inventoryNames = new ArrayList<>(); + inventoryNames.add(ALL_INVENTORIES_NAME); + inventoryNames.addAll(getMultiBlockTankArrayNames(aPart).values()); + return inventoryNames; + } + + @Override + public List getTankArrayIDs(MultiBlockPart aPart) { + final List inventoryIDs = new ArrayList<>(); + inventoryIDs.add(ALL_INVENTORIES_NAME); + inventoryIDs.addAll(getMultiBlockTankArray(aPart).keySet()); + return inventoryIDs; + } + + @Override + public boolean hasCustomInventoryName(MultiBlockPart aPart) { + return hasCustomInventoryName(); + } + + @Override + public int getInventoryStackLimit(MultiBlockPart aPart) { + return getInventoryStackLimit(); + } + + @Override + public void markDirty(MultiBlockPart aPart) { + markDirty(); + if (aPart.modeSelected(MultiBlockPart.ITEM_OUT)) markOutputInventoryBeenModified(); + else markInventoryBeenModified(); + } + + @Override + public boolean isUseableByPlayer(MultiBlockPart aPart, EntityPlayer aPlayer) { + return isUseableByPlayer(aPlayer); + } + + @Override + public void openInventory(MultiBlockPart aPart) { + // TODO: MultiInventory - consider the part's inventory + openInventory(); + } + + @Override + public void closeInventory(MultiBlockPart aPart) { + // TODO: MultiInventory - consider the part's inventory + closeInventory(); + } + + @Override + public boolean isItemValidForSlot(MultiBlockPart aPart, int aSlot, ItemStack aStack) { + return isItemValidForSlot(aSlot, aStack); + } + + /* + * Helper Methods For Recipe checking + */ + + @Override + protected ItemStack[] getInputItems() { + return getInventoriesForInput().getStacks() + .toArray(new ItemStack[0]); + } + + protected ItemStack[] getOutputItems() { + return getInventoriesForOutput().getStacks() + .toArray(new ItemStack[0]); + } + + protected Iterable> getItemInputsForEachInventory() { + return multiBlockInputInventory.entrySet() + .stream() + .map( + (entry) -> Pair.of( + entry.getValue() + .getStacks() + .toArray(new ItemStack[0]), + entry.getKey())) + .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 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 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> 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; + } + + @Override + protected void setItemOutputs(ItemStack... outputs) { + super.setItemOutputs(outputs); + inventoryName = null; + } + + @Override + protected void outputItems() { + if (itemsToOutput == null) { + return; + } + + IItemHandlerModifiable inv; + if (inventoryName != null) { + inv = multiBlockOutputInventory.getOrDefault(inventoryName, getInventoriesForOutput()); + } else { + inv = getInventoriesForOutput(); + } + for (ItemStack item : itemsToOutput) { + int index = 0; + while (item != null && item.stackSize > 0 && index < inv.getSlots()) { + item = inv.insertItem(index++, item.copy(), false); + } + } + itemsToOutput = null; + } + + protected void setFluidOutputs(String tank, FluidStack... fluidOuputs) { + fluidsToOutput = fluidOuputs; + tankName = tank; + } + + @Override + protected void setFluidOutputs(FluidStack... outputs) { + super.setFluidOutputs(outputs); + tankName = null; + } + + @Override + protected void outputFluids() { + if (fluidsToOutput == null) { + return; + } + + List tanks = Arrays.asList(outputTanks); + for (FluidStack fluid : fluidsToOutput) { + int index = 0; + while (fluid != null && fluid.amount > 0 && index < tanks.size()) { + int filled = tanks.get(index++) + .fill(fluid, true); + fluid.amount -= filled; + } + } + } + + @Override + protected void updateSlots() { + IItemHandlerModifiable inv = getInventoriesForInput(); + for (int i = 0; i < inv.getSlots(); i++) { + 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 + protected boolean checkRecipe() { + if (!(this instanceof ProcessingLogicHost)) { + return false; + } + ProcessingLogic logic = ((ProcessingLogicHost) this).getProcessingLogic(); + logic.clear(); + boolean result = false; + if (isSeparateInputs()) { + // TODO: Add separation with fluids + for (Pair inventory : getItemInputsForEachInventory()) { + IItemHandlerModifiable outputInventory = multiBlockOutputInventory + .getOrDefault(inventory.getLeft(), null); + result = logic.setInputItems(inventory.getLeft()) + .setCurrentOutputItems(getOutputItems()) + .process(); + if (result) { + inventoryName = inventory.getRight(); + break; + } + logic.clear(); + } + } else { + result = logic.setInputItems(getInputItems()) + .setCurrentOutputItems(getOutputItems()) + .setInputFluids(getInputFluids()) + .setCurrentOutputFluids(getOutputFluids()) + .process(); + } + setDuration(logic.getDuration()); + setEut(logic.getEut()); + setItemOutputs(logic.getOutputItems()); + setFluidOutputs(logic.getOutputFluids()); + return result; + } + + public IItemHandlerModifiable getOutputInventory() { + return outputInventory; + } + + public FluidTankGT[] getOutputTanks() { + return outputTanks; + } + + /* + * GUI Work - Multiblock GUI related methods + */ + @Override + public boolean useModularUI() { + return true; + } + + @Override + public ModularWindow createWindow(UIBuildContext buildContext) { + System.out.println("MultiBlockController::createWindow"); + if (!useModularUI()) return null; + + buildContext.setValidator(getValidator()); + final ModularWindow.Builder builder = ModularWindow.builder(getGUIWidth(), getGUIHeight()); + builder.setBackground(getGUITextureSet().getMainBackground()); + builder.setGuiTint(getGUIColorization()); + if (doesBindPlayerInventory()) { + bindPlayerInventoryUI(builder, buildContext); + } + addUIWidgets(builder, buildContext); + addTitleToUI(builder); + addCoverTabs(builder, buildContext); + return builder.build(); + } + + @Override + public boolean hasGui(byte aSide) { + return true; + } + + @Override + protected void addTitleTextStyle(ModularWindow.Builder builder, String title) { + // leave empty + } + + @Override + public int getGUIHeight() { + return 192; + } + + protected Widget getGregTechLogo() { + return new DrawableWidget().setDrawable(getGUITextureSet().getGregTechLogo()) + .setSize(17, 17); + } + + @Override + public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) { + if (isServerSide()) { + for (UpgradeCasing tPart : upgradeCasings) { + if (!(tPart instanceof Inventory)) continue; + tPart.issueClientUpdate(); + } + } + int page = 0; + TabContainer tabs = new TabContainer().setButtonSize(20, 24); + tabs.addTabButton( + new TabButton(page++) + .setBackground( + false, + ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0, 1f, 0.5f), + new ItemDrawable(getStackForm(1)).withFixedSize(16, 16) + .withOffset(2, 4)) + .setBackground( + true, + ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0.5f, 1f, 1f), + new ItemDrawable(getStackForm(1)).withFixedSize(16, 16) + .withOffset(2, 4)) + .addTooltip(getLocalName()) + .setPos(20 * (page - 1), -20)) + .addPage(createMainPage().setSize(getGUIWidth(), getGUIHeight())); + if (hasItemInput()) { + tabs.addTabButton( + new TabButton(page++) + .setBackground( + false, + 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_MIDDLE.getSubArea(0, 0.5f, 1f, 1f), + GT_UITextures.PICTURE_ITEM_IN.withFixedSize(16, 16) + .withOffset(2, 4)) + .setPos(20 * (page - 1), -20)) + .addPage( + new MultiChildWidget().addChild(getItemInventoryInputGUI()) + .addChild(getGregTechLogo().setPos(147, 86)) + .setSize(getGUIWidth(), getGUIHeight())); + } + + if (hasItemOutput()) { + tabs.addTabButton( + new TabButton(page++) + .setBackground( + false, + 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_MIDDLE.getSubArea(0, 0.5f, 1f, 1f), + GT_UITextures.PICTURE_ITEM_OUT.withFixedSize(16, 16) + .withOffset(2, 4)) + .setPos(20 * (page - 1), -20)) + .addPage( + new MultiChildWidget().addChild(getItemInventoryOutputGUI()) + .addChild(getGregTechLogo().setPos(147, 86)) + .setSize(getGUIWidth(), getGUIHeight())); + } + + if (hasFluidInput()) { + tabs.addTabButton( + new TabButton(page++) + .setBackground( + false, + 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_MIDDLE.getSubArea(0, 0.5f, 1f, 1f), + GT_UITextures.PICTURE_FLUID_IN.withFixedSize(16, 16) + .withOffset(2, 4)) + .setPos(20 * (page - 1), -20)) + .addPage( + new MultiChildWidget().addChild(getFluidInventoryInputGUI()) + .addChild(getGregTechLogo().setPos(147, 86)) + .setSize(getGUIWidth(), getGUIHeight())); + } + + if (hasFluidOutput()) { + tabs.addTabButton( + new TabButton(page++) + .setBackground( + false, + 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_MIDDLE.getSubArea(0, 0.5f, 1f, 1f), + GT_UITextures.PICTURE_FLUID_OUT.withFixedSize(16, 16) + .withOffset(2, 4)) + .setPos(20 * (page - 1), -20)) + .addPage( + new MultiChildWidget().addChild(getFluidInventoryOutputGUI()) + .addChild(getGregTechLogo().setPos(147, 86)) + .setSize(getGUIWidth(), getGUIHeight())); + } + builder.widget(tabs); + } + + protected MultiChildWidget createMainPage() { + MultiChildWidget page = new MultiChildWidget(); + page.addChild( + new DrawableWidget().setDrawable(GT_UITextures.PICTURE_SCREEN_BLACK) + .setPos(7, 4) + .setSize(160, 75)) + .addChild(createButtons()); + return page; + } + + protected MultiChildWidget createButtons() { + MultiChildWidget buttons = new MultiChildWidget(); + buttons.setSize(16, 167) + .setPos(7, 86); + buttons.addChild(createPowerSwitchButton()) + .addChild(new FakeSyncWidget.BooleanSyncer(this::isAllowedToWork, val -> { + if (val) enableWorking(); + else disableWorking(); + })) + .addChild(createVoidExcessButton()) + .addChild(new FakeSyncWidget.BooleanSyncer(() -> voidExcess, val -> voidExcess = val)) + .addChild(createInputSeparationButton()) + .addChild(new FakeSyncWidget.BooleanSyncer(() -> separateInputs, val -> separateInputs = val)) + .addChild(createBatchModeButton()) + .addChild(new FakeSyncWidget.BooleanSyncer(() -> batchMode, val -> batchMode = val)) + .addChild(createLockToSingleRecipeButton()) + .addChild(new FakeSyncWidget.BooleanSyncer(() -> recipeLock, val -> recipeLock = val)); + + return buttons; + } + + protected Widget getItemInventoryInputGUI() { + final IItemHandlerModifiable inv = getInventoriesForInput(); + final Scrollable scrollable = new Scrollable().setVerticalScroll(); + for (int rows = 0; rows * 4 < Math.min(inv.getSlots(), 128); rows++) { + final int columnsToMake = Math.min(Math.min(inv.getSlots(), 128) - rows * 4, 4); + for (int column = 0; column < columnsToMake; column++) { + scrollable.widget( + new SlotWidget(inv, rows * 4 + column).setPos(column * 18, rows * 18) + .setSize(18, 18)); + } + } + return scrollable.setSize(18 * 4 + 4, 18 * 5) + .setPos(52, 7); + } + + protected Widget getItemInventoryOutputGUI() { + final IItemHandlerModifiable inv = getInventoriesForOutput(); + final Scrollable scrollable = new Scrollable().setVerticalScroll(); + for (int rows = 0; rows * 4 < Math.min(inv.getSlots(), 128); rows++) { + final int columnsToMake = Math.min(Math.min(inv.getSlots(), 128) - rows * 4, 4); + for (int column = 0; column < columnsToMake; column++) { + scrollable.widget( + new SlotWidget(inv, rows * 4 + column).setPos(column * 18, rows * 18) + .setSize(18, 18)); + } + } + return scrollable.setSize(18 * 4 + 4, 18 * 5) + .setPos(52, 7); + } + + protected IItemHandlerModifiable getInventoriesForInput() { + return new ListItemHandler(multiBlockInputInventory.values()); + } + + protected IItemHandlerModifiable getInventoriesForOutput() { + return new ListItemHandler(multiBlockOutputInventory.values()); + } + + protected Widget getFluidInventoryInputGUI() { + 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); + for (int column = 0; column < columnsToMake; column++) { + final FluidSlotWidget fluidSlot = new FluidSlotWidget(tanks[rows * 4 + column]); + scrollable.widget( + fluidSlot.setPos(column * 18, rows * 18) + .setSize(18, 18)); + } + } + return scrollable.setSize(18 * 4 + 4, 18 * 5) + .setPos(52, 7); + } + + protected Widget getFluidInventoryOutputGUI() { + 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); + for (int column = 0; column < columnsToMake; column++) { + final FluidSlotWidget fluidSlot = new FluidSlotWidget(tanks[rows * 4 + column]); + fluidSlot.setInteraction(true, false); + scrollable.widget( + fluidSlot.setPos(column * 18, rows * 18) + .setSize(18, 18)); + } + } + return scrollable.setSize(18 * 4 + 4, 18 * 5) + .setPos(52, 7); + } + + protected ButtonWidget createPowerSwitchButton() { + ButtonWidget button = new ButtonWidget().setOnClick((clickData, widget) -> { + if (isAllowedToWork()) { + disableWorking(); + } else { + enableWorking(); + } + }) + .setPlayClickSoundResource( + () -> isAllowedToWork() ? SoundResource.GUI_BUTTON_UP.resourceLocation + : SoundResource.GUI_BUTTON_DOWN.resourceLocation); + button.setBackground(() -> { + List ret = new ArrayList<>(); + ret.add(GT_UITextures.BUTTON_STANDARD); + if (isAllowedToWork()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_POWER_SWITCH_ON); + } else { + ret.add(GT_UITextures.OVERLAY_BUTTON_POWER_SWITCH_OFF); + } + return ret.toArray(new IDrawable[0]); + }) + .setPos(144, 0) + .setSize(16, 16); + button.addTooltip(StatCollector.translateToLocal("GT5U.gui.button.power_switch")) + .setTooltipShowUpDelay(TOOLTIP_DELAY); + return button; + } + + protected ButtonWidget createVoidExcessButton() { + ButtonWidget button = new ButtonWidget().setOnClick((clickData, widget) -> { + if (isVoidExcessButtonEnabled()) { + voidExcess = !voidExcess; + } + }) + .setPlayClickSound(true); + button.setBackground(() -> { + List ret = new ArrayList<>(); + ret.add(GT_UITextures.BUTTON_STANDARD); + if (isVoidExcessButtonEnabled()) { + if (isVoidExcessEnabled()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_VOID_EXCESS_ON); + } else { + ret.add(GT_UITextures.OVERLAY_BUTTON_VOID_EXCESS_OFF); + } + } else { + if (isVoidExcessEnabled()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_VOID_EXCESS_ON_DISABLED); + } else { + ret.add(GT_UITextures.OVERLAY_BUTTON_VOID_EXCESS_OFF_DISABLED); + } + } + return ret.toArray(new IDrawable[0]); + }) + .setPos(54, 0) + .setSize(16, 16); + button.addTooltip(StatCollector.translateToLocal("GT5U.gui.button.void_excess")) + .setTooltipShowUpDelay(TOOLTIP_DELAY); + return button; + } + + protected boolean isVoidExcessEnabled() { + return voidExcess; + } + + protected boolean isVoidExcessButtonEnabled() { + return true; + } + + protected ButtonWidget createInputSeparationButton() { + Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { + if (isInputSeparationButtonEnabled()) { + separateInputs = !separateInputs; + } + }) + .setPlayClickSound(true) + .setBackground(() -> { + List ret = new ArrayList<>(); + ret.add(GT_UITextures.BUTTON_STANDARD); + if (isInputSeparationButtonEnabled()) { + if (isInputSeparationEnabled()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_INPUT_SEPARATION_ON); + } else { + ret.add(GT_UITextures.OVERLAY_BUTTON_INPUT_SEPARATION_OFF); + } + } else { + if (isInputSeparationEnabled()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_INPUT_SEPARATION_ON_DISABLED); + } else { + ret.add(GT_UITextures.OVERLAY_BUTTON_INPUT_SEPARATION_OFF_DISABLED); + } + } + return ret.toArray(new IDrawable[0]); + }) + .setPos(36, 0) + .setSize(16, 16); + button.addTooltip(StatCollector.translateToLocal("GT5U.gui.button.input_separation")) + .setTooltipShowUpDelay(TOOLTIP_DELAY); + return (ButtonWidget) button; + } + + protected boolean isInputSeparationEnabled() { + return separateInputs; + } + + protected boolean isInputSeparationButtonEnabled() { + return true; + } + + protected ButtonWidget createBatchModeButton() { + Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { + if (isBatchModeButtonEnabled()) { + batchMode = !batchMode; + } + }) + .setPlayClickSound(true) + .setBackground(() -> { + List ret = new ArrayList<>(); + ret.add(GT_UITextures.BUTTON_STANDARD); + if (isBatchModeButtonEnabled()) { + if (isBatchModeEnabled()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_BATCH_MODE_ON); + } else { + ret.add(GT_UITextures.OVERLAY_BUTTON_BATCH_MODE_OFF); + } + } else { + if (isBatchModeEnabled()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_BATCH_MODE_ON_DISABLED); + } else { + ret.add(GT_UITextures.OVERLAY_BUTTON_BATCH_MODE_OFF_DISABLED); + } + } + return ret.toArray(new IDrawable[0]); + }) + .setPos(18, 0) + .setSize(16, 16); + button.addTooltip(StatCollector.translateToLocal("GT5U.gui.button.batch_mode")) + .setTooltipShowUpDelay(TOOLTIP_DELAY); + return (ButtonWidget) button; + } + + protected boolean isBatchModeButtonEnabled() { + return true; + } + + protected boolean isBatchModeEnabled() { + return batchMode; + } + + protected ButtonWidget createLockToSingleRecipeButton() { + Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { + if (supportsSingleRecipeLocking()) { + recipeLock = !recipeLock; + } + }) + .setPlayClickSound(true) + .setBackground(() -> { + List ret = new ArrayList<>(); + ret.add(GT_UITextures.BUTTON_STANDARD); + if (supportsSingleRecipeLocking()) { + if (isRecipeLockingEnabled()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_RECIPE_LOCKED); + } else { + ret.add(GT_UITextures.OVERLAY_BUTTON_RECIPE_UNLOCKED); + } + } else { + if (isRecipeLockingEnabled()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_RECIPE_LOCKED_DISABLED); + } else { + ret.add(GT_UITextures.OVERLAY_BUTTON_RECIPE_UNLOCKED_DISABLED); + } + } + return ret.toArray(new IDrawable[0]); + }) + .setPos(0, 0) + .setSize(16, 16); + button.addTooltip(StatCollector.translateToLocal("GT5U.gui.button.lock_recipe")) + .setTooltipShowUpDelay(TOOLTIP_DELAY); + return (ButtonWidget) button; + } + + protected boolean supportsSingleRecipeLocking() { + return false; + } + + 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 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/MultiBlockController.java b/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockController.java deleted file mode 100644 index 1355ac13a6..0000000000 --- a/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockController.java +++ /dev/null @@ -1,1709 +0,0 @@ -package gregtech.api.multitileentity.multiblock.base; - -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 java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; - -import net.minecraft.block.Block; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; -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.ForgeDirection; -import net.minecraftforge.fluids.Fluid; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.FluidTankInfo; -import net.minecraftforge.fluids.IFluidTank; - -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.apache.commons.lang3.tuple.Pair; -import org.lwjgl.input.Keyboard; - -import com.gtnewhorizon.structurelib.StructureLibAPI; -import com.gtnewhorizon.structurelib.alignment.IAlignment; -import com.gtnewhorizon.structurelib.alignment.IAlignmentLimits; -import com.gtnewhorizon.structurelib.alignment.constructable.IConstructable; -import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable; -import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing; -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.ISurvivalBuildEnvironment; -import com.gtnewhorizon.structurelib.util.Vec3Impl; -import com.gtnewhorizons.modularui.api.ModularUITextures; -import com.gtnewhorizons.modularui.api.drawable.IDrawable; -import com.gtnewhorizons.modularui.api.drawable.ItemDrawable; -import com.gtnewhorizons.modularui.api.drawable.UITexture; -import com.gtnewhorizons.modularui.api.forge.IItemHandlerModifiable; -import com.gtnewhorizons.modularui.api.forge.ItemStackHandler; -import com.gtnewhorizons.modularui.api.forge.ListItemHandler; -import com.gtnewhorizons.modularui.api.screen.*; -import com.gtnewhorizons.modularui.api.widget.Widget; -import com.gtnewhorizons.modularui.common.widget.ButtonWidget; -import com.gtnewhorizons.modularui.common.widget.DrawableWidget; -import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget; -import com.gtnewhorizons.modularui.common.widget.FluidSlotWidget; -import com.gtnewhorizons.modularui.common.widget.MultiChildWidget; -import com.gtnewhorizons.modularui.common.widget.Scrollable; -import com.gtnewhorizons.modularui.common.widget.SlotWidget; -import com.gtnewhorizons.modularui.common.widget.TabButton; -import com.gtnewhorizons.modularui.common.widget.TabContainer; - -import cpw.mods.fml.common.network.NetworkRegistry; -import gnu.trove.list.TIntList; -import gnu.trove.list.array.TIntArrayList; -import gregtech.api.enums.GT_Values; -import gregtech.api.enums.GT_Values.NBT; -import gregtech.api.enums.OrePrefixes; -import gregtech.api.enums.SoundResource; -import gregtech.api.enums.TextureSet; -import gregtech.api.fluid.FluidTankGT; -import gregtech.api.gui.modularui.GT_UITextures; -import gregtech.api.interfaces.IDescribable; -import gregtech.api.logic.PowerLogic; -import gregtech.api.logic.ProcessingLogic; -import gregtech.api.logic.interfaces.PowerLogicHost; -import gregtech.api.logic.interfaces.ProcessingLogicHost; -import gregtech.api.multitileentity.MultiTileEntityContainer; -import gregtech.api.multitileentity.MultiTileEntityRegistry; -import gregtech.api.multitileentity.interfaces.IMultiBlockController; -import gregtech.api.multitileentity.interfaces.IMultiBlockPart; -import gregtech.api.multitileentity.interfaces.IMultiTileEntity; -import gregtech.api.multitileentity.interfaces.IMultiTileEntity.IMTE_AddToolTips; -import gregtech.api.multitileentity.machine.MultiTileBasicMachine; -import gregtech.api.multitileentity.multiblock.casing.FunctionalCasing; -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; - -public abstract class MultiBlockController> extends MultiTileBasicMachine implements - IAlignment, IConstructable, IMultiBlockController, IDescribable, IMTE_AddToolTips, ISurvivalConstructable { - - private static final Map tooltip = new ConcurrentHashMap<>(); - private final List upgradeCasings = new ArrayList<>(); - private final List functionalCasings = new ArrayList<>(); - protected BuildState buildState = new BuildState(); - - protected Map multiBlockInputInventoryNames = new LinkedHashMap<>(); - protected Map multiBlockOutputInventoryNames = new LinkedHashMap<>(); - protected Map multiBlockInputInventoryToTankLink = new LinkedHashMap<>(); - protected Map multiBlockInputInventory = new LinkedHashMap<>(); - protected Map multiBlockOutputInventory = new LinkedHashMap<>(); - - protected Map multiBlockInputTankNames = new LinkedHashMap<>(); - protected Map multiBlockOutputTankNames = new LinkedHashMap<>(); - protected Map multiBlockInputTank = new LinkedHashMap<>(); - protected Map multiBlockOutputTank = new LinkedHashMap<>(); - - private boolean structureOkay = false, structureChanged = false; - private ExtendedFacing extendedFacing = ExtendedFacing.DEFAULT; - private IAlignmentLimits limits = getInitialAlignmentLimits(); - private String inventoryName; - private String tankName; - protected boolean separateInputs = false; - protected boolean voidExcess = false; - protected boolean batchMode = false; - protected boolean recipeLock = false; - - // A list of sides - // Each side has a list of parts that have a cover that need to be ticked - protected List>> registeredCoveredParts = Arrays.asList( - new LinkedList<>(), - new LinkedList<>(), - new LinkedList<>(), - new LinkedList<>(), - new LinkedList<>(), - new LinkedList<>()); - - /** Registry ID of the required casing */ - public abstract short getCasingRegistryID(); - - /** Meta ID of the required casing */ - public abstract short getCasingMeta(); - - /** - * Create the tooltip for this multi block controller. - */ - protected abstract GT_Multiblock_Tooltip_Builder createTooltip(); - - /** - * @return The starting offset for the structure builder - */ - public abstract Vec3Impl getStartingStructureOffset(); - - /** - * Due to limitation of Java type system, you might need to do an unchecked cast. HOWEVER, the returned - * IStructureDefinition is expected to be evaluated against current instance only, and should not be used against - * other instances, even for those of the same class. - */ - @Override - public abstract IStructureDefinition getStructureDefinition(); - - /** - * Checks the Machine. - *

- * NOTE: If using `buildState` be sure to `startBuilding()` and either `endBuilding()` or `failBuilding()` - */ - public boolean checkMachine() { - double sum = 0; - for (FunctionalCasing casing : functionalCasings) { - sum += casing.getPartTier(); - } - tier = (int) Math.floor(sum / functionalCasings.size()); - // Maximum Energy stores will have a cap of 2 minute work time of current voltage - return tier > 0; - } - - @Override - public void writeMultiTileNBT(NBTTagCompound nbt) { - super.writeMultiTileNBT(nbt); - - nbt.setBoolean(NBT.STRUCTURE_OK, structureOkay); - nbt.setByte( - NBT.ROTATION, - (byte) extendedFacing.getRotation() - .getIndex()); - nbt.setByte( - NBT.FLIP, - (byte) extendedFacing.getFlip() - .getIndex()); - - saveUpgradeInventoriesToNBT(nbt); - } - - private void saveUpgradeInventoriesToNBT(NBTTagCompound nbt) { - final NBTTagList inputInvList = new NBTTagList(); - multiBlockInputInventory.forEach((id, inv) -> { - if (!id.equals("controller")) { - final NBTTagCompound tTag = new NBTTagCompound(); - tTag.setString(NBT.UPGRADE_INVENTORY_UUID, id); - tTag.setString(NBT.UPGRADE_INVENTORY_NAME, multiBlockInputInventoryNames.get(id)); - tTag.setInteger(NBT.UPGRADE_INVENTORY_SIZE, inv.getSlots()); - writeInventory(tTag, inv, NBT.INV_INPUT_LIST); - inputInvList.appendTag(tTag); - } - }); - final NBTTagList outputInvList = new NBTTagList(); - multiBlockOutputInventory.forEach((id, inv) -> { - if (!id.equals("controller")) { - final NBTTagCompound tTag = new NBTTagCompound(); - tTag.setString(NBT.UPGRADE_INVENTORY_UUID, id); - tTag.setString(NBT.UPGRADE_INVENTORY_NAME, multiBlockOutputInventoryNames.get(id)); - tTag.setInteger(NBT.UPGRADE_INVENTORY_SIZE, inv.getSlots()); - writeInventory(tTag, inv, NBT.INV_OUTPUT_LIST); - outputInvList.appendTag(tTag); - } - }); - nbt.setTag(NBT.UPGRADE_INVENTORIES_INPUT, inputInvList); - nbt.setTag(NBT.UPGRADE_INVENTORIES_OUTPUT, outputInvList); - } - - @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); - - structureOkay = nbt.getBoolean(NBT.STRUCTURE_OK); - extendedFacing = ExtendedFacing.of( - ForgeDirection.getOrientation(getFrontFacing()), - Rotation.byIndex(nbt.getByte(NBT.ROTATION)), - Flip.byIndex(nbt.getByte(NBT.FLIP))); - - loadUpgradeInventoriesFromNBT(nbt); - } - - private void loadUpgradeInventoriesFromNBT(NBTTagCompound nbt) { - final NBTTagList listInputInventories = nbt.getTagList(NBT.UPGRADE_INVENTORIES_INPUT, 10); - for (int i = 0; i < listInputInventories.tagCount(); i++) { - final NBTTagCompound nbtInv = listInputInventories.getCompoundTagAt(i); - String invUUID = nbtInv.getString(NBT.UPGRADE_INVENTORY_UUID); - String invName = nbtInv.getString(NBT.UPGRADE_INVENTORY_NAME); - 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); - } - - final NBTTagList listOutputInventories = nbt.getTagList(NBT.UPGRADE_INVENTORIES_OUTPUT, 10); - for (int i = 0; i < listOutputInventories.tagCount(); i++) { - final NBTTagCompound nbtInv = listOutputInventories.getCompoundTagAt(i); - String invUUID = nbtInv.getString(NBT.UPGRADE_INVENTORY_UUID); - String invName = nbtInv.getString(NBT.UPGRADE_INVENTORY_NAME); - 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); - } - } - - @Override - public void addToolTips(List aList, ItemStack aStack, boolean aF3_H) { - aList.addAll(Arrays.asList(getDescription())); - } - - @Override - public String[] getDescription() { - if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) { - return getTooltip().getStructureInformation(); - } else { - return getTooltip().getInformation(); - } - } - - @Override - protected void addDebugInfo(EntityPlayer aPlayer, int aLogLevel, ArrayList tList) { - super.addDebugInfo(aPlayer, aLogLevel, tList); - tList.add("Structure ok: " + checkStructure(false)); - } - - protected int getToolTipID() { - return getMultiTileEntityRegistryID() << 16 + getMultiTileEntityID(); - } - - protected GT_Multiblock_Tooltip_Builder getTooltip() { - return createTooltip(); - } - - @Override - public boolean checkStructure(boolean aForceReset) { - if (!isServerSide()) return structureOkay; - - // Only trigger an update if forced (from onPostTick, generally), or if the structure has changed - if ((structureChanged || aForceReset)) { - structureOkay = checkMachine(); - } - structureChanged = false; - return structureOkay; - } - - @Override - public void onStructureChange() { - structureChanged = true; - } - - public final boolean checkPiece(String piece, Vec3Impl offset) { - return checkPiece(piece, offset.get0(), offset.get1(), offset.get2()); - } - - /** - * Explanation of the world coordinate these offset means: - *

- * Imagine you stand in front of the controller, with controller facing towards you not rotated or flipped. - *

- * The horizontalOffset would be the number of blocks on the left side of the controller, not counting controller - * itself. The verticalOffset would be the number of blocks on the top side of the controller, not counting - * controller itself. The depthOffset would be the number of blocks between you and controller, not counting - * controller itself. - *

- * All these offsets can be negative. - */ - protected final boolean checkPiece(String piece, int horizontalOffset, int verticalOffset, int depthOffset) { - return getCastedStructureDefinition().check( - this, - piece, - getWorld(), - getExtendedFacing(), - getXCoord(), - getYCoord(), - getZCoord(), - horizontalOffset, - verticalOffset, - depthOffset, - !structureOkay); - } - - public final boolean buildPiece(String piece, ItemStack trigger, boolean hintsOnly, Vec3Impl offset) { - return buildPiece(piece, trigger, hintsOnly, offset.get0(), offset.get1(), offset.get2()); - } - - protected final boolean buildPiece(String piece, ItemStack trigger, boolean hintOnly, int horizontalOffset, - int verticalOffset, int depthOffset) { - return getCastedStructureDefinition().buildOrHints( - this, - trigger, - piece, - getWorld(), - getExtendedFacing(), - getXCoord(), - getYCoord(), - getZCoord(), - horizontalOffset, - verticalOffset, - depthOffset, - hintOnly); - } - - protected final int survivalBuildPiece(String piece, ItemStack trigger, Vec3Impl offset, int elementBudget, - ISurvivalBuildEnvironment env, boolean check) { - return survivalBuildPiece( - piece, - trigger, - offset.get0(), - offset.get1(), - offset.get2(), - elementBudget, - env, - check); - } - - protected final Integer survivalBuildPiece(String piece, ItemStack trigger, int horizontalOffset, - int verticalOffset, int depthOffset, int elementBudget, ISurvivalBuildEnvironment env, boolean check) { - return getCastedStructureDefinition().survivalBuild( - this, - trigger, - piece, - getWorld(), - getExtendedFacing(), - getXCoord(), - getYCoord(), - getZCoord(), - horizontalOffset, - verticalOffset, - depthOffset, - elementBudget, - env, - check); - } - - @SuppressWarnings("unchecked") - private IStructureDefinition> getCastedStructureDefinition() { - return (IStructureDefinition>) getStructureDefinition(); - } - - @Override - public ExtendedFacing getExtendedFacing() { - return extendedFacing; - } - - @Override - public void setExtendedFacing(ExtendedFacing newExtendedFacing) { - if (extendedFacing != newExtendedFacing) { - onStructureChange(); - if (structureOkay) stopMachine(false); - extendedFacing = newExtendedFacing; - structureOkay = false; - if (isServerSide()) { - StructureLibAPI.sendAlignment( - this, - new NetworkRegistry.TargetPoint( - getWorld().provider.dimensionId, - getXCoord(), - getYCoord(), - getZCoord(), - 512)); - } else { - issueTextureUpdate(); - } - } - } - - @Override - public boolean onWrenchRightClick(EntityPlayer aPlayer, ItemStack tCurrentItem, byte wrenchSide, float aX, float aY, - float aZ) { - if (wrenchSide != getFrontFacing()) - return super.onWrenchRightClick(aPlayer, tCurrentItem, wrenchSide, aX, aY, aZ); - if (aPlayer.isSneaking()) { - // we won't be allowing horizontal flips, as it can be perfectly emulated by rotating twice and flipping - // horizontally allowing an extra round of flip make it hard to draw meaningful flip markers in - // GT_Proxy#drawGrid - toolSetFlip(getFlip().isHorizontallyFlipped() ? Flip.NONE : Flip.HORIZONTAL); - } else { - toolSetRotation(null); - } - return true; - } - - @Override - public void registerCoveredPartOnSide(final int aSide, IMultiBlockPart part) { - if (aSide < 0 || aSide >= 6) return; - - final LinkedList> registeredCovers = registeredCoveredParts.get(aSide); - // TODO: Make sure that we're not already registered on this side - registeredCovers.add(new WeakReference<>(part)); - } - - @Override - public void unregisterCoveredPartOnSide(final int aSide, IMultiBlockPart aPart) { - if (aSide < 0 || aSide >= 6) return; - - final LinkedList> coveredParts = registeredCoveredParts.get(aSide); - final Iterator> it = coveredParts.iterator(); - while (it.hasNext()) { - final IMultiBlockPart part = (it.next()).get(); - if (part == null || part == aPart) it.remove(); - } - } - - @Override - public void onFirstTick(boolean isServerSide) { - super.onFirstTick(isServerSide); - if (isServerSide) { - checkStructure(true); - } else { - StructureLibAPI.queryAlignment(this); - } - } - - private boolean tickCovers() { - for (byte side : ALL_VALID_SIDES) { - // TODO: Tick controller covers, if any - final LinkedList> coveredParts = this.registeredCoveredParts.get(side); - final Iterator> it = coveredParts.iterator(); - while (it.hasNext()) { - final IMultiBlockPart part = (it.next()).get(); - if (part == null) { - it.remove(); - continue; - } - if (!part.tickCoverAtSide(side, mTickTimer)) it.remove(); - } - } - - return true; - } - - @Override - public void onTick(long timer, boolean isServerSide) { - if (!tickCovers()) { - return; - } - } - - @Override - public void onPostTick(long tick, boolean isServerSide) { - if (isServerSide) { - if (tick % 600 == 5) { - clearSpecialLists(); - // Recheck the structure every 30 seconds or so - if (!checkStructure(false)) checkStructure(true); - } - if (structureOkay) { - runMachine(tick); - } else { - stopMachine(false); - } - } else { - doActivitySound(getActivitySoundLoop()); - } - } - - protected void clearSpecialLists() { - upgradeCasings.clear(); - } - - @Override - public final boolean isFacingValid(byte aFacing) { - return canSetToDirectionAny(ForgeDirection.getOrientation(aFacing)); - } - - @Override - public void onFacingChange() { - toolSetDirection(ForgeDirection.getOrientation(getFrontFacing())); - onStructureChange(); - } - - @Override - public boolean allowCoverOnSide(byte aSide, GT_ItemStack aCoverID) { - return aSide != facing; - } - - @Override - public String[] getStructureDescription(ItemStack stackSize) { - return getTooltip().getStructureHint(); - } - - @Override - public IAlignmentLimits getAlignmentLimits() { - return limits; - } - - protected void setAlignmentLimits(IAlignmentLimits mLimits) { - this.limits = mLimits; - } - - // IMachineProgress - @Override - public long getProgress() { - return progressTime; - } - - @Override - public long getMaxProgress() { - return maxProgressTime; - } - - @Override - public boolean increaseProgress(int aProgressAmountInTicks) { - return increaseProgressGetOverflow(aProgressAmountInTicks) != aProgressAmountInTicks; - } - - @Override - public FluidStack getDrainableFluid(byte aSide) { - final IFluidTank tank = getFluidTankDrainable(aSide, null); - return tank == null ? null : tank.getFluid(); - } - - /** - * Increases the Progress, returns the overflown Progress. - */ - public int increaseProgressGetOverflow(int aProgress) { - return 0; - } - - @Override - public boolean hasThingsToDo() { - return getMaxProgress() > 0; - } - - public boolean isSeparateInputs() { - return separateInputs; - } - - public void setSeparateInputs(boolean aSeparateInputs) { - separateInputs = aSeparateInputs; - } - - // End IMachineProgress - - protected IAlignmentLimits getInitialAlignmentLimits() { - return (d, r, f) -> !f.isVerticallyFliped(); - } - - public static class BuildState { - - /** - * Utility class to keep track of the build state of a multiblock - */ - boolean building = false; - - Vec3Impl currentOffset; - - public void startBuilding(Vec3Impl structureOffset) { - if (building) throw new IllegalStateException("Already building!"); - building = true; - setCurrentOffset(structureOffset); - } - - public Vec3Impl setCurrentOffset(Vec3Impl structureOffset) { - verifyBuilding(); - return (currentOffset = structureOffset); - } - - private void verifyBuilding() { - if (!building) throw new IllegalStateException("Not building!"); - } - - public boolean failBuilding() { - building = false; - currentOffset = null; - return false; - } - - public Vec3Impl stopBuilding() { - final Vec3Impl toReturn = getCurrentOffset(); - building = false; - currentOffset = null; - - return toReturn; - } - - public Vec3Impl getCurrentOffset() { - verifyBuilding(); - return currentOffset; - } - - public Vec3Impl addOffset(Vec3Impl offset) { - verifyBuilding(); - return setCurrentOffset(currentOffset.add(offset)); - } - } - - public IStructureElement addMultiTileCasing(String registryName, int meta, int modes) { - MultiTileEntityRegistry registry = MultiTileEntityRegistry.getRegistry(registryName); - int registryID = Block.getIdFromBlock(registry.mBlock); - return addMultiTileCasing(registryID, meta, modes); - } - - public IStructureElement addMultiTileCasing(int registryID, int meta, int modes) { - return new IStructureElement() { - - private final short[] DEFAULT = new short[] { 255, 255, 255, 0 }; - private IIcon[] mIcons = null; - - @Override - public boolean check(S t, World world, int x, int y, int z) { - final TileEntity tileEntity = world.getTileEntity(x, y, z); - if (!(tileEntity instanceof MultiBlockPart part)) return false; - - if (registryID != part.getMultiTileEntityRegistryID() || meta != part.getMultiTileEntityID()) - return false; - - final IMultiBlockController tTarget = part.getTarget(false); - if (tTarget != null && tTarget != MultiBlockController.this) return false; - - part.setTarget(MultiBlockController.this, modes); - - registerSpecialCasings(part); - return true; - } - - @Override - public boolean spawnHint(S t, World world, int x, int y, int z, ItemStack trigger) { - if (mIcons == null) { - mIcons = new IIcon[6]; - Arrays.fill(mIcons, TextureSet.SET_NONE.mTextures[OrePrefixes.block.mTextureIndex].getIcon()); - // Arrays.fill(mIcons, getTexture(aCasing); - // for (byte i : ALL_VALID_SIDES) { - // mIcons[i] = aCasing.getIcon(i, aMeta); - // } - } - final short[] RGBA = DEFAULT; - StructureLibAPI.hintParticleTinted(world, x, y, z, mIcons, RGBA); - // StructureLibAPI.hintParticle(world, x, y, z, aCasing, aMeta); - return true; - } - - @Override - public boolean placeBlock(S t, World world, int x, int y, int z, ItemStack trigger) { - final MultiTileEntityRegistry tRegistry = MultiTileEntityRegistry.getRegistry(registryID); - final MultiTileEntityContainer tContainer = tRegistry - .getNewTileEntityContainer(world, x, y, z, meta, null); - if (tContainer == null) { - GT_FML_LOGGER.error("NULL CONTAINER"); - return false; - } - final IMultiTileEntity te = ((IMultiTileEntity) tContainer.mTileEntity); - if (!(te instanceof MultiBlockPart)) { - GT_FML_LOGGER.error("Not a multiblock part"); - return false; - } - if (world.setBlock(x, y, z, tContainer.mBlock, 15 - tContainer.mBlockMetaData, 2)) { - tContainer.setMultiTile(world, x, y, z); - ((MultiBlockPart) te).setTarget(MultiBlockController.this, modes); - - registerSpecialCasings((MultiBlockPart) te); - } - - return false; - } - - public IIcon getTexture(OrePrefixes aBlock) { - return TextureSet.SET_NONE.mTextures[OrePrefixes.block.mTextureIndex].getIcon(); - } - }; - } - - protected void registerSpecialCasings(MultiBlockPart part) { - if (part instanceof UpgradeCasing) { - upgradeCasings.add((UpgradeCasing) part); - } - if (part instanceof FunctionalCasing) { - functionalCasings.add((FunctionalCasing) part); - } - } - - /** - * Fluid - MultiBlock related Fluid Tank behaviour. - */ - protected IFluidTank getFluidTankFillable(MultiBlockPart aPart, byte aSide, FluidStack aFluidToFill) { - return getFluidTankFillable(aSide, aFluidToFill); - } - - protected IFluidTank getFluidTankDrainable(MultiBlockPart aPart, byte aSide, FluidStack aFluidToDrain) { - return getFluidTankDrainable(aSide, aFluidToDrain); - } - - protected IFluidTank[] getFluidTanks(MultiBlockPart aPart, byte aSide) { - return getFluidTanks(aSide); - } - - @Override - public int fill(MultiBlockPart aPart, ForgeDirection aDirection, FluidStack aFluid, boolean aDoFill) { - if (aFluid == null || aFluid.amount <= 0) return 0; - final IFluidTank tTank = getFluidTankFillable(aPart, (byte) aDirection.ordinal(), aFluid); - if (tTank == null) return 0; - final int rFilledAmount = tTank.fill(aFluid, aDoFill); - if (rFilledAmount > 0 && aDoFill) hasInventoryChanged = true; - return rFilledAmount; - } - - @Override - public FluidStack drain(MultiBlockPart aPart, ForgeDirection aDirection, FluidStack aFluid, boolean aDoDrain) { - if (aFluid == null || aFluid.amount <= 0) return null; - final IFluidTank tTank = getFluidTankDrainable(aPart, (byte) aDirection.ordinal(), aFluid); - if (tTank == null || tTank.getFluid() == null - || tTank.getFluidAmount() == 0 - || !tTank.getFluid() - .isFluidEqual(aFluid)) - return null; - final FluidStack rDrained = tTank.drain(aFluid.amount, aDoDrain); - if (rDrained != null && aDoDrain) markInventoryBeenModified(); - return rDrained; - } - - @Override - public FluidStack drain(MultiBlockPart aPart, ForgeDirection aDirection, int aAmountToDrain, boolean aDoDrain) { - if (aAmountToDrain <= 0) return null; - final IFluidTank tTank = getFluidTankDrainable(aPart, (byte) aDirection.ordinal(), null); - if (tTank == null || tTank.getFluid() == null || tTank.getFluidAmount() == 0) return null; - final FluidStack rDrained = tTank.drain(aAmountToDrain, aDoDrain); - if (rDrained != null && aDoDrain) markInventoryBeenModified(); - return rDrained; - } - - @Override - public boolean canFill(MultiBlockPart aPart, ForgeDirection aDirection, Fluid aFluid) { - if (aFluid == null) return false; - final IFluidTank tTank = getFluidTankFillable(aPart, (byte) aDirection.ordinal(), new FluidStack(aFluid, 0)); - return tTank != null && (tTank.getFluid() == null || tTank.getFluid() - .getFluid() == aFluid); - } - - @Override - public boolean canDrain(MultiBlockPart aPart, ForgeDirection aDirection, Fluid aFluid) { - if (aFluid == null) return false; - final IFluidTank tTank = getFluidTankDrainable(aPart, (byte) aDirection.ordinal(), new FluidStack(aFluid, 0)); - return tTank != null && (tTank.getFluid() != null && tTank.getFluid() - .getFluid() == aFluid); - } - - @Override - public FluidTankInfo[] getTankInfo(MultiBlockPart aPart, ForgeDirection aDirection) { - final IFluidTank[] tTanks = getFluidTanks(aPart, (byte) aDirection.ordinal()); - if (tTanks == null || tTanks.length <= 0) return GT_Values.emptyFluidTankInfo; - final FluidTankInfo[] rInfo = new FluidTankInfo[tTanks.length]; - for (int i = 0; i < tTanks.length; i++) rInfo[i] = new FluidTankInfo(tTanks[i]); - return rInfo; - } - - @Override - public IFluidTank[] getFluidTanksForGUI(MultiBlockPart aPart) { - if (aPart.modeSelected(MultiBlockPart.FLUID_IN)) return inputTanks; - if (aPart.modeSelected(MultiBlockPart.FLUID_OUT)) return outputTanks; - return GT_Values.emptyFluidTank; - } - - // #region Energy - @Override - public PowerLogic getPowerLogic(IMultiBlockPart part, byte side) { - if (!(this instanceof PowerLogicHost)) { - return null; - } - - if (part.getFrontFacing() != side) { - return null; - } - - return ((PowerLogicHost) this).getPowerLogic(side); - } - // #endregion Energy - - /** - * Item - MultiBlock related Item behaviour. - */ - @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); - } - if (aType == InventoryUpgrade.OUTPUT || aType == InventoryUpgrade.BOTH) { - if (multiBlockOutputInventory.containsKey(aID)) return; - multiBlockOutputInventory.put(aID, new ItemStackHandler(aInventorySize)); - multiBlockOutputInventoryNames.put(aID, aName); - } - } - - @Override - public void unregisterInventory(String aName, String aID, int aType) { - if ((aType == InventoryUpgrade.INPUT || aType == InventoryUpgrade.BOTH) - && multiBlockInputInventory.containsKey(aID)) { - multiBlockInputInventory.remove(aID, multiBlockInputInventory.get(aID)); - multiBlockInputInventoryNames.remove(aID, aName); - } - if ((aType == InventoryUpgrade.OUTPUT || aType == InventoryUpgrade.BOTH) - && multiBlockOutputInventory.containsKey(aID)) { - multiBlockOutputInventory.remove(aID, multiBlockOutputInventory.get(aID)); - multiBlockOutputInventoryNames.remove(aID, aName); - } - } - - @Override - public void changeInventoryName(String aName, String aID, int aType) { - if ((aType == InventoryUpgrade.INPUT || aType == InventoryUpgrade.BOTH) - && multiBlockInputInventoryNames.containsKey(aID)) { - multiBlockInputInventoryNames.put(aID, aName); - } - if ((aType == InventoryUpgrade.OUTPUT || aType == InventoryUpgrade.BOTH) - && multiBlockOutputInventoryNames.containsKey(aID)) { - multiBlockOutputInventoryNames.put(aID, aName); - } - } - - @Override - public boolean hasInventoryBeenModified(MultiBlockPart aPart) { - if (aPart.modeSelected(MultiBlockPart.ITEM_IN)) return hasInventoryBeenModified(); - else if (aPart.modeSelected(MultiBlockPart.ITEM_OUT)) return hasOutputInventoryBeenModified(); - - return false; - } - - @Override - public boolean isValidSlot(MultiBlockPart aPart, int aIndex) { - return false; - } - - @Override - public IItemHandlerModifiable getInventoryForGUI(MultiBlockPart aPart) { - if (isServerSide()) { - for (UpgradeCasing tPart : upgradeCasings) { - if (!(tPart instanceof InventoryUpgrade)) continue; - tPart.issueClientUpdate(); - } - } - final Map multiBlockInventory = getMultiBlockInventory(aPart); - if (multiBlockInventory == null) return null; - - final String lockedInventory = aPart.getLockedInventory(); - if (lockedInventory == null) { - return new ListItemHandler(multiBlockInventory.values()); - } else { - final IItemHandlerModifiable inv = multiBlockInventory.get(lockedInventory); - return inv != null ? inv : null; - } - } - - @Override - public boolean addStackToSlot(MultiBlockPart aPart, int aIndex, ItemStack aStack) { - return false; - } - - @Override - public boolean addStackToSlot(MultiBlockPart aPart, int aIndex, ItemStack aStack, int aAmount) { - return false; - } - - protected Map getMultiBlockInventory(MultiBlockPart aPart) { - if (aPart.modeSelected(MultiBlockPart.ITEM_IN)) return multiBlockInputInventory; - else if (aPart.modeSelected(MultiBlockPart.ITEM_OUT)) return multiBlockOutputInventory; - return null; - } - - protected Map getMultiBlockInventoryNames(MultiBlockPart aPart) { - if (aPart.modeSelected(MultiBlockPart.ITEM_IN)) return multiBlockInputInventoryNames; - else if (aPart.modeSelected(MultiBlockPart.ITEM_OUT)) return multiBlockOutputInventoryNames; - return null; - } - - protected Pair getInventory(MultiBlockPart aPart, int aSlot) { - final Map multiBlockInventory = getMultiBlockInventory(aPart); - if (multiBlockInventory == null) return null; - - final String invName = aPart.getLockedInventory(); - if (invName != null && !invName.isEmpty()) return new ImmutablePair<>(multiBlockInventory.get(invName), aSlot); - - int start = 0; - for (IItemHandlerModifiable inv : multiBlockInventory.values()) { - if (aSlot >= start && aSlot < start + inv.getSlots()) { - return new ImmutablePair<>(inv, aSlot - start); - } - start += inv.getSlots(); - } - return null; - } - - @Override - public int[] getAccessibleSlotsFromSide(MultiBlockPart aPart, byte aSide) { - final TIntList tList = new TIntArrayList(); - final Map multiBlockInventory = getMultiBlockInventory(aPart); - if (multiBlockInventory == null) return tList.toArray(); - - final String lockedInventory = aPart.getLockedInventory(); - // Item in --> input inv - // Item out --> output inv - - int start = 0; - if (lockedInventory == null) { - for (IItemHandlerModifiable inv : multiBlockInventory.values()) { - for (int i = start; i < inv.getSlots() + start; i++) tList.add(i); - start += inv.getSlots(); - } - } else { - final IItemHandlerModifiable inv = multiBlockInventory.get(lockedInventory); - final int len = inv != null ? inv.getSlots() : 0; - for (int i = 0; i < len; i++) tList.add(i); - } - return tList.toArray(); - } - - @Override - public boolean canInsertItem(MultiBlockPart aPart, int aSlot, ItemStack aStack, byte aSide) { - final Pair tInv = getInventory(aPart, aSlot); - if (tInv == null) return false; - - final int tSlot = tInv.getRight(); - final IItemHandlerModifiable inv = tInv.getLeft(); - - return inv.getStackInSlot(tSlot) == null || GT_Utility.areStacksEqual(aStack, inv.getStackInSlot(tSlot)); // && - // allowPutStack(getBaseMetaTileEntity(), - // aIndex, - // (byte) - // aSide, - // aStack) - } - - @Override - public boolean canExtractItem(MultiBlockPart aPart, int aSlot, ItemStack aStack, byte aSide) { - final Pair tInv = getInventory(aPart, aSlot); - if (tInv == null) return false; - - final int tSlot = tInv.getRight(); - final IItemHandlerModifiable inv = tInv.getLeft(); - - return inv.getStackInSlot(tSlot) != null; // && allowPullStack(getBaseMetaTileEntity(), aIndex, (byte) aSide, - // aStack); - } - - @Override - public int getSizeInventory(MultiBlockPart aPart) { - final Map multiBlockInventory = getMultiBlockInventory(aPart); - if (multiBlockInventory == null) return 0; - - final String lockedInventory = aPart.getLockedInventory(); - if (lockedInventory == null) { - int len = 0; - for (IItemHandlerModifiable inv : multiBlockInventory.values()) len += inv.getSlots(); - return len; - } else { - final IItemHandlerModifiable inv = multiBlockInventory.get(lockedInventory); - return inv != null ? inv.getSlots() : 0; - } - } - - @Override - public ItemStack getStackInSlot(MultiBlockPart aPart, int aSlot) { - final Pair tInv = getInventory(aPart, aSlot); - if (tInv == null) return null; - - final int tSlot = tInv.getRight(); - final IItemHandlerModifiable inv = tInv.getLeft(); - if (inv == null) return null; - - return inv.getStackInSlot(tSlot); - } - - @Override - public ItemStack decrStackSize(MultiBlockPart aPart, int aSlot, int aDecrement) { - final ItemStack tStack = getStackInSlot(aPart, aSlot); - ItemStack rStack = GT_Utility.copyOrNull(tStack); - if (tStack != null) { - if (tStack.stackSize <= aDecrement) { - setInventorySlotContents(aPart, aSlot, null); - } else { - rStack = tStack.splitStack(aDecrement); - if (tStack.stackSize == 0) setInventorySlotContents(aPart, aSlot, null); - } - } - return rStack; - } - - @Override - public ItemStack getStackInSlotOnClosing(MultiBlockPart aPart, int aSlot) { - final Pair tInv = getInventory(aPart, aSlot); - if (tInv == null) return null; - - final IItemHandlerModifiable inv = tInv.getLeft(); - final int tSlot = tInv.getRight(); - - final ItemStack rStack = inv.getStackInSlot(tSlot); - inv.setStackInSlot(tSlot, null); - return rStack; - } - - @Override - public void setInventorySlotContents(MultiBlockPart aPart, int aSlot, ItemStack aStack) { - final Pair tInv = getInventory(aPart, aSlot); - if (tInv == null) return; - - final IItemHandlerModifiable inv = tInv.getLeft(); - final int tSlot = tInv.getRight(); - inv.setStackInSlot(tSlot, aStack); - } - - @Override - public List getInventoryNames(MultiBlockPart aPart) { - final List inventoryNames = new ArrayList<>(); - inventoryNames.add("all"); - inventoryNames.add("controller"); - inventoryNames.addAll(getMultiBlockInventoryNames(aPart).values()); - return inventoryNames; - } - - @Override - public List getInventoryIDs(MultiBlockPart aPart) { - final List tInventoryIDs = new ArrayList<>(); - tInventoryIDs.add("all"); - tInventoryIDs.addAll(getMultiBlockInventory(aPart).keySet()); - return tInventoryIDs; - } - - @Override - public String getInventoryName(MultiBlockPart aPart) { - final StringBuilder str = new StringBuilder(); - str.append(getInventoryName()); - if (aPart.modeSelected(MultiBlockPart.ITEM_IN)) { - str.append(" Input"); - } else if (aPart.modeSelected(MultiBlockPart.ITEM_OUT)) { - str.append(" Output"); - String a; - } else { - str.append(" Unknown"); - } - final String lockedInventory = aPart.getLockedInventory(); - if (lockedInventory != null && !lockedInventory.equals("")) { - str.append(" [Locked: ") - .append(lockedInventory) - .append("]"); - } - - return str.toString(); - } - - @Override - public boolean hasCustomInventoryName(MultiBlockPart aPart) { - return hasCustomInventoryName(); - } - - @Override - public int getInventoryStackLimit(MultiBlockPart aPart) { - return getInventoryStackLimit(); - } - - @Override - public void markDirty(MultiBlockPart aPart) { - markDirty(); - if (aPart.modeSelected(MultiBlockPart.ITEM_OUT)) markOutputInventoryBeenModified(); - else markInventoryBeenModified(); - } - - @Override - public boolean isUseableByPlayer(MultiBlockPart aPart, EntityPlayer aPlayer) { - return isUseableByPlayer(aPlayer); - } - - @Override - public void openInventory(MultiBlockPart aPart) { - // TODO: MultiInventory - consider the part's inventory - openInventory(); - } - - @Override - public void closeInventory(MultiBlockPart aPart) { - // TODO: MultiInventory - consider the part's inventory - closeInventory(); - } - - @Override - public boolean isItemValidForSlot(MultiBlockPart aPart, int aSlot, ItemStack aStack) { - return isItemValidForSlot(aSlot, aStack); - } - - /* - * Helper Methods For Recipe checking - */ - - protected ItemStack[] getAllItemInputs() { - return getInventoriesForInput().getStacks() - .toArray(new ItemStack[0]); - } - - protected ItemStack[] getAllOutputItems() { - return getInventoriesForOutput().getStacks() - .toArray(new ItemStack[0]); - } - - protected Iterable> getItemInputsForEachInventory() { - return multiBlockInputInventory.entrySet() - .stream() - .map( - (entry) -> Pair.of( - entry.getValue() - .getStacks() - .toArray(new ItemStack[0]), - entry.getKey())) - .collect(Collectors.toList()); - } - - protected void setItemOutputs(String inventory, ItemStack... itemOutputs) { - itemsToOutput = itemOutputs; - inventoryName = inventory; - } - - @Override - protected void setItemOutputs(ItemStack... outputs) { - super.setItemOutputs(outputs); - inventoryName = null; - } - - @Override - protected void outputItems() { - if (itemsToOutput == null) { - return; - } - - IItemHandlerModifiable inv; - if (inventoryName != null) { - inv = multiBlockOutputInventory.getOrDefault(inventoryName, getInventoriesForOutput()); - } else { - inv = getInventoriesForOutput(); - } - for (ItemStack item : itemsToOutput) { - int index = 0; - while (item != null && item.stackSize > 0 && index < inv.getSlots()) { - item = inv.insertItem(index++, item.copy(), false); - } - } - itemsToOutput = null; - } - - protected void setFluidOutputs(String tank, FluidStack... fluidOuputs) { - fluidsToOutput = fluidOuputs; - tankName = tank; - } - - @Override - protected void setFluidOutputs(FluidStack... outputs) { - super.setFluidOutputs(outputs); - tankName = null; - } - - @Override - protected void outputFluids() { - if (fluidsToOutput == null) { - return; - } - - List tanks = new ArrayList<>(multiBlockOutputTank.values()); - for (FluidStack fluid : fluidsToOutput) { - int index = 0; - while (fluid != null && fluid.amount > 0 && index < tanks.size()) { - int filled = tanks.get(index++) - .fill(fluid, true); - fluid.amount -= filled; - } - } - } - - @Override - protected void updateSlots() { - IItemHandlerModifiable inv = getInventoriesForInput(); - for (int i = 0; i < inv.getSlots(); i++) { - if (inv.getStackInSlot(i).stackSize <= 0) { - inv.setStackInSlot(i, null); - } - } - } - - @Override - protected boolean checkRecipe() { - if (!(this instanceof ProcessingLogicHost)) { - return false; - } - ProcessingLogic logic = ((ProcessingLogicHost) this).getProcessingLogic(); - logic.clear(); - boolean result = false; - if (isSeparateInputs()) { - for (Pair inventory : getItemInputsForEachInventory()) { - IItemHandlerModifiable outputInventory = multiBlockOutputInventory - .getOrDefault(inventory.getLeft(), null); - result = logic.setInputItems(inventory.getLeft()) - .setCurrentOutputItems( - outputInventory != null ? outputInventory.getStacks() - .toArray(new ItemStack[0]) : null) - .process(); - if (result) { - inventoryName = inventory.getRight(); - break; - } - logic.clear(); - } - } else { - result = logic.setInputItems(getAllItemInputs()) - .setCurrentOutputItems(getAllOutputItems()) - .process(); - } - setDuration(logic.getDuration()); - setEut(logic.getEut()); - setItemOutputs(logic.getOutputItems()); - setFluidOutputs(logic.getOutputFluids()); - return result; - } - - /* - * GUI Work - Multiblock GUI related methods - */ - @Override - public boolean useModularUI() { - return true; - } - - @Override - public ModularWindow createWindow(UIBuildContext buildContext) { - System.out.println("MultiBlockController::createWindow"); - if (!useModularUI()) return null; - - buildContext.setValidator(getValidator()); - final ModularWindow.Builder builder = ModularWindow.builder(getGUIWidth(), getGUIHeight()); - builder.setBackground(getGUITextureSet().getMainBackground()); - builder.setGuiTint(getGUIColorization()); - if (doesBindPlayerInventory()) { - bindPlayerInventoryUI(builder, buildContext); - } - addUIWidgets(builder, buildContext); - addTitleToUI(builder); - addCoverTabs(builder, buildContext); - return builder.build(); - } - - @Override - public boolean hasGui(byte aSide) { - return true; - } - - @Override - protected void addTitleTextStyle(ModularWindow.Builder builder, String title) { - // leave empty - } - - @Override - public int getGUIHeight() { - return 192; - } - - protected Widget getGregTechLogo() { - return new DrawableWidget().setDrawable(getGUITextureSet().getGregTechLogo()) - .setSize(17, 17); - } - - @Override - public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) { - if (isServerSide()) { - for (UpgradeCasing tPart : upgradeCasings) { - if (!(tPart instanceof InventoryUpgrade)) continue; - tPart.issueClientUpdate(); - } - } - int page = 0; - TabContainer tabs = new TabContainer().setButtonSize(20, 24); - tabs.addTabButton( - new TabButton(page++) - .setBackground( - false, - ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0, 1f, 0.5f), - new ItemDrawable(getStackForm(1)).withFixedSize(16, 16) - .withOffset(2, 4)) - .setBackground( - true, - ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0.5f, 1f, 1f), - new ItemDrawable(getStackForm(1)).withFixedSize(16, 16) - .withOffset(2, 4)) - .addTooltip(getLocalName()) - .setPos(20 * (page - 1), -20)) - .addPage(createMainPage().setSize(getGUIWidth(), getGUIHeight())); - if (hasItemInput()) { - tabs.addTabButton( - new TabButton(page++) - .setBackground( - false, - ModularUITextures.VANILLA_TAB_TOP_START.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), - GT_UITextures.PICTURE_ITEM_IN.withFixedSize(16, 16) - .withOffset(2, 4)) - .setPos(20 * (page - 1), -20)) - .addPage( - new MultiChildWidget().addChild(getItemInventoryInputGUI()) - .addChild(getGregTechLogo().setPos(147, 86)) - .setSize(getGUIWidth(), getGUIHeight())); - } - - if (hasItemOutput()) { - tabs.addTabButton( - new TabButton(page++) - .setBackground( - false, - ModularUITextures.VANILLA_TAB_TOP_START.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), - GT_UITextures.PICTURE_ITEM_OUT.withFixedSize(16, 16) - .withOffset(2, 4)) - .setPos(20 * (page - 1), -20)) - .addPage( - new MultiChildWidget().addChild(getItemInventoryOutputGUI()) - .addChild(getGregTechLogo().setPos(147, 86)) - .setSize(getGUIWidth(), getGUIHeight())); - } - - if (hasFluidInput()) { - tabs.addTabButton( - new TabButton(page++) - .setBackground( - false, - ModularUITextures.VANILLA_TAB_TOP_START.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), - GT_UITextures.PICTURE_FLUID_IN.withFixedSize(16, 16) - .withOffset(2, 4)) - .setPos(20 * (page - 1), -20)) - .addPage( - new MultiChildWidget().addChild(getFluidInventoryInputGUI()) - .addChild(getGregTechLogo().setPos(147, 86)) - .setSize(getGUIWidth(), getGUIHeight())); - } - - if (hasFluidOutput()) { - tabs.addTabButton( - new TabButton(page++) - .setBackground( - false, - ModularUITextures.VANILLA_TAB_TOP_START.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), - GT_UITextures.PICTURE_FLUID_OUT.withFixedSize(16, 16) - .withOffset(2, 4)) - .setPos(20 * (page - 1), -20)) - .addPage( - new MultiChildWidget().addChild(getFluidInventoryOutputGUI()) - .addChild(getGregTechLogo().setPos(147, 86)) - .setSize(getGUIWidth(), getGUIHeight())); - } - builder.widget(tabs); - } - - protected MultiChildWidget createMainPage() { - MultiChildWidget page = new MultiChildWidget(); - page.addChild( - new DrawableWidget().setDrawable(GT_UITextures.PICTURE_SCREEN_BLACK) - .setPos(7, 4) - .setSize(160, 75)) - .addChild(createButtons()); - return page; - } - - protected MultiChildWidget createButtons() { - MultiChildWidget buttons = new MultiChildWidget(); - buttons.setSize(16, 167) - .setPos(7, 86); - buttons.addChild(createPowerSwitchButton()) - .addChild(new FakeSyncWidget.BooleanSyncer(this::isAllowedToWork, val -> { - if (val) enableWorking(); - else disableWorking(); - })) - .addChild(createVoidExcessButton()) - .addChild(new FakeSyncWidget.BooleanSyncer(() -> voidExcess, val -> voidExcess = val)) - .addChild(createInputSeparationButton()) - .addChild(new FakeSyncWidget.BooleanSyncer(() -> separateInputs, val -> separateInputs = val)) - .addChild(createBatchModeButton()) - .addChild(new FakeSyncWidget.BooleanSyncer(() -> batchMode, val -> batchMode = val)) - .addChild(createLockToSingleRecipeButton()) - .addChild(new FakeSyncWidget.BooleanSyncer(() -> recipeLock, val -> recipeLock = val)); - - return buttons; - } - - protected Widget getItemInventoryInputGUI() { - final IItemHandlerModifiable inv = getInventoriesForInput(); - final Scrollable scrollable = new Scrollable().setVerticalScroll(); - for (int rows = 0; rows * 4 < Math.min(inv.getSlots(), 128); rows++) { - final int columnsToMake = Math.min(Math.min(inv.getSlots(), 128) - rows * 4, 4); - for (int column = 0; column < columnsToMake; column++) { - scrollable.widget( - new SlotWidget(inv, rows * 4 + column).setPos(column * 18, rows * 18) - .setSize(18, 18)); - } - } - return scrollable.setSize(18 * 4 + 4, 18 * 5) - .setPos(52, 7); - } - - protected Widget getItemInventoryOutputGUI() { - final IItemHandlerModifiable inv = getInventoriesForOutput(); - final Scrollable scrollable = new Scrollable().setVerticalScroll(); - for (int rows = 0; rows * 4 < Math.min(inv.getSlots(), 128); rows++) { - final int columnsToMake = Math.min(Math.min(inv.getSlots(), 128) - rows * 4, 4); - for (int column = 0; column < columnsToMake; column++) { - scrollable.widget( - new SlotWidget(inv, rows * 4 + column).setPos(column * 18, rows * 18) - .setSize(18, 18)); - } - } - return scrollable.setSize(18 * 4 + 4, 18 * 5) - .setPos(52, 7); - } - - protected IItemHandlerModifiable getInventoriesForInput() { - return new ListItemHandler(multiBlockInputInventory.values()); - } - - protected IItemHandlerModifiable getInventoriesForOutput() { - return new ListItemHandler(multiBlockOutputInventory.values()); - } - - protected Widget getFluidInventoryInputGUI() { - final IFluidTank[] tanks = inputTanks; - 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); - for (int column = 0; column < columnsToMake; column++) { - final FluidSlotWidget fluidSlot = new FluidSlotWidget(tanks[rows * 4 + column]); - scrollable.widget( - fluidSlot.setPos(column * 18, rows * 18) - .setSize(18, 18)); - } - } - return scrollable.setSize(18 * 4 + 4, 18 * 4) - .setPos(52, 7); - } - - protected Widget getFluidInventoryOutputGUI() { - final IFluidTank[] tanks = outputTanks; - 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); - for (int column = 0; column < columnsToMake; column++) { - final FluidSlotWidget fluidSlot = new FluidSlotWidget(tanks[rows * 4 + column]); - fluidSlot.setInteraction(true, false); - scrollable.widget( - fluidSlot.setPos(column * 18, rows * 18) - .setSize(18, 18)); - } - } - return scrollable.setSize(18 * 4 + 4, 18 * 5) - .setPos(52, 7); - } - - protected ButtonWidget createPowerSwitchButton() { - ButtonWidget button = new ButtonWidget().setOnClick((clickData, widget) -> { - if (isAllowedToWork()) { - disableWorking(); - } else { - enableWorking(); - } - }) - .setPlayClickSoundResource( - () -> isAllowedToWork() ? SoundResource.GUI_BUTTON_UP.resourceLocation - : SoundResource.GUI_BUTTON_DOWN.resourceLocation); - button.setBackground(() -> { - List ret = new ArrayList<>(); - ret.add(GT_UITextures.BUTTON_STANDARD); - if (isAllowedToWork()) { - ret.add(GT_UITextures.OVERLAY_BUTTON_POWER_SWITCH_ON); - } else { - ret.add(GT_UITextures.OVERLAY_BUTTON_POWER_SWITCH_OFF); - } - return ret.toArray(new IDrawable[0]); - }) - .setPos(144, 0) - .setSize(16, 16); - button.addTooltip(StatCollector.translateToLocal("GT5U.gui.button.power_switch")) - .setTooltipShowUpDelay(TOOLTIP_DELAY); - return button; - } - - protected ButtonWidget createVoidExcessButton() { - ButtonWidget button = new ButtonWidget().setOnClick((clickData, widget) -> { - if (isVoidExcessButtonEnabled()) { - voidExcess = !voidExcess; - } - }) - .setPlayClickSound(true); - button.setBackground(() -> { - List ret = new ArrayList<>(); - ret.add(GT_UITextures.BUTTON_STANDARD); - if (isVoidExcessButtonEnabled()) { - if (isVoidExcessEnabled()) { - ret.add(GT_UITextures.OVERLAY_BUTTON_VOID_EXCESS_ON); - } else { - ret.add(GT_UITextures.OVERLAY_BUTTON_VOID_EXCESS_OFF); - } - } else { - if (isVoidExcessEnabled()) { - ret.add(GT_UITextures.OVERLAY_BUTTON_VOID_EXCESS_ON_DISABLED); - } else { - ret.add(GT_UITextures.OVERLAY_BUTTON_VOID_EXCESS_OFF_DISABLED); - } - } - return ret.toArray(new IDrawable[0]); - }) - .setPos(54, 0) - .setSize(16, 16); - button.addTooltip(StatCollector.translateToLocal("GT5U.gui.button.void_excess")) - .setTooltipShowUpDelay(TOOLTIP_DELAY); - return button; - } - - protected boolean isVoidExcessEnabled() { - return voidExcess; - } - - protected boolean isVoidExcessButtonEnabled() { - return true; - } - - protected ButtonWidget createInputSeparationButton() { - Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { - if (isInputSeparationButtonEnabled()) { - separateInputs = !separateInputs; - } - }) - .setPlayClickSound(true) - .setBackground(() -> { - List ret = new ArrayList<>(); - ret.add(GT_UITextures.BUTTON_STANDARD); - if (isInputSeparationButtonEnabled()) { - if (isInputSeparationEnabled()) { - ret.add(GT_UITextures.OVERLAY_BUTTON_INPUT_SEPARATION_ON); - } else { - ret.add(GT_UITextures.OVERLAY_BUTTON_INPUT_SEPARATION_OFF); - } - } else { - if (isInputSeparationEnabled()) { - ret.add(GT_UITextures.OVERLAY_BUTTON_INPUT_SEPARATION_ON_DISABLED); - } else { - ret.add(GT_UITextures.OVERLAY_BUTTON_INPUT_SEPARATION_OFF_DISABLED); - } - } - return ret.toArray(new IDrawable[0]); - }) - .setPos(36, 0) - .setSize(16, 16); - button.addTooltip(StatCollector.translateToLocal("GT5U.gui.button.input_separation")) - .setTooltipShowUpDelay(TOOLTIP_DELAY); - return (ButtonWidget) button; - } - - protected boolean isInputSeparationEnabled() { - return separateInputs; - } - - protected boolean isInputSeparationButtonEnabled() { - return true; - } - - protected ButtonWidget createBatchModeButton() { - Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { - if (isBatchModeButtonEnabled()) { - batchMode = !batchMode; - } - }) - .setPlayClickSound(true) - .setBackground(() -> { - List ret = new ArrayList<>(); - ret.add(GT_UITextures.BUTTON_STANDARD); - if (isBatchModeButtonEnabled()) { - if (isBatchModeEnabled()) { - ret.add(GT_UITextures.OVERLAY_BUTTON_BATCH_MODE_ON); - } else { - ret.add(GT_UITextures.OVERLAY_BUTTON_BATCH_MODE_OFF); - } - } else { - if (isBatchModeEnabled()) { - ret.add(GT_UITextures.OVERLAY_BUTTON_BATCH_MODE_ON_DISABLED); - } else { - ret.add(GT_UITextures.OVERLAY_BUTTON_BATCH_MODE_OFF_DISABLED); - } - } - return ret.toArray(new IDrawable[0]); - }) - .setPos(18, 0) - .setSize(16, 16); - button.addTooltip(StatCollector.translateToLocal("GT5U.gui.button.batch_mode")) - .setTooltipShowUpDelay(TOOLTIP_DELAY); - return (ButtonWidget) button; - } - - protected boolean isBatchModeButtonEnabled() { - return true; - } - - protected boolean isBatchModeEnabled() { - return batchMode; - } - - protected ButtonWidget createLockToSingleRecipeButton() { - Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { - if (supportsSingleRecipeLocking()) { - recipeLock = !recipeLock; - } - }) - .setPlayClickSound(true) - .setBackground(() -> { - List ret = new ArrayList<>(); - ret.add(GT_UITextures.BUTTON_STANDARD); - if (supportsSingleRecipeLocking()) { - if (isRecipeLockingEnabled()) { - ret.add(GT_UITextures.OVERLAY_BUTTON_RECIPE_LOCKED); - } else { - ret.add(GT_UITextures.OVERLAY_BUTTON_RECIPE_UNLOCKED); - } - } else { - if (isRecipeLockingEnabled()) { - ret.add(GT_UITextures.OVERLAY_BUTTON_RECIPE_LOCKED_DISABLED); - } else { - ret.add(GT_UITextures.OVERLAY_BUTTON_RECIPE_UNLOCKED_DISABLED); - } - } - return ret.toArray(new IDrawable[0]); - }) - .setPos(0, 0) - .setSize(16, 16); - button.addTooltip(StatCollector.translateToLocal("GT5U.gui.button.lock_recipe")) - .setTooltipShowUpDelay(TOOLTIP_DELAY); - return (ButtonWidget) button; - } - - protected boolean supportsSingleRecipeLocking() { - return false; - } - - protected boolean isRecipeLockingEnabled() { - return recipeLock; - } -} 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 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> extends MultiBlockController - 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/MultiBlock_Stackable.java b/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlock_Stackable.java deleted file mode 100644 index 11d931433f..0000000000 --- a/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlock_Stackable.java +++ /dev/null @@ -1,111 +0,0 @@ -package gregtech.api.multitileentity.multiblock.base; - -import net.minecraft.item.ItemStack; - -import com.gtnewhorizon.structurelib.util.Vec3Impl; - -public abstract class MultiBlock_Stackable> extends MultiBlockPowerController { - - protected static String STACKABLE_TOP = "STACKABLE_TOP"; - protected static String STACKABLE_MIDDLE = "STACKABLE_MIDDLE"; - protected static String STACKABLE_BOTTOM = "STACKABLE_BOTTOM"; - - /** - * construct implementation for stackable multi-blocks - */ - @Override - public void construct(ItemStack trigger, boolean hintsOnly) { - final int blueprintCount = (trigger.stackSize - 1) + getMinStacks(); - final int stackCount = Math.min(blueprintCount, getMaxStacks()); - - buildState.startBuilding(getStartingStructureOffset()); - buildPiece(STACKABLE_BOTTOM, trigger, hintsOnly, buildState.getCurrentOffset()); - buildState.addOffset(getStartingStackOffset()); - - for (int i = 0; i < stackCount; i++) { - buildPiece(STACKABLE_MIDDLE, trigger, hintsOnly, buildState.getCurrentOffset()); - buildState.addOffset(getPerStackOffset()); - } - if (hasTop()) { - buildState.addOffset(getAfterLastStackOffset()); - buildPiece(STACKABLE_TOP, trigger, hintsOnly, buildState.stopBuilding()); - } else { - buildState.stopBuilding(); - } - } - - /** - * Stackable - * - * @return The minimum number of stacks required for this multi-block to form - */ - public abstract int getMinStacks(); - - /** - * Stackable - * - * @return The maximum number of stacks allowed for this multi-block to form - */ - public abstract int getMaxStacks(); - - /** - * Stackable - * - * @return The starting offset for the first stack - */ - public abstract Vec3Impl getStartingStackOffset(); - - /** - * Stackable - * - * @return The per stack offset - */ - public abstract Vec3Impl getPerStackOffset(); - - /** - * Stackable - * - * @return Whether this structure has a Top/Cap. Defaults to true. - */ - public boolean hasTop() { - return true; - } - - /** - * Stackable - * - * @return Any offset needed after the last stack - */ - public Vec3Impl getAfterLastStackOffset() { - return new Vec3Impl(0, 0, 0); - } - - /** - * checkMachine implementation for stackable multi-blocks - */ - @Override - public boolean checkMachine() { - int stackCount = 0; - - buildState.startBuilding(getStartingStructureOffset()); - if (!checkPiece(STACKABLE_BOTTOM, buildState.getCurrentOffset())) return buildState.failBuilding(); - - buildState.addOffset(getStartingStackOffset()); - - for (int i = 0; i < getMaxStacks(); i++) { - if (checkPiece(STACKABLE_MIDDLE, buildState.getCurrentOffset())) { - buildState.addOffset(getPerStackOffset()); - stackCount++; - } else { - break; - } - } - if (stackCount < getMinStacks()) return buildState.failBuilding(); - - buildState.addOffset(getAfterLastStackOffset()); - if (!checkPiece(STACKABLE_TOP, buildState.stopBuilding())) { - return buildState.failBuilding(); - } - return super.checkMachine(); - } -} 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> extends Controller 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 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/StackableController.java b/src/main/java/gregtech/api/multitileentity/multiblock/base/StackableController.java new file mode 100644 index 0000000000..90a2742290 --- /dev/null +++ b/src/main/java/gregtech/api/multitileentity/multiblock/base/StackableController.java @@ -0,0 +1,111 @@ +package gregtech.api.multitileentity.multiblock.base; + +import net.minecraft.item.ItemStack; + +import com.gtnewhorizon.structurelib.util.Vec3Impl; + +public abstract class StackableController> extends PowerController { + + protected static String STACKABLE_TOP = "STACKABLE_TOP"; + protected static String STACKABLE_MIDDLE = "STACKABLE_MIDDLE"; + protected static String STACKABLE_BOTTOM = "STACKABLE_BOTTOM"; + + /** + * construct implementation for stackable multi-blocks + */ + @Override + public void construct(ItemStack trigger, boolean hintsOnly) { + final int blueprintCount = (trigger.stackSize - 1) + getMinStacks(); + final int stackCount = Math.min(blueprintCount, getMaxStacks()); + + buildState.startBuilding(getStartingStructureOffset()); + buildPiece(STACKABLE_BOTTOM, trigger, hintsOnly, buildState.getCurrentOffset()); + buildState.addOffset(getStartingStackOffset()); + + for (int i = 0; i < stackCount; i++) { + buildPiece(STACKABLE_MIDDLE, trigger, hintsOnly, buildState.getCurrentOffset()); + buildState.addOffset(getPerStackOffset()); + } + if (hasTop()) { + buildState.addOffset(getAfterLastStackOffset()); + buildPiece(STACKABLE_TOP, trigger, hintsOnly, buildState.stopBuilding()); + } else { + buildState.stopBuilding(); + } + } + + /** + * Stackable + * + * @return The minimum number of stacks required for this multi-block to form + */ + public abstract int getMinStacks(); + + /** + * Stackable + * + * @return The maximum number of stacks allowed for this multi-block to form + */ + public abstract int getMaxStacks(); + + /** + * Stackable + * + * @return The starting offset for the first stack + */ + public abstract Vec3Impl getStartingStackOffset(); + + /** + * Stackable + * + * @return The per stack offset + */ + public abstract Vec3Impl getPerStackOffset(); + + /** + * Stackable + * + * @return Whether this structure has a Top/Cap. Defaults to true. + */ + public boolean hasTop() { + return true; + } + + /** + * Stackable + * + * @return Any offset needed after the last stack + */ + public Vec3Impl getAfterLastStackOffset() { + return new Vec3Impl(0, 0, 0); + } + + /** + * checkMachine implementation for stackable multi-blocks + */ + @Override + public boolean checkMachine() { + int stackCount = 0; + + buildState.startBuilding(getStartingStructureOffset()); + if (!checkPiece(STACKABLE_BOTTOM, buildState.getCurrentOffset())) return buildState.failBuilding(); + + buildState.addOffset(getStartingStackOffset()); + + for (int i = 0; i < getMaxStacks(); i++) { + if (checkPiece(STACKABLE_MIDDLE, buildState.getCurrentOffset())) { + buildState.addOffset(getPerStackOffset()); + stackCount++; + } else { + break; + } + } + if (stackCount < getMinStacks()) return buildState.failBuilding(); + + buildState.addOffset(getAfterLastStackOffset()); + if (!checkPiece(STACKABLE_TOP, buildState.stopBuilding())) { + return buildState.failBuilding(); + } + return super.checkMachine(); + } +} 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); } } @@ -343,6 +349,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 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> 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> 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 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> aParallelQueue = new PriorityQueue<>( + Comparator.comparing(MutableTriple::getLeft)); + for (Entry> 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 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 */ @@ -434,6 +515,82 @@ public class GT_ParallelHelper { return 0; } + /** + * 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 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> 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 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> aParallelQueue = new PriorityQueue<>( + Comparator.comparing(MutableTriple::getLeft)); + for (Entry> entry : tParallels.entrySet()) { + aParallelQueue.add(new MutableTriple<>(entry.getValue().left, entry.getValue().right, entry.getKey())); + } + + while (tSlotsFree > 0) { + MutableTriple 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 */ 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) { diff --git a/src/main/java/gregtech/common/GT_Client.java b/src/main/java/gregtech/common/GT_Client.java index 2874bde726..4ae0204636 100644 --- a/src/main/java/gregtech/common/GT_Client.java +++ b/src/main/java/gregtech/common/GT_Client.java @@ -64,6 +64,7 @@ import gregtech.api.interfaces.tileentity.IGregTechTileEntity; import gregtech.api.interfaces.tileentity.ITurnable; import gregtech.api.items.GT_MetaGenerated_Item; import gregtech.api.metatileentity.BaseMetaPipeEntity; +import gregtech.api.multitileentity.multiblock.base.MultiBlockPart; import gregtech.api.net.GT_Packet_ClientPreference; import gregtech.api.objects.GT_ItemStack; import gregtech.api.util.ColorsMetadataSection; @@ -567,6 +568,7 @@ public class GT_Client extends GT_Proxy implements Runnable { public void onLoad() { super.onLoad(); new GT_Renderer_Block(); + new GT_MultiTile_Renderer(); metaGeneratedItemRenderer = new GT_MetaGenerated_Item_Renderer(); for (GT_MetaGenerated_Item item : GT_MetaGenerated_Item.sInstances.values()) { metaGeneratedItemRenderer.registerItem(item); @@ -778,7 +780,9 @@ public class GT_Client extends GT_Proxy implements Runnable { if (!(aTileEntity instanceof ICoverable)) return; if (GT_Utility.isStackInList(aEvent.currentItem, GregTech_API.sWireCutterList) - || GT_Utility.isStackInList(aEvent.currentItem, GregTech_API.sSolderingToolList)) { + || GT_Utility.isStackInList(aEvent.currentItem, GregTech_API.sSolderingToolList) + || (GT_Utility.isStackInList(aEvent.currentItem, GregTech_API.sSoftHammerList) + && aTileEntity instanceof MultiBlockPart) && aEvent.player.isSneaking()) { if (((ICoverable) aTileEntity).getCoverIDAtSide((byte) aEvent.target.sideHit) == 0) drawGrid(aEvent, false, false, aEvent.player.isSneaking()); return; diff --git a/src/main/java/gregtech/common/render/GT_MultiTile_Renderer.java b/src/main/java/gregtech/common/render/GT_MultiTile_Renderer.java new file mode 100644 index 0000000000..4d55979658 --- /dev/null +++ b/src/main/java/gregtech/common/render/GT_MultiTile_Renderer.java @@ -0,0 +1,181 @@ +package gregtech.common.render; + +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.IBlockAccess; +import net.minecraftforge.common.util.ForgeDirection; + +import org.lwjgl.opengl.GL11; + +import cpw.mods.fml.client.registry.ISimpleBlockRenderingHandler; +import cpw.mods.fml.client.registry.RenderingRegistry; +import gregtech.GT_Mod; +import gregtech.api.interfaces.ITexture; +import gregtech.api.logic.ModelRenderLogic; +import gregtech.api.logic.interfaces.ModelRenderLogicHost; +import gregtech.api.multitileentity.MultiTileEntityBlockInternal; +import gregtech.api.multitileentity.MultiTileEntityClassContainer; +import gregtech.api.multitileentity.MultiTileEntityRegistry; +import gregtech.api.multitileentity.interfaces.IMultiBlockController; +import gregtech.api.multitileentity.multiblock.base.MultiBlockPart; + +public class GT_MultiTile_Renderer implements ISimpleBlockRenderingHandler { + + private final int renderID; + public static GT_MultiTile_Renderer INSTANCE; + + public GT_MultiTile_Renderer() { + this.renderID = RenderingRegistry.getNextAvailableRenderId(); + INSTANCE = this; + RenderingRegistry.registerBlockHandler(this); + } + + @Override + public void renderInventoryBlock(Block block, int metadata, int modelId, RenderBlocks renderer) { + if (!(block instanceof MultiTileEntityBlockInternal)) { + return; + } + + GL11.glRotatef(90.0F, 0.0F, 1.0F, 0.0F); + GL11.glTranslatef(-0.5F, -0.5F, -0.5F); + + MultiTileEntityBlockInternal mteBlock = (MultiTileEntityBlockInternal) block; + MultiTileEntityRegistry registry = mteBlock.getRegistry(); + if (registry == null) return; + MultiTileEntityClassContainer classContainer = registry.getClassContainer(metadata); + if (classContainer == null) return; + renderer.setRenderBoundsFromBlock(mteBlock); + + for (ForgeDirection side : ForgeDirection.VALID_DIRECTIONS) { + ITexture texture = classContainer.mCanonicalTileEntity.getTexture(side); + if (texture == null) continue; + switch (side) { + case DOWN -> renderYNegative(null, renderer, 0, 0, 0, block, texture, side); + case UP -> renderYPositive(null, renderer, 0, 0, 0, block, texture, side); + case WEST -> renderXNegative(null, renderer, 0, 0, 0, block, texture, side); + case EAST -> renderXPositive(null, renderer, 0, 0, 0, block, texture, side); + case NORTH -> renderZNegative(null, renderer, 0, 0, 0, block, texture, side); + case SOUTH -> renderZPositive(null, renderer, 0, 0, 0, block, texture, side); + default -> { + // Do nothing + } + } + } + + GL11.glTranslatef(0.5F, 0.5F, 0.5F); + } + + @Override + public boolean renderWorldBlock(IBlockAccess world, int x, int y, int z, Block block, int modelId, + RenderBlocks renderer) { + TileEntity entity = world.getTileEntity(x, y, z); + if (entity == null) { + return false; + } + + renderer.enableAO = Minecraft.isAmbientOcclusionEnabled() && GT_Mod.gregtechproxy.mRenderTileAmbientOcclusion; + renderer.useInventoryTint = false; + + if (entity instanceof ModelRenderLogicHost modelEntity && modelEntity.shouldRenderModel()) { + ModelRenderLogic renderLogic = modelEntity.getRenderLogic(); + return true; + } + + if (!(entity instanceof MultiTileBasicRender)) { + return false; + } + + if (entity instanceof MultiBlockPart) { + IMultiBlockController controller = ((MultiBlockPart) entity).getTarget(false); + if (controller instanceof ModelRenderLogicHost && ((ModelRenderLogicHost) controller).shouldRenderModel()) { + return false; + } + } + + MultiTileBasicRender renderedEntity = (MultiTileBasicRender) entity; + + for (ForgeDirection side : ForgeDirection.VALID_DIRECTIONS) { + ITexture texture = renderedEntity.getTexture(side); + if (texture == null) continue; + switch (side) { + case DOWN -> renderYNegative(world, renderer, x, y, z, block, texture, side); + case UP -> renderYPositive(world, renderer, x, y, z, block, texture, side); + case WEST -> renderXNegative(world, renderer, x, y, z, block, texture, side); + case EAST -> renderXPositive(world, renderer, x, y, z, block, texture, side); + case NORTH -> renderZNegative(world, renderer, x, y, z, block, texture, side); + case SOUTH -> renderZPositive(world, renderer, x, y, z, block, texture, side); + default -> { + // Do nothing + } + } + } + return true; + } + + @Override + public boolean shouldRender3DInInventory(int modelId) { + return true; + } + + @Override + public int getRenderId() { + return renderID; + } + + private static void renderYNegative(IBlockAccess world, RenderBlocks renderer, int x, int y, int z, Block block, + ITexture texture, ForgeDirection side) { + if (world != null) { + if (!block.shouldSideBeRendered(world, x, y - 1, z, side.ordinal())) return; + Tessellator.instance.setBrightness(block.getMixedBrightnessForBlock(world, x, y - 1, z)); + } + texture.renderYNeg(renderer, block, x, y, z); + } + + private static void renderZNegative(IBlockAccess world, RenderBlocks renderer, int x, int y, int z, Block block, + ITexture texture, ForgeDirection side) { + if (world != null) { + if (!block.shouldSideBeRendered(world, x, y, z - 1, side.ordinal())) return; + Tessellator.instance.setBrightness(block.getMixedBrightnessForBlock(world, x, y, z - 1)); + } + texture.renderZNeg(renderer, block, x, y, z); + } + + private static void renderXNegative(IBlockAccess world, RenderBlocks renderer, int x, int y, int z, Block block, + ITexture texture, ForgeDirection side) { + if (world != null) { + if (!block.shouldSideBeRendered(world, x - 1, y, z, side.ordinal())) return; + Tessellator.instance.setBrightness(block.getMixedBrightnessForBlock(world, x - 1, y, z)); + } + texture.renderXNeg(renderer, block, x, y, z); + } + + private static void renderYPositive(IBlockAccess world, RenderBlocks renderer, int x, int y, int z, Block block, + ITexture texture, ForgeDirection side) { + if (world != null) { + if (!block.shouldSideBeRendered(world, x, y + 1, z, side.ordinal())) return; + Tessellator.instance.setBrightness(block.getMixedBrightnessForBlock(world, x, y + 1, z)); + } + texture.renderYPos(renderer, block, x, y, z); + } + + private static void renderXPositive(IBlockAccess world, RenderBlocks renderer, int x, int y, int z, Block block, + ITexture texture, ForgeDirection side) { + if (world != null) { + if (!block.shouldSideBeRendered(world, x + 1, y, z, side.ordinal())) return; + Tessellator.instance.setBrightness(block.getMixedBrightnessForBlock(world, x + 1, y, z)); + } + texture.renderXPos(renderer, block, x, y, z); + } + + private static void renderZPositive(IBlockAccess world, RenderBlocks renderer, int x, int y, int z, Block block, + ITexture texture, ForgeDirection side) { + if (world != null) { + if (!block.shouldSideBeRendered(world, x, y, z + 1, side.ordinal())) return; + Tessellator.instance.setBrightness(block.getMixedBrightnessForBlock(world, x, y, z + 1)); + } + texture.renderZPos(renderer, block, x, y, z); + } +} diff --git a/src/main/java/gregtech/common/render/GT_Renderer_Block.java b/src/main/java/gregtech/common/render/GT_Renderer_Block.java index 7646ee31fa..012115efa3 100644 --- a/src/main/java/gregtech/common/render/GT_Renderer_Block.java +++ b/src/main/java/gregtech/common/render/GT_Renderer_Block.java @@ -1,9 +1,5 @@ package gregtech.common.render; -import static gregtech.api.enums.GT_Values.ALL_VALID_SIDES; -import static gregtech.api.enums.GT_Values.OFFX; -import static gregtech.api.enums.GT_Values.OFFY; -import static gregtech.api.enums.GT_Values.OFFZ; import static gregtech.api.interfaces.metatileentity.IConnectable.CONNECTED_DOWN; import static gregtech.api.interfaces.metatileentity.IConnectable.CONNECTED_EAST; import static gregtech.api.interfaces.metatileentity.IConnectable.CONNECTED_NORTH; @@ -27,7 +23,6 @@ import net.minecraft.client.particle.EffectRenderer; import net.minecraft.client.particle.EntityDiggingFX; import net.minecraft.client.renderer.RenderBlocks; import net.minecraft.client.renderer.Tessellator; -import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; @@ -529,150 +524,73 @@ public class GT_Renderer_Block implements ISimpleBlockRenderingHandler { GL11.glRotatef(90.0F, 0.0F, 1.0F, 0.0F); GL11.glTranslatef(-0.5F, -0.5F, -0.5F); - if (aBlock instanceof IRenderedBlock) { - boolean tNeedsToSetBounds = true; - final ItemStack aStack = new ItemStack(aBlock, 1, aMeta); - IRenderedBlock tRenderer = ((IRenderedBlock) aBlock).passRenderingToObject(aStack); - if (tRenderer != null) tRenderer = tRenderer.passRenderingToObject(aStack); - if (tRenderer == null) tRenderer = IRenderedBlock.ErrorRenderer.INSTANCE; - for (int i = 0, j = tRenderer.getRenderPasses(aBlock); i < j; i++) { - if (tRenderer.usesRenderPass(i)) { - if (tRenderer.setBlockBounds(aBlock, i)) { - tNeedsToSetBounds = true; - aRenderer.setRenderBoundsFromBlock(aBlock); - } else { - if (tNeedsToSetBounds) aBlock.setBlockBoundsForItemRender(); - aRenderer.setRenderBoundsFromBlock(aBlock); - tNeedsToSetBounds = false; - } + if (aBlock instanceof GT_Block_Ores_Abstract) { + final GT_TileEntity_Ores tTileEntity = new GT_TileEntity_Ores(); + tTileEntity.mMetaData = ((short) aMeta); - renderNegativeYFacing( - null, - aRenderer, - aBlock, - 0, - 0, - 0, - tRenderer.getTexture(aBlock, (byte) DOWN.ordinal(), true, i), - !tNeedsToSetBounds); - renderPositiveYFacing( - null, - aRenderer, - aBlock, - 0, - 0, - 0, - tRenderer.getTexture(aBlock, (byte) UP.ordinal(), true, i), - !tNeedsToSetBounds); - renderNegativeZFacing( - null, - aRenderer, - aBlock, - 0, - 0, - 0, - tRenderer.getTexture(aBlock, (byte) NORTH.ordinal(), true, i), - !tNeedsToSetBounds); - renderPositiveZFacing( - null, - aRenderer, - aBlock, - 0, - 0, - 0, - tRenderer.getTexture(aBlock, (byte) SOUTH.ordinal(), true, i), - !tNeedsToSetBounds); - renderNegativeXFacing( - null, - aRenderer, - aBlock, - 0, - 0, - 0, - tRenderer.getTexture(aBlock, (byte) WEST.ordinal(), true, i), - !tNeedsToSetBounds); - renderPositiveXFacing( - null, - aRenderer, - aBlock, - 0, - 0, - 0, - tRenderer.getTexture(aBlock, (byte) EAST.ordinal(), true, i), - !tNeedsToSetBounds); - } + aBlock.setBlockBoundsForItemRender(); + aRenderer.setRenderBoundsFromBlock(aBlock); + renderNegativeYFacing( + null, + aRenderer, + aBlock, + 0, + 0, + 0, + tTileEntity.getTexture(aBlock, (byte) DOWN.ordinal()), + true); + renderPositiveYFacing( + null, + aRenderer, + aBlock, + 0, + 0, + 0, + tTileEntity.getTexture(aBlock, (byte) UP.ordinal()), + true); + renderNegativeZFacing( + null, + aRenderer, + aBlock, + 0, + 0, + 0, + tTileEntity.getTexture(aBlock, (byte) NORTH.ordinal()), + true); + renderPositiveZFacing( + null, + aRenderer, + aBlock, + 0, + 0, + 0, + tTileEntity.getTexture(aBlock, (byte) SOUTH.ordinal()), + true); + renderNegativeXFacing( + null, + aRenderer, + aBlock, + 0, + 0, + 0, + tTileEntity.getTexture(aBlock, (byte) WEST.ordinal()), + true); + renderPositiveXFacing( + null, + aRenderer, + aBlock, + 0, + 0, + 0, + tTileEntity.getTexture(aBlock, (byte) EAST.ordinal()), + true); + } else if (aMeta > 0 && (aMeta < GregTech_API.METATILEENTITIES.length) + && aBlock instanceof GT_Block_Machines + && (GregTech_API.METATILEENTITIES[aMeta] != null) + && (!GregTech_API.METATILEENTITIES[aMeta].renderInInventory(aBlock, aMeta, aRenderer))) { + renderNormalInventoryMetaTileEntity(aBlock, aMeta, aRenderer); } - if (tNeedsToSetBounds) aBlock.setBlockBounds(0, 0, 0, 1, 1, 1); - - } else { - if (aBlock instanceof GT_Block_Ores_Abstract) { - final GT_TileEntity_Ores tTileEntity = new GT_TileEntity_Ores(); - tTileEntity.mMetaData = ((short) aMeta); - - aBlock.setBlockBoundsForItemRender(); - aRenderer.setRenderBoundsFromBlock(aBlock); - renderNegativeYFacing( - null, - aRenderer, - aBlock, - 0, - 0, - 0, - tTileEntity.getTexture(aBlock, (byte) DOWN.ordinal()), - true); - renderPositiveYFacing( - null, - aRenderer, - aBlock, - 0, - 0, - 0, - tTileEntity.getTexture(aBlock, (byte) UP.ordinal()), - true); - renderNegativeZFacing( - null, - aRenderer, - aBlock, - 0, - 0, - 0, - tTileEntity.getTexture(aBlock, (byte) NORTH.ordinal()), - true); - renderPositiveZFacing( - null, - aRenderer, - aBlock, - 0, - 0, - 0, - tTileEntity.getTexture(aBlock, (byte) SOUTH.ordinal()), - true); - renderNegativeXFacing( - null, - aRenderer, - aBlock, - 0, - 0, - 0, - tTileEntity.getTexture(aBlock, (byte) WEST.ordinal()), - true); - renderPositiveXFacing( - null, - aRenderer, - aBlock, - 0, - 0, - 0, - tTileEntity.getTexture(aBlock, (byte) EAST.ordinal()), - true); - } else if (aMeta > 0 && (aMeta < GregTech_API.METATILEENTITIES.length) - && aBlock instanceof GT_Block_Machines - && (GregTech_API.METATILEENTITIES[aMeta] != null) - && (!GregTech_API.METATILEENTITIES[aMeta].renderInInventory(aBlock, aMeta, aRenderer))) { - renderNormalInventoryMetaTileEntity(aBlock, aMeta, aRenderer); - } - aBlock.setBlockBounds(blockMin, blockMin, blockMin, blockMax, blockMax, blockMax); - } + aBlock.setBlockBounds(blockMin, blockMin, blockMin, blockMax, blockMax, blockMax); aRenderer.setRenderBoundsFromBlock(aBlock); @@ -979,94 +897,6 @@ public class GT_Renderer_Block implements ISimpleBlockRenderingHandler { RenderBlocks aRenderer) { aRenderer.enableAO = Minecraft.isAmbientOcclusionEnabled() && GT_Mod.gregtechproxy.mRenderTileAmbientOcclusion; aRenderer.useInventoryTint = false; - if (aBlock instanceof IRenderedBlock) { - IRenderedBlock tRenderer = ((IRenderedBlock) aBlock).passRenderingToObject(aWorld, aX, aY, aZ); - if (tRenderer != null) tRenderer = tRenderer.passRenderingToObject(aWorld, aX, aY, aZ); - if (tRenderer == null) tRenderer = IRenderedBlock.ErrorRenderer.INSTANCE; - boolean tNeedsToSetBounds = true; - boolean rReturn = false; - if (tRenderer.renderBlock(aBlock, aRenderer, aWorld, aX, aY, aZ)) { - rReturn = true; - } else { - final boolean[] tSides = new boolean[6]; - if (tRenderer instanceof IRenderedBlockSideCheck) { - for (byte tSide : ALL_VALID_SIDES) rReturn |= (tSides[tSide] = ((IRenderedBlockSideCheck) tRenderer) - .renderFullBlockSide(aBlock, aRenderer, tSide)); - } else { - for (byte tSide : ALL_VALID_SIDES) rReturn |= (tSides[tSide] = aBlock - .shouldSideBeRendered(aWorld, aX + OFFX[tSide], aY + OFFY[tSide], aZ + OFFZ[tSide], tSide)); - } - for (int i = 0, j = tRenderer.getRenderPasses(aBlock); i < j; i++) { - if (tRenderer.usesRenderPass(i)) { - if (tRenderer.setBlockBounds(aBlock, i)) { - tNeedsToSetBounds = true; - aRenderer.setRenderBoundsFromBlock(aBlock); - } else { - if (tNeedsToSetBounds) aBlock.setBlockBounds(0, 0, 0, 1, 1, 1); - aRenderer.setRenderBoundsFromBlock(aBlock); - tNeedsToSetBounds = false; - } - renderNegativeYFacing( - aWorld, - aRenderer, - aBlock, - aX, - aY, - aZ, - tRenderer.getTexture(aBlock, (byte) DOWN.ordinal(), i, tSides), - tSides[DOWN.ordinal()]); - renderPositiveYFacing( - aWorld, - aRenderer, - aBlock, - aX, - aY, - aZ, - tRenderer.getTexture(aBlock, (byte) UP.ordinal(), i, tSides), - tSides[UP.ordinal()]); - renderNegativeZFacing( - aWorld, - aRenderer, - aBlock, - aX, - aY, - aZ, - tRenderer.getTexture(aBlock, (byte) NORTH.ordinal(), i, tSides), - tSides[NORTH.ordinal()]); - renderPositiveZFacing( - aWorld, - aRenderer, - aBlock, - aX, - aY, - aZ, - tRenderer.getTexture(aBlock, (byte) SOUTH.ordinal(), i, tSides), - tSides[SOUTH.ordinal()]); - renderNegativeXFacing( - aWorld, - aRenderer, - aBlock, - aX, - aY, - aZ, - tRenderer.getTexture(aBlock, (byte) WEST.ordinal(), i, tSides), - tSides[WEST.ordinal()]); - renderPositiveXFacing( - aWorld, - aRenderer, - aBlock, - aX, - aY, - aZ, - tRenderer.getTexture(aBlock, (byte) EAST.ordinal(), i, tSides), - tSides[EAST.ordinal()]); - } - } - if (tNeedsToSetBounds) aBlock.setBlockBounds(0, 0, 0, 1, 1, 1); - } - - return rReturn; - } final TileEntity tileEntity = aWorld.getTileEntity(aX, aY, aZ); if (tileEntity == null) return false; diff --git a/src/main/java/gregtech/common/render/MultiTileBasicRender.java b/src/main/java/gregtech/common/render/MultiTileBasicRender.java new file mode 100644 index 0000000000..be41739401 --- /dev/null +++ b/src/main/java/gregtech/common/render/MultiTileBasicRender.java @@ -0,0 +1,10 @@ +package gregtech.common.render; + +import net.minecraftforge.common.util.ForgeDirection; + +import gregtech.api.interfaces.ITexture; + +public interface MultiTileBasicRender { + + ITexture getTexture(ForgeDirection side); +} diff --git a/src/main/java/gregtech/common/tileentities/casings/functional/Conveyor.java b/src/main/java/gregtech/common/tileentities/casings/functional/Conveyor.java new file mode 100644 index 0000000000..31dea4cf38 --- /dev/null +++ b/src/main/java/gregtech/common/tileentities/casings/functional/Conveyor.java @@ -0,0 +1,16 @@ +package gregtech.common.tileentities.casings.functional; + +import gregtech.api.multitileentity.multiblock.casing.FunctionalCasing; + +public class Conveyor extends FunctionalCasing { + + @Override + public String getTileEntityName() { + return "gt.multitileentity.multiblock.functional.conveyor"; + } + + @Override + public float getPartModifier() { + return 1.1f; + } +} diff --git a/src/main/java/gregtech/common/tileentities/casings/functional/Emitter.java b/src/main/java/gregtech/common/tileentities/casings/functional/Emitter.java new file mode 100644 index 0000000000..cce660ace4 --- /dev/null +++ b/src/main/java/gregtech/common/tileentities/casings/functional/Emitter.java @@ -0,0 +1,16 @@ +package gregtech.common.tileentities.casings.functional; + +import gregtech.api.multitileentity.multiblock.casing.FunctionalCasing; + +public class Emitter extends FunctionalCasing { + + @Override + public String getTileEntityName() { + return "gt.multitileentity.multiblock.functional.emitter"; + } + + @Override + public float getPartModifier() { + return 1.3f; + } +} diff --git a/src/main/java/gregtech/common/tileentities/casings/functional/FieldGenerator.java b/src/main/java/gregtech/common/tileentities/casings/functional/FieldGenerator.java new file mode 100644 index 0000000000..3787d45af8 --- /dev/null +++ b/src/main/java/gregtech/common/tileentities/casings/functional/FieldGenerator.java @@ -0,0 +1,16 @@ +package gregtech.common.tileentities.casings.functional; + +import gregtech.api.multitileentity.multiblock.casing.FunctionalCasing; + +public class FieldGenerator extends FunctionalCasing { + + @Override + public String getTileEntityName() { + return "gt.multitileentity.multiblock.functional.field.generator"; + } + + @Override + public float getPartModifier() { + return 2f; + } +} diff --git a/src/main/java/gregtech/common/tileentities/casings/functional/Motor.java b/src/main/java/gregtech/common/tileentities/casings/functional/Motor.java new file mode 100644 index 0000000000..cddb293cc2 --- /dev/null +++ b/src/main/java/gregtech/common/tileentities/casings/functional/Motor.java @@ -0,0 +1,16 @@ +package gregtech.common.tileentities.casings.functional; + +import gregtech.api.multitileentity.multiblock.casing.FunctionalCasing; + +public class Motor extends FunctionalCasing { + + @Override + public String getTileEntityName() { + return "gt.multitileentity.multiblock.functional.motor"; + } + + @Override + public float getPartModifier() { + return 1; + } +} diff --git a/src/main/java/gregtech/common/tileentities/casings/functional/MotorCasing.java b/src/main/java/gregtech/common/tileentities/casings/functional/MotorCasing.java deleted file mode 100644 index 32a53d418a..0000000000 --- a/src/main/java/gregtech/common/tileentities/casings/functional/MotorCasing.java +++ /dev/null @@ -1,11 +0,0 @@ -package gregtech.common.tileentities.casings.functional; - -import gregtech.api.multitileentity.multiblock.casing.FunctionalCasing; - -public class MotorCasing extends FunctionalCasing { - - @Override - public String getTileEntityName() { - return "gt.multitileentity.multiblock.functional.motor"; - } -} diff --git a/src/main/java/gregtech/common/tileentities/casings/functional/Piston.java b/src/main/java/gregtech/common/tileentities/casings/functional/Piston.java new file mode 100644 index 0000000000..2255fbf8a2 --- /dev/null +++ b/src/main/java/gregtech/common/tileentities/casings/functional/Piston.java @@ -0,0 +1,16 @@ +package gregtech.common.tileentities.casings.functional; + +import gregtech.api.multitileentity.multiblock.casing.FunctionalCasing; + +public class Piston extends FunctionalCasing { + + @Override + public String getTileEntityName() { + return "gt.multitileentity.multiblock.functional.piston"; + } + + @Override + public float getPartModifier() { + return 1.1f; + } +} diff --git a/src/main/java/gregtech/common/tileentities/casings/functional/Pump.java b/src/main/java/gregtech/common/tileentities/casings/functional/Pump.java new file mode 100644 index 0000000000..3acddbe9dc --- /dev/null +++ b/src/main/java/gregtech/common/tileentities/casings/functional/Pump.java @@ -0,0 +1,16 @@ +package gregtech.common.tileentities.casings.functional; + +import gregtech.api.multitileentity.multiblock.casing.FunctionalCasing; + +public class Pump extends FunctionalCasing { + + @Override + public String getTileEntityName() { + return "gt.multitileentity.multiblock.functional.pump"; + } + + @Override + public float getPartModifier() { + return 1.1f; + } +} diff --git a/src/main/java/gregtech/common/tileentities/casings/functional/RobotArm.java b/src/main/java/gregtech/common/tileentities/casings/functional/RobotArm.java new file mode 100644 index 0000000000..2273705397 --- /dev/null +++ b/src/main/java/gregtech/common/tileentities/casings/functional/RobotArm.java @@ -0,0 +1,16 @@ +package gregtech.common.tileentities.casings.functional; + +import gregtech.api.multitileentity.multiblock.casing.FunctionalCasing; + +public class RobotArm extends FunctionalCasing { + + @Override + public String getTileEntityName() { + return "gt.multitileentity.multiblock.functional.robot.arm"; + } + + @Override + public float getPartModifier() { + return 1.5f; + } +} diff --git a/src/main/java/gregtech/common/tileentities/casings/functional/Sensor.java b/src/main/java/gregtech/common/tileentities/casings/functional/Sensor.java new file mode 100644 index 0000000000..e88060e902 --- /dev/null +++ b/src/main/java/gregtech/common/tileentities/casings/functional/Sensor.java @@ -0,0 +1,16 @@ +package gregtech.common.tileentities.casings.functional; + +import gregtech.api.multitileentity.multiblock.casing.FunctionalCasing; + +public class Sensor extends FunctionalCasing { + + @Override + public String getTileEntityName() { + return "gt.multitileentity.multiblock.functional.sensor"; + } + + @Override + public float getPartModifier() { + return 1.3f; + } +} diff --git a/src/main/java/gregtech/common/tileentities/casings/upgrade/Inventory.java b/src/main/java/gregtech/common/tileentities/casings/upgrade/Inventory.java new file mode 100644 index 0000000000..c153e6c1c5 --- /dev/null +++ b/src/main/java/gregtech/common/tileentities/casings/upgrade/Inventory.java @@ -0,0 +1,108 @@ +package gregtech.common.tileentities.casings.upgrade; + +import java.util.UUID; + +import net.minecraft.nbt.NBTTagCompound; + +import com.gtnewhorizons.modularui.api.screen.ModularWindow.Builder; +import com.gtnewhorizons.modularui.api.screen.UIBuildContext; +import com.gtnewhorizons.modularui.common.widget.textfield.TextFieldWidget; + +import gregtech.api.enums.GT_Values.NBT; +import gregtech.api.multitileentity.interfaces.IMultiBlockController; +import gregtech.api.multitileentity.multiblock.casing.UpgradeCasing; +import gregtech.api.net.GT_Packet_MultiTileEntity; + +public class Inventory extends UpgradeCasing { + + public UUID mInventoryID; + public static final int INPUT = 0; + public static final int OUTPUT = 1; + public static final int BOTH = 2; + private String mInventoryName = "inventory"; + private int mInventorySize; + private int mType = BOTH; + + public String getInventoryName() { + return mInventoryName; + } + + public void setInventoryName(String aInventoryName) { + mInventoryName = aInventoryName; + } + + @Override + protected void customWork(IMultiBlockController aTarget) { + int tInvSize = mInventorySize; + if (mType == BOTH) { + tInvSize /= 2; + } + aTarget.registerInventory(mInventoryName, mInventoryID.toString(), tInvSize, mType); + } + + @Override + public String getTileEntityName() { + return "gt.multitileentity.multiblock.inventory"; + } + + @Override + public void readMultiTileNBT(NBTTagCompound aNBT) { + super.readMultiTileNBT(aNBT); + if (aNBT.hasKey(NBT.UPGRADE_INVENTORY_UUID)) { + mInventoryID = UUID.fromString(aNBT.getString(NBT.UPGRADE_INVENTORY_UUID)); + } else { + mInventoryID = UUID.randomUUID(); + } + mInventorySize = aNBT.getInteger(NBT.UPGRADE_INVENTORY_SIZE); + mInventoryName = aNBT.getString(NBT.UPGRADE_INVENTORY_NAME); + + } + + @Override + public void writeMultiTileNBT(NBTTagCompound aNBT) { + super.writeMultiTileNBT(aNBT); + aNBT.setString(NBT.UPGRADE_INVENTORY_UUID, mInventoryID.toString()); + aNBT.setString(NBT.UPGRADE_INVENTORY_NAME, mInventoryName); + } + + @Override + protected void onBaseTEDestroyed() { + super.onBaseTEDestroyed(); + unregisterInventories(); + } + + private void unregisterInventories() { + final IMultiBlockController controller = getTarget(false); + if (controller != null) { + controller.unregisterInventory(mInventoryName, mInventoryID.toString(), mType); + } + } + + @Override + public boolean hasGui(byte aSide) { + return true; + } + + @Override + public void addUIWidgets(Builder builder, UIBuildContext buildContext) { + builder.widget( + new TextFieldWidget().setGetter(() -> mInventoryName) + .setSetter((val) -> { + mInventoryName = val; + final IMultiBlockController controller = getTarget(false); + if (controller != null) { + controller.changeInventoryName(mInventoryName, mInventoryID.toString(), mType); + } + }) + .setSize(100, 25) + .setPos(50, 30)); + } + + @Override + public GT_Packet_MultiTileEntity getClientDataPacket() { + final GT_Packet_MultiTileEntity packet = super.getClientDataPacket(); + String name = getInventoryName(); + packet.setInventoryName(name); + return packet; + } +} diff --git a/src/main/java/gregtech/common/tileentities/casings/upgrade/InventoryUpgrade.java b/src/main/java/gregtech/common/tileentities/casings/upgrade/InventoryUpgrade.java deleted file mode 100644 index 06bb75c62f..0000000000 --- a/src/main/java/gregtech/common/tileentities/casings/upgrade/InventoryUpgrade.java +++ /dev/null @@ -1,108 +0,0 @@ -package gregtech.common.tileentities.casings.upgrade; - -import java.util.UUID; - -import net.minecraft.nbt.NBTTagCompound; - -import com.gtnewhorizons.modularui.api.screen.ModularWindow.Builder; -import com.gtnewhorizons.modularui.api.screen.UIBuildContext; -import com.gtnewhorizons.modularui.common.widget.textfield.TextFieldWidget; - -import gregtech.api.enums.GT_Values.NBT; -import gregtech.api.multitileentity.interfaces.IMultiBlockController; -import gregtech.api.multitileentity.multiblock.casing.UpgradeCasing; -import gregtech.api.net.GT_Packet_MultiTileEntity; - -public class InventoryUpgrade extends UpgradeCasing { - - public UUID mInventoryID; - public static final int INPUT = 0; - public static final int OUTPUT = 1; - public static final int BOTH = 2; - private String mInventoryName = "inventory"; - private int mInventorySize; - private int mType = BOTH; - - public String getInventoryName() { - return mInventoryName; - } - - public void setInventoryName(String aInventoryName) { - mInventoryName = aInventoryName; - } - - @Override - protected void customWork(IMultiBlockController aTarget) { - int tInvSize = mInventorySize; - if (mType == BOTH) { - tInvSize /= 2; - } - aTarget.registerInventory(mInventoryName, mInventoryID.toString(), tInvSize, mType); - } - - @Override - public String getTileEntityName() { - return "gt.multitileentity.multiblock.inventory"; - } - - @Override - public void readMultiTileNBT(NBTTagCompound aNBT) { - super.readMultiTileNBT(aNBT); - if (aNBT.hasKey(NBT.UPGRADE_INVENTORY_UUID)) { - mInventoryID = UUID.fromString(aNBT.getString(NBT.UPGRADE_INVENTORY_UUID)); - } else { - mInventoryID = UUID.randomUUID(); - } - mInventorySize = aNBT.getInteger(NBT.UPGRADE_INVENTORY_SIZE); - mInventoryName = aNBT.getString(NBT.UPGRADE_INVENTORY_NAME); - - } - - @Override - public void writeMultiTileNBT(NBTTagCompound aNBT) { - super.writeMultiTileNBT(aNBT); - aNBT.setString(NBT.UPGRADE_INVENTORY_UUID, mInventoryID.toString()); - aNBT.setString(NBT.UPGRADE_INVENTORY_NAME, mInventoryName); - } - - @Override - protected void onBaseTEDestroyed() { - super.onBaseTEDestroyed(); - unregisterInventories(); - } - - private void unregisterInventories() { - final IMultiBlockController controller = getTarget(false); - if (controller != null) { - controller.unregisterInventory(mInventoryName, mInventoryID.toString(), mType); - } - } - - @Override - public boolean hasGui(byte aSide) { - return true; - } - - @Override - public void addUIWidgets(Builder builder, UIBuildContext buildContext) { - builder.widget( - new TextFieldWidget().setGetter(() -> mInventoryName) - .setSetter((val) -> { - mInventoryName = val; - final IMultiBlockController controller = getTarget(false); - if (controller != null) { - controller.changeInventoryName(mInventoryName, mInventoryID.toString(), mType); - } - }) - .setSize(100, 25) - .setPos(50, 30)); - } - - @Override - public GT_Packet_MultiTileEntity getClientDataPacket() { - final GT_Packet_MultiTileEntity packet = super.getClientDataPacket(); - String name = getInventoryName(); - packet.setInventoryName(name); - return packet; - } -} diff --git a/src/main/java/gregtech/common/tileentities/machines/multiblock/AdvChemicalReactor.java b/src/main/java/gregtech/common/tileentities/machines/multiblock/AdvChemicalReactor.java new file mode 100644 index 0000000000..ca8cc6332b --- /dev/null +++ b/src/main/java/gregtech/common/tileentities/machines/multiblock/AdvChemicalReactor.java @@ -0,0 +1,432 @@ +package gregtech.common.tileentities.machines.multiblock; + +import static com.google.common.primitives.Ints.saturatedCast; +import static com.gtnewhorizon.structurelib.structure.StructureUtility.*; +import static gregtech.api.enums.Mods.*; +import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.*; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.stream.Collectors; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraftforge.common.util.Constants; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.IFluidTank; + +import org.apache.commons.lang3.ArrayUtils; + +import com.gtnewhorizon.structurelib.structure.IStructureDefinition; +import com.gtnewhorizon.structurelib.structure.StructureDefinition; +import com.gtnewhorizon.structurelib.util.Vec3Impl; +import com.gtnewhorizons.modularui.api.forge.ItemStackHandler; +import com.gtnewhorizons.modularui.api.math.Alignment; +import com.gtnewhorizons.modularui.api.screen.ModularWindow; +import com.gtnewhorizons.modularui.api.screen.UIBuildContext; +import com.gtnewhorizons.modularui.common.widget.ButtonWidget; +import com.gtnewhorizons.modularui.common.widget.MultiChildWidget; +import com.gtnewhorizons.modularui.common.widget.SlotGroup; +import com.gtnewhorizons.modularui.common.widget.TextWidget; + +import gregtech.api.GregTech_API; +import gregtech.api.enums.GT_Values; +import gregtech.api.enums.HeatingCoilLevel; +import gregtech.api.fluid.FluidTankGT; +import gregtech.api.gui.modularui.GT_UITextures; +import gregtech.api.logic.ComplexParallelProcessingLogic; +import gregtech.api.multitileentity.enums.GT_MultiTileCasing; +import gregtech.api.multitileentity.multiblock.base.ComplexParallelController; +import gregtech.api.util.GT_Multiblock_Tooltip_Builder; +import gregtech.api.util.GT_Recipe; +import gregtech.api.util.GT_StructureUtility; +import gregtech.common.tileentities.casings.upgrade.Inventory; + +public class AdvChemicalReactor extends ComplexParallelController { + + private static IStructureDefinition STRUCTURE_DEFINITION = null; + protected static final String STRUCTURE_PIECE_T1 = "T1"; + protected static final Vec3Impl STRUCTURE_OFFSET = new Vec3Impl(3, 1, 0); + protected static final int PROCESS_WINDOW_BASE_ID = 100; + protected static final int ITEM_WHITELIST_SLOTS = 8; + protected static final int FLUID_WHITELIST_SLOTS = 8; + protected static final int MAX_PROCESSES = 4; + protected int numberOfProcessors = MAX_PROCESSES; // TODO: Set this value depending on structure + protected HeatingCoilLevel coilTier; + protected final ArrayList> processWhitelists = new ArrayList<>(MAX_PROCESSES); + protected final ArrayList processWhitelistInventoryHandlers = new ArrayList<>(MAX_PROCESSES); + protected final ArrayList> processFluidWhiteLists = new ArrayList<>(MAX_PROCESSES); + protected boolean wasWhitelistOpened = false; + + public AdvChemicalReactor() { + super(); + for (int i = 0; i < MAX_PROCESSES; i++) { + processWhitelists.add(null); + processWhitelistInventoryHandlers.add(new ItemStackHandler(ITEM_WHITELIST_SLOTS)); + ArrayList processFluidTanks = new ArrayList<>(FLUID_WHITELIST_SLOTS); + for (int j = 0; j < FLUID_WHITELIST_SLOTS; j++) { + processFluidTanks.add(new FluidTankGT()); + } + processFluidWhiteLists.add(processFluidTanks); + } + processingLogic = new ComplexParallelProcessingLogic( + GT_Recipe.GT_Recipe_Map_LargeChemicalReactor.sChemicalRecipes, + MAX_PROCESSES); + } + + @Override + public void readMultiTileNBT(NBTTagCompound nbt) { + super.readMultiTileNBT(nbt); + final NBTTagCompound processWhiteLists = nbt.getCompoundTag("whiteLists"); + long capacity = 1000; + if (nbt.hasKey(GT_Values.NBT.TANK_CAPACITY)) { + capacity = saturatedCast(nbt.getLong(GT_Values.NBT.TANK_CAPACITY)); + } + for (int i = 0; i < MAX_PROCESSES; i++) { + registerInventory("processInventory" + i, "processInventory" + i, 8, Inventory.INPUT); + registerFluidInventory( + "processInventory" + i, + "processInventory" + i, + 8, + capacity, + maxParallel * 2L, + Inventory.INPUT); + if (processWhiteLists != null) { + final NBTTagCompound itemList = processWhiteLists.getCompoundTag("items" + i); + if (itemList != null) { + processWhitelistInventoryHandlers.get(i) + .deserializeNBT(itemList); + } + final NBTTagList fluidList = processWhiteLists.getTagList("fluids" + i, Constants.NBT.TAG_COMPOUND); + if (fluidList != null) { + for (int j = 0; j < fluidList.tagCount(); j++) { + final NBTTagCompound fluid = fluidList.getCompoundTagAt(j); + if (fluid != null) { + short index = fluid.getShort("s"); + FluidStack fluidStack = FluidStack.loadFluidStackFromNBT(fluid); + if (fluidStack != null) { + processFluidWhiteLists.get(i) + .get(index) + .fill(fluidStack, true); + } + } + } + } + } + } + } + + @Override + public void writeMultiTileNBT(NBTTagCompound nbt) { + super.writeMultiTileNBT(nbt); + final NBTTagCompound processWhiteLists = new NBTTagCompound(); + for (int i = 0; i < MAX_PROCESSES; i++) { + processWhiteLists.setTag( + "items" + i, + processWhitelistInventoryHandlers.get(i) + .serializeNBT()); + final NBTTagList fluidList = new NBTTagList(); + for (int j = 0; j < FLUID_WHITELIST_SLOTS; j++) { + final FluidStack fluidStack = processFluidWhiteLists.get(i) + .get(j) + .getFluid(); + if (fluidStack != null) { + final NBTTagCompound tag = new NBTTagCompound(); + tag.setByte("s", (byte) j); + fluidStack.writeToNBT(tag); + fluidList.appendTag(tag); + } + } + processWhiteLists.setTag("fluids" + i, fluidList); + } + nbt.setTag("whiteLists", processWhiteLists); + } + + @Override + public short getCasingRegistryID() { + return 0; + } + + @Override + public int getCasingMeta() { + return GT_MultiTileCasing.Chemical.getId(); + } + + @Override + public GT_Multiblock_Tooltip_Builder createTooltip() { + final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder(); + tt.addMachineType("Chemical Reactor") + .addInfo("Controller block for the Advanced Chemical Reactor") + .addInfo("Does not lose efficiency when overclocked") + .addInfo("Accepts fluids instead of fluid cells") + .addInfo("Can do multiple different recipes at once") + .addInfo("By using the whitelist filter a recipe can push its output") + .addInfo("to a different recipes input to chain them") + .addInfo(GT_Values.Authorminecraft7771) + .addSeparator() + .beginStructureBlock(5, 3, 3, false) + .addController("Front center") + .addCasingInfoExactly("PTFE Pipe Machine Casing", 8, false) + .addCasingInfoExactly("Heating Coils", 3, true) + .addCasingInfoExactly("EV+ Glass", 3, true) + .addCasingInfoExactly("Motor Casing", 3, true) + .addCasingInfoExactly("Chemical Casing", 27, false) + .toolTipFinisher("Gregtech"); + return tt; + } + + @Override + public Vec3Impl getStartingStructureOffset() { + return STRUCTURE_OFFSET; + } + + @Override + public boolean checkMachine() { + setCoilTier(HeatingCoilLevel.None); + setMaxComplexParallels(MAX_PROCESSES); + buildState.startBuilding(getStartingStructureOffset()); + boolean result = checkPiece(STRUCTURE_PIECE_T1, buildState.stopBuilding()); + return result && super.checkMachine(); + } + + @Override + public void construct(ItemStack trigger, boolean hintsOnly) { + buildState.startBuilding(getStartingStructureOffset()); + buildPiece(STRUCTURE_PIECE_T1, trigger, hintsOnly, buildState.stopBuilding()); + } + + @Override + public IStructureDefinition getStructureDefinition() { + if (STRUCTURE_DEFINITION == null) { + STRUCTURE_DEFINITION = StructureDefinition.builder() + .addShape( + STRUCTURE_PIECE_T1, + transpose( + new String[][] { { "CPCPC", "CCCCC", "CPCPC" }, { "CGC~C", "GWWWC", "CGCCC" }, + { "CPCPC", "CTTTC", "CPCPC" } })) + .addElement( + 'C', + addMultiTileCasing( + "gt.multitileentity.casings", + getCasingMeta(), + FLUID_IN | ITEM_IN | FLUID_OUT | ITEM_OUT | ENERGY_IN)) + .addElement('P', ofBlock(GregTech_API.sBlockCasings8, 1)) + .addElement('T', addMotorCasings(NOTHING)) + .addElement( + 'W', + GT_StructureUtility.ofCoil(AdvChemicalReactor::setCoilTier, AdvChemicalReactor::getCoilTier)) + .addElement( + 'G', + ofChain( + ofBlockUnlocalizedName(IndustrialCraft2.ID, "blockAlloyGlass", 0, true), + ofBlockUnlocalizedName(BartWorks.ID, "BW_GlasBlocks", 0, true), + ofBlockUnlocalizedName(BartWorks.ID, "BW_GlasBlocks2", 0, true), + ofBlockUnlocalizedName(Thaumcraft.ID, "blockCosmeticOpaque", 2, false))) + .build(); + } + return STRUCTURE_DEFINITION; + } + + @Override + protected FluidStack[] getInputFluids(int index) { + if (index < 0 || index >= MAX_PROCESSES) { + return null; + } + if (separateInputs) { + return ArrayUtils.addAll( + getFluidInputsForTankArray("processInventory" + index), + FluidTankGT.getFluidsFromTanks(inputTanks)); + } else { + return super.getInputFluids(index); + } + } + + @Override + protected ItemStack[] getInputItems(int index) { + if (index < 0 || index >= MAX_PROCESSES) { + return null; + } + if (separateInputs) { + return ArrayUtils.addAll( + getItemInputsForInventory("processInventory" + index), + inputInventory.getStacks() + .toArray(new ItemStack[0])); + } else { + return super.getInputItems(index); + } + } + + @Override + protected void outputItems(int index) { + ComplexParallelProcessingLogic processingLogic = getComplexProcessingLogic(); + if (processingLogic != null && index >= 0 && index < maxComplexParallels) { + for (int i = 0; i < MAX_PROCESSES; i++) { + // Regenerate whitelist, if it has been reset + if (processWhitelists.get(i) == null) { + generateWhitelist(i); + } + int outputIndex = i; + // Output items that are on the whitelist of this process + outputItems( + multiBlockInputInventory.get("processInventory" + i), + Arrays.stream(processingLogic.getOutputItems(index)) + .filter( + itemStack -> processWhitelists.get(outputIndex) + .contains(getWhitelistString(itemStack))) + .collect(Collectors.toList()) + .toArray(new ItemStack[0])); + } + // Output remaining items + if (processingLogic.getOutputItems(index) != null && processingLogic.getOutputItems(index).length > 0) { + outputItems(processingLogic.getOutputItems(index)); + } + } + } + + @Override + protected void outputFluids(int index) { + ComplexParallelProcessingLogic processingLogic = getComplexProcessingLogic(); + if (processingLogic != null && index >= 0 && index < maxComplexParallels) { + for (int i = 0; i < MAX_PROCESSES; i++) { + // Regenerate whitelist, if it has been reset + if (processWhitelists.get(i) == null) { + generateWhitelist(i); + } + int outputIndex = i; + // Output fluids that are on the whitelist of this process + outputFluids( + multiBlockInputTank.get("processInventory" + i), + Arrays.stream(processingLogic.getOutputFluids(index)) + .filter( + fluidStack -> processWhitelists.get(outputIndex) + .contains(getWhitelistString(fluidStack))) + .collect(Collectors.toList()) + .toArray(new FluidStack[0])); + } + // Output remaining fluids + if (processingLogic.getOutputFluids(index) != null && processingLogic.getOutputFluids(index).length > 0) { + outputFluids(processingLogic.getOutputFluids(index)); + } + } + } + + @Override + protected MultiChildWidget createMainPage() { + MultiChildWidget child = super.createMainPage(); + for (int i = 0; i < MAX_PROCESSES; i++) { + final int processIndex = i; + child.addChild( + new ButtonWidget().setPlayClickSound(true) + .setOnClick( + (clickData, widget) -> { + if (!widget.isClient()) widget.getContext() + .openSyncedWindow(PROCESS_WINDOW_BASE_ID + processIndex); + }) + .setBackground(GT_UITextures.BUTTON_STANDARD, GT_UITextures.OVERLAY_BUTTON_WHITELIST) + .setSize(18, 18) + .setPos(20 * i + 18, 18)); + } + return child; + } + + @Override + public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) { + super.addUIWidgets(builder, buildContext); + for (int i = 0; i < MAX_PROCESSES; i++) { + final int processIndex = i; + buildContext.addSyncedWindow( + PROCESS_WINDOW_BASE_ID + i, + (player) -> createProcessConfigWindow(player, processIndex)); + } + buildContext.addCloseListener(() -> { + // Reset HashSet, we will let it re-generate on next item output + if (wasWhitelistOpened) { + for (int i = 0; i < MAX_PROCESSES; i++) { + processWhitelists.set(i, null); + } + wasWhitelistOpened = false; + } + }); + } + + protected ModularWindow createProcessConfigWindow(final EntityPlayer player, final int processIndex) { + wasWhitelistOpened = true; + ModularWindow.Builder builder = ModularWindow.builder(86, 100); + builder.widget( + new TextWidget("Process " + processIndex).setTextAlignment(Alignment.Center) + .setPos(13, 7)); + builder.setBackground(GT_UITextures.BACKGROUND_SINGLEBLOCK_DEFAULT); + builder.widget( + SlotGroup.ofItemHandler(processWhitelistInventoryHandlers.get(processIndex), 4) + .startFromSlot(0) + .endAtSlot(ITEM_WHITELIST_SLOTS - 1) + .phantom(true) + .background(getGUITextureSet().getItemSlot()) + .build() + .setPos(7, 19)); + builder.widget( + SlotGroup.ofFluidTanks(processFluidWhiteLists.get(processIndex), 4) + .startFromSlot(0) + .endAtSlot(FLUID_WHITELIST_SLOTS - 1) + .phantom(true) + .build() + .setPos(7, 55)); + return builder.build(); + } + + @Override + public String getTileEntityName() { + return "gt.multitileentity.multiblock.advchemicalreactor"; + } + + @Override + public String getLocalName() { + return "Advanced Chemical Reactor"; + } + + public void setCoilTier(HeatingCoilLevel coilTier) { + this.coilTier = coilTier; + } + + public HeatingCoilLevel getCoilTier() { + return coilTier; + } + + @Override + protected boolean hasPerfectOverclock() { + return true; + } + + protected void generateWhitelist(int processIndex) { + HashSet whitelist = new HashSet<>(); + for (ItemStack itemStack : processWhitelistInventoryHandlers.get(processIndex) + .getStacks()) { + if (itemStack != null) { + whitelist.add(getWhitelistString(itemStack)); + } + } + for (IFluidTank tank : processFluidWhiteLists.get(processIndex)) { + if (tank.getFluid() != null) { + whitelist.add(getWhitelistString(tank.getFluid())); + } + } + processWhitelists.set(processIndex, whitelist); + } + + protected String getWhitelistString(ItemStack itemStack) { + if (itemStack != null) { + return itemStack.getUnlocalizedName(); + } + return null; + } + + protected String getWhitelistString(FluidStack fluidStack) { + if (fluidStack != null) { + return fluidStack.getUnlocalizedName(); + } + return null; + } +} diff --git a/src/main/java/gregtech/common/tileentities/machines/multiblock/CokeOven.java b/src/main/java/gregtech/common/tileentities/machines/multiblock/CokeOven.java new file mode 100644 index 0000000000..3e465bb6ae --- /dev/null +++ b/src/main/java/gregtech/common/tileentities/machines/multiblock/CokeOven.java @@ -0,0 +1,172 @@ +package gregtech.common.tileentities.machines.multiblock; + +import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.ITEM_IN; +import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.ITEM_OUT; + +import java.util.List; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.StatCollector; + +import com.gtnewhorizon.structurelib.structure.IStructureDefinition; +import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment; +import com.gtnewhorizon.structurelib.structure.StructureDefinition; +import com.gtnewhorizon.structurelib.util.Vec3Impl; +import com.gtnewhorizons.modularui.api.math.Alignment; +import com.gtnewhorizons.modularui.api.screen.ModularWindow; +import com.gtnewhorizons.modularui.api.screen.UIBuildContext; +import com.gtnewhorizons.modularui.common.internal.network.NetworkUtils; +import com.gtnewhorizons.modularui.common.widget.DrawableWidget; +import com.gtnewhorizons.modularui.common.widget.SlotWidget; +import com.gtnewhorizons.modularui.common.widget.TextWidget; + +import gregtech.GT_Mod; +import gregtech.api.enums.GT_Values; +import gregtech.api.logic.PollutionLogic; +import gregtech.api.logic.ProcessingLogic; +import gregtech.api.logic.interfaces.PollutionLogicHost; +import gregtech.api.logic.interfaces.ProcessingLogicHost; +import gregtech.api.multitileentity.enums.GT_MultiTileCasing; +import gregtech.api.multitileentity.multiblock.base.Controller; +import gregtech.api.util.GT_Multiblock_Tooltip_Builder; +import gregtech.common.tileentities.machines.multiblock.logic.CokeOvenProcessingLogic; + +public class CokeOven extends Controller implements PollutionLogicHost, ProcessingLogicHost { + + private static IStructureDefinition STRUCTURE_DEFINITION = null; + private static final Vec3Impl OFFSET = new Vec3Impl(1, 1, 0); + private static final String MAIN = "Main"; + private static final PollutionLogic POLLUTION_LOGIC = new PollutionLogic().setPollutionAmount(10); + private final ProcessingLogic PROCESSING_LOGIC = new CokeOvenProcessingLogic(); + + public CokeOven() { + super(); + setElectric(false); + } + + @Override + public void construct(ItemStack trigger, boolean hintsOnly) { + buildState.startBuilding(getStartingStructureOffset()); + buildPiece(MAIN, trigger, hintsOnly, buildState.stopBuilding()); + } + + @Override + public boolean checkMachine() { + buildState.startBuilding(getStartingStructureOffset()); + return checkPiece(MAIN, buildState.stopBuilding()); + } + + @Override + public int survivalConstruct(ItemStack trigger, int elementBudget, ISurvivalBuildEnvironment env) { + buildState.startBuilding(getStartingStructureOffset()); + return survivalBuildPiece(MAIN, trigger, buildState.stopBuilding(), elementBudget, env, false); + } + + @Override + public short getCasingRegistryID() { + return 0; + } + + @Override + public int getCasingMeta() { + return GT_MultiTileCasing.CokeOven.getId(); + } + + @Override + protected GT_Multiblock_Tooltip_Builder createTooltip() { + final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder(); + tt.addMachineType("Coke Oven") + .addInfo("Used for charcoal") + .beginStructureBlock(3, 3, 3, true) + .addCasingInfoExactly("Coke Oven Bricks", 25, false) + .addPollutionAmount(POLLUTION_LOGIC.getPollutionAmount()) + .toolTipFinisher(GT_Values.AuthorBlueWeabo); + return tt; + } + + @Override + public Vec3Impl getStartingStructureOffset() { + return OFFSET; + } + + @Override + public IStructureDefinition getStructureDefinition() { + if (STRUCTURE_DEFINITION == null) { + STRUCTURE_DEFINITION = StructureDefinition.builder() + .addShape( + MAIN, + new String[][] { { "AAA", "A~A", "AAA" }, { "AAA", "A-A", "AAA" }, { "AAA", "AAA", "AAA" } }) + .addElement('A', addMultiTileCasing("gt.multitileentity.casings", getCasingMeta(), ITEM_IN | ITEM_OUT)) + .build(); + } + return STRUCTURE_DEFINITION; + } + + @Override + protected boolean hasFluidInput() { + return false; + } + + @Override + public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) { + builder.widget( + new SlotWidget(inputInventory, 0).setPos(18, 18) + .setSize(18, 18)); + builder.widget( + new SlotWidget(outputInventory, 0).setPos(36, 36) + .setSize(18, 18)); + builder.widget(createButtons()); + } + + @Override + protected void addTitleTextStyle(ModularWindow.Builder builder, String title) { + final int TAB_PADDING = 3; + final int TITLE_PADDING = 2; + int titleWidth = 0, titleHeight = 0; + if (NetworkUtils.isClient()) { + final FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer; + // noinspection unchecked + final List titleLines = fontRenderer + .listFormattedStringToWidth(title, getGUIWidth() - (TAB_PADDING + TITLE_PADDING) * 2); + titleWidth = titleLines.size() > 1 ? getGUIWidth() - (TAB_PADDING + TITLE_PADDING) * 2 + : fontRenderer.getStringWidth(title); + // noinspection PointlessArithmeticExpression + titleHeight = titleLines.size() * fontRenderer.FONT_HEIGHT + (titleLines.size() - 1); + } + + final DrawableWidget tab = new DrawableWidget(); + final TextWidget text = new TextWidget(title).setDefaultColor(getTitleColor()) + .setTextAlignment(Alignment.CenterLeft) + .setMaxWidth(titleWidth); + if (GT_Mod.gregtechproxy.mTitleTabStyle == 1) { + tab.setDrawable(getGUITextureSet().getTitleTabAngular()) + .setPos(0, -(titleHeight + TAB_PADDING) + 1) + .setSize(getGUIWidth(), titleHeight + TAB_PADDING * 2); + text.setPos(TAB_PADDING + TITLE_PADDING, -titleHeight + TAB_PADDING); + } else { + tab.setDrawable(getGUITextureSet().getTitleTabDark()) + .setPos(0, -(titleHeight + TAB_PADDING * 2) + 1) + .setSize(titleWidth + (TAB_PADDING + TITLE_PADDING) * 2, titleHeight + TAB_PADDING * 2 - 1); + text.setPos(TAB_PADDING + TITLE_PADDING, -titleHeight); + } + builder.widget(tab) + .widget(text); + } + + @Override + public String getLocalName() { + return StatCollector.translateToLocal("gt.multiBlock.controller.cokeOven"); + } + + @Override + public PollutionLogic getPollutionLogic() { + return POLLUTION_LOGIC; + } + + @Override + public ProcessingLogic getProcessingLogic() { + return PROCESSING_LOGIC; + } +} diff --git a/src/main/java/gregtech/common/tileentities/machines/multiblock/Macerator.java b/src/main/java/gregtech/common/tileentities/machines/multiblock/Macerator.java new file mode 100644 index 0000000000..5d837f1150 --- /dev/null +++ b/src/main/java/gregtech/common/tileentities/machines/multiblock/Macerator.java @@ -0,0 +1,175 @@ +package gregtech.common.tileentities.machines.multiblock; + +import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofChain; +import static com.gtnewhorizon.structurelib.structure.StructureUtility.transpose; +import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.ENERGY_IN; +import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.FLUID_IN; +import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.FLUID_OUT; +import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.ITEM_IN; +import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.ITEM_OUT; +import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.NOTHING; + +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; + +import org.apache.commons.lang3.tuple.Pair; + +import com.gtnewhorizon.structurelib.structure.IStructureDefinition; +import com.gtnewhorizon.structurelib.structure.StructureDefinition; +import com.gtnewhorizon.structurelib.util.Vec3Impl; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import gregtech.api.enums.SoundResource; +import gregtech.api.enums.TierEU; +import gregtech.api.multitileentity.multiblock.base.StackableController; +import gregtech.api.util.GT_Multiblock_Tooltip_Builder; +import gregtech.api.util.GT_Recipe; +import gregtech.api.util.GT_Recipe.GT_Recipe_Map; + +public class Macerator extends StackableController { + + private static IStructureDefinition STRUCTURE_DEFINITION = null; + + public Macerator() { + super(); + } + + @Override + public String getTileEntityName() { + return "gt.multitileentity.multiblock.macerator"; + } + + @Override + public IStructureDefinition getStructureDefinition() { + if (STRUCTURE_DEFINITION == null) { + STRUCTURE_DEFINITION = StructureDefinition.builder() + .addShape(STACKABLE_TOP, transpose(new String[][] { { " CCC ", "CCCCC", "CCCCC", "CCCCC", " CCC " }, })) + .addShape( + STACKABLE_MIDDLE, + transpose(new String[][] { { " BBB ", " B---B ", "DC---CD", " B---B ", " BBB " }, })) + .addShape( + STACKABLE_BOTTOM, + transpose(new String[][] { { " G~F ", "AAAAA", "AAAAA", "AAAAA", " AAA " }, })) + .addElement('A', ofChain(addMultiTileCasing("gt.multitileentity.casings", getCasingMeta(), ENERGY_IN))) + .addElement( + 'B', + ofChain( + addMultiTileCasing( + "gt.multitileentity.casings", + getCasingMeta(), + FLUID_IN | ITEM_IN | FLUID_OUT | ITEM_OUT))) + .addElement('C', addMultiTileCasing("gt.multitileentity.casings", getCasingMeta(), NOTHING)) + .addElement('D', addMultiTileCasing("gt.multitileentity.casings", getCasingMeta(), NOTHING)) + .addElement('F', addMotorCasings(NOTHING)) + .addElement('G', addMultiTileCasing("gt.multitileentity.component.casings", 10000, NOTHING)) + .build(); + } + return STRUCTURE_DEFINITION; + } + + @Override + public short getCasingRegistryID() { + return 0; + } + + @Override + public int getCasingMeta() { + return 18000; + } + + @Override + public boolean hasTop() { + return true; + } + + @Override + protected GT_Multiblock_Tooltip_Builder createTooltip() { + final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder(); + tt.addMachineType("Macerator") + .addInfo("Controller for the Macerator") + .addSeparator() + .beginVariableStructureBlock(7, 9, 2 + getMinStacks(), 2 + getMaxStacks(), 7, 9, true) + .addController("Bottom Front Center") + .addCasingInfoExactly("Test Casing", 60, false) + .addEnergyHatch("Any bottom layer casing") + .addInputHatch("Any non-optional external facing casing on the stacks") + .addInputBus("Any non-optional external facing casing on the stacks") + .addOutputHatch("Any non-optional external facing casing on the stacks") + .addOutputBus("Any non-optional external facing casing on the stacks") + .addStructureInfo( + String.format("Stackable middle stacks between %d-%d time(s).", getMinStacks(), getMaxStacks())) + .toolTipFinisher("Wildcard"); + return tt; + } + + @Override + public int getMinStacks() { + return 1; + } + + @Override + public int getMaxStacks() { + return 10; + } + + @Override + public Vec3Impl getStartingStructureOffset() { + return new Vec3Impl(2, 0, 0); + } + + @Override + public Vec3Impl getStartingStackOffset() { + return new Vec3Impl(1, 1, 0); + } + + @Override + public Vec3Impl getPerStackOffset() { + return new Vec3Impl(0, 1, 0); + } + + @Override + public Vec3Impl getAfterLastStackOffset() { + return new Vec3Impl(-1, 0, 0); + } + + @Override + protected boolean checkRecipe() { + if (isSeparateInputs()) { + for (Pair tItemInputs : getItemInputsForEachInventory()) { + if (processRecipe(tItemInputs.getLeft(), tItemInputs.getRight())) { + return true; + } + } + return false; + } else { + ItemStack[] tItemInputs = getInventoriesForInput().getStacks() + .toArray(new ItemStack[0]); + return processRecipe(tItemInputs, null); + } + } + + private boolean processRecipe(ItemStack[] aItemInputs, String aInventory) { + GT_Recipe_Map tRecipeMap = GT_Recipe_Map.sMaceratorRecipes; + GT_Recipe tRecipe = tRecipeMap.findRecipe(this, false, TierEU.IV, null, aItemInputs); + if (tRecipe == null) { + return false; + } + + if (!tRecipe.isRecipeInputEqual(true, false, 1, null, aItemInputs)) { + return false; + } + + setDuration(tRecipe.mDuration); + setEut(tRecipe.mEUt); + + setItemOutputs(aInventory, tRecipe.mOutputs); + return true; + } + + @SideOnly(Side.CLIENT) + @Override + protected ResourceLocation getActivitySoundLoop() { + return SoundResource.IC2_MACHINES_MACERATOR_OP.resourceLocation; + } +} diff --git a/src/main/java/gregtech/common/tileentities/machines/multiblock/MultiBlock_CokeOven.java b/src/main/java/gregtech/common/tileentities/machines/multiblock/MultiBlock_CokeOven.java deleted file mode 100644 index 66e9333961..0000000000 --- a/src/main/java/gregtech/common/tileentities/machines/multiblock/MultiBlock_CokeOven.java +++ /dev/null @@ -1,173 +0,0 @@ -package gregtech.common.tileentities.machines.multiblock; - -import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.ITEM_IN; -import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.ITEM_OUT; - -import java.util.List; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.FontRenderer; -import net.minecraft.item.ItemStack; -import net.minecraft.util.StatCollector; - -import com.gtnewhorizon.structurelib.structure.IStructureDefinition; -import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment; -import com.gtnewhorizon.structurelib.structure.StructureDefinition; -import com.gtnewhorizon.structurelib.util.Vec3Impl; -import com.gtnewhorizons.modularui.api.math.Alignment; -import com.gtnewhorizons.modularui.api.screen.ModularWindow; -import com.gtnewhorizons.modularui.api.screen.UIBuildContext; -import com.gtnewhorizons.modularui.common.internal.network.NetworkUtils; -import com.gtnewhorizons.modularui.common.widget.DrawableWidget; -import com.gtnewhorizons.modularui.common.widget.SlotWidget; -import com.gtnewhorizons.modularui.common.widget.TextWidget; - -import gregtech.GT_Mod; -import gregtech.api.enums.GT_Values; -import gregtech.api.logic.PollutionLogic; -import gregtech.api.logic.ProcessingLogic; -import gregtech.api.logic.interfaces.PollutionLogicHost; -import gregtech.api.logic.interfaces.ProcessingLogicHost; -import gregtech.api.multitileentity.enums.GT_MultiTileCasing; -import gregtech.api.multitileentity.multiblock.base.MultiBlockController; -import gregtech.api.util.GT_Multiblock_Tooltip_Builder; -import gregtech.common.tileentities.machines.multiblock.logic.CokeOvenProcessingLogic; - -public class MultiBlock_CokeOven extends MultiBlockController - implements PollutionLogicHost, ProcessingLogicHost { - - private static IStructureDefinition STRUCTURE_DEFINITION = null; - private static final Vec3Impl OFFSET = new Vec3Impl(1, 1, 0); - private static final String MAIN = "Main"; - private static final PollutionLogic POLLUTION_LOGIC = new PollutionLogic().setPollutionAmount(10); - private final ProcessingLogic PROCESSING_LOGIC = new CokeOvenProcessingLogic(); - - public MultiBlock_CokeOven() { - super(); - setElectric(false); - } - - @Override - public void construct(ItemStack trigger, boolean hintsOnly) { - buildState.startBuilding(getStartingStructureOffset()); - buildPiece(MAIN, trigger, hintsOnly, buildState.stopBuilding()); - } - - @Override - public boolean checkMachine() { - buildState.startBuilding(getStartingStructureOffset()); - return checkPiece(MAIN, buildState.stopBuilding()); - } - - @Override - public int survivalConstruct(ItemStack trigger, int elementBudget, ISurvivalBuildEnvironment env) { - buildState.startBuilding(getStartingStructureOffset()); - return survivalBuildPiece(MAIN, trigger, buildState.stopBuilding(), elementBudget, env, false); - } - - @Override - public short getCasingRegistryID() { - return 0; - } - - @Override - public short getCasingMeta() { - return GT_MultiTileCasing.CokeOven.getId(); - } - - @Override - protected GT_Multiblock_Tooltip_Builder createTooltip() { - final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder(); - tt.addMachineType("Coke Oven") - .addInfo("Used for charcoal") - .beginStructureBlock(3, 3, 3, true) - .addCasingInfoExactly("Coke Oven Bricks", 25, false) - .addPollutionAmount(POLLUTION_LOGIC.getPollutionAmount()) - .toolTipFinisher(GT_Values.AuthorBlueWeabo); - return tt; - } - - @Override - public Vec3Impl getStartingStructureOffset() { - return OFFSET; - } - - @Override - public IStructureDefinition getStructureDefinition() { - if (STRUCTURE_DEFINITION == null) { - STRUCTURE_DEFINITION = StructureDefinition.builder() - .addShape( - MAIN, - new String[][] { { "AAA", "A~A", "AAA" }, { "AAA", "A-A", "AAA" }, { "AAA", "AAA", "AAA" } }) - .addElement('A', addMultiTileCasing("gt.multitileentity.casings", getCasingMeta(), ITEM_IN | ITEM_OUT)) - .build(); - } - return STRUCTURE_DEFINITION; - } - - @Override - protected boolean hasFluidInput() { - return false; - } - - @Override - public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) { - builder.widget( - new SlotWidget(inputInventory, 0).setPos(18, 18) - .setSize(18, 18)); - builder.widget( - new SlotWidget(outputInventory, 0).setPos(36, 36) - .setSize(18, 18)); - builder.widget(createButtons()); - } - - @Override - protected void addTitleTextStyle(ModularWindow.Builder builder, String title) { - final int TAB_PADDING = 3; - final int TITLE_PADDING = 2; - int titleWidth = 0, titleHeight = 0; - if (NetworkUtils.isClient()) { - final FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer; - // noinspection unchecked - final List titleLines = fontRenderer - .listFormattedStringToWidth(title, getGUIWidth() - (TAB_PADDING + TITLE_PADDING) * 2); - titleWidth = titleLines.size() > 1 ? getGUIWidth() - (TAB_PADDING + TITLE_PADDING) * 2 - : fontRenderer.getStringWidth(title); - // noinspection PointlessArithmeticExpression - titleHeight = titleLines.size() * fontRenderer.FONT_HEIGHT + (titleLines.size() - 1); - } - - final DrawableWidget tab = new DrawableWidget(); - final TextWidget text = new TextWidget(title).setDefaultColor(getTitleColor()) - .setTextAlignment(Alignment.CenterLeft) - .setMaxWidth(titleWidth); - if (GT_Mod.gregtechproxy.mTitleTabStyle == 1) { - tab.setDrawable(getGUITextureSet().getTitleTabAngular()) - .setPos(0, -(titleHeight + TAB_PADDING) + 1) - .setSize(getGUIWidth(), titleHeight + TAB_PADDING * 2); - text.setPos(TAB_PADDING + TITLE_PADDING, -titleHeight + TAB_PADDING); - } else { - tab.setDrawable(getGUITextureSet().getTitleTabDark()) - .setPos(0, -(titleHeight + TAB_PADDING * 2) + 1) - .setSize(titleWidth + (TAB_PADDING + TITLE_PADDING) * 2, titleHeight + TAB_PADDING * 2 - 1); - text.setPos(TAB_PADDING + TITLE_PADDING, -titleHeight); - } - builder.widget(tab) - .widget(text); - } - - @Override - public String getLocalName() { - return StatCollector.translateToLocal("gt.multiBlock.controller.cokeOven"); - } - - @Override - public PollutionLogic getPollutionLogic() { - return POLLUTION_LOGIC; - } - - @Override - public ProcessingLogic getProcessingLogic() { - return PROCESSING_LOGIC; - } -} diff --git a/src/main/java/gregtech/common/tileentities/machines/multiblock/MultiBlock_Macerator.java b/src/main/java/gregtech/common/tileentities/machines/multiblock/MultiBlock_Macerator.java deleted file mode 100644 index c2bf782d40..0000000000 --- a/src/main/java/gregtech/common/tileentities/machines/multiblock/MultiBlock_Macerator.java +++ /dev/null @@ -1,216 +0,0 @@ -package gregtech.common.tileentities.machines.multiblock; - -import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofChain; -import static com.gtnewhorizon.structurelib.structure.StructureUtility.transpose; -import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASINGS; -import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ELECTRIC_BLAST_FURNACE; -import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ELECTRIC_BLAST_FURNACE_ACTIVE; -import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ELECTRIC_BLAST_FURNACE_ACTIVE_GLOW; -import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ELECTRIC_BLAST_FURNACE_GLOW; -import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.ENERGY_IN; -import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.FLUID_IN; -import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.FLUID_OUT; -import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.ITEM_IN; -import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.ITEM_OUT; -import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.NOTHING; - -import net.minecraft.block.Block; -import net.minecraft.item.ItemStack; -import net.minecraft.util.ResourceLocation; - -import org.apache.commons.lang3.tuple.Pair; - -import com.gtnewhorizon.structurelib.structure.IStructureDefinition; -import com.gtnewhorizon.structurelib.structure.StructureDefinition; -import com.gtnewhorizon.structurelib.util.Vec3Impl; - -import gregtech.api.enums.SoundResource; -import gregtech.api.enums.TierEU; -import gregtech.api.interfaces.ITexture; -import gregtech.api.multitileentity.multiblock.base.MultiBlock_Stackable; -import gregtech.api.render.TextureFactory; -import gregtech.api.util.GT_Multiblock_Tooltip_Builder; -import gregtech.api.util.GT_Recipe; -import gregtech.api.util.GT_Recipe.GT_Recipe_Map; - -public class MultiBlock_Macerator extends MultiBlock_Stackable { - - private static IStructureDefinition STRUCTURE_DEFINITION = null; - - public MultiBlock_Macerator() { - super(); - } - - @Override - public String getTileEntityName() { - return "gt.multitileentity.multiblock.macerator"; - } - - @Override - public IStructureDefinition getStructureDefinition() { - if (STRUCTURE_DEFINITION == null) { - STRUCTURE_DEFINITION = StructureDefinition.builder() - .addShape(STACKABLE_TOP, transpose(new String[][] { { " CCC ", "CCCCC", "CCCCC", "CCCCC", " CCC " }, })) - .addShape( - STACKABLE_MIDDLE, - transpose(new String[][] { { " BBB ", " B---B ", "DC---CD", " B---B ", " BBB " }, })) - .addShape( - STACKABLE_BOTTOM, - transpose(new String[][] { { " G~F ", "AAAAA", "AAAAA", "AAAAA", " AAA " }, })) - .addElement('A', ofChain(addMultiTileCasing("gt.multitileentity.casings", getCasingMeta(), ENERGY_IN))) - .addElement( - 'B', - ofChain( - addMultiTileCasing( - "gt.multitileentity.casings", - getCasingMeta(), - FLUID_IN | ITEM_IN | FLUID_OUT | ITEM_OUT))) - .addElement('C', addMultiTileCasing("gt.multitileentity.casings", getCasingMeta(), NOTHING)) - .addElement('D', addMultiTileCasing("gt.multitileentity.casings", getCasingMeta(), NOTHING)) - .addElement( - 'F', - ofChain( - addMultiTileCasing("gt.multitileentity.casings", 20001, NOTHING), - addMultiTileCasing("gt.multitileentity.casings", 20002, NOTHING))) - .addElement('G', addMultiTileCasing("gt.multitileentity.casings", 10000, NOTHING)) - .build(); - } - return STRUCTURE_DEFINITION; - } - - @Override - public short getCasingRegistryID() { - return 0; - } - - @Override - public short getCasingMeta() { - return 18000; - } - - @Override - public boolean hasTop() { - return true; - } - - @Override - protected GT_Multiblock_Tooltip_Builder createTooltip() { - final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder(); - tt.addMachineType("Macerator") - .addInfo("Controller for the Macerator") - .addSeparator() - .beginVariableStructureBlock(7, 9, 2 + getMinStacks(), 2 + getMaxStacks(), 7, 9, true) - .addController("Bottom Front Center") - .addCasingInfoExactly("Test Casing", 60, false) - .addEnergyHatch("Any bottom layer casing") - .addInputHatch("Any non-optional external facing casing on the stacks") - .addInputBus("Any non-optional external facing casing on the stacks") - .addOutputHatch("Any non-optional external facing casing on the stacks") - .addOutputBus("Any non-optional external facing casing on the stacks") - .addStructureInfo( - String.format("Stackable middle stacks between %d-%d time(s).", getMinStacks(), getMaxStacks())) - .toolTipFinisher("Wildcard"); - return tt; - } - - @Override - public int getMinStacks() { - return 1; - } - - @Override - public int getMaxStacks() { - return 10; - } - - @Override - public Vec3Impl getStartingStructureOffset() { - return new Vec3Impl(2, 0, 0); - } - - @Override - public Vec3Impl getStartingStackOffset() { - return new Vec3Impl(1, 1, 0); - } - - @Override - public Vec3Impl getPerStackOffset() { - return new Vec3Impl(0, 1, 0); - } - - @Override - public Vec3Impl getAfterLastStackOffset() { - return new Vec3Impl(-1, 0, 0); - } - - @Override - public ITexture[] getTexture(Block aBlock, byte aSide, boolean isActive, int aRenderPass) { - // TODO: MTE(Texture) - if (facing == aSide) { - return new ITexture[] { - // Base Texture - MACHINE_CASINGS[1][0], - // Active - isActive() ? TextureFactory.builder() - .addIcon(OVERLAY_FRONT_ELECTRIC_BLAST_FURNACE_ACTIVE) - .extFacing() - .build() - : TextureFactory.builder() - .addIcon(OVERLAY_FRONT_ELECTRIC_BLAST_FURNACE) - .extFacing() - .build(), - // Active Glow - isActive() ? TextureFactory.builder() - .addIcon(OVERLAY_FRONT_ELECTRIC_BLAST_FURNACE_ACTIVE_GLOW) - .extFacing() - .glow() - .build() - : TextureFactory.builder() - .addIcon(OVERLAY_FRONT_ELECTRIC_BLAST_FURNACE_GLOW) - .extFacing() - .glow() - .build() }; - } - // Base Texture - return new ITexture[] { MACHINE_CASINGS[1][0] }; - } - - @Override - protected boolean checkRecipe() { - if (isSeparateInputs()) { - for (Pair tItemInputs : getItemInputsForEachInventory()) { - if (processRecipe(tItemInputs.getLeft(), tItemInputs.getRight())) { - return true; - } - } - return false; - } else { - ItemStack[] tItemInputs = getInventoriesForInput().getStacks() - .toArray(new ItemStack[0]); - return processRecipe(tItemInputs, null); - } - } - - private boolean processRecipe(ItemStack[] aItemInputs, String aInventory) { - GT_Recipe_Map tRecipeMap = GT_Recipe_Map.sMaceratorRecipes; - GT_Recipe tRecipe = tRecipeMap.findRecipe(this, false, TierEU.IV, null, aItemInputs); - if (tRecipe == null) { - return false; - } - - if (!tRecipe.isRecipeInputEqual(true, false, 1, null, aItemInputs)) { - return false; - } - - setDuration(tRecipe.mDuration); - setEut(tRecipe.mEUt); - - setItemOutputs(aInventory, tRecipe.mOutputs); - return true; - } - - @Override - protected ResourceLocation getActivitySoundLoop() { - return SoundResource.IC2_MACHINES_MACERATOR_OP.resourceLocation; - } -} diff --git a/src/main/java/gregtech/loaders/preload/GT_Loader_MultiTileEntities.java b/src/main/java/gregtech/loaders/preload/GT_Loader_MultiTileEntities.java index 9bb65b2230..e8935c707d 100644 --- a/src/main/java/gregtech/loaders/preload/GT_Loader_MultiTileEntities.java +++ b/src/main/java/gregtech/loaders/preload/GT_Loader_MultiTileEntities.java @@ -2,100 +2,942 @@ package gregtech.loaders.preload; import static gregtech.GT_Mod.GT_FML_LOGGER; import static gregtech.api.multitileentity.enums.GT_MultiTileCasing.*; +import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.*; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import gregtech.api.enums.Materials; import gregtech.api.enums.MaterialsUEVplus; +import gregtech.api.enums.Mods; import gregtech.api.multitileentity.MultiTileEntityBlock; import gregtech.api.multitileentity.MultiTileEntityRegistry; import gregtech.api.multitileentity.multiblock.base.WallShareablePart; import gregtech.api.multitileentity.multiblock.casing.BasicCasing; -import gregtech.common.tileentities.casings.functional.MotorCasing; -import gregtech.common.tileentities.casings.upgrade.InventoryUpgrade; -import gregtech.common.tileentities.machines.multiblock.MultiBlock_CokeOven; -import gregtech.common.tileentities.machines.multiblock.MultiBlock_Macerator; +import gregtech.common.tileentities.casings.functional.Conveyor; +import gregtech.common.tileentities.casings.functional.Emitter; +import gregtech.common.tileentities.casings.functional.FieldGenerator; +import gregtech.common.tileentities.casings.functional.Motor; +import gregtech.common.tileentities.casings.functional.Piston; +import gregtech.common.tileentities.casings.functional.Pump; +import gregtech.common.tileentities.casings.functional.RobotArm; +import gregtech.common.tileentities.casings.functional.Sensor; +import gregtech.common.tileentities.casings.upgrade.Inventory; +import gregtech.common.tileentities.machines.multiblock.AdvChemicalReactor; +import gregtech.common.tileentities.machines.multiblock.CokeOven; +import gregtech.common.tileentities.machines.multiblock.Macerator; public class GT_Loader_MultiTileEntities implements Runnable { - public static int CASING_REGISTRY = 0; + public static final String COMPONENT_CASING_REGISTRY = "gt.multitileentity.component.casings"; + public static final String CASING_REGISTRY = "gt.multitileentity.casings"; + public static final String MACHINE_REGISTRY = "gt.multitileentity.controllers"; @Override public void run() { + if (Mods.NewHorizonsCoreMod.isModLoaded()) { + return; + } GT_FML_LOGGER.info("GT_Mod: Registering MultiTileEntities"); - // registerMachines(); - // registerCasings(); - + registerMachines(); + registerCasings(); + registerComponentCasings(); } private static void registerMachines() { + final MultiTileEntityRegistry machineRegistry = new MultiTileEntityRegistry(MACHINE_REGISTRY); final MultiTileEntityBlock machine = MultiTileEntityBlock .getOrCreate("GregTech", "machine", Material.iron, Block.soundTypeMetal, "wrench", 0, 0, 15, true, true); - final MultiTileEntityRegistry machineRegistry = new MultiTileEntityRegistry("gt.multitileentity.controllers"); // Disable for now - machineRegistry.create(1000, MultiBlock_Macerator.class) + machineRegistry.create(1000, Macerator.class) .name("Large Macerator") .category("Multiblock Controller") .setBlock(machine) .material(Materials.Iron) - .texture("metalwall") + .textureFolder("macerator") .tankCapacity(128000L) .inputInventorySize(16) .outputInventorySize(16) .register(); - machineRegistry.create(0, MultiBlock_CokeOven.class) + machineRegistry.create(0, CokeOven.class) .name("Coke Oven") .category("MultiblockController") .setBlock(machine) - .texture("cokeOven") + .textureFolder("cokeOven") .inputInventorySize(1) .outputInventorySize(1) .register(); + machineRegistry.create(1, AdvChemicalReactor.class) + .name("Advanced Chemical Reactor") + .category("MultiblockController") + .setBlock(machine) + // TODO: Texture + .textureFolder("advChemicalReactor") + .inputInventorySize(16) + .outputInventorySize(16) + .tankCapacity(128000L) + .register(); } private static void registerCasings() { - final MultiTileEntityRegistry casingRegistry = new MultiTileEntityRegistry("gt.multitileentity.casings"); + final MultiTileEntityRegistry casingRegistry = new MultiTileEntityRegistry(CASING_REGISTRY); final MultiTileEntityBlock casing = MultiTileEntityBlock .getOrCreate("GregTech", "casing", Material.iron, Block.soundTypeMetal, "wrench", 0, 0, 15, true, true); casingRegistry.create(CokeOven.getId(), WallShareablePart.class) .name("Coke Oven Bricks") .category("MultiBlock Casing") .setBlock(casing) - .texture("cokeOven") + .textureFolder("cokeOven") + .register(); + casingRegistry.create(Chemical.getId(), BasicCasing.class) + .name("Chemical Casing") + .category("MultiBlock Casing") + .setBlock(casing) + .textureFolder("advChemicalReactor") .register(); casingRegistry.create(18000, BasicCasing.class) .name("Test Casing") .category("Multiblock Casing") .setBlock(casing) .material(Materials.Cobalt) - .texture("metalwall") + .textureFolder("macerator") .register(); - casingRegistry.create(20001, InventoryUpgrade.class) + + } + + private static void registerComponentCasings() { + final MultiTileEntityRegistry componentCasingRegistry = new MultiTileEntityRegistry(COMPONENT_CASING_REGISTRY); + final MultiTileEntityBlock componentCasing = MultiTileEntityBlock.getOrCreate( + "GregTech", + "componentCasing", + Material.iron, + Block.soundTypeMetal, + "wrench", + 0, + 0, + 15, + true, + true); + registerMotorCasings(componentCasingRegistry, componentCasing); + registerPumpCasings(componentCasingRegistry, componentCasing); + registerPistonCasings(componentCasingRegistry, componentCasing); + registerRobotArmCasings(componentCasingRegistry, componentCasing); + registerConveyorCasings(componentCasingRegistry, componentCasing); + registerEmitterCasings(componentCasingRegistry, componentCasing); + registerSensorCasings(componentCasingRegistry, componentCasing); + registerFieldGeneratorCasings(componentCasingRegistry, componentCasing); + + componentCasingRegistry.create(20001, Inventory.class) .name("Inventory Upgrade LV") - .category("MultiBlock Special Casing") - .setBlock(casing) + .category("MultiBlock Upgrade Casing") + .setBlock(componentCasing) .material(MaterialsUEVplus.SpaceTime) - .texture("metalwall") + .textureFolder("macerator") .upgradeInventorySize(16) .tier(1) .register(); - casingRegistry.create(20002, InventoryUpgrade.class) + componentCasingRegistry.create(20002, Inventory.class) .name("Inventory Upgrade MV") .category("MultiBlock Upgrade Casing") - .setBlock(casing) + .setBlock(componentCasing) .material(Materials.Neutronium) - .texture("metalwall") + .textureFolder("macerator") .upgradeInventorySize(24) .tier(2) .register(); - casingRegistry.create(10000, MotorCasing.class) + } + + private static void registerMotorCasings(MultiTileEntityRegistry registry, MultiTileEntityBlock casing) { + registry.create(LV_Motor.getId(), Motor.class) .name("Motor Casing LV") .tier(1) .category("MultiBlock Functional Casing") .setBlock(casing) - .material(Materials.Arsenic) - .texture("metalwall") + .textureFolder("motor") + .register(); + registry.create(MV_Motor.getId(), Motor.class) + .name("Motor Casing MV") + .tier(2) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("motor") + .register(); + registry.create(HV_Motor.getId(), Motor.class) + .name("Motor Casing HV") + .tier(3) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("motor") + .register(); + registry.create(EV_Motor.getId(), Motor.class) + .name("Motor Casing EV") + .tier(4) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("motor") + .register(); + registry.create(IV_Motor.getId(), Motor.class) + .name("Motor Casing IV") + .tier(5) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("motor") + .register(); + registry.create(LuV_Motor.getId(), Motor.class) + .name("Motor Casing LuV") + .tier(6) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("motor") + .register(); + registry.create(ZPM_Motor.getId(), Motor.class) + .name("Motor Casing ZPM") + .tier(7) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("motor") + .register(); + registry.create(UV_Motor.getId(), Motor.class) + .name("Motor Casing UV") + .tier(8) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("motor") + .register(); + registry.create(UHV_Motor.getId(), Motor.class) + .name("Motor Casing UHV") + .tier(9) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("motor") + .register(); + registry.create(UEV_Motor.getId(), Motor.class) + .name("Motor Casing UEV") + .tier(10) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("motor") + .register(); + registry.create(UIV_Motor.getId(), Motor.class) + .name("Motor Casing UIV") + .tier(11) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("motor") + .register(); + registry.create(UMV_Motor.getId(), Motor.class) + .name("Motor Casing UMV") + .tier(12) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("motor") + .register(); + registry.create(UXV_Motor.getId(), Motor.class) + .name("Motor Casing UXV") + .tier(13) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("motor") + .register(); + registry.create(MAX_Motor.getId(), Motor.class) + .name("Motor Casing MAX") + .tier(14) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("motor") + .register(); + } + + private static void registerPumpCasings(MultiTileEntityRegistry registry, MultiTileEntityBlock casing) { + registry.create(LV_Pump.getId(), Pump.class) + .name("Pump Casing LV") + .tier(1) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("pump") + .register(); + registry.create(MV_Pump.getId(), Pump.class) + .name("Pump Casing MV") + .tier(2) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("pump") + .register(); + registry.create(HV_Pump.getId(), Pump.class) + .name("Pump Casing HV") + .tier(3) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("pump") + .register(); + registry.create(EV_Pump.getId(), Pump.class) + .name("Pump Casing EV") + .tier(4) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("pump") + .register(); + registry.create(IV_Pump.getId(), Pump.class) + .name("Pump Casing IV") + .tier(5) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("pump") + .register(); + registry.create(LuV_Pump.getId(), Pump.class) + .name("Pump Casing LuV") + .tier(6) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("pump") + .register(); + registry.create(LuV_Pump.getId(), Pump.class) + .name("Pump Casing LuV") + .tier(6) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("pump") + .register(); + registry.create(ZPM_Pump.getId(), Pump.class) + .name("Pump Casing ZPM") + .tier(7) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("pump") + .register(); + registry.create(UV_Pump.getId(), Pump.class) + .name("Pump Casing UV") + .tier(8) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("pump") + .register(); + registry.create(UHV_Pump.getId(), Pump.class) + .name("Pump Casing UHV") + .tier(9) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("pump") + .register(); + registry.create(UEV_Pump.getId(), Pump.class) + .name("Pump Casing UEV") + .tier(10) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("pump") + .register(); + registry.create(UIV_Pump.getId(), Pump.class) + .name("Pump Casing UIV") + .tier(11) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("pump") + .register(); + registry.create(UMV_Pump.getId(), Pump.class) + .name("Pump Casing UMV") + .tier(12) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("pump") + .register(); + registry.create(UXV_Pump.getId(), Pump.class) + .name("Pump Casing UXV") + .tier(13) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("pump") + .register(); + registry.create(MAX_Pump.getId(), Pump.class) + .name("Pump Casing MAX") + .tier(14) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("pump") + .register(); + } + + private static void registerPistonCasings(MultiTileEntityRegistry registry, MultiTileEntityBlock casing) { + registry.create(LV_Piston.getId(), Piston.class) + .name("Piston Casing LV") + .tier(1) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("piston") + .register(); + registry.create(MV_Piston.getId(), Piston.class) + .name("Piston Casing MV") + .tier(2) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("piston") + .register(); + registry.create(HV_Piston.getId(), Piston.class) + .name("Piston Casing HV") + .tier(3) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("piston") + .register(); + registry.create(EV_Piston.getId(), Piston.class) + .name("Piston Casing EV") + .tier(4) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("piston") + .register(); + registry.create(IV_Piston.getId(), Piston.class) + .name("Piston Casing IV") + .tier(5) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("piston") + .register(); + registry.create(LuV_Piston.getId(), Piston.class) + .name("Piston Casing LuV") + .tier(6) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("piston") + .register(); + registry.create(ZPM_Piston.getId(), Piston.class) + .name("Piston Casing ZPM") + .tier(7) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("piston") + .register(); + registry.create(UV_Piston.getId(), Piston.class) + .name("Piston Casing UV") + .tier(8) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("piston") + .register(); + registry.create(UHV_Piston.getId(), Piston.class) + .name("Piston Casing UHV") + .tier(9) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("piston") + .register(); + registry.create(UEV_Piston.getId(), Piston.class) + .name("Piston Casing UEV") + .tier(10) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("piston") + .register(); + registry.create(UIV_Piston.getId(), Piston.class) + .name("Piston Casing UIV") + .tier(11) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("piston") + .register(); + registry.create(UMV_Piston.getId(), Piston.class) + .name("Piston Casing UMV") + .tier(12) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("piston") + .register(); + registry.create(UXV_Piston.getId(), Piston.class) + .name("Piston Casing UXV") + .tier(13) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("piston") + .register(); + registry.create(MAX_Piston.getId(), Piston.class) + .name("Piston Casing MAX") + .tier(14) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("piston") + .register(); + } + + private static void registerConveyorCasings(MultiTileEntityRegistry registry, MultiTileEntityBlock casing) { + registry.create(LV_Conveyor.getId(), Conveyor.class) + .name("Conveyor Casing LV") + .tier(1) + .category("MultiBlock Structural Casing") + .setBlock(casing) + .textureFolder("conveyor") + .register(); + registry.create(MV_Conveyor.getId(), Conveyor.class) + .name("Conveyor Casing MV") + .tier(2) + .category("MultiBlock Structural Casing") + .setBlock(casing) + .textureFolder("conveyor") + .register(); + registry.create(HV_Conveyor.getId(), Conveyor.class) + .name("Conveyor Casing HV") + .tier(3) + .category("MultiBlock Structural Casing") + .setBlock(casing) + .textureFolder("conveyor") + .register(); + registry.create(EV_Conveyor.getId(), Conveyor.class) + .name("Conveyor Casing EV") + .tier(4) + .category("MultiBlock Structural Casing") + .setBlock(casing) + .textureFolder("conveyor") + .register(); + registry.create(IV_Conveyor.getId(), Conveyor.class) + .name("Conveyor Casing IV") + .tier(5) + .category("MultiBlock Structural Casing") + .setBlock(casing) + .textureFolder("conveyor") + .register(); + registry.create(LuV_Conveyor.getId(), Conveyor.class) + .name("Conveyor Casing LuV") + .tier(6) + .category("MultiBlock Structural Casing") + .setBlock(casing) + .textureFolder("conveyor") + .register(); + registry.create(ZPM_Conveyor.getId(), Conveyor.class) + .name("Conveyor Casing ZPM") + .tier(7) + .category("MultiBlock Structural Casing") + .setBlock(casing) + .textureFolder("conveyor") + .register(); + registry.create(UV_Conveyor.getId(), Conveyor.class) + .name("Conveyor Casing UV") + .tier(8) + .category("MultiBlock Structural Casing") + .setBlock(casing) + .textureFolder("conveyor") + .register(); + registry.create(UHV_Conveyor.getId(), Conveyor.class) + .name("Conveyor Casing UHV") + .tier(9) + .category("MultiBlock Structural Casing") + .setBlock(casing) + .textureFolder("conveyor") + .register(); + registry.create(UEV_Conveyor.getId(), Conveyor.class) + .name("Conveyor Casing UEV") + .tier(10) + .category("MultiBlock Structural Casing") + .setBlock(casing) + .textureFolder("conveyor") + .register(); + registry.create(UIV_Conveyor.getId(), Conveyor.class) + .name("Conveyor Casing UIV") + .tier(11) + .category("MultiBlock Structural Casing") + .setBlock(casing) + .textureFolder("conveyor") + .register(); + } + + private static void registerRobotArmCasings(MultiTileEntityRegistry registry, MultiTileEntityBlock casing) { + registry.create(LV_RobotArm.getId(), RobotArm.class) + .name("Robot Arm Casing LV") + .tier(1) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("robotArm") + .register(); + registry.create(MV_RobotArm.getId(), RobotArm.class) + .name("Robot Arm Casing MV") + .tier(2) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("robotArm") + .register(); + registry.create(HV_RobotArm.getId(), RobotArm.class) + .name("Robot Arm Casing HV") + .tier(3) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("robotArm") + .register(); + registry.create(EV_RobotArm.getId(), RobotArm.class) + .name("Robot Arm Casing EV") + .tier(4) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("robotArm") + .register(); + registry.create(IV_RobotArm.getId(), RobotArm.class) + .name("Robot Arm Casing IV") + .tier(5) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("robotArm") + .register(); + registry.create(LuV_RobotArm.getId(), RobotArm.class) + .name("Robot Arm Casing LuV") + .tier(6) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("robotArm") + .register(); + registry.create(ZPM_RobotArm.getId(), RobotArm.class) + .name("Robot Arm Casing ZPM") + .tier(7) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("robotArm") + .register(); + registry.create(UV_RobotArm.getId(), RobotArm.class) + .name("Robot Arm Casing UV") + .tier(8) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("robotArm") + .register(); + registry.create(UHV_RobotArm.getId(), RobotArm.class) + .name("Robot Arm Casing UHV") + .tier(9) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("robotArm") + .register(); + registry.create(UEV_RobotArm.getId(), RobotArm.class) + .name("Robot Arm Casing UEV") + .tier(10) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("robotArm") + .register(); + registry.create(UIV_RobotArm.getId(), RobotArm.class) + .name("Robot Arm Casing UIV") + .tier(11) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("robotArm") + .register(); + registry.create(UMV_RobotArm.getId(), RobotArm.class) + .name("Robot Arm Casing UMV") + .tier(12) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("robotArm") + .register(); + registry.create(UXV_RobotArm.getId(), RobotArm.class) + .name("Robot Arm Casing UXV") + .tier(13) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("robotArm") + .register(); + registry.create(MAX_RobotArm.getId(), RobotArm.class) + .name("Robot Arm Casing MAX") + .tier(14) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("robotArm") + .register(); + } + + private static void registerSensorCasings(MultiTileEntityRegistry registry, MultiTileEntityBlock casing) { + registry.create(LV_Sensor.getId(), Sensor.class) + .name("Sensor Casing LV") + .tier(1) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("sensor") + .register(); + registry.create(MV_Sensor.getId(), Sensor.class) + .name("Sensor Casing MV") + .tier(2) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("sensor") + .register(); + registry.create(HV_Sensor.getId(), Sensor.class) + .name("Sensor Casing HV") + .tier(3) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("sensor") + .register(); + registry.create(EV_Sensor.getId(), Sensor.class) + .name("Sensor Casing EV") + .tier(4) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("sensor") + .register(); + registry.create(IV_Sensor.getId(), Sensor.class) + .name("Sensor Casing IV") + .tier(5) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("sensor") + .register(); + registry.create(LuV_Sensor.getId(), Sensor.class) + .name("Sensor Casing LuV") + .tier(6) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("sensor") + .register(); + registry.create(ZPM_Sensor.getId(), Sensor.class) + .name("Sensor Casing ZPM") + .tier(7) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("sensor") + .register(); + registry.create(UV_Sensor.getId(), Sensor.class) + .name("Sensor Casing UV") + .tier(8) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("sensor") + .register(); + registry.create(UHV_Sensor.getId(), Sensor.class) + .name("Sensor Casing UHV") + .tier(9) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("sensor") + .register(); + registry.create(UEV_Sensor.getId(), Sensor.class) + .name("Sensor Casing UEV") + .tier(10) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("sensor") + .register(); + registry.create(UIV_Sensor.getId(), Sensor.class) + .name("Sensor Casing UIV") + .tier(11) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("sensor") + .register(); + registry.create(UMV_Sensor.getId(), Sensor.class) + .name("Sensor Casing UMV") + .tier(12) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("sensor") + .register(); + registry.create(UXV_Sensor.getId(), Sensor.class) + .name("Sensor Casing UXV") + .tier(13) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("sensor") + .register(); + registry.create(MAX_Sensor.getId(), Sensor.class) + .name("Sensor Casing MAX") + .tier(14) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("sensor") + .register(); + } + + private static void registerEmitterCasings(MultiTileEntityRegistry registry, MultiTileEntityBlock casing) { + registry.create(LV_Emitter.getId(), Emitter.class) + .name("Emitter Casing LV") + .tier(1) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("emitter") + .register(); + registry.create(MV_Emitter.getId(), Emitter.class) + .name("Emitter Casing MV") + .tier(2) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("emitter") + .register(); + registry.create(HV_Emitter.getId(), Emitter.class) + .name("Emitter Casing HV") + .tier(3) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("emitter") + .register(); + registry.create(EV_Emitter.getId(), Emitter.class) + .name("Emitter Casing EV") + .tier(4) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("emitter") + .register(); + registry.create(IV_Emitter.getId(), Emitter.class) + .name("Emitter Casing IV") + .tier(5) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("emitter") + .register(); + registry.create(LuV_Emitter.getId(), Emitter.class) + .name("Emitter Casing LuV") + .tier(6) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("emitter") + .register(); + registry.create(ZPM_Emitter.getId(), Emitter.class) + .name("Emitter Casing ZPM") + .tier(7) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("emitter") + .register(); + registry.create(UV_Emitter.getId(), Emitter.class) + .name("Emitter Casing UV") + .tier(8) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("emitter") + .register(); + registry.create(UHV_Emitter.getId(), Emitter.class) + .name("Emitter Casing UHV") + .tier(9) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("emitter") + .register(); + registry.create(UEV_Emitter.getId(), Emitter.class) + .name("Emitter Casing UEV") + .tier(10) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("emitter") + .register(); + registry.create(UIV_Emitter.getId(), Emitter.class) + .name("Emitter Casing UIV") + .tier(11) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("emitter") + .register(); + registry.create(UMV_Emitter.getId(), Emitter.class) + .name("Emitter Casing UMV") + .tier(12) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("emitter") + .register(); + registry.create(UXV_Emitter.getId(), Emitter.class) + .name("Emitter Casing UXV") + .tier(13) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("emitter") + .register(); + registry.create(MAX_Emitter.getId(), Emitter.class) + .name("Emitter Casing MAX") + .tier(14) + .category("MultiBlock Functional Casing") + .setBlock(casing) + .textureFolder("emitter") + .register(); + } + + private static void registerFieldGeneratorCasings(MultiTileEntityRegistry registry, MultiTileEntityBlock casing) { + registry.create(LV_FieldGenerator.getId(), FieldGenerator.class) + .name("Field Generator LV") + .tier(1) + .category("Multiblock Energy Field") + .setBlock(casing) + .textureFolder("fieldGenerator") + .register(); + registry.create(MV_FieldGenerator.getId(), FieldGenerator.class) + .name("Field Generator MV") + .tier(2) + .category("Multiblock Energy Field") + .setBlock(casing) + .textureFolder("fieldGenerator") + .register(); + registry.create(HV_FieldGenerator.getId(), FieldGenerator.class) + .name("Field Generator HV") + .tier(3) + .category("Multiblock Energy Field") + .setBlock(casing) + .textureFolder("fieldGenerator") + .register(); + registry.create(EV_FieldGenerator.getId(), FieldGenerator.class) + .name("Field Generator EV") + .tier(4) + .category("Multiblock Energy Field") + .setBlock(casing) + .textureFolder("fieldGenerator") + .register(); + registry.create(IV_FieldGenerator.getId(), FieldGenerator.class) + .name("Field Generator IV") + .tier(5) + .category("Multiblock Energy Field") + .setBlock(casing) + .textureFolder("fieldGenerator") + .register(); + registry.create(LuV_FieldGenerator.getId(), FieldGenerator.class) + .name("Field Generator LuV") + .tier(6) + .category("Multiblock Energy Field") + .setBlock(casing) + .textureFolder("fieldGenerator") + .register(); + registry.create(ZPM_FieldGenerator.getId(), FieldGenerator.class) + .name("Field Generator ZPM") + .tier(7) + .category("Multiblock Energy Field") + .setBlock(casing) + .textureFolder("fieldGenerator") + .register(); + registry.create(UV_FieldGenerator.getId(), FieldGenerator.class) + .name("Field Generator UV") + .tier(8) + .category("Multiblock Energy Field") + .setBlock(casing) + .textureFolder("fieldGenerator") + .register(); + registry.create(UHV_FieldGenerator.getId(), FieldGenerator.class) + .name("Field Generator UHV") + .tier(9) + .category("Multiblock Energy Field") + .setBlock(casing) + .textureFolder("fieldGenerator") + .register(); + registry.create(UEV_FieldGenerator.getId(), FieldGenerator.class) + .name("Field Generator UEV") + .tier(10) + .category("Multiblock Energy Field") + .setBlock(casing) + .textureFolder("fieldGenerator") + .register(); + registry.create(UIV_FieldGenerator.getId(), FieldGenerator.class) + .name("Field Generator UIV") + .tier(11) + .category("Multiblock Energy Field") + .setBlock(casing) + .textureFolder("fieldGenerator") + .register(); + registry.create(UMV_FieldGenerator.getId(), FieldGenerator.class) + .name("Field Generator UMV") + .tier(12) + .category("Multiblock Energy Field") + .setBlock(casing) + .textureFolder("fieldGenerator") + .register(); + registry.create(UXV_FieldGenerator.getId(), FieldGenerator.class) + .name("Field Generator UXV") + .tier(13) + .category("Multiblock Energy Field") + .setBlock(casing) + .textureFolder("fieldGenerator") + .register(); + registry.create(MAX_FieldGenerator.getId(), FieldGenerator.class) + .name("Field Generator MAX") + .tier(14) + .category("Multiblock Energy Field") + .setBlock(casing) + .textureFolder("fieldGenerator") .register(); } } diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalReactor/active.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalReactor/active.png new file mode 100644 index 0000000000..ffd43d8dc2 Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalReactor/active.png differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalReactor/active_glow.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalReactor/active_glow.png new file mode 100644 index 0000000000..3bb29bbda6 Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalReactor/active_glow.png differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalReactor/base.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalReactor/base.png new file mode 100644 index 0000000000..84cd5fa9f2 Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalReactor/base.png differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalReactor/inactive.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalReactor/inactive.png new file mode 100644 index 0000000000..6092ec4c18 Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalReactor/inactive.png differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalReactor/inactive_glow.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalReactor/inactive_glow.png new file mode 100644 index 0000000000..b7955d63ab Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalReactor/inactive_glow.png differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/base/cokeOven/bottom.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/base/cokeOven/bottom.png deleted file mode 100644 index f125fa6bbc..0000000000 Binary files a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/base/cokeOven/bottom.png and /dev/null differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/base/cokeOven/side.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/base/cokeOven/side.png deleted file mode 100644 index f125fa6bbc..0000000000 Binary files a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/base/cokeOven/side.png and /dev/null differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/base/cokeOven/top.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/base/cokeOven/top.png deleted file mode 100644 index f125fa6bbc..0000000000 Binary files a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/base/cokeOven/top.png and /dev/null differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/base/metalwall/bottom.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/base/metalwall/bottom.png deleted file mode 100644 index e05f5d89c7..0000000000 Binary files a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/base/metalwall/bottom.png and /dev/null differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/base/metalwall/side.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/base/metalwall/side.png deleted file mode 100644 index e05f5d89c7..0000000000 Binary files a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/base/metalwall/side.png and /dev/null differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/base/metalwall/top.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/base/metalwall/top.png deleted file mode 100644 index e05f5d89c7..0000000000 Binary files a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/base/metalwall/top.png and /dev/null differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/cokeOven/active.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/cokeOven/active.png new file mode 100644 index 0000000000..708971d8cf Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/cokeOven/active.png differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/cokeOven/active_glow.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/cokeOven/active_glow.png new file mode 100644 index 0000000000..c2866f4570 Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/cokeOven/active_glow.png differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/cokeOven/base.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/cokeOven/base.png new file mode 100644 index 0000000000..f125fa6bbc Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/cokeOven/base.png differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/cokeOven/inactive.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/cokeOven/inactive.png new file mode 100644 index 0000000000..c684fbb353 Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/cokeOven/inactive.png differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/conveyor/base.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/conveyor/base.png new file mode 100644 index 0000000000..e05f5d89c7 Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/conveyor/base.png differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/emitter/base.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/emitter/base.png new file mode 100644 index 0000000000..e05f5d89c7 Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/emitter/base.png differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/fieldGenerator/base.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/fieldGenerator/base.png new file mode 100644 index 0000000000..e05f5d89c7 Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/fieldGenerator/base.png differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/macerator/active.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/macerator/active.png new file mode 100644 index 0000000000..ffd43d8dc2 Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/macerator/active.png differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/macerator/active_glow.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/macerator/active_glow.png new file mode 100644 index 0000000000..3bb29bbda6 Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/macerator/active_glow.png differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/macerator/base.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/macerator/base.png new file mode 100644 index 0000000000..e05f5d89c7 Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/macerator/base.png differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/macerator/inactive.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/macerator/inactive.png new file mode 100644 index 0000000000..6092ec4c18 Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/macerator/inactive.png differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/macerator/inactive_glow.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/macerator/inactive_glow.png new file mode 100644 index 0000000000..b7955d63ab Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/macerator/inactive_glow.png differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/cokeOven/bottom.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/cokeOven/bottom.png deleted file mode 100644 index f125fa6bbc..0000000000 Binary files a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/cokeOven/bottom.png and /dev/null differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/cokeOven/front.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/cokeOven/front.png deleted file mode 100644 index f125fa6bbc..0000000000 Binary files a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/cokeOven/front.png and /dev/null differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/cokeOven/left.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/cokeOven/left.png deleted file mode 100644 index f125fa6bbc..0000000000 Binary files a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/cokeOven/left.png and /dev/null differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/cokeOven/overlay/active/front.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/cokeOven/overlay/active/front.png deleted file mode 100644 index 708971d8cf..0000000000 Binary files a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/cokeOven/overlay/active/front.png and /dev/null differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/cokeOven/overlay/inactive/front.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/cokeOven/overlay/inactive/front.png deleted file mode 100644 index c684fbb353..0000000000 Binary files a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/cokeOven/overlay/inactive/front.png and /dev/null differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/cokeOven/right.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/cokeOven/right.png deleted file mode 100644 index f125fa6bbc..0000000000 Binary files a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/cokeOven/right.png and /dev/null differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/cokeOven/side.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/cokeOven/side.png deleted file mode 100644 index f125fa6bbc..0000000000 Binary files a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/cokeOven/side.png and /dev/null differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/cokeOven/top.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/cokeOven/top.png deleted file mode 100644 index f125fa6bbc..0000000000 Binary files a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/cokeOven/top.png and /dev/null differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/metalwall/bottom.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/metalwall/bottom.png deleted file mode 100644 index e05f5d89c7..0000000000 Binary files a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/metalwall/bottom.png and /dev/null differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/metalwall/side.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/metalwall/side.png deleted file mode 100644 index e05f5d89c7..0000000000 Binary files a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/metalwall/side.png and /dev/null differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/metalwall/top.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/metalwall/top.png deleted file mode 100644 index e05f5d89c7..0000000000 Binary files a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/machines/metalwall/top.png and /dev/null differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/motor/base.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/motor/base.png new file mode 100644 index 0000000000..e05f5d89c7 Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/motor/base.png differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/multiblockparts/cokeOven/bottom.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/multiblockparts/cokeOven/bottom.png deleted file mode 100644 index f125fa6bbc..0000000000 Binary files a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/multiblockparts/cokeOven/bottom.png and /dev/null differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/multiblockparts/cokeOven/side.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/multiblockparts/cokeOven/side.png deleted file mode 100644 index f125fa6bbc..0000000000 Binary files a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/multiblockparts/cokeOven/side.png and /dev/null differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/multiblockparts/cokeOven/top.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/multiblockparts/cokeOven/top.png deleted file mode 100644 index f125fa6bbc..0000000000 Binary files a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/multiblockparts/cokeOven/top.png and /dev/null differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/multiblockparts/metalwall/bottom.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/multiblockparts/metalwall/bottom.png deleted file mode 100644 index e05f5d89c7..0000000000 Binary files a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/multiblockparts/metalwall/bottom.png and /dev/null differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/multiblockparts/metalwall/side.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/multiblockparts/metalwall/side.png deleted file mode 100644 index e05f5d89c7..0000000000 Binary files a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/multiblockparts/metalwall/side.png and /dev/null differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/multiblockparts/metalwall/top.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/multiblockparts/metalwall/top.png deleted file mode 100644 index e05f5d89c7..0000000000 Binary files a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/multiblockparts/metalwall/top.png and /dev/null differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/piston/base.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/piston/base.png new file mode 100644 index 0000000000..e05f5d89c7 Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/piston/base.png differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/pump/base.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/pump/base.png new file mode 100644 index 0000000000..e05f5d89c7 Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/pump/base.png differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/robotArm/base.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/robotArm/base.png new file mode 100644 index 0000000000..e05f5d89c7 Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/robotArm/base.png differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/sensor/base.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/sensor/base.png new file mode 100644 index 0000000000..e05f5d89c7 Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/sensor/base.png differ -- cgit