aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/gregtech/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/gregtech/common')
-rw-r--r--src/main/java/gregtech/common/GT_Client.java1096
-rw-r--r--src/main/java/gregtech/common/GT_DummyWorld.java138
-rw-r--r--src/main/java/gregtech/common/GT_IteratorRandom.java17
-rw-r--r--src/main/java/gregtech/common/GT_Network.java183
-rw-r--r--src/main/java/gregtech/common/GT_PlayerActivityLogger.java34
-rw-r--r--src/main/java/gregtech/common/GT_Pollution.java507
-rw-r--r--src/main/java/gregtech/common/GT_Proxy.java3163
-rw-r--r--src/main/java/gregtech/common/GT_RecipeAdder.java3245
-rw-r--r--src/main/java/gregtech/common/GT_Server.java36
-rw-r--r--src/main/java/gregtech/common/GT_ThaumcraftCompat.java285
-rw-r--r--src/main/java/gregtech/common/GT_UndergroundOil.java339
-rw-r--r--src/main/java/gregtech/common/GT_Worldgen_GT_Ore_Layer.java456
-rw-r--r--src/main/java/gregtech/common/GT_Worldgen_GT_Ore_SmallPieces.java115
-rw-r--r--src/main/java/gregtech/common/GT_Worldgen_Stone.java295
-rw-r--r--src/main/java/gregtech/common/GT_Worldgenerator.java688
-rw-r--r--src/main/java/gregtech/common/bees/GT_AlleleBeeSpecies.java53
-rw-r--r--src/main/java/gregtech/common/bees/GT_AlleleHelper.java268
-rw-r--r--src/main/java/gregtech/common/bees/GT_Bee_Mutation.java85
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Block_Casings1.java108
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Block_Casings2.java102
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Block_Casings3.java82
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Block_Casings4.java250
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Block_Casings5.java159
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Block_Casings6.java94
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Block_Casings8.java199
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Block_Casings9.java43
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Block_Casings_Abstract.java144
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Block_Concretes.java83
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Block_Drone.java65
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Block_Granites.java77
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Block_Machines.java703
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Block_Metal.java68
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Block_Ores.java154
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Block_Ores_Abstract.java324
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Block_Reinforced.java409
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Block_Stones.java62
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Block_Stones_Abstract.java250
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Block_Storage.java103
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Cyclotron_Coils.java127
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Cyclotron_Item_Casings.java10
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Item_Casings1.java14
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Item_Casings2.java26
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Item_Casings3.java14
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Item_Casings4.java14
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Item_Casings5.java36
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Item_Casings6.java14
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Item_Casings8.java14
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Item_Casings9.java14
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Item_Casings_Abstract.java63
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Item_Concretes.java25
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Item_Granites.java10
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Item_LongDistancePipe.java43
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Item_Machines.java430
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Item_Ores.java81
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Item_Stones_Abstract.java42
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Item_Storage.java47
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Material_Casings.java19
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Material_Machines.java19
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Material_Reinforced.java18
-rw-r--r--src/main/java/gregtech/common/blocks/GT_Packet_Ores.java61
-rw-r--r--src/main/java/gregtech/common/blocks/GT_TileEntity_Ores.java485
-rw-r--r--src/main/java/gregtech/common/covers/CoverInfo.java335
-rw-r--r--src/main/java/gregtech/common/covers/GT_Cover_Arm.java436
-rw-r--r--src/main/java/gregtech/common/covers/GT_Cover_ControlsWork.java275
-rw-r--r--src/main/java/gregtech/common/covers/GT_Cover_Conveyor.java333
-rw-r--r--src/main/java/gregtech/common/covers/GT_Cover_Crafting.java56
-rw-r--r--src/main/java/gregtech/common/covers/GT_Cover_DoesWork.java257
-rw-r--r--src/main/java/gregtech/common/covers/GT_Cover_Drain.java140
-rw-r--r--src/main/java/gregtech/common/covers/GT_Cover_EUMeter.java415
-rw-r--r--src/main/java/gregtech/common/covers/GT_Cover_FacadeAE.java31
-rw-r--r--src/main/java/gregtech/common/covers/GT_Cover_FacadeBase.java401
-rw-r--r--src/main/java/gregtech/common/covers/GT_Cover_FluidLimiter.java207
-rw-r--r--src/main/java/gregtech/common/covers/GT_Cover_FluidRegulator.java536
-rw-r--r--src/main/java/gregtech/common/covers/GT_Cover_FluidStorageMonitor.java507
-rw-r--r--src/main/java/gregtech/common/covers/GT_Cover_Fluidfilter.java422
-rw-r--r--src/main/java/gregtech/common/covers/GT_Cover_ItemFilter.java303
-rw-r--r--src/main/java/gregtech/common/covers/GT_Cover_ItemMeter.java389
-rw-r--r--src/main/java/gregtech/common/covers/GT_Cover_Lens.java28
-rw-r--r--src/main/java/gregtech/common/covers/GT_Cover_LiquidMeter.java297
-rw-r--r--src/main/java/gregtech/common/covers/GT_Cover_Metrics_Transmitter.java212
-rw-r--r--src/main/java/gregtech/common/covers/GT_Cover_NeedMaintainance.java303
-rw-r--r--src/main/java/gregtech/common/covers/GT_Cover_PlayerDetector.java207
-rw-r--r--src/main/java/gregtech/common/covers/GT_Cover_Pump.java339
-rw-r--r--src/main/java/gregtech/common/covers/GT_Cover_RedstoneConductor.java101
-rw-r--r--src/main/java/gregtech/common/covers/GT_Cover_RedstoneReceiverExternal.java41
-rw-r--r--src/main/java/gregtech/common/covers/GT_Cover_RedstoneReceiverInternal.java46
-rw-r--r--src/main/java/gregtech/common/covers/GT_Cover_RedstoneSignalizer.java99
-rw-r--r--src/main/java/gregtech/common/covers/GT_Cover_RedstoneTransmitterExternal.java53
-rw-r--r--src/main/java/gregtech/common/covers/GT_Cover_RedstoneTransmitterInternal.java43
-rw-r--r--src/main/java/gregtech/common/covers/GT_Cover_RedstoneWirelessBase.java233
-rw-r--r--src/main/java/gregtech/common/covers/GT_Cover_Screen.java100
-rw-r--r--src/main/java/gregtech/common/covers/GT_Cover_Shutter.java201
-rw-r--r--src/main/java/gregtech/common/covers/GT_Cover_SolarPanel.java139
-rw-r--r--src/main/java/gregtech/common/covers/GT_Cover_SteamRegulator.java18
-rw-r--r--src/main/java/gregtech/common/covers/GT_Cover_SteamValve.java26
-rw-r--r--src/main/java/gregtech/common/covers/GT_Cover_Vent.java111
-rw-r--r--src/main/java/gregtech/common/covers/redstone/GT_Cover_AdvancedRedstoneReceiverBase.java202
-rw-r--r--src/main/java/gregtech/common/covers/redstone/GT_Cover_AdvancedRedstoneReceiverExternal.java35
-rw-r--r--src/main/java/gregtech/common/covers/redstone/GT_Cover_AdvancedRedstoneReceiverInternal.java42
-rw-r--r--src/main/java/gregtech/common/covers/redstone/GT_Cover_AdvancedRedstoneTransmitterBase.java188
-rw-r--r--src/main/java/gregtech/common/covers/redstone/GT_Cover_AdvancedRedstoneTransmitterExternal.java51
-rw-r--r--src/main/java/gregtech/common/covers/redstone/GT_Cover_AdvancedRedstoneTransmitterInternal.java50
-rw-r--r--src/main/java/gregtech/common/covers/redstone/GT_Cover_AdvancedWirelessRedstoneBase.java303
-rw-r--r--src/main/java/gregtech/common/covers/redstone/GT_Cover_WirelessDoesWorkDetector.java245
-rw-r--r--src/main/java/gregtech/common/covers/redstone/GT_Cover_WirelessFluidDetector.java186
-rw-r--r--src/main/java/gregtech/common/covers/redstone/GT_Cover_WirelessItemDetector.java262
-rw-r--r--src/main/java/gregtech/common/covers/redstone/GT_Cover_WirelessMaintenanceDetector.java242
-rw-r--r--src/main/java/gregtech/common/entities/GT_EntityFXPollution.java59
-rw-r--r--src/main/java/gregtech/common/entities/GT_Entity_Arrow.java438
-rw-r--r--src/main/java/gregtech/common/entities/GT_Entity_Arrow_Potion.java78
-rw-r--r--src/main/java/gregtech/common/events/BaseMetricsCoverEvent.java21
-rw-r--r--src/main/java/gregtech/common/events/MetricsCoverDataEvent.java37
-rw-r--r--src/main/java/gregtech/common/events/MetricsCoverHostDeconstructedEvent.java16
-rw-r--r--src/main/java/gregtech/common/events/MetricsCoverSelfDestructEvent.java15
-rw-r--r--src/main/java/gregtech/common/fluid/GT_Fluid.java209
-rw-r--r--src/main/java/gregtech/common/fluid/GT_FluidBuilder.java146
-rw-r--r--src/main/java/gregtech/common/gui/ComplexParallelMachineGUIProvider.java32
-rw-r--r--src/main/java/gregtech/common/gui/MachineGUIProvider.java510
-rw-r--r--src/main/java/gregtech/common/gui/PartGUIProvider.java33
-rw-r--r--src/main/java/gregtech/common/gui/modularui/UIHelper.java200
-rw-r--r--src/main/java/gregtech/common/gui/modularui/uifactory/SelectItemUIFactory.java229
-rw-r--r--src/main/java/gregtech/common/gui/modularui/widget/AESlotWidget.java64
-rw-r--r--src/main/java/gregtech/common/gui/modularui/widget/CheckRecipeResultSyncer.java26
-rw-r--r--src/main/java/gregtech/common/gui/modularui/widget/CoverCycleButtonWidget.java91
-rw-r--r--src/main/java/gregtech/common/gui/modularui/widget/CoverDataControllerWidget.java133
-rw-r--r--src/main/java/gregtech/common/gui/modularui/widget/CoverDataFollower_CycleButtonWidget.java39
-rw-r--r--src/main/java/gregtech/common/gui/modularui/widget/CoverDataFollower_NumericWidget.java60
-rw-r--r--src/main/java/gregtech/common/gui/modularui/widget/CoverDataFollower_SlotWidget.java101
-rw-r--r--src/main/java/gregtech/common/gui/modularui/widget/CoverDataFollower_TextFieldWidget.java134
-rw-r--r--src/main/java/gregtech/common/gui/modularui/widget/CoverDataFollower_ToggleButtonWidget.java86
-rw-r--r--src/main/java/gregtech/common/gui/modularui/widget/DataControllerWidget.java166
-rw-r--r--src/main/java/gregtech/common/gui/modularui/widget/FluidLockWidget.java17
-rw-r--r--src/main/java/gregtech/common/gui/modularui/widget/ItemWatcherSlotWidget.java50
-rw-r--r--src/main/java/gregtech/common/gui/modularui/widget/ShutDownReasonSyncer.java26
-rw-r--r--src/main/java/gregtech/common/items/CombType.java284
-rw-r--r--src/main/java/gregtech/common/items/DropType.java46
-rw-r--r--src/main/java/gregtech/common/items/GT_AdvancedSensorCard_Item.java327
-rw-r--r--src/main/java/gregtech/common/items/GT_DepletetCell_Item.java49
-rw-r--r--src/main/java/gregtech/common/items/GT_FluidDisplayItem.java181
-rw-r--r--src/main/java/gregtech/common/items/GT_IntegratedCircuit_Item.java328
-rw-r--r--src/main/java/gregtech/common/items/GT_MetaGenerated_Item_01.java4627
-rw-r--r--src/main/java/gregtech/common/items/GT_MetaGenerated_Item_02.java2831
-rw-r--r--src/main/java/gregtech/common/items/GT_MetaGenerated_Item_03.java1087
-rw-r--r--src/main/java/gregtech/common/items/GT_MetaGenerated_Item_98.java352
-rw-r--r--src/main/java/gregtech/common/items/GT_MetaGenerated_Item_99.java214
-rw-r--r--src/main/java/gregtech/common/items/GT_MetaGenerated_Tool_01.java824
-rw-r--r--src/main/java/gregtech/common/items/GT_NeutronReflector_Item.java54
-rw-r--r--src/main/java/gregtech/common/items/GT_SensorCard_Item.java111
-rw-r--r--src/main/java/gregtech/common/items/GT_TierDrone.java18
-rw-r--r--src/main/java/gregtech/common/items/GT_VolumetricFlask.java361
-rw-r--r--src/main/java/gregtech/common/items/ItemComb.java1908
-rw-r--r--src/main/java/gregtech/common/items/ItemDrop.java241
-rw-r--r--src/main/java/gregtech/common/items/ItemPollen.java89
-rw-r--r--src/main/java/gregtech/common/items/ItemPropolis.java141
-rw-r--r--src/main/java/gregtech/common/items/PollenType.java35
-rw-r--r--src/main/java/gregtech/common/items/PropolisType.java46
-rw-r--r--src/main/java/gregtech/common/items/behaviors/Behaviour_Arrow.java141
-rw-r--r--src/main/java/gregtech/common/items/behaviors/Behaviour_Arrow_Potion.java71
-rw-r--r--src/main/java/gregtech/common/items/behaviors/Behaviour_Cover_Tool.java193
-rw-r--r--src/main/java/gregtech/common/items/behaviors/Behaviour_Crowbar.java61
-rw-r--r--src/main/java/gregtech/common/items/behaviors/Behaviour_DataOrb.java105
-rw-r--r--src/main/java/gregtech/common/items/behaviors/Behaviour_DataStick.java52
-rw-r--r--src/main/java/gregtech/common/items/behaviors/Behaviour_Hoe.java72
-rw-r--r--src/main/java/gregtech/common/items/behaviors/Behaviour_Lighter.java140
-rw-r--r--src/main/java/gregtech/common/items/behaviors/Behaviour_None.java96
-rw-r--r--src/main/java/gregtech/common/items/behaviors/Behaviour_Plunger_Essentia.java54
-rw-r--r--src/main/java/gregtech/common/items/behaviors/Behaviour_Plunger_Fluid.java75
-rw-r--r--src/main/java/gregtech/common/items/behaviors/Behaviour_Plunger_Item.java88
-rw-r--r--src/main/java/gregtech/common/items/behaviors/Behaviour_PrintedPages.java39
-rw-r--r--src/main/java/gregtech/common/items/behaviors/Behaviour_Prospecting.java159
-rw-r--r--src/main/java/gregtech/common/items/behaviors/Behaviour_Scanner.java65
-rw-r--r--src/main/java/gregtech/common/items/behaviors/Behaviour_Scoop.java63
-rw-r--r--src/main/java/gregtech/common/items/behaviors/Behaviour_Screwdriver.java52
-rw-r--r--src/main/java/gregtech/common/items/behaviors/Behaviour_Sense.java56
-rw-r--r--src/main/java/gregtech/common/items/behaviors/Behaviour_SensorKit.java56
-rw-r--r--src/main/java/gregtech/common/items/behaviors/Behaviour_SoftHammer.java131
-rw-r--r--src/main/java/gregtech/common/items/behaviors/Behaviour_Sonictron.java135
-rw-r--r--src/main/java/gregtech/common/items/behaviors/Behaviour_Spray_Color.java222
-rw-r--r--src/main/java/gregtech/common/items/behaviors/Behaviour_Spray_Color_Remover.java48
-rw-r--r--src/main/java/gregtech/common/items/behaviors/Behaviour_Switch_Metadata.java67
-rw-r--r--src/main/java/gregtech/common/items/behaviors/Behaviour_Switch_Mode.java53
-rw-r--r--src/main/java/gregtech/common/items/behaviors/Behaviour_Wrench.java278
-rw-r--r--src/main/java/gregtech/common/items/behaviors/Behaviour_WrittenBook.java40
-rw-r--r--src/main/java/gregtech/common/misc/GT_ClientPollutionMap.java140
-rw-r--r--src/main/java/gregtech/common/misc/GT_Command.java340
-rw-r--r--src/main/java/gregtech/common/misc/GT_DrillingLogicDelegate.java266
-rw-r--r--src/main/java/gregtech/common/misc/GT_IDrillingLogicDelegateOwner.java22
-rw-r--r--src/main/java/gregtech/common/misc/GlobalEnergyWorldSavedData.java125
-rw-r--r--src/main/java/gregtech/common/misc/GlobalMetricsCoverDatabase.java492
-rw-r--r--src/main/java/gregtech/common/misc/GlobalVariableStorage.java15
-rw-r--r--src/main/java/gregtech/common/misc/WirelessNetworkManager.java93
-rw-r--r--src/main/java/gregtech/common/misc/spaceprojects/SpaceProjectManager.java309
-rw-r--r--src/main/java/gregtech/common/misc/spaceprojects/SpaceProjectWorldSavedData.java343
-rw-r--r--src/main/java/gregtech/common/misc/spaceprojects/base/SP_Requirements.java74
-rw-r--r--src/main/java/gregtech/common/misc/spaceprojects/base/SP_Upgrade.java362
-rw-r--r--src/main/java/gregtech/common/misc/spaceprojects/base/SpaceProject.java451
-rw-r--r--src/main/java/gregtech/common/misc/spaceprojects/commands/SPM_Command.java288
-rw-r--r--src/main/java/gregtech/common/misc/spaceprojects/commands/SP_Command.java166
-rw-r--r--src/main/java/gregtech/common/misc/spaceprojects/enums/JsonVariables.java22
-rw-r--r--src/main/java/gregtech/common/misc/spaceprojects/enums/SolarSystem.java104
-rw-r--r--src/main/java/gregtech/common/misc/spaceprojects/enums/SpaceBodyType.java17
-rw-r--r--src/main/java/gregtech/common/misc/spaceprojects/enums/StarType.java32
-rw-r--r--src/main/java/gregtech/common/misc/spaceprojects/enums/UpgradeStatus.java11
-rw-r--r--src/main/java/gregtech/common/misc/spaceprojects/interfaces/ISpaceBody.java37
-rw-r--r--src/main/java/gregtech/common/misc/spaceprojects/interfaces/ISpaceProject.java430
-rw-r--r--src/main/java/gregtech/common/net/MessageSetFlaskCapacity.java67
-rw-r--r--src/main/java/gregtech/common/redstonecircuits/GT_Circuit_BasicLogic.java137
-rw-r--r--src/main/java/gregtech/common/redstonecircuits/GT_Circuit_BitAnd.java81
-rw-r--r--src/main/java/gregtech/common/redstonecircuits/GT_Circuit_CombinationLock.java109
-rw-r--r--src/main/java/gregtech/common/redstonecircuits/GT_Circuit_Equals.java73
-rw-r--r--src/main/java/gregtech/common/redstonecircuits/GT_Circuit_Pulser.java92
-rw-r--r--src/main/java/gregtech/common/redstonecircuits/GT_Circuit_Randomizer.java86
-rw-r--r--src/main/java/gregtech/common/redstonecircuits/GT_Circuit_RedstoneMeter.java94
-rw-r--r--src/main/java/gregtech/common/redstonecircuits/GT_Circuit_Repeater.java86
-rw-r--r--src/main/java/gregtech/common/redstonecircuits/GT_Circuit_Timer.java108
-rw-r--r--src/main/java/gregtech/common/render/GT_CapeRenderer.java148
-rw-r--r--src/main/java/gregtech/common/render/GT_CopiedBlockTexture.java112
-rw-r--r--src/main/java/gregtech/common/render/GT_CopiedCTMBlockTexture.java118
-rw-r--r--src/main/java/gregtech/common/render/GT_FlaskRenderer.java71
-rw-r--r--src/main/java/gregtech/common/render/GT_FluidDisplayStackRenderer.java98
-rw-r--r--src/main/java/gregtech/common/render/GT_IconFlipped.java91
-rw-r--r--src/main/java/gregtech/common/render/GT_MetaGenerated_Tool_Renderer.java130
-rw-r--r--src/main/java/gregtech/common/render/GT_MultiTexture.java69
-rw-r--r--src/main/java/gregtech/common/render/GT_MultiTile_Renderer.java181
-rw-r--r--src/main/java/gregtech/common/render/GT_PollutionRenderer.java251
-rw-r--r--src/main/java/gregtech/common/render/GT_RenderDrone.java93
-rw-r--r--src/main/java/gregtech/common/render/GT_RenderUtil.java141
-rw-r--r--src/main/java/gregtech/common/render/GT_RenderedTexture.java395
-rw-r--r--src/main/java/gregtech/common/render/GT_Renderer_Block.java747
-rw-r--r--src/main/java/gregtech/common/render/GT_Renderer_Entity_Arrow.java23
-rw-r--r--src/main/java/gregtech/common/render/GT_SidedTexture.java78
-rw-r--r--src/main/java/gregtech/common/render/GT_TextureBase.java31
-rw-r--r--src/main/java/gregtech/common/render/GT_TextureBuilder.java151
-rw-r--r--src/main/java/gregtech/common/render/IRenderedBlock.java114
-rw-r--r--src/main/java/gregtech/common/render/IRenderedBlockSideCheck.java15
-rw-r--r--src/main/java/gregtech/common/render/MultiTileBasicRender.java10
-rw-r--r--src/main/java/gregtech/common/render/items/CosmicNeutroniumRenderer.java109
-rw-r--r--src/main/java/gregtech/common/render/items/GT_DataStick_Renderer.java42
-rw-r--r--src/main/java/gregtech/common/render/items/GT_GeneratedItem_Renderer.java166
-rw-r--r--src/main/java/gregtech/common/render/items/GT_GeneratedMaterial_Renderer.java130
-rw-r--r--src/main/java/gregtech/common/render/items/GT_MetaGenerated_Item_Renderer.java85
-rw-r--r--src/main/java/gregtech/common/render/items/GaiaSpiritRenderer.java27
-rw-r--r--src/main/java/gregtech/common/render/items/InfinityRenderer.java139
-rw-r--r--src/main/java/gregtech/common/render/items/TranscendentMetalRenderer.java145
-rw-r--r--src/main/java/gregtech/common/render/items/UniversiumRenderer.java197
-rw-r--r--src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_ChestBuffer.java137
-rw-r--r--src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_Filter.java144
-rw-r--r--src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_ItemDistributor.java204
-rw-r--r--src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_RecipeFilter.java328
-rw-r--r--src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_Regulator.java228
-rw-r--r--src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_SuperBuffer.java105
-rw-r--r--src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_TypeFilter.java213
-rw-r--r--src/main/java/gregtech/common/tileentities/boilers/GT_MetaTileEntity_Boiler.java516
-rw-r--r--src/main/java/gregtech/common/tileentities/boilers/GT_MetaTileEntity_Boiler_Bronze.java311
-rw-r--r--src/main/java/gregtech/common/tileentities/boilers/GT_MetaTileEntity_Boiler_Lava.java524
-rw-r--r--src/main/java/gregtech/common/tileentities/boilers/GT_MetaTileEntity_Boiler_Solar.java381
-rw-r--r--src/main/java/gregtech/common/tileentities/boilers/GT_MetaTileEntity_Boiler_Solar_Steel.java77
-rw-r--r--src/main/java/gregtech/common/tileentities/boilers/GT_MetaTileEntity_Boiler_Steel.java108
-rw-r--r--src/main/java/gregtech/common/tileentities/casings/functional/Conveyor.java16
-rw-r--r--src/main/java/gregtech/common/tileentities/casings/functional/Emitter.java16
-rw-r--r--src/main/java/gregtech/common/tileentities/casings/functional/FieldGenerator.java16
-rw-r--r--src/main/java/gregtech/common/tileentities/casings/functional/Motor.java16
-rw-r--r--src/main/java/gregtech/common/tileentities/casings/functional/Piston.java16
-rw-r--r--src/main/java/gregtech/common/tileentities/casings/functional/Pump.java16
-rw-r--r--src/main/java/gregtech/common/tileentities/casings/functional/RobotArm.java16
-rw-r--r--src/main/java/gregtech/common/tileentities/casings/functional/Sensor.java16
-rw-r--r--src/main/java/gregtech/common/tileentities/casings/upgrade/Ampere.java47
-rw-r--r--src/main/java/gregtech/common/tileentities/casings/upgrade/Cleanroom.java26
-rw-r--r--src/main/java/gregtech/common/tileentities/casings/upgrade/Heater.java21
-rw-r--r--src/main/java/gregtech/common/tileentities/casings/upgrade/Insulator.java22
-rw-r--r--src/main/java/gregtech/common/tileentities/casings/upgrade/Inventory.java123
-rw-r--r--src/main/java/gregtech/common/tileentities/casings/upgrade/Laser.java26
-rw-r--r--src/main/java/gregtech/common/tileentities/casings/upgrade/Tank.java61
-rw-r--r--src/main/java/gregtech/common/tileentities/casings/upgrade/Wireless.java26
-rw-r--r--src/main/java/gregtech/common/tileentities/debug/GT_MetaTileEntity_AdvDebugStructureWriter.java439
-rw-r--r--src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_DieselGenerator.java283
-rw-r--r--src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_GasTurbine.java216
-rw-r--r--src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_LightningRod.java169
-rw-r--r--src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_MagicEnergyConverter.java178
-rw-r--r--src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_MagicalEnergyAbsorber.java817
-rw-r--r--src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_NaquadahReactor.java208
-rw-r--r--src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_PlasmaGenerator.java147
-rw-r--r--src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_SteamTurbine.java245
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_BasicHull_Bronze.java45
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_BasicHull_BronzeBricks.java53
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_BasicHull_Steel.java47
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_BasicHull_SteelBricks.java53
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_Hatch_CraftingInput_ME.java1039
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_Hatch_CraftingInput_Slave.java262
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_Hatch_InputBus_ME.java804
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_Hatch_Input_ME.java884
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_Hatch_OutputBus_ME.java327
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_Hatch_Output_ME.java383
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/IDualInputHatch.java21
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/IDualInputInventory.java11
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/IRecipeProcessingAwareHatch.java26
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_AdvSeismicProspector.java309
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Boxinator.java231
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Charger.java110
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_IndustrialApiary.java1560
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Massfabricator.java243
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_MicrowaveEnergyTransmitter.java501
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Miner.java412
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_MonsterRepellent.java182
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_PotionBrewer.java235
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Pump.java851
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Replicator.java127
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_RockBreaker.java169
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Scanner.java425
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Teleporter.java609
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/long_distance/GT_MetaTileEntity_LongDistancePipelineBase.java415
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/long_distance/GT_MetaTileEntity_LongDistancePipelineFluid.java125
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/long_distance/GT_MetaTileEntity_LongDistancePipelineItem.java214
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_AbstractMultiFurnace.java48
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_AssemblyLine.java505
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_BrickedBlastFurnace.java155
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_Charcoal_Pit.java313
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_Cleanroom.java514
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ConcreteBackfiller1.java53
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ConcreteBackfiller2.java54
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ConcreteBackfillerBase.java180
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DieselEngine.java416
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DistillationTower.java367
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DrillerBase.java985
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ElectricBlastFurnace.java401
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ExtremeDieselEngine.java237
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_FusionComputer.java656
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_FusionComputer1.java103
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_FusionComputer2.java103
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_FusionComputer3.java103
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_HeatExchanger.java416
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ImplosionCompressor.java163
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_IntegratedOreFactory.java831
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeBoiler.java504
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeBoiler_Bronze.java96
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeBoiler_Steel.java96
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeBoiler_Titanium.java96
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeBoiler_TungstenSteel.java96
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeChemicalReactor.java298
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeTurbine.java492
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeTurbine_Gas.java222
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeTurbine_GasAdvanced.java219
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeTurbine_HPSteam.java232
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeTurbine_Plasma.java391
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeTurbine_Steam.java273
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_MultiFurnace.java377
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_NanoForge.java467
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilCracker.java423
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilDrill1.java53
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilDrill2.java55
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilDrill3.java55
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilDrill4.java55
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilDrillBase.java489
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilDrillInfinite.java87
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OreDrillingPlant1.java60
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OreDrillingPlant2.java60
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OreDrillingPlant3.java60
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OreDrillingPlant4.java60
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OreDrillingPlantBase.java745
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PCBFactory.java1276
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PlasmaForge.java986
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PrimitiveBlastFurnace.java526
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ProcessingArray.java545
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PyrolyseOven.java263
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_TranscendentPlasmaMixer.java288
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_VacuumFreezer.java163
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/drone/DroneConnection.java143
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/drone/GT_MetaTileEntity_DroneCentre.java912
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/drone/GT_MetaTileEntity_Hatch_DroneDownLink.java340
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multiblock/AdvChemicalProcessor.java508
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multiblock/CokeOven.java153
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multiblock/DistillationTower.java174
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multiblock/LaserEngraver.java305
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multiblock/LayeredCokeBattery.java295
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multiblock/Macerator.java132
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multiblock/logic/AdvChemicalProcessorProcessingLogic.java12
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multiblock/logic/CokeOvenProcessingLogic.java79
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multiblock/logic/DistillationTowerProcessingLogic.java7
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multiblock/logic/LaserEngraverProcessingLogic.java7
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multiblock/logic/LayeredCokeBatteryProcessingLogic.java7
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multiblock/logic/MaceratorProcessingLogic.java7
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_AlloySmelter_Bronze.java139
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_AlloySmelter_Steel.java139
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_Compressor_Bronze.java134
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_Compressor_Steel.java134
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_Extractor_Bronze.java134
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_Extractor_Steel.java134
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_ForgeHammer_Bronze.java202
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_ForgeHammer_Steel.java202
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_Furnace_Bronze.java161
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_Furnace_Steel.java159
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_Macerator_Bronze.java189
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_Macerator_Steel.java188
-rw-r--r--src/main/java/gregtech/common/tileentities/render/TileDrone.java24
-rw-r--r--src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_DigitalChestBase.java564
-rw-r--r--src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_DigitalTankBase.java699
-rw-r--r--src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_Locker.java283
-rw-r--r--src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_QuantumChest.java102
-rw-r--r--src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_QuantumTank.java55
-rw-r--r--src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_SuperChest.java30
-rw-r--r--src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_SuperTank.java54
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool.java196
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_Axe.java175
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_BranchCutter.java101
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_ButcheryKnife.java104
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_BuzzSaw.java81
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_Chainsaw_HV.java57
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_Chainsaw_LV.java185
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_Chainsaw_MV.java57
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_Crowbar.java140
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_Drill_HV.java68
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_Drill_LV.java152
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_Drill_MV.java58
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_File.java124
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_HardHammer.java203
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_Hoe.java132
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_JackHammer.java128
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_Knife.java76
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_Mortar.java120
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_Pickaxe.java139
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_Plow.java110
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_Plunger.java92
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_RollingPin.java70
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_Saw.java149
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_Scoop.java130
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_Screwdriver.java160
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_Screwdriver_LV.java34
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_Sense.java114
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_Shovel.java127
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_SoftHammer.java139
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_Soldering_Iron.java153
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_Sword.java128
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_Turbine.java58
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_Turbine_Huge.java27
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_Turbine_Large.java27
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_Turbine_Normal.java27
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_Turbine_Small.java27
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_UniversalSpade.java160
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_WireCutter.java117
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_Wrench.java272
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_Wrench_HV.java69
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_Wrench_LV.java77
-rw-r--r--src/main/java/gregtech/common/tools/GT_Tool_Wrench_MV.java69
-rw-r--r--src/main/java/gregtech/common/tools/pocket/GT_Tool_Pocket_BranchCutter.java39
-rw-r--r--src/main/java/gregtech/common/tools/pocket/GT_Tool_Pocket_File.java39
-rw-r--r--src/main/java/gregtech/common/tools/pocket/GT_Tool_Pocket_Knife.java39
-rw-r--r--src/main/java/gregtech/common/tools/pocket/GT_Tool_Pocket_Multitool.java50
-rw-r--r--src/main/java/gregtech/common/tools/pocket/GT_Tool_Pocket_Saw.java39
-rw-r--r--src/main/java/gregtech/common/tools/pocket/GT_Tool_Pocket_Screwdriver.java39
-rw-r--r--src/main/java/gregtech/common/tools/pocket/GT_Tool_Pocket_WireCutter.java39
450 files changed, 100080 insertions, 0 deletions
diff --git a/src/main/java/gregtech/common/GT_Client.java b/src/main/java/gregtech/common/GT_Client.java
new file mode 100644
index 0000000000..4cb063b3b5
--- /dev/null
+++ b/src/main/java/gregtech/common/GT_Client.java
@@ -0,0 +1,1096 @@
+// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
+// Jad home page: http://www.kpdus.com/jad.html
+// Decompiler options: packimports(3)
+// Source File Name: GT_Client.java
+
+package gregtech.common;
+
+import static gregtech.api.enums.GT_Values.calculateMaxPlasmaTurbineEfficiency;
+import static gregtech.api.enums.Mods.Forestry;
+import static gregtech.api.enums.Mods.GregTech;
+import static org.lwjgl.opengl.GL11.GL_LINE_LOOP;
+
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Scanner;
+import java.util.function.Function;
+
+import net.minecraft.block.Block;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.GLAllocation;
+import net.minecraft.client.renderer.Tessellator;
+import net.minecraft.client.resources.IReloadableResourceManager;
+import net.minecraft.client.resources.IResourceManager;
+import net.minecraft.client.resources.IResourceManagerReloadListener;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.ItemStack;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.MovingObjectPosition;
+import net.minecraft.world.ChunkCoordIntPair;
+import net.minecraft.world.World;
+import net.minecraftforge.client.event.DrawBlockHighlightEvent;
+import net.minecraftforge.common.MinecraftForge;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.oredict.OreDictionary;
+
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL20;
+
+import com.glodblock.github.nei.recipes.FluidRecipe;
+import com.glodblock.github.nei.recipes.extractor.GregTech5RecipeExtractor;
+import com.gtnewhorizon.structurelib.alignment.IAlignment;
+import com.gtnewhorizon.structurelib.alignment.IAlignmentProvider;
+
+import appeng.api.util.IOrientable;
+import appeng.tile.misc.TileInterface;
+import codechicken.lib.vec.Rotation;
+import codechicken.lib.vec.Scale;
+import codechicken.lib.vec.Transformation;
+import codechicken.lib.vec.Translation;
+import cpw.mods.fml.client.event.ConfigChangedEvent;
+import cpw.mods.fml.client.registry.RenderingRegistry;
+import cpw.mods.fml.common.eventhandler.SubscribeEvent;
+import cpw.mods.fml.common.gameevent.TickEvent;
+import cpw.mods.fml.common.network.FMLNetworkEvent;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.SoundResource;
+import gregtech.api.gui.GT_GUIColorOverride;
+import gregtech.api.gui.modularui.FallbackableSteamTexture;
+import gregtech.api.interfaces.tileentity.ICoverable;
+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.metatileentity.BaseMetaTileEntity;
+import gregtech.api.metatileentity.MetaPipeEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachine;
+import gregtech.api.multitileentity.multiblock.base.MultiBlockPart;
+import gregtech.api.net.GT_Packet_ClientPreference;
+import gregtech.api.objects.GT_ItemStack;
+import gregtech.api.recipe.RecipeCategory;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.util.ColorsMetadataSection;
+import gregtech.api.util.ColorsMetadataSectionSerializer;
+import gregtech.api.util.GT_ClientPreference;
+import gregtech.api.util.GT_CoverBehaviorBase;
+import gregtech.api.util.GT_Log;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_PlayedSound;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.WorldSpawnedEventBuilder;
+import gregtech.common.blocks.GT_Item_Machines;
+import gregtech.common.entities.GT_Entity_Arrow;
+import gregtech.common.entities.GT_Entity_Arrow_Potion;
+import gregtech.common.render.GT_CapeRenderer;
+import gregtech.common.render.GT_FlaskRenderer;
+import gregtech.common.render.GT_FluidDisplayStackRenderer;
+import gregtech.common.render.GT_MetaGenerated_Tool_Renderer;
+import gregtech.common.render.GT_MultiTile_Renderer;
+import gregtech.common.render.GT_PollutionRenderer;
+import gregtech.common.render.GT_RenderDrone;
+import gregtech.common.render.GT_Renderer_Block;
+import gregtech.common.render.GT_Renderer_Entity_Arrow;
+import gregtech.common.render.items.GT_MetaGenerated_Item_Renderer;
+import gregtech.common.tileentities.debug.GT_MetaTileEntity_AdvDebugStructureWriter;
+import gregtech.loaders.ExtraIcons;
+import gregtech.loaders.misc.GT_Bees;
+import gregtech.loaders.preload.GT_PreLoad;
+import gregtech.nei.NEI_GT_Config;
+import ic2.api.tile.IWrenchable;
+
+// Referenced classes of package gregtech.common:
+// GT_Proxy
+
+public class GT_Client extends GT_Proxy implements Runnable {
+
+ public static final String GTNH_CAPE_LIST_URL = "https://raw.githubusercontent.com/GTNewHorizons/CustomGTCapeHook-Cape-List/master/capes.txt";
+ public static final String GT_CAPE_LIST_URL = "http://gregtech.overminddl1.com/com/gregoriust/gregtech/supporterlist.txt";
+ private static final List<Block> ROTATABLE_VANILLA_BLOCKS;
+
+ private static final int[][] GRID_SWITCH_TABLE = new int[][] { { 0, 5, 3, 1, 2, 4 }, { 5, 0, 1, 3, 2, 4 },
+ { 1, 3, 0, 5, 2, 4 }, { 3, 1, 5, 0, 2, 4 }, { 4, 2, 3, 1, 0, 5 }, { 2, 4, 3, 1, 5, 0 }, };
+
+ // don't ask. these "just works"
+ private static final Transformation ROTATION_MARKER_TRANSFORM_CENTER = new Scale(0.5);
+ private static final Transformation[] ROTATION_MARKER_TRANSFORMS_SIDES_TRANSFORMS = {
+ new Scale(0.25).with(new Translation(0, 0, 0.375))
+ .compile(),
+ new Scale(0.25).with(new Translation(0.375, 0, 0))
+ .compile(),
+ new Scale(0.25).with(new Translation(0, 0, -0.375))
+ .compile(),
+ new Scale(0.25).with(new Translation(-0.375, 0, 0))
+ .compile(), };
+ private static final int[] ROTATION_MARKER_TRANSFORMS_SIDES = { -1, -1, 2, 0, 3, 1, -1, -1, 0, 2, 3, 1, 0, 2, -1,
+ -1, 3, 1, 2, 0, -1, -1, 3, 1, 1, 3, 2, 0, -1, -1, 3, 1, 2, 0, -1, -1 };
+ private static final Transformation[] ROTATION_MARKER_TRANSFORMS_CORNER = {
+ new Scale(0.25).with(new Translation(0.375, 0, 0.375))
+ .compile(),
+ new Scale(0.25).with(new Translation(-0.375, 0, 0.375))
+ .compile(),
+ new Scale(0.25).with(new Translation(0.375, 0, -0.375))
+ .compile(),
+ new Scale(0.25).with(new Translation(-0.375, 0, -0.375))
+ .compile(), };
+ private static int rotationMarkerDisplayList;
+ private static boolean rotationMarkerDisplayListCompiled = false;
+
+ static {
+ ROTATABLE_VANILLA_BLOCKS = Arrays.asList(
+ Blocks.piston,
+ Blocks.sticky_piston,
+ Blocks.furnace,
+ Blocks.lit_furnace,
+ Blocks.dropper,
+ Blocks.dispenser,
+ Blocks.chest,
+ Blocks.trapped_chest,
+ Blocks.ender_chest,
+ Blocks.hopper,
+ Blocks.pumpkin,
+ Blocks.lit_pumpkin);
+ }
+
+ private final HashSet<String> mCapeList = new HashSet<>();
+ public static final GT_PollutionRenderer mPollutionRenderer = new GT_PollutionRenderer();
+ private final GT_CapeRenderer mCapeRenderer;
+ private final List<Materials> mPosR;
+ private final List<Materials> mPosG;
+ private final List<Materials> mPosB;
+ private final List<Materials> mPosA = Collections.emptyList();
+ private final List<Materials> mNegR;
+ private final List<Materials> mNegG;
+ private final List<Materials> mNegB;
+ private final List<Materials> mNegA = Collections.emptyList();
+ private final List<Materials> mMoltenPosR;
+ private final List<Materials> mMoltenPosG;
+ private final List<Materials> mMoltenPosB;
+ private final List<Materials> mMoltenPosA = Collections.emptyList();
+ private final List<Materials> mMoltenNegR;
+ private final List<Materials> mMoltenNegG;
+ private final List<Materials> mMoltenNegB;
+ private final List<Materials> mMoltenNegA = Collections.emptyList();
+ private long mAnimationTick;
+ /**
+ * This is the place to def the value used below
+ **/
+ private long afterSomeTime;
+
+ private boolean mAnimationDirection;
+ private GT_ClientPreference mPreference;
+ private boolean mFirstTick = false;
+ public static final int ROTATION_MARKER_RESOLUTION = 120;
+ private int mReloadCount;
+ private float renderTickTime;
+ public static GT_MetaGenerated_Item_Renderer metaGeneratedItemRenderer;
+
+ public GT_Client() {
+ mCapeRenderer = new GT_CapeRenderer(mCapeList);
+ mAnimationTick = 0L;
+ mAnimationDirection = false;
+ mPosR = Arrays.asList(
+ Materials.Enderium,
+ Materials.Vinteum,
+ Materials.Uranium235,
+ Materials.InfusedGold,
+ Materials.Plutonium241,
+ Materials.NaquadahEnriched,
+ Materials.Naquadria,
+ Materials.InfusedOrder,
+ Materials.Force,
+ Materials.Pyrotheum,
+ Materials.Sunnarium,
+ Materials.Glowstone,
+ Materials.Thaumium,
+ Materials.InfusedVis,
+ Materials.InfusedAir,
+ Materials.InfusedFire,
+ Materials.FierySteel,
+ Materials.Firestone);
+ mPosG = Arrays.asList(
+ Materials.Enderium,
+ Materials.Vinteum,
+ Materials.Uranium235,
+ Materials.InfusedGold,
+ Materials.Plutonium241,
+ Materials.NaquadahEnriched,
+ Materials.Naquadria,
+ Materials.InfusedOrder,
+ Materials.Force,
+ Materials.Pyrotheum,
+ Materials.Sunnarium,
+ Materials.Glowstone,
+ Materials.InfusedAir,
+ Materials.InfusedEarth);
+ mPosB = Arrays.asList(
+ Materials.Enderium,
+ Materials.Vinteum,
+ Materials.Uranium235,
+ Materials.InfusedGold,
+ Materials.Plutonium241,
+ Materials.NaquadahEnriched,
+ Materials.Naquadria,
+ Materials.InfusedOrder,
+ Materials.InfusedVis,
+ Materials.InfusedWater,
+ Materials.Thaumium);
+ mNegR = Arrays.asList(Materials.InfusedEntropy, Materials.NetherStar);
+ mNegG = Arrays.asList(Materials.InfusedEntropy, Materials.NetherStar);
+ mNegB = Arrays.asList(Materials.InfusedEntropy, Materials.NetherStar);
+ mMoltenPosR = Arrays.asList(
+ Materials.Enderium,
+ Materials.NetherStar,
+ Materials.Vinteum,
+ Materials.Uranium235,
+ Materials.InfusedGold,
+ Materials.Plutonium241,
+ Materials.NaquadahEnriched,
+ Materials.Naquadria,
+ Materials.InfusedOrder,
+ Materials.Force,
+ Materials.Pyrotheum,
+ Materials.Sunnarium,
+ Materials.Glowstone,
+ Materials.Thaumium,
+ Materials.InfusedVis,
+ Materials.InfusedAir,
+ Materials.InfusedFire,
+ Materials.FierySteel,
+ Materials.Firestone);
+ mMoltenPosG = Arrays.asList(
+ Materials.Enderium,
+ Materials.NetherStar,
+ Materials.Vinteum,
+ Materials.Uranium235,
+ Materials.InfusedGold,
+ Materials.Plutonium241,
+ Materials.NaquadahEnriched,
+ Materials.Naquadria,
+ Materials.InfusedOrder,
+ Materials.Force,
+ Materials.Pyrotheum,
+ Materials.Sunnarium,
+ Materials.Glowstone,
+ Materials.InfusedAir,
+ Materials.InfusedEarth);
+ mMoltenPosB = Arrays.asList(
+ Materials.Enderium,
+ Materials.NetherStar,
+ Materials.Vinteum,
+ Materials.Uranium235,
+ Materials.InfusedGold,
+ Materials.Plutonium241,
+ Materials.NaquadahEnriched,
+ Materials.Naquadria,
+ Materials.InfusedOrder,
+ Materials.InfusedVis,
+ Materials.InfusedWater,
+ Materials.Thaumium);
+ mMoltenNegR = Collections.singletonList(Materials.InfusedEntropy);
+ mMoltenNegG = Collections.singletonList(Materials.InfusedEntropy);
+ mMoltenNegB = Collections.singletonList(Materials.InfusedEntropy);
+ }
+
+ private static boolean checkedForChicken = false;
+
+ private static void drawGrid(DrawBlockHighlightEvent aEvent, boolean showCoverConnections, boolean aIsWrench,
+ boolean aIsSneaking) {
+ if (!checkedForChicken) {
+ try {
+ Class.forName("codechicken.lib.vec.Rotation");
+ } catch (ClassNotFoundException e) {
+ return;
+ }
+ checkedForChicken = true;
+ }
+
+ GL11.glPushMatrix();
+
+ GL11.glEnable(GL11.GL_BLEND);
+ GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ GL11.glDisable(GL11.GL_TEXTURE_2D);
+
+ // pause shader
+ int program = GL11.glGetInteger(GL20.GL_CURRENT_PROGRAM);
+ GL20.glUseProgram(0);
+
+ MovingObjectPosition target = aEvent.target;
+ EntityPlayer player = aEvent.player;
+ double camX = player.lastTickPosX + (player.posX - player.lastTickPosX) * (double) aEvent.partialTicks;
+ double camY = player.lastTickPosY + (player.posY - player.lastTickPosY) * (double) aEvent.partialTicks;
+ double camZ = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * (double) aEvent.partialTicks;
+ GL11.glTranslated(target.blockX - (int) camX, target.blockY - (int) camY, target.blockZ - (int) camZ);
+ GL11.glTranslated(0.5D - (camX - (int) camX), 0.5D - (camY - (int) camY), 0.5D - (camZ - (int) camZ));
+ final int tSideHit = target.sideHit;
+ Rotation.sideRotations[tSideHit].glApply();
+ // draw grid
+ GL11.glTranslated(0.0D, -0.502D, 0.0D);
+ GL11.glLineWidth(2.5F);
+ GL11.glColor4f(0.0F, 0.0F, 0.0F, 0.5F);
+ GL11.glBegin(GL11.GL_LINES);
+ GL11.glVertex3d(+.50D, .0D, -.25D);
+ GL11.glVertex3d(-.50D, .0D, -.25D);
+ GL11.glVertex3d(+.50D, .0D, +.25D);
+ GL11.glVertex3d(-.50D, .0D, +.25D);
+ GL11.glVertex3d(+.25D, .0D, -.50D);
+ GL11.glVertex3d(+.25D, .0D, +.50D);
+ GL11.glVertex3d(-.25D, .0D, -.50D);
+ GL11.glVertex3d(-.25D, .0D, +.50D);
+ final TileEntity tTile = player.worldObj.getTileEntity(target.blockX, target.blockY, target.blockZ);
+ final Block block = player.worldObj.getBlock(target.blockX, target.blockY, target.blockZ);
+ final int meta = player.worldObj.getBlockMetadata(target.blockX, target.blockY, target.blockZ);
+
+ // draw connection indicators
+ int tConnections = 0;
+ if (tTile instanceof ICoverable iCoverable) {
+ if (showCoverConnections) {
+ for (final ForgeDirection tSide : ForgeDirection.VALID_DIRECTIONS) {
+ if (iCoverable.getCoverIDAtSide(tSide) != 0) tConnections |= tSide.flag;
+ }
+ } else if (tTile instanceof BaseMetaTileEntity baseMetaTile && baseMetaTile.getAlignment() == null) {
+ if (!aIsSneaking) tConnections |= baseMetaTile.getFrontFacing().flag;
+ else if (baseMetaTile.getMetaTileEntity() instanceof GT_MetaTileEntity_BasicMachine basicMachine) {
+ tConnections |= basicMachine.mMainFacing.flag;
+ }
+ } else if (tTile instanceof BaseMetaPipeEntity pipeEntity) tConnections = pipeEntity.mConnections;
+ } else if (tTile instanceof IWrenchable wrenchable) {
+ tConnections |= ForgeDirection.getOrientation(wrenchable.getFacing()).flag;
+ } else if (ROTATABLE_VANILLA_BLOCKS.contains(block)) {
+ tConnections |= ForgeDirection.getOrientation(meta).flag;
+ } else if (tTile instanceof TileInterface tileInterface) tConnections |= tileInterface.getUp()
+ .getOpposite().flag;
+
+ if (tConnections != 0) {
+ for (ForgeDirection tSide : ForgeDirection.VALID_DIRECTIONS) {
+ if ((tConnections & tSide.flag) != 0) {
+ switch (GRID_SWITCH_TABLE[target.sideHit][tSide.ordinal()]) {
+ case 0 -> {
+ GL11.glVertex3d(+.25D, .0D, +.25D);
+ GL11.glVertex3d(-.25D, .0D, -.25D);
+ GL11.glVertex3d(-.25D, .0D, +.25D);
+ GL11.glVertex3d(+.25D, .0D, -.25D);
+ }
+ case 1 -> {
+ GL11.glVertex3d(-.25D, .0D, +.50D);
+ GL11.glVertex3d(+.25D, .0D, +.25D);
+ GL11.glVertex3d(-.25D, .0D, +.25D);
+ GL11.glVertex3d(+.25D, .0D, +.50D);
+ }
+ case 2 -> {
+ GL11.glVertex3d(-.50D, .0D, -.25D);
+ GL11.glVertex3d(-.25D, .0D, +.25D);
+ GL11.glVertex3d(-.50D, .0D, +.25D);
+ GL11.glVertex3d(-.25D, .0D, -.25D);
+ }
+ case 3 -> {
+ GL11.glVertex3d(-.25D, .0D, -.50D);
+ GL11.glVertex3d(+.25D, .0D, -.25D);
+ GL11.glVertex3d(-.25D, .0D, -.25D);
+ GL11.glVertex3d(+.25D, .0D, -.50D);
+ }
+ case 4 -> {
+ GL11.glVertex3d(+.50D, .0D, -.25D);
+ GL11.glVertex3d(+.25D, .0D, +.25D);
+ GL11.glVertex3d(+.50D, .0D, +.25D);
+ GL11.glVertex3d(+.25D, .0D, -.25D);
+ }
+ case 5 -> {
+ GL11.glVertex3d(+.50D, .0D, +.50D);
+ GL11.glVertex3d(+.25D, .0D, +.25D);
+ GL11.glVertex3d(+.50D, .0D, +.25D);
+ GL11.glVertex3d(+.25D, .0D, +.50D);
+ GL11.glVertex3d(+.50D, .0D, -.50D);
+ GL11.glVertex3d(+.25D, .0D, -.25D);
+ GL11.glVertex3d(+.50D, .0D, -.25D);
+ GL11.glVertex3d(+.25D, .0D, -.50D);
+ GL11.glVertex3d(-.50D, .0D, +.50D);
+ GL11.glVertex3d(-.25D, .0D, +.25D);
+ GL11.glVertex3d(-.50D, .0D, +.25D);
+ GL11.glVertex3d(-.25D, .0D, +.50D);
+ GL11.glVertex3d(-.50D, .0D, -.50D);
+ GL11.glVertex3d(-.25D, .0D, -.25D);
+ GL11.glVertex3d(-.50D, .0D, -.25D);
+ GL11.glVertex3d(-.25D, .0D, -.50D);
+ }
+ }
+ }
+ }
+ }
+ GL11.glEnd();
+ // draw turning indicator
+ Function<ForgeDirection, Transformation[]> getTransform = (ForgeDirection direction) -> {
+ try {
+ if (direction.ordinal() == tSideHit) return new Transformation[] { ROTATION_MARKER_TRANSFORM_CENTER };
+ else if (direction.getOpposite()
+ .ordinal() == tSideHit) {
+ return ROTATION_MARKER_TRANSFORMS_CORNER;
+ } else {
+ return new Transformation[] {
+ ROTATION_MARKER_TRANSFORMS_SIDES_TRANSFORMS[ROTATION_MARKER_TRANSFORMS_SIDES[tSideHit * 6
+ + direction.ordinal()]] };
+ }
+ } catch (ArrayIndexOutOfBoundsException e) {
+ return new Transformation[] {};
+ }
+
+ };
+
+ if (aIsWrench && tTile instanceof IAlignmentProvider) {
+ final IAlignment tAlignment = ((IAlignmentProvider) (tTile)).getAlignment();
+ if (tAlignment != null) {
+ for (var transform : getTransform.apply(tAlignment.getDirection())) {
+ drawExtendedRotationMarker(transform, aIsSneaking, tAlignment);
+ }
+ }
+ }
+ if (aIsWrench && tTile instanceof IOrientable orientable
+ && !(tTile instanceof TileInterface)
+ && orientable.canBeRotated()) {
+ for (var transform : getTransform.apply(aIsSneaking ? orientable.getForward() : orientable.getUp())) {
+ drawExtendedRotationMarker(transform, aIsSneaking, orientable);
+ }
+ }
+ GL20.glUseProgram(program); // resume shader
+ GL11.glPopMatrix(); // get back to player center
+ }
+
+ private static void drawExtendedRotationMarker(Transformation transform, boolean sneaking, IAlignment alignment) {
+ if (sneaking) {
+ if (alignment.isFlipChangeAllowed()) {
+ drawFlipMarker(transform);
+ }
+ } else {
+ if (alignment.isRotationChangeAllowed()) {
+ drawRotationMarker(transform);
+ }
+ }
+ }
+
+ private static void drawExtendedRotationMarker(Transformation transform, boolean sneaking, IOrientable orientable) {
+ drawRotationMarker(transform);
+ }
+
+ private static void drawRotationMarker(Transformation transform) {
+ if (!rotationMarkerDisplayListCompiled) {
+ rotationMarkerDisplayList = GLAllocation.generateDisplayLists(1);
+ compileRotationMarkerDisplayList(rotationMarkerDisplayList);
+ rotationMarkerDisplayListCompiled = true;
+ }
+ GL11.glPushMatrix();
+ transform.glApply();
+ GL11.glCallList(rotationMarkerDisplayList);
+ GL11.glPopMatrix();
+ }
+
+ private static void compileRotationMarkerDisplayList(int displayList) {
+ GL11.glNewList(displayList, GL11.GL_COMPILE);
+ GL11.glBegin(GL_LINE_LOOP);
+ for (int i = 0; i <= ROTATION_MARKER_RESOLUTION; i++) {
+ GL11.glVertex3d(
+ Math.cos(i * Math.PI * 1.75 / ROTATION_MARKER_RESOLUTION) * 0.4,
+ 0,
+ Math.sin(i * Math.PI * 1.75 / ROTATION_MARKER_RESOLUTION) * 0.4);
+ }
+ for (int i = ROTATION_MARKER_RESOLUTION; i >= 0; i--) {
+ GL11.glVertex3d(
+ Math.cos(i * Math.PI * 1.75 / ROTATION_MARKER_RESOLUTION) * 0.24,
+ 0,
+ Math.sin(i * Math.PI * 1.75 / ROTATION_MARKER_RESOLUTION) * 0.24);
+ }
+ GL11.glVertex3d(0.141114561800, 0, 0);
+ GL11.glVertex3d(0.32, 0, -0.178885438199);
+ GL11.glVertex3d(0.498885438199, 0, 0);
+ GL11.glEnd();
+ GL11.glEndList();
+ }
+
+ private static void drawFlipMarker(Transformation transform) {
+ GL11.glPushMatrix();
+ transform.glApply();
+ final Tessellator t = Tessellator.instance;
+ // right shape
+ GL11.glLineStipple(4, (short) 0xAAAA);
+ GL11.glEnable(GL11.GL_LINE_STIPPLE);
+ t.startDrawing(GL11.GL_LINE_STRIP);
+ t.addVertex(0.1d, 0d, 0.04d);
+ t.addVertex(0.1d, 0d, 0.2d);
+ t.addVertex(0.35d, 0d, 0.35d);
+ t.addVertex(0.35d, 0d, -0.35d);
+ t.addVertex(0.1d, 0d, -0.2d);
+ t.addVertex(0.1d, 0d, -0.04d);
+ t.draw();
+ GL11.glDisable(GL11.GL_LINE_STIPPLE);
+ // left shape
+ t.startDrawing(GL11.GL_LINE_STRIP);
+ t.addVertex(-0.1d, 0d, 0.04d);
+ t.addVertex(-0.1d, 0d, 0.2d);
+ t.addVertex(-0.35d, 0d, 0.35d);
+ t.addVertex(-0.35d, 0d, -0.35d);
+ t.addVertex(-0.1d, 0d, -0.2d);
+ t.addVertex(-0.1d, 0d, -0.04d);
+ t.draw();
+ // arrow
+ t.startDrawing(GL11.GL_LINE_LOOP);
+ t.addVertex(0.15d, 0d, -0.04d);
+ t.addVertex(0.15d, 0d, -0.1d);
+ t.addVertex(0.25d, 0d, 0.d);
+ t.addVertex(0.15d, 0d, 0.1d);
+ t.addVertex(0.15d, 0d, 0.04d);
+ t.addVertex(-0.15d, 0d, 0.04d);
+ t.addVertex(-0.15d, 0d, 0.1d);
+ t.addVertex(-0.25d, 0d, 0.d);
+ t.addVertex(-0.15d, 0d, -0.1d);
+ t.addVertex(-0.15d, 0d, -0.04d);
+ t.draw();
+ GL11.glPopMatrix();
+ }
+
+ @Override
+ public boolean isServerSide() {
+ return true;
+ }
+
+ @Override
+ public boolean isClientSide() {
+ return true;
+ }
+
+ @Override
+ public boolean isBukkitSide() {
+ return false;
+ }
+
+ @Override
+ public EntityPlayer getThePlayer() {
+ return Minecraft.getMinecraft().thePlayer;
+ }
+
+ @Override
+ public int addArmor(String aPrefix) {
+ return RenderingRegistry.addNewArmourRendererPrefix(aPrefix);
+ }
+
+ @Override
+ public void onPreLoad() {
+ super.onPreLoad();
+
+ MinecraftForge.EVENT_BUS.register(new ExtraIcons());
+ Minecraft.getMinecraft()
+ .getResourcePackRepository().rprMetadataSerializer
+ .registerMetadataSectionType(new ColorsMetadataSectionSerializer(), ColorsMetadataSection.class);
+
+ new GT_MetaTileEntity_AdvDebugStructureWriter.ForgeEventHandler();
+
+ final String[] arr = { "renadi", "hanakocz", "MysteryDump", "Flaver4", "x_Fame", "Peluche321",
+ "Goshen_Ithilien", "manf", "Bimgo", "leagris", "IAmMinecrafter02", "Cerous", "Devilin_Pixy", "Bkarlsson87",
+ "BadAlchemy", "CaballoCraft", "melanclock", "Resursator", "demanzke", "AndrewAmmerlaan", "Deathlycraft",
+ "Jirajha", "Axlegear", "kei_kouma", "Dracion", "dungi", "Dorfschwein", "Zero Tw0", "mattiagraz85",
+ "sebastiank30", "Plem", "invultri", "grillo126", "malcanteth", "Malevolence_", "Nicholas_Manuel", "Sirbab",
+ "kehaan", "bpgames123", "semig0d", "9000bowser", "Sovereignty89", "Kris1432", "xander_cage_", "samuraijp",
+ "bsaa", "SpwnX", "tworf", "Kadah", "kanni", "Stute", "Hegik", "Onlyme", "t3hero", "Hotchi", "jagoly",
+ "Nullav", "BH5432", "Sibmer", "inceee", "foxxx0", "Hartok", "TMSama", "Shlnen", "Carsso", "zessirb",
+ "meep310", "Seldron", "yttr1um", "hohounk", "freebug", "Sylphio", "jmarler", "Saberawr", "r00teniy",
+ "Neonbeta", "yinscape", "voooon24", "Quintine", "peach774", "lepthymo", "bildeman", "Kremnari", "Aerosalo",
+ "OndraSter", "oscares91", "mr10movie", "Daxx367x2", "EGERTRONx", "aka13_404", "Abouttabs", "Johnstaal",
+ "djshiny99", "megatronp", "DZCreeper", "Kane_Hart", "Truculent", "vidplace7", "simon6689", "MomoNasty",
+ "UnknownXLV", "goreacraft", "Fluttermine", "Daddy_Cecil", "MrMaleficus", "TigersFangs", "cublikefoot",
+ "chainman564", "NikitaBuker", "Misha999777", "25FiveDetail", "AntiCivilBoy", "michaelbrady",
+ "xXxIceFirexXx", "Speedynutty68", "GarretSidzaka", "HallowCharm977", "mastermind1919", "The_Hypersonic",
+ "diamondguy2798", "zF4ll3nPr3d4t0r", "CrafterOfMines57", "XxELIT3xSNIP3RxX", "SuterusuKusanagi",
+ "xavier0014", "adamros", "alexbegt" };
+ for (String tName : arr) {
+ mCapeList.add(tName.toLowerCase());
+ }
+ new Thread(this).start();
+
+ mPollutionRenderer.preLoad();
+
+ mPreference = new GT_ClientPreference(GregTech_API.sClientDataFile);
+
+ Materials.initClient();
+ }
+
+ @Override
+ public void onLoad() {
+ super.onLoad();
+ GT_Renderer_Block.register();
+ new GT_MultiTile_Renderer();
+ new GT_RenderDrone();
+ metaGeneratedItemRenderer = new GT_MetaGenerated_Item_Renderer();
+ for (GT_MetaGenerated_Item item : GT_MetaGenerated_Item.sInstances.values()) {
+ metaGeneratedItemRenderer.registerItem(item);
+ }
+ if (Forestry.isModLoaded()) {
+ metaGeneratedItemRenderer.registerItem(GT_Bees.combs);
+ }
+ new GT_MetaGenerated_Tool_Renderer();
+ new GT_Renderer_Entity_Arrow(GT_Entity_Arrow.class, "arrow");
+ new GT_Renderer_Entity_Arrow(GT_Entity_Arrow_Potion.class, "arrow_potions");
+ new GT_FlaskRenderer();
+ new GT_FluidDisplayStackRenderer();
+ MinecraftForge.EVENT_BUS.register(new NEI_GT_Config());
+ }
+
+ @Override
+ public void onPostLoad() {
+ super.onPostLoad();
+
+ if (GregTech_API.sClientDataFile.get("debug", "PrintMetaIDs", false)) {
+ try {
+ for (int i = 1; i < GregTech_API.METATILEENTITIES.length; i++) {
+ try {
+ if (GregTech_API.METATILEENTITIES[i] != null) {
+ GregTech_API.METATILEENTITIES[i].getStackForm(1L)
+ .getTooltip(null, true);
+ GT_Log.out.println("META " + i + " " + GregTech_API.METATILEENTITIES[i].getMetaName());
+ }
+ } catch (Throwable e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ }
+ } catch (Throwable e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ }
+
+ // reobf doesn't work with lambda, so this must be a class
+ // noinspection Convert2Lambda
+ ((IReloadableResourceManager) Minecraft.getMinecraft()
+ .getResourceManager()).registerReloadListener(new IResourceManagerReloadListener() {
+
+ @Override
+ public void onResourceManagerReload(IResourceManager l) {
+ GT_GUIColorOverride.onResourceManagerReload();
+ FallbackableSteamTexture.reload();
+ GregTech_API.sCoverBehaviors.values()
+ .forEach(GT_CoverBehaviorBase::reloadColorOverride);
+ }
+ });
+ }
+
+ @Override
+ public void onLoadComplete() {
+ super.onLoadComplete();
+ for (RecipeCategory category : RecipeCategory.ALL_RECIPE_CATEGORIES.values()) {
+ if (category.recipeMap.getFrontend()
+ .getNEIProperties().registerNEI) {
+ FluidRecipe.addRecipeMap(
+ category.unlocalizedName,
+ new GregTech5RecipeExtractor(
+ category.unlocalizedName.equals("gt.recipe.scanner")
+ || category.unlocalizedName.equals("gt.recipe.fakeAssemblylineProcess")));
+ }
+ }
+ }
+
+ @Override
+ public void run() {
+ GT_Log.out.println("GT_Mod: Downloading Cape List.");
+ try (final Scanner tScanner = new Scanner(new URL(GT_CAPE_LIST_URL).openStream())) {
+ while (tScanner.hasNextLine()) {
+ this.mCapeList.add(
+ tScanner.nextLine()
+ .toLowerCase());
+ }
+ } catch (Throwable e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ GT_Log.out.println("GT New Horizons: Downloading Cape List.");
+ try (final Scanner tScanner = new Scanner(new URL(GTNH_CAPE_LIST_URL).openStream())) {
+ while (tScanner.hasNextLine()) {
+ final String tName = tScanner.nextLine()
+ .toLowerCase();
+ if (tName.contains(":")) {
+ if (!this.mCapeList.contains(tName.substring(0, tName.indexOf(":")))) {
+ this.mCapeList.add(tName);
+ }
+ } else {
+ this.mCapeList.add(tName);
+ }
+ }
+ } catch (Throwable e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ }
+
+ @Override
+ @SubscribeEvent
+ public void onClientConnectedToServerEvent(FMLNetworkEvent.ClientConnectedToServerEvent aEvent) {
+ mFirstTick = true;
+ mReloadCount++;
+ // For utility methods elsewhere.
+ calculateMaxPlasmaTurbineEfficiency();
+ }
+
+ @Override
+ public void reloadNEICache() {
+ mReloadCount++;
+ }
+
+ @Override
+ public int getNEIReloadCount() {
+ return mReloadCount;
+ }
+
+ @SubscribeEvent
+ public void receiveRenderSpecialsEvent(net.minecraftforge.client.event.RenderPlayerEvent.Specials.Pre aEvent) {
+ mCapeRenderer.receiveRenderSpecialsEvent(aEvent);
+ }
+
+ @SubscribeEvent
+ public void onPlayerTickEventClient(TickEvent.PlayerTickEvent aEvent) {
+ if ((aEvent.side.isClient()) && (aEvent.phase == TickEvent.Phase.END) && (!aEvent.player.isDead)) {
+ if (mFirstTick) {
+ mFirstTick = false;
+ GT_Values.NW.sendToServer(new GT_Packet_ClientPreference(mPreference));
+
+ if (!Minecraft.getMinecraft()
+ .isSingleplayer()) {
+ // Check for more IC2 recipes to also catch MineTweaker additions
+ GT_ModHandler.addIC2RecipesToGT(
+ GT_ModHandler.getMaceratorRecipeList(),
+ RecipeMaps.maceratorRecipes,
+ true,
+ true,
+ true);
+ GT_ModHandler.addIC2RecipesToGT(
+ GT_ModHandler.getCompressorRecipeList(),
+ RecipeMaps.compressorRecipes,
+ true,
+ true,
+ true);
+ GT_ModHandler.addIC2RecipesToGT(
+ GT_ModHandler.getExtractorRecipeList(),
+ RecipeMaps.extractorRecipes,
+ true,
+ true,
+ true);
+ GT_ModHandler.addIC2RecipesToGT(
+ GT_ModHandler.getOreWashingRecipeList(),
+ RecipeMaps.oreWasherRecipes,
+ false,
+ true,
+ true);
+ GT_ModHandler.addIC2RecipesToGT(
+ GT_ModHandler.getThermalCentrifugeRecipeList(),
+ RecipeMaps.thermalCentrifugeRecipes,
+ true,
+ true,
+ true);
+ }
+ }
+ afterSomeTime++;
+ if (afterSomeTime >= 100L) {
+ afterSomeTime = 0;
+ }
+ for (Iterator<Map.Entry<GT_PlayedSound, Integer>> iterator = GT_Utility.sPlayedSoundMap.entrySet()
+ .iterator(); iterator.hasNext();) {
+ Map.Entry<GT_PlayedSound, Integer> tEntry = iterator.next();
+ if (tEntry.getValue() < 0) {
+ iterator.remove();
+ } else {
+ tEntry.setValue(tEntry.getValue() - 1);
+ }
+ }
+ if (!GregTech_API.mServerStarted) GregTech_API.mServerStarted = true;
+ }
+ }
+
+ @SubscribeEvent
+ public void onConfigChange(ConfigChangedEvent.OnConfigChangedEvent e) {
+ if (GregTech.ID.equals(e.modID) && "client".equals(e.configID)) {
+ GregTech_API.sClientDataFile.mConfig.save();
+ // refresh client preference and send to server, since it's the only config we allow changing at runtime.
+ mPreference = new GT_ClientPreference(GregTech_API.sClientDataFile);
+ GT_PreLoad.loadClientConfig();
+ if (e.isWorldRunning) GT_Values.NW.sendToServer(new GT_Packet_ClientPreference(mPreference));
+ }
+ }
+
+ @SubscribeEvent
+ public void onDrawBlockHighlight(DrawBlockHighlightEvent aEvent) {
+ final Block aBlock = aEvent.player.worldObj
+ .getBlock(aEvent.target.blockX, aEvent.target.blockY, aEvent.target.blockZ);
+ final TileEntity aTileEntity = aEvent.player.worldObj
+ .getTileEntity(aEvent.target.blockX, aEvent.target.blockY, aEvent.target.blockZ);
+
+ if (GT_Utility.isStackInList(aEvent.currentItem, GregTech_API.sWrenchList)) {
+ if (aTileEntity instanceof ITurnable || ROTATABLE_VANILLA_BLOCKS.contains(aBlock)
+ || aTileEntity instanceof IWrenchable
+ || (aTileEntity instanceof IOrientable orientable && orientable.canBeRotated()))
+ drawGrid(aEvent, false, true, aEvent.player.isSneaking());
+ return;
+ }
+
+ if (!(aTileEntity instanceof ICoverable)) return;
+
+ if (aEvent.player.isSneaking() && aTileEntity instanceof IGregTechTileEntity gtEntity
+ && gtEntity.getMetaTileEntity() instanceof MetaPipeEntity) {
+ if (aEvent.currentItem != null && aEvent.currentItem.getItem() instanceof GT_Item_Machines
+ && GregTech_API.METATILEENTITIES[aEvent.currentItem.getItemDamage()] instanceof MetaPipeEntity) {
+ drawGrid(aEvent, false, false, false);
+ }
+ }
+
+ if (GT_Utility.isStackInList(aEvent.currentItem, GregTech_API.sWireCutterList)
+ || 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(ForgeDirection.getOrientation(aEvent.target.sideHit)) == 0)
+ drawGrid(aEvent, false, false, aEvent.player.isSneaking());
+ return;
+ }
+
+ if ((aEvent.currentItem == null && aEvent.player.isSneaking())
+ || GT_Utility.isStackInList(aEvent.currentItem, GregTech_API.sCrowbarList)
+ || GT_Utility.isStackInList(aEvent.currentItem, GregTech_API.sScrewdriverList)) {
+ if (((ICoverable) aTileEntity).getCoverIDAtSide(ForgeDirection.getOrientation(aEvent.target.sideHit)) == 0)
+ for (final ForgeDirection tSide : ForgeDirection.VALID_DIRECTIONS) {
+ if (((ICoverable) aTileEntity).getCoverIDAtSide(tSide) > 0) {
+ drawGrid(aEvent, true, false, true);
+ return;
+ }
+ }
+ return;
+ }
+
+ if (GT_Utility.isStackInList(aEvent.currentItem, GregTech_API.sCovers.keySet())) {
+ if (((ICoverable) aTileEntity).getCoverIDAtSide(ForgeDirection.getOrientation(aEvent.target.sideHit)) == 0)
+ drawGrid(aEvent, true, false, aEvent.player.isSneaking());
+ }
+
+ if (GT_Utility.areStacksEqual(ItemList.Tool_Cover_Copy_Paste.get(1), aEvent.currentItem, true)) {
+ if (((ICoverable) aTileEntity).getCoverIDAtSide(ForgeDirection.getOrientation(aEvent.target.sideHit)) == 0)
+ drawGrid(aEvent, true, false, aEvent.player.isSneaking());
+ }
+ }
+
+ @SubscribeEvent
+ public void receiveRenderEvent(net.minecraftforge.client.event.RenderPlayerEvent.Pre aEvent) {
+ if (GT_Utility.getFullInvisibility(aEvent.entityPlayer)) {
+ aEvent.setCanceled(true);
+ }
+ }
+
+ @SubscribeEvent
+ public void onRenderStart(cpw.mods.fml.common.gameevent.TickEvent.RenderTickEvent aEvent) {
+ if (aEvent.phase == TickEvent.Phase.START) {
+ renderTickTime = aEvent.renderTickTime;
+ }
+ }
+
+ @SubscribeEvent
+ public void onClientTickEvent(cpw.mods.fml.common.gameevent.TickEvent.ClientTickEvent aEvent) {
+ if (aEvent.phase == cpw.mods.fml.common.gameevent.TickEvent.Phase.END) {
+ if (changeDetected > 0) changeDetected--;
+ final int newHideValue = shouldHeldItemHideThings();
+ if (newHideValue != hideValue) {
+ hideValue = newHideValue;
+ changeDetected = 5;
+ }
+ mAnimationTick++;
+ if (mAnimationTick % 50L == 0L) {
+ mAnimationDirection = !mAnimationDirection;
+ }
+ final int tDirection = mAnimationDirection ? 1 : -1;
+ for (Materials tMaterial : mPosR) {
+ tMaterial.mRGBa[0] = getSafeRGBValue(tMaterial.mRGBa[0], tDirection);
+ }
+
+ for (Materials tMaterial : mPosG) {
+ tMaterial.mRGBa[1] = getSafeRGBValue(tMaterial.mRGBa[1], tDirection);
+ }
+
+ for (Materials tMaterial : mPosB) {
+ tMaterial.mRGBa[2] = getSafeRGBValue(tMaterial.mRGBa[2], tDirection);
+ }
+
+ for (Materials tMaterial : mPosA) {
+ tMaterial.mRGBa[3] = getSafeRGBValue(tMaterial.mRGBa[3], tDirection);
+ }
+
+ for (Materials tMaterial : mNegR) {
+ tMaterial.mRGBa[0] = getSafeRGBValue(tMaterial.mRGBa[0], -tDirection);
+ }
+
+ for (Materials tMaterial : mNegG) {
+ tMaterial.mRGBa[1] = getSafeRGBValue(tMaterial.mRGBa[1], -tDirection);
+ }
+
+ for (Materials tMaterial : mNegB) {
+ tMaterial.mRGBa[2] = getSafeRGBValue(tMaterial.mRGBa[2], -tDirection);
+ }
+
+ for (Materials tMaterial : mNegA) {
+ tMaterial.mRGBa[3] = getSafeRGBValue(tMaterial.mRGBa[3], -tDirection);
+ }
+
+ for (Materials tMaterial : mMoltenPosR) {
+ tMaterial.mMoltenRGBa[0] = getSafeRGBValue(tMaterial.mMoltenRGBa[0], tDirection);
+ }
+
+ for (Materials tMaterial : mMoltenPosG) {
+ tMaterial.mMoltenRGBa[1] = getSafeRGBValue(tMaterial.mMoltenRGBa[1], tDirection);
+ }
+
+ for (Materials tMaterial : mMoltenPosB) {
+ tMaterial.mMoltenRGBa[2] = getSafeRGBValue(tMaterial.mMoltenRGBa[2], tDirection);
+ }
+
+ for (Materials tMaterial : mMoltenPosA) {
+ tMaterial.mMoltenRGBa[3] = getSafeRGBValue(tMaterial.mMoltenRGBa[3], tDirection);
+ }
+
+ for (Materials tMaterial : mMoltenNegR) {
+ tMaterial.mMoltenRGBa[0] = getSafeRGBValue(tMaterial.mMoltenRGBa[0], -tDirection);
+ }
+
+ for (Materials tMaterial : mMoltenNegG) {
+ tMaterial.mMoltenRGBa[1] = getSafeRGBValue(tMaterial.mMoltenRGBa[1], -tDirection);
+ }
+
+ for (Materials tMaterial : mMoltenNegB) {
+ tMaterial.mMoltenRGBa[2] = getSafeRGBValue(tMaterial.mMoltenRGBa[2], -tDirection);
+ }
+
+ for (Materials tMaterial : mMoltenNegA) {
+ tMaterial.mMoltenRGBa[3] = getSafeRGBValue(tMaterial.mMoltenRGBa[3], -tDirection);
+ }
+ }
+ }
+
+ public short getSafeRGBValue(short aRBG, int aDelta) {
+ int tmp = aRBG + aDelta;
+ if (tmp > 255) tmp = 255;
+ if (tmp < 0) tmp = 0;
+ return (short) tmp;
+ }
+
+ @Override
+ public long getAnimationTicks() {
+ return mAnimationTick;
+ }
+
+ @Override
+ public float getPartialRenderTicks() {
+ return renderTickTime;
+ }
+
+ @Override
+ public void doSonictronSound(ItemStack aStack, World aWorld, double aX, double aY, double aZ) {
+ if (GT_Utility.isStackInvalid(aStack)) return;
+ String tString = SoundResource.NOTE_HARP.toString();
+ int i = 0;
+ int j = mSoundItems.size();
+ do {
+ if (i >= j) break;
+ if (GT_Utility.areStacksEqual(mSoundItems.get(i), aStack)) {
+ tString = mSoundNames.get(i);
+ break;
+ }
+ i++;
+ } while (true);
+ if (tString.startsWith(SoundResource.RANDOM_EXPLODE.toString()))
+ if (aStack.stackSize == 3) tString = SoundResource.RANDOM_FUSE.toString();
+ else if (aStack.stackSize == 2) tString = "random.old_explode";
+ if (tString.startsWith("streaming.")) tString = switch (aStack.stackSize) {
+ case 1 -> // '\001'
+ tString + "13";
+ case 2 -> // '\002'
+ tString + "cat";
+ case 3 -> // '\003'
+ tString + "blocks";
+ case 4 -> // '\004'
+ tString + "chirp";
+ case 5 -> // '\005'
+ tString + "far";
+ case 6 -> // '\006'
+ tString + "mall";
+ case 7 -> // '\007'
+ tString + "mellohi";
+ case 8 -> // '\b'
+ tString + "stal";
+ case 9 -> // '\t'
+ tString + "strad";
+ case 10 -> // '\n'
+ tString + "ward";
+ case 11 -> // '\013'
+ tString + "11";
+ case 12 -> // '\f'
+ tString + "wait";
+ default -> tString + "wherearewenow";
+ };
+ if (tString.startsWith("streaming.")) {
+ new WorldSpawnedEventBuilder.RecordEffectEventBuilder().setIdentifier(tString.substring(10))
+ .setPosition(aX, aY, aZ)
+ .run();
+ } else {
+ new WorldSpawnedEventBuilder.SoundEventBuilder().setVolume(3f)
+ .setPitch(
+ tString.startsWith("note.") ? (float) Math.pow(2D, (double) (aStack.stackSize - 13) / 12D) : 1.0F)
+ .setIdentifier(tString)
+ .setPosition(aX, aY, aZ)
+ .run();
+ }
+ }
+
+ public static int hideValue = 0;
+
+ /**
+ * <p>
+ * Client tick counter that is set to 5 on hiding pipes and covers.
+ * </p>
+ * <p>
+ * It triggers a texture update next client tick when reaching 4, with provision for 3 more update tasks, spreading
+ * client change detection related work and network traffic on different ticks, until it reaches 0.
+ * </p>
+ */
+ public static int changeDetected = 0;
+
+ private static int shouldHeldItemHideThings() {
+ try {
+ final EntityPlayer player = Minecraft.getMinecraft().thePlayer;
+ if (player == null) return 0;
+ final ItemStack tCurrentItem = player.getCurrentEquippedItem();
+ if (tCurrentItem == null) return 0;
+ final int[] ids = OreDictionary.getOreIDs(tCurrentItem);
+ int hide = 0;
+ for (int i : ids) {
+ if (OreDictionary.getOreName(i)
+ .equals("craftingToolSolderingIron")) {
+ hide |= 0x1;
+ break;
+ }
+ }
+ if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sWrenchList)
+ || GT_Utility.isStackInList(tCurrentItem, GregTech_API.sScrewdriverList)
+ || GT_Utility.isStackInList(tCurrentItem, GregTech_API.sHardHammerList)
+ || GT_Utility.isStackInList(tCurrentItem, GregTech_API.sSoftHammerList)
+ || GT_Utility.isStackInList(tCurrentItem, GregTech_API.sWireCutterList)
+ || GT_Utility.isStackInList(tCurrentItem, GregTech_API.sSolderingToolList)
+ || GT_Utility.isStackInList(tCurrentItem, GregTech_API.sCrowbarList)
+ || GregTech_API.sCovers.containsKey(new GT_ItemStack(tCurrentItem))
+ || (tCurrentItem.getItem() instanceof GT_Item_Machines
+ && GregTech_API.METATILEENTITIES[tCurrentItem.getItemDamage()] instanceof MetaPipeEntity
+ && player.isSneaking())) {
+ hide |= 0x2;
+ }
+ return hide;
+ } catch (Exception e) {
+ return 0;
+ }
+ }
+
+ public static void recieveChunkPollutionPacket(ChunkCoordIntPair chunk, int pollution) {
+ mPollutionRenderer.processPacket(chunk, pollution);
+ }
+}
diff --git a/src/main/java/gregtech/common/GT_DummyWorld.java b/src/main/java/gregtech/common/GT_DummyWorld.java
new file mode 100644
index 0000000000..d394ad3703
--- /dev/null
+++ b/src/main/java/gregtech/common/GT_DummyWorld.java
@@ -0,0 +1,138 @@
+package gregtech.common;
+
+import java.io.File;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.Entity;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.profiler.Profiler;
+import net.minecraft.world.World;
+import net.minecraft.world.WorldProvider;
+import net.minecraft.world.WorldSettings;
+import net.minecraft.world.biome.BiomeGenBase;
+import net.minecraft.world.chunk.IChunkProvider;
+import net.minecraft.world.chunk.storage.IChunkLoader;
+import net.minecraft.world.storage.IPlayerFileData;
+import net.minecraft.world.storage.ISaveHandler;
+import net.minecraft.world.storage.WorldInfo;
+
+public class GT_DummyWorld extends World {
+
+ public GT_IteratorRandom mRandom = new GT_IteratorRandom();
+ public ItemStack mLastSetBlock = null;
+
+ public GT_DummyWorld(ISaveHandler saveHandler, String name, WorldProvider worldProvider,
+ WorldSettings worldSettings, Profiler profiler) {
+ super(saveHandler, name, worldSettings, worldProvider, profiler);
+ this.rand = this.mRandom;
+ }
+
+ public GT_DummyWorld() {
+ this(new ISaveHandler() {
+
+ @Override
+ public void saveWorldInfoWithPlayer(WorldInfo worldInfo, NBTTagCompound nbtTagCompound) {}
+
+ @Override
+ public void saveWorldInfo(WorldInfo worldInfo) {}
+
+ @Override
+ public WorldInfo loadWorldInfo() {
+ return null;
+ }
+
+ @Override
+ public IPlayerFileData getSaveHandler() {
+ return null;
+ }
+
+ @Override
+ public File getMapFileFromName(String mapName) {
+ return null;
+ }
+
+ @Override
+ public IChunkLoader getChunkLoader(WorldProvider worldProvider) {
+ return null;
+ }
+
+ @Override
+ public void flush() {}
+
+ @Override
+ public void checkSessionLock() {}
+
+ @Override
+ public String getWorldDirectoryName() {
+ return null;
+ }
+
+ @Override
+ public File getWorldDirectory() {
+ return null;
+ }
+ }, "DUMMY_DIMENSION", null, new WorldSettings(new WorldInfo(new NBTTagCompound())), new Profiler());
+ }
+
+ @Override
+ protected IChunkProvider createChunkProvider() {
+ return null;
+ }
+
+ @Override
+ public Entity getEntityByID(int aEntityID) {
+ return null;
+ }
+
+ @Override
+ public boolean setBlock(int aX, int aY, int aZ, Block aBlock, int aMeta, int aFlags) {
+ this.mLastSetBlock = new ItemStack(aBlock, 1, aMeta);
+ return true;
+ }
+
+ @Override
+ public float getSunBrightnessFactor(float p_72967_1_) {
+ return 1.0F;
+ }
+
+ @Override
+ public BiomeGenBase getBiomeGenForCoords(int aX, int aZ) {
+ if ((aX >= 16) && (aZ >= 16) && (aX < 32) && (aZ < 32)) {
+ return BiomeGenBase.plains;
+ }
+ return BiomeGenBase.ocean;
+ }
+
+ @Override
+ public int getFullBlockLightValue(int aX, int aY, int aZ) {
+ return 10;
+ }
+
+ @Override
+ public Block getBlock(int aX, int aY, int aZ) {
+ if ((aX >= 16) && (aZ >= 16) && (aX < 32) && (aZ < 32)) {
+ return aY == 64 ? Blocks.grass : Blocks.air;
+ }
+ return Blocks.air;
+ }
+
+ @Override
+ public int getBlockMetadata(int aX, int aY, int aZ) {
+ return 0;
+ }
+
+ @Override
+ public boolean canBlockSeeTheSky(int aX, int aY, int aZ) {
+ if ((aX >= 16) && (aZ >= 16) && (aX < 32) && (aZ < 32)) {
+ return aY > 64;
+ }
+ return true;
+ }
+
+ @Override
+ protected int func_152379_p() {
+ return 0;
+ }
+}
diff --git a/src/main/java/gregtech/common/GT_IteratorRandom.java b/src/main/java/gregtech/common/GT_IteratorRandom.java
new file mode 100644
index 0000000000..addce0a456
--- /dev/null
+++ b/src/main/java/gregtech/common/GT_IteratorRandom.java
@@ -0,0 +1,17 @@
+package gregtech.common;
+
+import java.util.Random;
+
+public class GT_IteratorRandom extends Random {
+
+ private static final long serialVersionUID = 1L;
+ public int mIterationStep = 2147483647;
+
+ @Override
+ public int nextInt(int aParameter) {
+ if ((this.mIterationStep == 0) || (this.mIterationStep > aParameter)) {
+ this.mIterationStep = aParameter;
+ }
+ return --this.mIterationStep;
+ }
+}
diff --git a/src/main/java/gregtech/common/GT_Network.java b/src/main/java/gregtech/common/GT_Network.java
new file mode 100644
index 0000000000..3d081b3320
--- /dev/null
+++ b/src/main/java/gregtech/common/GT_Network.java
@@ -0,0 +1,183 @@
+package gregtech.common;
+
+import static gregtech.GT_Mod.GT_FML_LOGGER;
+
+import java.util.EnumMap;
+import java.util.List;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.world.World;
+import net.minecraft.world.chunk.Chunk;
+
+import com.google.common.io.ByteArrayDataInput;
+import com.google.common.io.ByteStreams;
+
+import cpw.mods.fml.common.network.FMLEmbeddedChannel;
+import cpw.mods.fml.common.network.FMLOutboundHandler;
+import cpw.mods.fml.common.network.NetworkRegistry;
+import cpw.mods.fml.common.network.internal.FMLProxyPacket;
+import cpw.mods.fml.relauncher.Side;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.net.GT_Packet;
+import gregtech.api.net.GT_Packet_Block_Event;
+import gregtech.api.net.GT_Packet_ClientPreference;
+import gregtech.api.net.GT_Packet_GtTileEntityGuiRequest;
+import gregtech.api.net.GT_Packet_MultiTileEntity;
+import gregtech.api.net.GT_Packet_Pollution;
+import gregtech.api.net.GT_Packet_RequestCoverData;
+import gregtech.api.net.GT_Packet_SendCoverData;
+import gregtech.api.net.GT_Packet_SendOregenPattern;
+import gregtech.api.net.GT_Packet_SetConfigurationCircuit;
+import gregtech.api.net.GT_Packet_Sound;
+import gregtech.api.net.GT_Packet_TileEntity;
+import gregtech.api.net.GT_Packet_TileEntityCover;
+import gregtech.api.net.GT_Packet_TileEntityCoverGUI;
+import gregtech.api.net.GT_Packet_TileEntityCoverNew;
+import gregtech.api.net.GT_Packet_UpdateItem;
+import gregtech.api.net.GT_Packet_WirelessRedstoneCover;
+import gregtech.api.net.IGT_NetworkHandler;
+import gregtech.common.blocks.GT_Packet_Ores;
+import gregtech.common.net.MessageSetFlaskCapacity;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.SimpleChannelInboundHandler;
+import io.netty.handler.codec.MessageToMessageCodec;
+
+@ChannelHandler.Sharable
+@SuppressWarnings("deprecation")
+public class GT_Network extends MessageToMessageCodec<FMLProxyPacket, GT_Packet> implements IGT_NetworkHandler {
+
+ private final EnumMap<Side, FMLEmbeddedChannel> mChannel;
+ private final GT_Packet[] mSubChannels;
+
+ public GT_Network() {
+ this(
+ "GregTech",
+ new GT_Packet_TileEntity(), // 0
+ new GT_Packet_Sound(), // 1
+ new GT_Packet_Block_Event(), // 2
+ new GT_Packet_Ores(), // 3
+ new GT_Packet_Pollution(), // 4
+ new MessageSetFlaskCapacity(), // 5
+ new GT_Packet_TileEntityCover(), // 6
+ new GT_Packet_TileEntityCoverGUI(), // 7
+ // 8
+ new GT_Packet_ClientPreference(), // 9
+ new GT_Packet_WirelessRedstoneCover(), // 10
+ new GT_Packet_TileEntityCoverNew(), // 11
+ new GT_Packet_SetConfigurationCircuit(), // 12
+ new GT_Packet_UpdateItem(), // 13
+ // 14
+ new GT_Packet_GtTileEntityGuiRequest(), // 15
+ new GT_Packet_SendCoverData(), // 16
+ new GT_Packet_RequestCoverData(), // 17
+ new GT_Packet_MultiTileEntity(true), // 18
+ new GT_Packet_SendOregenPattern() // 19
+ );
+ }
+
+ public GT_Network(String channelName, GT_Packet... packetTypes) {
+ this.mChannel = NetworkRegistry.INSTANCE.newChannel(channelName, this, new HandlerShared());
+ final int lastPId = packetTypes[packetTypes.length - 1].getPacketID();
+ this.mSubChannels = new GT_Packet[lastPId + 1];
+ for (GT_Packet packetType : packetTypes) {
+ final int pId = packetType.getPacketID();
+ if (this.mSubChannels[pId] == null) this.mSubChannels[pId] = packetType;
+ else throw new IllegalArgumentException("Duplicate Packet ID! " + pId);
+ }
+ }
+
+ @Override
+ protected void encode(ChannelHandlerContext aContext, GT_Packet aPacket, List<Object> aOutput) {
+ final ByteBuf tBuf = Unpooled.buffer()
+ .writeByte(aPacket.getPacketID());
+ aPacket.encode(tBuf);
+ aOutput.add(
+ new FMLProxyPacket(
+ tBuf,
+ aContext.channel()
+ .attr(NetworkRegistry.FML_CHANNEL)
+ .get()));
+ }
+
+ @Override
+ protected void decode(ChannelHandlerContext aContext, FMLProxyPacket aPacket, List<Object> aOutput) {
+ final ByteArrayDataInput aData = ByteStreams.newDataInput(
+ aPacket.payload()
+ .array());
+ final GT_Packet tPacket = this.mSubChannels[aData.readByte()].decode(aData);
+ tPacket.setINetHandler(aPacket.handler());
+ aOutput.add(tPacket);
+ }
+
+ @Override
+ public void sendToPlayer(GT_Packet aPacket, EntityPlayerMP aPlayer) {
+ if (aPacket == null) {
+ GT_FML_LOGGER.info("packet null");
+ return;
+ }
+ if (aPlayer == null) {
+ GT_FML_LOGGER.info("player null");
+ return;
+ }
+ this.mChannel.get(Side.SERVER)
+ .attr(FMLOutboundHandler.FML_MESSAGETARGET)
+ .set(FMLOutboundHandler.OutboundTarget.PLAYER);
+ this.mChannel.get(Side.SERVER)
+ .attr(FMLOutboundHandler.FML_MESSAGETARGETARGS)
+ .set(aPlayer);
+ this.mChannel.get(Side.SERVER)
+ .writeAndFlush(aPacket);
+ }
+
+ @Override
+ public void sendToAllAround(GT_Packet aPacket, NetworkRegistry.TargetPoint aPosition) {
+ this.mChannel.get(Side.SERVER)
+ .attr(FMLOutboundHandler.FML_MESSAGETARGET)
+ .set(FMLOutboundHandler.OutboundTarget.ALLAROUNDPOINT);
+ this.mChannel.get(Side.SERVER)
+ .attr(FMLOutboundHandler.FML_MESSAGETARGETARGS)
+ .set(aPosition);
+ this.mChannel.get(Side.SERVER)
+ .writeAndFlush(aPacket);
+ }
+
+ @Override
+ public void sendToServer(GT_Packet aPacket) {
+ this.mChannel.get(Side.CLIENT)
+ .attr(FMLOutboundHandler.FML_MESSAGETARGET)
+ .set(FMLOutboundHandler.OutboundTarget.TOSERVER);
+ this.mChannel.get(Side.CLIENT)
+ .writeAndFlush(aPacket);
+ }
+
+ @Override
+ public void sendPacketToAllPlayersInRange(World aWorld, GT_Packet aPacket, int aX, int aZ) {
+ if (!aWorld.isRemote) {
+ for (Object tObject : aWorld.playerEntities) {
+ if (!(tObject instanceof EntityPlayerMP tPlayer)) {
+ break;
+ }
+ Chunk tChunk = aWorld.getChunkFromBlockCoords(aX, aZ);
+ if (tPlayer.getServerForPlayer()
+ .getPlayerManager()
+ .isPlayerWatchingChunk(tPlayer, tChunk.xPosition, tChunk.zPosition)) {
+ sendToPlayer(aPacket, tPlayer);
+ }
+ }
+ }
+ }
+
+ @ChannelHandler.Sharable
+ static final class HandlerShared extends SimpleChannelInboundHandler<GT_Packet> {
+
+ @Override
+ protected void channelRead0(ChannelHandlerContext ctx, GT_Packet aPacket) {
+ final EntityPlayer aPlayer = GT_Values.GT.getThePlayer();
+ aPacket.process(aPlayer == null ? null : aPlayer.worldObj);
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/GT_PlayerActivityLogger.java b/src/main/java/gregtech/common/GT_PlayerActivityLogger.java
new file mode 100644
index 0000000000..c60378ca5e
--- /dev/null
+++ b/src/main/java/gregtech/common/GT_PlayerActivityLogger.java
@@ -0,0 +1,34 @@
+package gregtech.common;
+
+import java.util.ArrayList;
+
+import gregtech.GT_Mod;
+import gregtech.api.util.GT_Log;
+
+public class GT_PlayerActivityLogger implements Runnable {
+
+ @Override
+ public void run() {
+ try {
+ ArrayList<String> buffer = new ArrayList<>();
+ for (;;) {
+ if (GT_Log.pal == null) {
+ return;
+ }
+ String tLastOutput = "";
+ // Block on first element for efficiency
+ buffer.add(GT_Mod.gregtechproxy.mBufferedPlayerActivity.take());
+ GT_Mod.gregtechproxy.mBufferedPlayerActivity.drainTo(buffer);
+ for (String output : buffer) {
+ if (!output.equals(tLastOutput)) {
+ GT_Log.pal.println(output);
+ tLastOutput = output;
+ }
+ }
+ buffer.clear();
+ // TODO: swap from sleep to event bus
+ Thread.sleep(10000L);
+ }
+ } catch (Throwable ignored) {}
+ }
+}
diff --git a/src/main/java/gregtech/common/GT_Pollution.java b/src/main/java/gregtech/common/GT_Pollution.java
new file mode 100644
index 0000000000..6a2b1e1082
--- /dev/null
+++ b/src/main/java/gregtech/common/GT_Pollution.java
@@ -0,0 +1,507 @@
+package gregtech.common;
+
+import static gregtech.api.objects.XSTR.XSTR_INSTANCE;
+import static gregtech.common.GT_Proxy.dimensionWisePollution;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Consumer;
+
+import javax.annotation.Nullable;
+import javax.annotation.ParametersAreNonnullByDefault;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.material.Material;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.init.Blocks;
+import net.minecraft.potion.Potion;
+import net.minecraft.potion.PotionEffect;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.AxisAlignedBB;
+import net.minecraft.world.ChunkCoordIntPair;
+import net.minecraft.world.ChunkPosition;
+import net.minecraft.world.World;
+import net.minecraft.world.chunk.Chunk;
+import net.minecraftforge.common.DimensionManager;
+import net.minecraftforge.common.MinecraftForge;
+import net.minecraftforge.event.world.ChunkDataEvent;
+import net.minecraftforge.event.world.ChunkWatchEvent;
+import net.minecraftforge.event.world.WorldEvent;
+
+import cpw.mods.fml.common.eventhandler.SubscribeEvent;
+import cpw.mods.fml.common.gameevent.TickEvent;
+import cpw.mods.fml.common.network.NetworkRegistry;
+import gregtech.GT_Mod;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.interfaces.ICleanroom;
+import gregtech.api.interfaces.ICleanroomReceiver;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.net.GT_Packet_Pollution;
+import gregtech.api.util.GT_ChunkAssociatedData;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.render.GT_PollutionRenderer;
+
+public class GT_Pollution {
+
+ private static final Storage STORAGE = new Storage();
+ /**
+ * Pollution dispersion until effects start: Calculation: ((Limit * 0.01) + 2000) * (4 <- spreading rate)
+ * <p>
+ * SMOG(500k) 466.7 pollution/sec Poison(750k) 633,3 pollution/sec Dying Plants(1mio) 800 pollution/sec Sour
+ * Rain(1.5mio) 1133.3 pollution/sec
+ * <p>
+ * Pollution producers (pollution/sec) Bronze Boiler(20) Lava Boiler(20) High Pressure Boiler(20) Bronze Blast
+ * Furnace(50) Diesel Generator(40/80/160) Gas Turbine(20/40/80) Charcoal Pile(100)
+ * <p>
+ * Large Diesel Engine(320) Electric Blast Furnace(100) Implosion Compressor(2000) Large Boiler(240) Large Gas
+ * Turbine(160) Multi Smelter(100) Pyrolyse Oven(400)
+ * <p>
+ * Machine Explosion(100,000)
+ * <p>
+ * Other Random Shit: lots and lots
+ * <p>
+ * Muffler Hatch Pollution reduction: ** inaccurate ** LV (0%), MV (30%), HV (52%), EV (66%), IV (76%), LuV (84%),
+ * ZPM (89%), UV (92%), MAX (95%)
+ */
+ private List<ChunkCoordIntPair> pollutionList = new ArrayList<>(); // chunks left to process in this cycle
+
+ private final Set<ChunkCoordIntPair> pollutedChunks = new HashSet<>(); // a global list of all chunks with positive
+ // pollution
+ private int operationsPerTick = 0; // how much chunks should be processed in each cycle
+ private static final short cycleLen = 1200;
+ private final World world;
+ private boolean blank = true;
+ public static int mPlayerPollution;
+
+ private static final int POLLUTIONPACKET_MINVALUE = 1000;
+
+ private static GT_PollutionEventHandler EVENT_HANDLER;
+
+ public GT_Pollution(World world) {
+ this.world = world;
+
+ if (EVENT_HANDLER == null) {
+ EVENT_HANDLER = new GT_PollutionEventHandler();
+ MinecraftForge.EVENT_BUS.register(EVENT_HANDLER);
+ }
+ }
+
+ public static void onWorldTick(TickEvent.WorldTickEvent aEvent) { // called from proxy
+ // return if pollution disabled
+ if (!GT_Mod.gregtechproxy.mPollution) return;
+ if (aEvent.phase == TickEvent.Phase.START) return;
+ final GT_Pollution pollutionInstance = dimensionWisePollution.get(aEvent.world.provider.dimensionId);
+ if (pollutionInstance == null) return;
+ pollutionInstance.tickPollutionInWorld((int) (aEvent.world.getTotalWorldTime() % cycleLen));
+ }
+
+ private void tickPollutionInWorld(int aTickID) { // called from method above
+ // gen data set
+ if (aTickID == 0 || blank) {
+ // make a snapshot of what to work on
+ pollutionList = new ArrayList<>(pollutedChunks);
+ // set operations per tick
+ if (pollutionList.size() > 0) operationsPerTick = Math.max(1, pollutionList.size() / cycleLen);
+ else operationsPerTick = 0; // SANity
+ blank = false;
+ }
+
+ for (int chunksProcessed = 0; chunksProcessed < operationsPerTick; chunksProcessed++) {
+ if (pollutionList.size() == 0) break; // no more stuff to do
+ ChunkCoordIntPair actualPos = pollutionList.remove(pollutionList.size() - 1); // faster
+ // get pollution
+ ChunkData currentData = STORAGE.get(world, actualPos);
+ int tPollution = currentData.getAmount();
+ // remove some
+ tPollution = (int) (0.9945f * tPollution);
+
+ if (tPollution > 400000) { // Spread Pollution
+
+ ChunkCoordIntPair[] tNeighbors = new ChunkCoordIntPair[4]; // array is faster
+ tNeighbors[0] = (new ChunkCoordIntPair(actualPos.chunkXPos + 1, actualPos.chunkZPos));
+ tNeighbors[1] = (new ChunkCoordIntPair(actualPos.chunkXPos - 1, actualPos.chunkZPos));
+ tNeighbors[2] = (new ChunkCoordIntPair(actualPos.chunkXPos, actualPos.chunkZPos + 1));
+ tNeighbors[3] = (new ChunkCoordIntPair(actualPos.chunkXPos, actualPos.chunkZPos - 1));
+ for (ChunkCoordIntPair neighborPosition : tNeighbors) {
+ ChunkData neighbor = STORAGE.get(world, neighborPosition);
+ int neighborPollution = neighbor.getAmount();
+ if (neighborPollution * 6 < tPollution * 5) { // MATHEMATICS...
+ int tDiff = tPollution - neighborPollution;
+ tDiff = tDiff / 20;
+ neighborPollution = GT_Utility.safeInt((long) neighborPollution + tDiff); // tNPol += tDiff;
+ tPollution -= tDiff;
+ setChunkPollution(neighborPosition, neighborPollution);
+ }
+ }
+
+ // Create Pollution effects
+ // Smog filter TODO
+ if (tPollution > GT_Mod.gregtechproxy.mPollutionSmogLimit) {
+ AxisAlignedBB chunk = AxisAlignedBB.getBoundingBox(
+ actualPos.chunkXPos << 4,
+ 0,
+ actualPos.chunkZPos << 4,
+ (actualPos.chunkXPos << 4) + 16,
+ 256,
+ (actualPos.chunkZPos << 4) + 16);
+ List<EntityLivingBase> tEntitys = world.getEntitiesWithinAABB(EntityLivingBase.class, chunk);
+ for (EntityLivingBase tEnt : tEntitys) {
+ if (tEnt instanceof EntityPlayerMP && ((EntityPlayerMP) tEnt).capabilities.isCreativeMode)
+ continue;
+ if (!(GT_Utility.isWearingFullGasHazmat(tEnt))) {
+ switch (XSTR_INSTANCE.nextInt(3)) {
+ default:
+ tEnt.addPotionEffect(
+ new PotionEffect(
+ Potion.digSlowdown.id,
+ Math.min(tPollution / 1000, 1000),
+ tPollution / 400000));
+ case 1:
+ tEnt.addPotionEffect(
+ new PotionEffect(
+ Potion.weakness.id,
+ Math.min(tPollution / 1000, 1000),
+ tPollution / 400000));
+ case 2:
+ tEnt.addPotionEffect(
+ new PotionEffect(
+ Potion.moveSlowdown.id,
+ Math.min(tPollution / 1000, 1000),
+ tPollution / 400000));
+ }
+ }
+ }
+
+ // Poison effects
+ if (tPollution > GT_Mod.gregtechproxy.mPollutionPoisonLimit) {
+ for (EntityLivingBase tEnt : tEntitys) {
+ if (tEnt instanceof EntityPlayerMP && ((EntityPlayerMP) tEnt).capabilities.isCreativeMode)
+ continue;
+ if (!GT_Utility.isWearingFullGasHazmat(tEnt)) {
+ switch (XSTR_INSTANCE.nextInt(4)) {
+ default:
+ tEnt.addPotionEffect(new PotionEffect(Potion.hunger.id, tPollution / 500000));
+ case 1:
+ tEnt.addPotionEffect(
+ new PotionEffect(
+ Potion.confusion.id,
+ Math.min(tPollution / 2000, 1000),
+ 1));
+ case 2:
+ tEnt.addPotionEffect(
+ new PotionEffect(
+ Potion.poison.id,
+ Math.min(tPollution / 4000, 1000),
+ tPollution / 500000));
+ case 3:
+ tEnt.addPotionEffect(
+ new PotionEffect(
+ Potion.blindness.id,
+ Math.min(tPollution / 2000, 1000),
+ 1));
+ }
+ }
+ }
+
+ // killing plants
+ if (tPollution > GT_Mod.gregtechproxy.mPollutionVegetationLimit) {
+ int f = 20;
+ for (; f < (tPollution / 25000); f++) {
+ int x = (actualPos.chunkXPos << 4) + XSTR_INSTANCE.nextInt(16);
+ int y = 60 + (-f + XSTR_INSTANCE.nextInt(f * 2 + 1));
+ int z = (actualPos.chunkZPos << 4) + XSTR_INSTANCE.nextInt(16);
+ damageBlock(world, x, y, z, tPollution > GT_Mod.gregtechproxy.mPollutionSourRainLimit);
+ }
+ }
+ }
+ }
+ }
+ // Write new pollution to Hashmap !!!
+ setChunkPollution(actualPos, tPollution);
+
+ // Send new value to players nearby
+ if (tPollution > POLLUTIONPACKET_MINVALUE) {
+ NetworkRegistry.TargetPoint point = new NetworkRegistry.TargetPoint(
+ world.provider.dimensionId,
+ (actualPos.chunkXPos << 4),
+ 64,
+ (actualPos.chunkZPos << 4),
+ 256);
+ GT_Values.NW.sendToAllAround(new GT_Packet_Pollution(actualPos, tPollution), point);
+ }
+ }
+ }
+
+ private void setChunkPollution(ChunkCoordIntPair coord, int pollution) {
+ mutatePollution(world, coord.chunkXPos, coord.chunkZPos, c -> c.setAmount(pollution), pollutedChunks);
+ }
+
+ private static void damageBlock(World world, int x, int y, int z, boolean sourRain) {
+ if (world.isRemote) return;
+ Block tBlock = world.getBlock(x, y, z);
+ int tMeta = world.getBlockMetadata(x, y, z);
+ if (tBlock == Blocks.air || tBlock == Blocks.stone || tBlock == Blocks.sand || tBlock == Blocks.deadbush)
+ return;
+
+ if (tBlock == Blocks.leaves || tBlock == Blocks.leaves2 || tBlock.getMaterial() == Material.leaves)
+ world.setBlockToAir(x, y, z);
+ if (tBlock == Blocks.reeds) {
+ tBlock.dropBlockAsItem(world, x, y, z, tMeta, 0);
+ world.setBlockToAir(x, y, z);
+ }
+ if (tBlock == Blocks.tallgrass) world.setBlock(x, y, z, Blocks.deadbush);
+ if (tBlock == Blocks.vine) {
+ tBlock.dropBlockAsItem(world, x, y, z, tMeta, 0);
+ world.setBlockToAir(x, y, z);
+ }
+ if (tBlock == Blocks.waterlily || tBlock == Blocks.wheat
+ || tBlock == Blocks.cactus
+ || tBlock.getMaterial() == Material.cactus
+ || tBlock == Blocks.melon_block
+ || tBlock == Blocks.melon_stem) {
+ tBlock.dropBlockAsItem(world, x, y, z, tMeta, 0);
+ world.setBlockToAir(x, y, z);
+ }
+ if (tBlock == Blocks.red_flower || tBlock == Blocks.yellow_flower
+ || tBlock == Blocks.carrots
+ || tBlock == Blocks.potatoes
+ || tBlock == Blocks.pumpkin
+ || tBlock == Blocks.pumpkin_stem) {
+ tBlock.dropBlockAsItem(world, x, y, z, tMeta, 0);
+ world.setBlockToAir(x, y, z);
+ }
+ if (tBlock == Blocks.sapling || tBlock.getMaterial() == Material.plants)
+ world.setBlock(x, y, z, Blocks.deadbush);
+ if (tBlock == Blocks.cocoa) {
+ tBlock.dropBlockAsItem(world, x, y, z, tMeta, 0);
+ world.setBlockToAir(x, y, z);
+ }
+ if (tBlock == Blocks.mossy_cobblestone) world.setBlock(x, y, z, Blocks.cobblestone);
+ if (tBlock == Blocks.grass || tBlock.getMaterial() == Material.grass) world.setBlock(x, y, z, Blocks.dirt);
+ if (tBlock == Blocks.farmland || tBlock == Blocks.dirt) {
+ world.setBlock(x, y, z, Blocks.sand);
+ }
+
+ if (sourRain && world.isRaining()
+ && (tBlock == Blocks.gravel || tBlock == Blocks.cobblestone)
+ && world.getBlock(x, y + 1, z) == Blocks.air
+ && world.canBlockSeeTheSky(x, y, z)) {
+ if (tBlock == Blocks.cobblestone) {
+ world.setBlock(x, y, z, Blocks.gravel);
+ } else {
+ world.setBlock(x, y, z, Blocks.sand);
+ }
+ }
+ }
+
+ private static GT_Pollution getPollutionManager(World world) {
+ return dimensionWisePollution.computeIfAbsent(world.provider.dimensionId, i -> new GT_Pollution(world));
+ }
+
+ /** @see #addPollution(TileEntity, int) */
+ public static void addPollution(IGregTechTileEntity te, int aPollution) {
+ addPollution((TileEntity) te, aPollution);
+ }
+
+ /**
+ * Also pollutes cleanroom if {@code te} is an instance of {@link ICleanroomReceiver}.
+ *
+ * @see #addPollution(World, int, int, int)
+ */
+ public static void addPollution(TileEntity te, int aPollution) {
+ if (!GT_Mod.gregtechproxy.mPollution || aPollution == 0 || te.getWorldObj().isRemote) return;
+
+ if (aPollution > 0 && te instanceof ICleanroomReceiver receiver) {
+ ICleanroom cleanroom = receiver.getCleanroom();
+ if (cleanroom != null && cleanroom.isValidCleanroom()) {
+ cleanroom.pollute();
+ }
+ }
+
+ addPollution(te.getWorldObj(), te.xCoord >> 4, te.zCoord >> 4, aPollution);
+ }
+
+ /** @see #addPollution(World, int, int, int) */
+ public static void addPollution(Chunk ch, int aPollution) {
+ addPollution(ch.worldObj, ch.xPosition, ch.zPosition, aPollution);
+ }
+
+ /**
+ * Add some pollution to given chunk. Can pass in negative to remove pollution. Will clamp the final pollution
+ * number to 0 if it would be changed into negative.
+ *
+ * @param w world to modify. do nothing if it's a client world
+ * @param chunkX chunk coordinate X, i.e. blockX >> 4
+ * @param chunkZ chunk coordinate Z, i.e. blockZ >> 4
+ * @param aPollution desired delta. Positive means the pollution in chunk would go higher.
+ */
+ public static void addPollution(World w, int chunkX, int chunkZ, int aPollution) {
+ if (!GT_Mod.gregtechproxy.mPollution || aPollution == 0 || w.isRemote) return;
+ mutatePollution(w, chunkX, chunkZ, d -> d.changeAmount(aPollution), null);
+ }
+
+ private static void mutatePollution(World world, int x, int z, Consumer<ChunkData> mutator,
+ @Nullable Set<ChunkCoordIntPair> chunks) {
+ ChunkData data = STORAGE.get(world, x, z);
+ boolean hadPollution = data.getAmount() > 0;
+ mutator.accept(data);
+ boolean hasPollution = data.getAmount() > 0;
+ if (hasPollution != hadPollution) {
+ if (chunks == null) chunks = getPollutionManager(world).pollutedChunks;
+ if (hasPollution) chunks.add(new ChunkCoordIntPair(x, z));
+ else chunks.remove(new ChunkCoordIntPair(x, z));
+ }
+ }
+
+ /** @see #getPollution(World, int, int) */
+ public static int getPollution(IGregTechTileEntity te) {
+ return getPollution(te.getWorld(), te.getXCoord() >> 4, te.getZCoord() >> 4);
+ }
+
+ /** @see #getPollution(World, int, int) */
+ public static int getPollution(Chunk ch) {
+ return getPollution(ch.worldObj, ch.xPosition, ch.zPosition);
+ }
+
+ /**
+ * Get the pollution in specified chunk
+ *
+ * @param w world to look in. can be a client world, but that limits the knowledge to what server side send us
+ * @param chunkX chunk coordinate X, i.e. blockX >> 4
+ * @param chunkZ chunk coordinate Z, i.e. blockZ >> 4
+ * @return pollution amount. may be 0 if pollution is disabled, or if it's a client world and server did not send us
+ * info about this chunk
+ */
+ public static int getPollution(World w, int chunkX, int chunkZ) {
+ if (!GT_Mod.gregtechproxy.mPollution) return 0;
+ if (w.isRemote)
+ // it really should be querying the client side stuff instead
+ return GT_PollutionRenderer.getKnownPollution(chunkX << 4, chunkZ << 4);
+ return STORAGE.get(w, chunkX, chunkZ)
+ .getAmount();
+ }
+
+ @Deprecated
+ public static int getPollution(ChunkCoordIntPair aCh, int aDim) {
+ return getPollution(DimensionManager.getWorld(aDim), aCh.chunkXPos, aCh.chunkZPos);
+ }
+
+ public static boolean hasPollution(Chunk ch) {
+ if (!GT_Mod.gregtechproxy.mPollution) return false;
+ return STORAGE.isCreated(ch.worldObj, ch.getChunkCoordIntPair()) && STORAGE.get(ch)
+ .getAmount() > 0;
+ }
+
+ // Add compatibility with old code
+ @Deprecated /* Don't use it... too weird way of passing position */
+ public static void addPollution(World aWorld, ChunkPosition aPos, int aPollution) {
+ // The abuse of ChunkPosition to store block position and dim...
+ // is just bad especially when that is both used to store ChunkPos and BlockPos depending on context
+ addPollution(aWorld.getChunkFromBlockCoords(aPos.chunkPosX, aPos.chunkPosZ), aPollution);
+ }
+
+ static void migrate(ChunkDataEvent.Load e) {
+ addPollution(
+ e.getChunk(),
+ e.getData()
+ .getInteger("GTPOLLUTION"));
+ }
+
+ public static class GT_PollutionEventHandler {
+
+ @SubscribeEvent
+ public void chunkWatch(ChunkWatchEvent.Watch event) {
+ if (!GT_Mod.gregtechproxy.mPollution) return;
+ World world = event.player.worldObj;
+ if (STORAGE.isCreated(world, event.chunk)) {
+ int pollution = STORAGE.get(world, event.chunk)
+ .getAmount();
+ if (pollution > POLLUTIONPACKET_MINVALUE)
+ GT_Values.NW.sendToPlayer(new GT_Packet_Pollution(event.chunk, pollution), event.player);
+ }
+ }
+
+ @SubscribeEvent
+ public void onWorldLoad(WorldEvent.Load e) {
+ // super class loads everything lazily. We force it to load them all.
+ if (!e.world.isRemote) STORAGE.loadAll(e.world);
+ }
+ }
+
+ @ParametersAreNonnullByDefault
+ private static final class Storage extends GT_ChunkAssociatedData<ChunkData> {
+
+ private Storage() {
+ super("Pollution", ChunkData.class, 64, (byte) 0, false);
+ }
+
+ @Override
+ protected void writeElement(DataOutput output, ChunkData element, World world, int chunkX, int chunkZ)
+ throws IOException {
+ output.writeInt(element.getAmount());
+ }
+
+ @Override
+ protected ChunkData readElement(DataInput input, int version, World world, int chunkX, int chunkZ)
+ throws IOException {
+ if (version != 0) throw new IOException("Region file corrupted");
+ ChunkData data = new ChunkData(input.readInt());
+ if (data.getAmount() > 0)
+ getPollutionManager(world).pollutedChunks.add(new ChunkCoordIntPair(chunkX, chunkZ));
+ return data;
+ }
+
+ @Override
+ protected ChunkData createElement(World world, int chunkX, int chunkZ) {
+ return new ChunkData();
+ }
+
+ @Override
+ public void loadAll(World w) {
+ super.loadAll(w);
+ }
+
+ public boolean isCreated(World world, ChunkCoordIntPair coord) {
+ return isCreated(world.provider.dimensionId, coord.chunkXPos, coord.chunkZPos);
+ }
+ }
+
+ private static final class ChunkData implements GT_ChunkAssociatedData.IData {
+
+ public int amount;
+
+ private ChunkData() {
+ this(0);
+ }
+
+ private ChunkData(int amount) {
+ this.amount = Math.max(0, amount);
+ }
+
+ /**
+ * Current pollution amount.
+ */
+ public int getAmount() {
+ return amount;
+ }
+
+ public void setAmount(int amount) {
+ this.amount = Math.max(amount, 0);
+ }
+
+ public void changeAmount(int delta) {
+ this.amount = Math.max(GT_Utility.safeInt(amount + (long) delta, 0), 0);
+ }
+
+ @Override
+ public boolean isSameAsDefault() {
+ return amount == 0;
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/GT_Proxy.java b/src/main/java/gregtech/common/GT_Proxy.java
new file mode 100644
index 0000000000..c80414843b
--- /dev/null
+++ b/src/main/java/gregtech/common/GT_Proxy.java
@@ -0,0 +1,3163 @@
+package gregtech.common;
+
+import static gregtech.GT_Mod.GT_FML_LOGGER;
+import static gregtech.api.enums.FluidState.GAS;
+import static gregtech.api.enums.FluidState.LIQUID;
+import static gregtech.api.enums.FluidState.MOLTEN;
+import static gregtech.api.enums.FluidState.PLASMA;
+import static gregtech.api.enums.GT_Values.W;
+import static gregtech.api.enums.GT_Values.debugEntityCramming;
+import static gregtech.api.enums.Mods.AdvancedSolarPanel;
+import static gregtech.api.enums.Mods.AppliedEnergistics2;
+import static gregtech.api.enums.Mods.Avaritia;
+import static gregtech.api.enums.Mods.BetterLoadingScreen;
+import static gregtech.api.enums.Mods.DraconicEvolution;
+import static gregtech.api.enums.Mods.ElectroMagicTools;
+import static gregtech.api.enums.Mods.EnderIO;
+import static gregtech.api.enums.Mods.Forestry;
+import static gregtech.api.enums.Mods.GTPlusPlus;
+import static gregtech.api.enums.Mods.GalacticraftCore;
+import static gregtech.api.enums.Mods.GalaxySpace;
+import static gregtech.api.enums.Mods.GanysSurface;
+import static gregtech.api.enums.Mods.GraviSuite;
+import static gregtech.api.enums.Mods.GregTech;
+import static gregtech.api.enums.Mods.IguanaTweaksTinkerConstruct;
+import static gregtech.api.enums.Mods.MagicalCrops;
+import static gregtech.api.enums.Mods.Names;
+import static gregtech.api.enums.Mods.Railcraft;
+import static gregtech.api.enums.Mods.TaintedMagic;
+import static gregtech.api.enums.Mods.Thaumcraft;
+import static gregtech.api.enums.Mods.ThaumicBoots;
+import static gregtech.api.enums.Mods.ThaumicTinkerer;
+import static gregtech.api.enums.Mods.TwilightForest;
+import static gregtech.api.enums.Mods.WitchingGadgets;
+import static gregtech.api.recipe.RecipeMaps.crackingRecipes;
+import static gregtech.api.recipe.RecipeMaps.cutterRecipes;
+import static gregtech.api.recipe.RecipeMaps.wiremillRecipes;
+import static gregtech.api.util.GT_RecipeBuilder.SECONDS;
+import static gregtech.api.util.GT_RecipeConstants.UniversalChemical;
+import static gregtech.api.util.GT_Util.LAST_BROKEN_TILEENTITY;
+import static net.minecraftforge.fluids.FluidRegistry.getFluidStack;
+
+import java.io.File;
+import java.text.DateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Date;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.stream.Collectors;
+
+import net.minecraft.block.Block;
+import net.minecraft.enchantment.Enchantment;
+import net.minecraft.enchantment.EnchantmentHelper;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.item.EntityItem;
+import net.minecraft.entity.monster.EntityEnderman;
+import net.minecraft.entity.monster.EntitySkeleton;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.projectile.EntityArrow;
+import net.minecraft.init.Blocks;
+import net.minecraft.init.Items;
+import net.minecraft.item.ItemBlock;
+import net.minecraft.item.ItemBow;
+import net.minecraft.item.ItemStack;
+import net.minecraft.item.crafting.CraftingManager;
+import net.minecraft.item.crafting.IRecipe;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.potion.Potion;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.DamageSource;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.MathHelper;
+import net.minecraft.util.ResourceLocation;
+import net.minecraft.world.ChunkCoordIntPair;
+import net.minecraft.world.World;
+import net.minecraft.world.WorldSettings.GameType;
+import net.minecraft.world.gen.feature.WorldGenMinable;
+import net.minecraftforge.common.MinecraftForge;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.event.ForgeEventFactory;
+import net.minecraftforge.event.entity.EntityJoinWorldEvent;
+import net.minecraftforge.event.entity.living.EnderTeleportEvent;
+import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent;
+import net.minecraftforge.event.entity.player.ArrowLooseEvent;
+import net.minecraftforge.event.entity.player.ArrowNockEvent;
+import net.minecraftforge.event.entity.player.ItemTooltipEvent;
+import net.minecraftforge.event.entity.player.PlayerEvent;
+import net.minecraftforge.event.entity.player.PlayerInteractEvent;
+import net.minecraftforge.event.terraingen.OreGenEvent;
+import net.minecraftforge.event.world.BlockEvent;
+import net.minecraftforge.event.world.ChunkDataEvent;
+import net.minecraftforge.event.world.WorldEvent;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidContainerRegistry;
+import net.minecraftforge.fluids.FluidStack;
+import net.minecraftforge.oredict.OreDictionary;
+import net.minecraftforge.oredict.RecipeSorter;
+import net.minecraftforge.oredict.ShapedOreRecipe;
+import net.minecraftforge.oredict.ShapelessOreRecipe;
+
+import cpw.mods.fml.common.FMLCommonHandler;
+import cpw.mods.fml.common.IFuelHandler;
+import cpw.mods.fml.common.Loader;
+import cpw.mods.fml.common.ModContainer;
+import cpw.mods.fml.common.ProgressManager;
+import cpw.mods.fml.common.eventhandler.Event.Result;
+import cpw.mods.fml.common.eventhandler.SubscribeEvent;
+import cpw.mods.fml.common.gameevent.TickEvent;
+import cpw.mods.fml.common.network.FMLNetworkEvent;
+import cpw.mods.fml.common.network.IGuiHandler;
+import cpw.mods.fml.common.network.NetworkRegistry;
+import cpw.mods.fml.common.registry.GameRegistry;
+import gregtech.GT_Mod;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.ConfigCategories;
+import gregtech.api.enums.Dyes;
+import gregtech.api.enums.FluidState;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.OreDictNames;
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.enums.SoundResource;
+import gregtech.api.enums.SubTag;
+import gregtech.api.enums.TC_Aspects.TC_AspectStack;
+import gregtech.api.enums.TierEU;
+import gregtech.api.enums.ToolDictNames;
+import gregtech.api.fluid.GT_FluidFactory;
+import gregtech.api.interfaces.IBlockOnWalkOver;
+import gregtech.api.interfaces.IProjectileItem;
+import gregtech.api.interfaces.IToolStats;
+import gregtech.api.interfaces.internal.IGT_Mod;
+import gregtech.api.interfaces.internal.IThaumcraftCompat;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.items.GT_MetaGenerated_Item;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.objects.GT_ChunkManager;
+import gregtech.api.objects.GT_ItemStack;
+import gregtech.api.objects.GT_UO_DimensionList;
+import gregtech.api.objects.ItemData;
+import gregtech.api.recipe.RecipeCategory;
+import gregtech.api.recipe.RecipeCategorySetting;
+import gregtech.api.util.GT_BlockMap;
+import gregtech.api.util.GT_CLS_Compat;
+import gregtech.api.util.GT_ChunkAssociatedData;
+import gregtech.api.util.GT_ClientPreference;
+import gregtech.api.util.GT_CoverBehaviorBase;
+import gregtech.api.util.GT_LanguageManager;
+import gregtech.api.util.GT_Log;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_OreDictUnificator;
+import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.GT_RecipeRegistrator;
+import gregtech.api.util.GT_Shaped_Recipe;
+import gregtech.api.util.GT_Shapeless_Recipe;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.WorldSpawnedEventBuilder;
+import gregtech.common.entities.GT_Entity_Arrow;
+import gregtech.common.items.GT_MetaGenerated_Item_98;
+import gregtech.common.items.GT_MetaGenerated_Tool_01;
+import gregtech.common.misc.GlobalEnergyWorldSavedData;
+import gregtech.common.misc.GlobalMetricsCoverDatabase;
+import gregtech.common.misc.spaceprojects.SpaceProjectWorldSavedData;
+import gregtech.common.tileentities.machines.multi.drone.GT_MetaTileEntity_DroneCentre;
+
+public abstract class GT_Proxy implements IGT_Mod, IGuiHandler, IFuelHandler {
+
+ private static final EnumSet<OreGenEvent.GenerateMinable.EventType> PREVENTED_ORES = EnumSet.of(
+ OreGenEvent.GenerateMinable.EventType.COAL,
+ OreGenEvent.GenerateMinable.EventType.IRON,
+ OreGenEvent.GenerateMinable.EventType.GOLD,
+ OreGenEvent.GenerateMinable.EventType.DIAMOND,
+ OreGenEvent.GenerateMinable.EventType.REDSTONE,
+ OreGenEvent.GenerateMinable.EventType.LAPIS,
+ OreGenEvent.GenerateMinable.EventType.QUARTZ);
+ public final HashSet<ItemStack> mRegisteredOres = new HashSet<>(10000);
+ public final ArrayList<String> mSoundNames = new ArrayList<>();
+ public final ArrayList<ItemStack> mSoundItems = new ArrayList<>();
+ public final ArrayList<Integer> mSoundCounts = new ArrayList<>();
+ private final Collection<OreDictEventContainer> mEvents = new HashSet<>();
+ private final Collection<String> mIgnoredItems = new HashSet<>(
+ Arrays.asList(
+ "itemGhastTear",
+ "itemFlint",
+ "itemClay",
+ "itemBucketSaltWater",
+ "itemBucketFreshWater",
+ "itemBucketWater",
+ "itemRock",
+ "itemReed",
+ "itemArrow",
+ "itemSaw",
+ "itemKnife",
+ "itemHammer",
+ "itemChisel",
+ "itemRubber",
+ "itemEssence",
+ "itemIlluminatedPanel",
+ "itemSkull",
+ "itemRawRubber",
+ "itemBacon",
+ "itemJetpackAccelerator",
+ "itemLazurite",
+ "itemIridium",
+ "itemTear",
+ "itemClaw",
+ "itemFertilizer",
+ "itemTar",
+ "itemSlimeball",
+ "itemCoke",
+ "itemBeeswax",
+ "itemBeeQueen",
+ "itemForcicium",
+ "itemForcillium",
+ "itemRoyalJelly",
+ "itemHoneydew",
+ "itemHoney",
+ "itemPollen",
+ "itemReedTypha",
+ "itemSulfuricAcid",
+ "itemPotash",
+ "itemCompressedCarbon",
+ "itemBitumen",
+ "itemBioFuel",
+ "itemCokeSugar",
+ "itemCokeCactus",
+ "itemCharcoalSugar",
+ "itemCharcoalCactus",
+ "itemSludge",
+ "itemEnrichedAlloy",
+ "itemQuicksilver",
+ "itemMercury",
+ "itemOsmium",
+ "itemUltimateCircuit",
+ "itemEnergizedStar",
+ "itemAntimatterMolecule",
+ "itemAntimatterGlob",
+ "itemCoal",
+ "itemBoat",
+ "itemHerbalMedicineCake",
+ "itemCakeSponge",
+ "itemFishandPumpkinCakeSponge",
+ "itemSoulCleaver",
+ "itemInstantCake",
+ "itemWhippingCream",
+ "itemGlisteningWhippingCream",
+ "itemCleaver",
+ "itemHerbalMedicineWhippingCream",
+ "itemStrangeWhippingCream",
+ "itemBlazeCleaver",
+ "itemBakedCakeSponge",
+ "itemMagmaCake",
+ "itemGlisteningCake",
+ "itemOgreCleaver",
+ "itemFishandPumpkinCake",
+ "itemMagmaWhippingCream",
+ "itemMultimeter",
+ "itemSuperconductor"));
+ private final Collection<String> mIgnoredNames = new HashSet<>(
+ Arrays.asList(
+ "grubBee",
+ "chainLink",
+ "candyCane",
+ "bRedString",
+ "bVial",
+ "bFlask",
+ "anorthositeSmooth",
+ "migmatiteSmooth",
+ "slateSmooth",
+ "travertineSmooth",
+ "limestoneSmooth",
+ "orthogneissSmooth",
+ "marbleSmooth",
+ "honeyDrop",
+ "lumpClay",
+ "honeyEqualssugar",
+ "flourEqualswheat",
+ "bluestoneInsulated",
+ "blockWaterstone",
+ "blockSand",
+ "blockTorch",
+ "blockPumpkin",
+ "blockClothRock",
+ "blockStainedHardenedClay",
+ "blockQuartzPillar",
+ "blockQuartzChiselled",
+ "blockSpawner",
+ "blockCloth",
+ "mobHead",
+ "mobEgg",
+ "enderFlower",
+ "enderChest",
+ "clayHardened",
+ "dayGemMaterial",
+ "nightGemMaterial",
+ "snowLayer",
+ "bPlaceholder",
+ "hardenedClay",
+ "eternalLifeEssence",
+ "sandstone",
+ "wheatRice",
+ "transdimBlock",
+ "bambooBasket",
+ "lexicaBotania",
+ "livingwoodTwig",
+ "redstoneCrystal",
+ "pestleAndMortar",
+ "glowstone",
+ "whiteStone",
+ "stoneSlab",
+ "transdimBlock",
+ "clayBowl",
+ "clayPlate",
+ "ceramicBowl",
+ "ceramicPlate",
+ "ovenRack",
+ "clayCup",
+ "ceramicCup",
+ "batteryBox",
+ "transmutationStone",
+ "torchRedstoneActive",
+ "coal",
+ "charcoal",
+ "cloth",
+ "cobblestoneSlab",
+ "stoneBrickSlab",
+ "cobblestoneWall",
+ "stoneBrickWall",
+ "cobblestoneStair",
+ "stoneBrickStair",
+ "blockCloud",
+ "blockDirt",
+ "blockTyrian",
+ "blockCarpet",
+ "blockFft",
+ "blockLavastone",
+ "blockHolystone",
+ "blockConcrete",
+ "sunnariumPart",
+ "brSmallMachineCyaniteProcessor",
+ "meteoriteCoal",
+ "blockCobble",
+ "pressOreProcessor",
+ "crusherOreProcessor",
+ "grinderOreProcessor",
+ "blockRubber",
+ "blockHoney",
+ "blockHoneydew",
+ "blockPeat",
+ "blockRadioactive",
+ "blockSlime",
+ "blockCocoa",
+ "blockSugarCane",
+ "blockLeather",
+ "blockClayBrick",
+ "solarPanelHV",
+ "cableRedNet",
+ "stoneBowl",
+ "crafterWood",
+ "taintedSoil",
+ "brickXyEngineering",
+ "breederUranium",
+ "wireMill",
+ "chunkLazurite",
+ "aluminumNatural",
+ "aluminiumNatural",
+ "naturalAluminum",
+ "naturalAluminium",
+ "antimatterMilligram",
+ "antimatterGram",
+ "strangeMatter",
+ "coalGenerator",
+ "electricFurnace",
+ "unfinishedTank",
+ "valvePart",
+ "aquaRegia",
+ "leatherSeal",
+ "leatherSlimeSeal",
+ "hambone",
+ "slimeball",
+ "clay",
+ "enrichedUranium",
+ "camoPaste",
+ "antiBlock",
+ "burntQuartz",
+ "salmonRaw",
+ "blockHopper",
+ "blockEnderObsidian",
+ "blockIcestone",
+ "blockMagicWood",
+ "blockEnderCore",
+ "blockHeeEndium",
+ "oreHeeEndPowder",
+ "oreHeeStardust",
+ "oreHeeIgneousRock",
+ "oreHeeInstabilityOrb",
+ "crystalPureFluix",
+ "shardNether",
+ "gemFluorite",
+ "stickObsidian",
+ "caveCrystal",
+ "shardCrystal",
+ "dyeCrystal",
+ "shardFire",
+ "shardWater",
+ "shardAir",
+ "shardEarth",
+ "ingotRefinedIron",
+ "blockMarble",
+ "ingotUnstable",
+ "obsidian",
+ "dirt",
+ "gravel",
+ "grass",
+ "soulsand",
+ "paper",
+ "brick",
+ "chest"));
+ private final Collection<String> mInvalidNames = new HashSet<>(
+ Arrays.asList(
+ "diamondShard",
+ "redstoneRoot",
+ "obsidianStick",
+ "bloodstoneOre",
+ "universalCable",
+ "bronzeTube",
+ "ironTube",
+ "netherTube",
+ "obbyTube",
+ "infiniteBattery",
+ "eliteBattery",
+ "advancedBattery",
+ "10kEUStore",
+ "blueDye",
+ "MonazitOre",
+ "quartzCrystal",
+ "whiteLuminiteCrystal",
+ "darkStoneIngot",
+ "invisiumIngot",
+ "demoniteOrb",
+ "enderGem",
+ "starconiumGem",
+ "osmoniumIngot",
+ "tapaziteGem",
+ "zectiumIngot",
+ "foolsRubyGem",
+ "rubyGem",
+ "meteoriteGem",
+ "adamiteShard",
+ "sapphireGem",
+ "copperIngot",
+ "ironStick",
+ "goldStick",
+ "diamondStick",
+ "reinforcedStick",
+ "draconicStick",
+ "emeraldStick",
+ "copperStick",
+ "tinStick",
+ "silverStick",
+ "bronzeStick",
+ "steelStick",
+ "leadStick",
+ "manyullynStick",
+ "arditeStick",
+ "cobaltStick",
+ "aluminiumStick",
+ "alumiteStick",
+ "oilsandsOre",
+ "copperWire",
+ "superconductorWire",
+ "sulfuricAcid",
+ "conveyorBelt",
+ "ironWire",
+ "aluminumWire",
+ "aluminiumWire",
+ "silverWire",
+ "tinWire",
+ "dustSiliconSmall",
+ "AluminumOre",
+ "plateHeavyT2",
+ "blockWool",
+ "alloyPlateEnergizedHardened",
+ "gasWood",
+ "alloyPlateEnergized",
+ "SilverOre",
+ "LeadOre",
+ "TinOre",
+ "CopperOre",
+ "silverOre",
+ "leadOre",
+ "tinOre",
+ "copperOre",
+ "bauxiteOre",
+ "HSLivingmetalIngot",
+ "oilMoving",
+ "oilStill",
+ "oilBucket",
+ "petroleumOre",
+ "dieselFuel",
+ "diamondNugget",
+ "planks",
+ "wood",
+ "stick",
+ "sticks",
+ "naquadah",
+ "obsidianRod",
+ "stoneRod",
+ "thaumiumRod",
+ "steelRod",
+ "netherrackRod",
+ "woodRod",
+ "ironRod",
+ "cactusRod",
+ "flintRod",
+ "copperRod",
+ "cobaltRod",
+ "alumiteRod",
+ "blueslimeRod",
+ "arditeRod",
+ "manyullynRod",
+ "bronzeRod",
+ "boneRod",
+ "slimeRod",
+ "redalloyBundled",
+ "bluestoneBundled",
+ "infusedteslatiteInsulated",
+ "redalloyInsulated",
+ "infusedteslatiteBundled"));
+ private final DateFormat mDateFormat = DateFormat.getInstance();
+ public final BlockingQueue<String> mBufferedPlayerActivity = new LinkedBlockingQueue<>();
+ public final GT_BlockMap<Boolean> mCTMBlockCache = new GT_BlockMap<>();
+ public boolean mHardcoreCables = false;
+ public boolean mDisableVanillaOres = true;
+ public boolean mHardMachineCasings = true;
+ public boolean mAllowSmallBoilerAutomation = false;
+ public boolean mNerfDustCrafting = true;
+ public boolean mSortToTheEnd = true;
+ public boolean mCraftingUnification = true;
+ public boolean mInventoryUnification = true;
+ public boolean mIncreaseDungeonLoot = true;
+ public boolean mAxeWhenAdventure = true;
+ public boolean mSurvivalIntoAdventure = false;
+ public boolean mNerfedWoodPlank = true;
+ public boolean mNerfedVanillaTools = true;
+ public boolean mHardRock = false;
+ public boolean mHungerEffect = true;
+ public boolean mOnline = true;
+ public boolean mIgnoreTcon = true;
+ public boolean mDisableIC2Cables = false;
+ public boolean mAchievements = true;
+ public boolean mArcSmeltIntoAnnealed = true;
+ public boolean mMagneticraftRecipes = false;
+ public boolean mImmersiveEngineeringRecipes = false;
+ private boolean isFirstServerWorldTick = true;
+ private boolean isFirstWorldTick = true;
+ private boolean mOreDictActivated = false;
+ public boolean mChangeHarvestLevels = false;
+ public boolean mNerfedCombs = true;
+ public boolean mNerfedCrops = true;
+ public boolean mGTBees = true;
+ public boolean mHideUnusedOres = true;
+ public boolean mPollution = true;
+ public boolean mExplosionItemDrop = false;
+ public boolean mUseGreatlyShrukenReplacementList = true;
+ public int mSkeletonsShootGTArrows = 16;
+ public int mMaxEqualEntitiesAtOneSpot = 3;
+ public int mFlintChance = 30;
+ public int mItemDespawnTime = 6000;
+ public int mUpgradeCount = 4;
+ public int[] mHarvestLevel = new int[1000];
+ public int mGraniteHavestLevel = 3;
+ public int mMaxHarvestLevel = 7;
+ public int mWireHeatingTicks = 4;
+ public double replicatorExponent = 1.2D;
+ public int mPollutionSmogLimit = 550000;
+ public int mPollutionPoisonLimit = 750000;
+ public int mPollutionVegetationLimit = 1000000;
+ public int mPollutionSourRainLimit = 2000000;
+ public int mPollutionOnExplosion = 100000;
+ public int mPollutionPrimitveBlastFurnacePerSecond = 200;
+ public int mPollutionEBFPerSecond = 400;
+ public int mPollutionCharcoalPitPerSecond = 100;
+ public int mPollutionLargeCombustionEnginePerSecond = 480;
+ public int mPollutionExtremeCombustionEnginePerSecond = 3840;
+ public int mPollutionImplosionCompressorPerSecond = 10000;
+ public int mPollutionLargeBronzeBoilerPerSecond = 1000;
+ public int mPollutionLargeSteelBoilerPerSecond = 2000;
+ public int mPollutionLargeTitaniumBoilerPerSecond = 3000;
+ public int mPollutionLargeTungstenSteelBoilerPerSecond = 4000;
+ public double mPollutionReleasedByThrottle = 1.0 / 24.0; // divided by 24 because 24 circuit conf
+ public int mPollutionLargeGasTurbinePerSecond = 300;
+ public int mPollutionMultiSmelterPerSecond = 400;
+ public int mPollutionPyrolyseOvenPerSecond = 300;
+ public int mPollutionSmallCoalBoilerPerSecond = 20;
+ public int mPollutionHighPressureLavaBoilerPerSecond = 20;
+ public int mPollutionHighPressureCoalBoilerPerSecond = 30;
+ public int mPollutionBaseDieselGeneratorPerSecond = 200;
+ public double[] mPollutionDieselGeneratorReleasedByTier = new double[] { 0.1, 1.0, 0.9, 0.8 };
+ public int mPollutionBaseGasTurbinePerSecond = 200;
+ public double[] mPollutionGasTurbineReleasedByTier = new double[] { 0.1, 1.0, 0.9, 0.8, 0.7, 0.6 };
+ public final GT_UO_DimensionList mUndergroundOil = new GT_UO_DimensionList();
+ public boolean enableUndergroundGravelGen = true;
+ public boolean enableUndergroundDirtGen = true;
+ public int mTicksUntilNextCraftSound = 0;
+ public double mMagneticraftBonusOutputPercent = 0d;
+ private World mUniverse = null;
+ public boolean mTEMachineRecipes = false;
+ public boolean mEnableAllMaterials = false;
+ public boolean mEnableCleanroom = true;
+ public boolean mLowGravProcessing = false;
+ public boolean mAprilFool = false;
+ public boolean mCropNeedBlock = true;
+ @Deprecated
+ public boolean mDisableOldChemicalRecipes = false;
+ public boolean mAMHInteraction = true;
+ public boolean mForceFreeFace = true;
+ public boolean mBrickedBlastFurnace = true;
+ @Deprecated
+ public boolean mEasierIVPlusCables = false;
+ public boolean mMixedOreOnlyYieldsTwoThirdsOfPureOre = false;
+ public boolean mRichOreYieldMultiplier = true;
+ public boolean mNetherOreYieldMultiplier = true;
+ public boolean mEndOreYieldMultiplier = true;
+ public boolean enableBlackGraniteOres = true;
+ public boolean enableRedGraniteOres = true;
+ public boolean enableMarbleOres = true;
+ public boolean enableBasaltOres = true;
+ public boolean gt6Pipe = true;
+ public boolean gt6Cable = true;
+ public boolean ic2EnergySourceCompat = true;
+ public boolean costlyCableConnection = false;
+ public boolean crashOnNullRecipeInput = false;
+
+ public enum OreDropSystem {
+ Block,
+ PerDimBlock,
+ UnifiedBlock,
+ FortuneItem,
+ Item
+ }
+
+ public OreDropSystem oreDropSystem = OreDropSystem.FortuneItem;
+
+ /**
+ * This enables ambient-occlusion smooth lighting on tiles
+ */
+ public boolean mRenderTileAmbientOcclusion = true;
+
+ /**
+ * This enables rendering of glowing textures
+ */
+ public boolean mRenderGlowTextures = true;
+
+ /**
+ * Render flipped textures
+ */
+ public boolean mRenderFlippedMachinesFlipped = true;
+
+ /**
+ * This enables indicators on input/output hatches
+ */
+ public boolean mRenderIndicatorsOnHatch = true;
+
+ /**
+ * This enables the rendering of dirt particles if pollution is enabled too
+ */
+ public boolean mRenderDirtParticles = true;
+
+ /**
+ * This enables the rendering of the pollution fog if pollution is enabled too
+ */
+ public boolean mRenderPollutionFog = true;
+
+ /**
+ * This enables BaseMetaTileEntity block updates handled by BlockUpdateHandler
+ */
+ public boolean mUseBlockUpdateHandler = false;
+
+ /**
+ * This makes cover tabs visible on GregTech machines
+ */
+ public boolean mCoverTabsVisible = true;
+
+ /**
+ * This controls whether cover tabs display on the left (default) or right side of the UI
+ */
+ public boolean mCoverTabsFlipped = false;
+
+ /**
+ * How verbose should tooltips be? 0: disabled, 1: one-line, 2: normal, 3+: extended
+ */
+ public int mTooltipVerbosity = 2;
+
+ /**
+ * How verbose should tooltips be when LSHIFT is held? 0: disabled, 1: one-line, 2: normal, 3+: extended
+ */
+ public int mTooltipShiftVerbosity = 3;
+
+ /**
+ * Which style to use for title tab on machine GUI? 0: text tab split-dark, 1: text tab unified, 2: item icon tab
+ */
+ public int mTitleTabStyle = 0;
+
+ /**
+ * Whether to show seconds or ticks on NEI
+ */
+ public boolean mNEIRecipeSecondMode = true;
+
+ /**
+ * This enables "Recipe by" display on NEI
+ */
+ public boolean mNEIRecipeOwner = false;
+
+ /**
+ * This enables showing stack traces where the recipe was added. Reboot needed
+ */
+ public boolean mNEIRecipeOwnerStackTrace = false;
+
+ /**
+ * This enables showing original voltage when overclocked
+ */
+ public boolean mNEIOriginalVoltage = false;
+
+ /**
+ * This enables the green->red durability for an item's damage value
+ */
+ public boolean mRenderItemDurabilityBar = true;
+
+ /**
+ * This enables the blue charge bar for an electric item's charge
+ */
+ public boolean mRenderItemChargeBar = true;
+
+ public final Map<RecipeCategory, RecipeCategorySetting> recipeCategorySettings = new HashMap<>();
+
+ /**
+ * This enables showing voltage tier of transformer for Waila, instead of raw voltage number
+ */
+ public boolean mWailaTransformerVoltageTier = true;
+
+ /**
+ * What is the order of the circuits when they are selected?
+ */
+ public Map<String, Integer> mCircuitsOrder = new HashMap<>();
+
+ public boolean wailaAverageNS = false;
+
+ public static final int GUI_ID_COVER_SIDE_BASE = 10; // Takes GUI ID 10 - 15
+
+ public static Map<String, Integer> oreDictBurnTimes = new HashMap<>();
+
+ // Locking
+ public static ReentrantLock TICK_LOCK = new ReentrantLock();
+
+ private final ConcurrentMap<UUID, GT_ClientPreference> mClientPrefernces = new ConcurrentHashMap<>();
+
+ static {
+ oreDictBurnTimes.put("dustTinyWood", 11);
+ oreDictBurnTimes.put("dustTinySodium", 44);
+ oreDictBurnTimes.put("dustSmallWood", 25);
+ oreDictBurnTimes.put("dustSmallSodium", 100);
+ oreDictBurnTimes.put("dustWood", 100);
+ oreDictBurnTimes.put("dustTinyCoal", 177);
+ oreDictBurnTimes.put("dustTinyCharcoal", 177);
+ oreDictBurnTimes.put("dustTinyLignite", 166);
+ oreDictBurnTimes.put("plateWood", 300);
+ oreDictBurnTimes.put("dustSmallLignite", 375);
+ oreDictBurnTimes.put("dustSodium", 400);
+ oreDictBurnTimes.put("dustSmallCoal", 400);
+ oreDictBurnTimes.put("dustSmallCharcoal", 400);
+ oreDictBurnTimes.put("dustTinyLithium", 888);
+ oreDictBurnTimes.put("dustTinyCaesium", 888);
+ oreDictBurnTimes.put("gemLignite", 1200);
+ oreDictBurnTimes.put("crushedLignite", 1200);
+ oreDictBurnTimes.put("dustImpureLignite", 1200);
+ oreDictBurnTimes.put("dustLignite", 1200);
+ oreDictBurnTimes.put("dustSulfur", 1600);
+ oreDictBurnTimes.put("gemCoal", 1600);
+ oreDictBurnTimes.put("crushedCoal", 1600);
+ oreDictBurnTimes.put("dustImpureCoal", 1600);
+ oreDictBurnTimes.put("dustCoal", 1600);
+ oreDictBurnTimes.put("gemCharcoal", 1600);
+ oreDictBurnTimes.put("crushedCharcoal", 1600);
+ oreDictBurnTimes.put("dustImpureCharcoal", 1600);
+ oreDictBurnTimes.put("dustCharcoal", 1600);
+ oreDictBurnTimes.put("dustSmallLithium", 2000);
+ oreDictBurnTimes.put("dustSmallCaesium", 2000);
+ oreDictBurnTimes.put("gemSodium", 4000);
+ oreDictBurnTimes.put("crushedSodium", 4000);
+ oreDictBurnTimes.put("dustImpureSodium", 4000);
+ oreDictBurnTimes.put("gemLithium", 6000);
+ oreDictBurnTimes.put("crushedLithium", 6000);
+ oreDictBurnTimes.put("dustImpureLithium", 6000);
+ oreDictBurnTimes.put("dustLithium", 6000);
+ oreDictBurnTimes.put("gemCaesium", 6000);
+ oreDictBurnTimes.put("crushedCaesium", 6000);
+ oreDictBurnTimes.put("dustImpureCaesium", 6000);
+ oreDictBurnTimes.put("dustCaesium", 6000);
+ oreDictBurnTimes.put("blockLignite", 12000);
+ oreDictBurnTimes.put("blockCharcoal", 16000);
+ oreDictBurnTimes.put("gemDiamond", 102400);
+ oreDictBurnTimes.put("blockDiamond", 1024000);
+ oreDictBurnTimes.put("crushedDiamond", 102400);
+ oreDictBurnTimes.put("dustImpureDiamond", 102400);
+ oreDictBurnTimes.put("dustDiamond", 102400);
+ oreDictBurnTimes.put("dustSmallDiamond", 25600);
+ oreDictBurnTimes.put("dustTinyDiamond", 11378);
+ }
+
+ public GT_Proxy() {
+ GameRegistry.registerFuelHandler(this);
+ MinecraftForge.EVENT_BUS.register(this);
+ MinecraftForge.ORE_GEN_BUS.register(this);
+ FMLCommonHandler.instance()
+ .bus()
+ .register(this);
+ GregTech_API.sThaumcraftCompat = (IThaumcraftCompat) GT_Utility
+ .callConstructor("gregtech.common.GT_ThaumcraftCompat", 0, null, GT_Values.D1, new Object[0]);
+ for (FluidContainerRegistry.FluidContainerData tData : FluidContainerRegistry
+ .getRegisteredFluidContainerData()) {
+ onFluidContainerRegistration(new FluidContainerRegistry.FluidContainerRegisterEvent(tData));
+ }
+ try {
+ for (String tOreName : OreDictionary.getOreNames()) {
+ ItemStack tOreStack;
+ for (Iterator<ItemStack> i$ = OreDictionary.getOres(tOreName)
+ .iterator(); i$.hasNext(); registerOre(new OreDictionary.OreRegisterEvent(tOreName, tOreStack))) {
+ tOreStack = i$.next();
+ }
+ }
+ } catch (Throwable e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ }
+
+ public void onPreLoad() {
+ GT_Log.out.println("GT_Mod: Preload-Phase started!");
+ GT_Log.ore.println("GT_Mod: Preload-Phase started!");
+
+ GregTech_API.sPreloadStarted = true;
+ this.mIgnoreTcon = GregTech_API.sOPStuff.get(ConfigCategories.general, "ignoreTConstruct", true);
+ this.mWireHeatingTicks = GregTech_API.sOPStuff.get(ConfigCategories.general, "WireHeatingTicks", 4);
+ this.replicatorExponent = GregTech_API.sOPStuff.get("Replicator", "Nerf Exponent", 1.2D);
+ NetworkRegistry.INSTANCE.registerGuiHandler(GT_Values.GT, this);
+ for (FluidContainerRegistry.FluidContainerData tData : FluidContainerRegistry
+ .getRegisteredFluidContainerData()) {
+ if ((tData.filledContainer.getItem() == Items.potionitem) && (tData.filledContainer.getItemDamage() == 0)) {
+ tData.fluid.amount = 0;
+ break;
+ }
+ }
+ GT_Log.out.println("GT_Mod: Getting required Items of other Mods.");
+
+ ItemList.RC_ShuntingWire.set(GT_ModHandler.getModItem(Railcraft.ID, "machine.delta", 1L, 0));
+ ItemList.RC_ShuntingWireFrame.set(GT_ModHandler.getModItem(Railcraft.ID, "frame", 1L, 0));
+ ItemList.RC_Rail_Standard.set(GT_ModHandler.getModItem(Railcraft.ID, "part.rail", 1L, 0));
+ ItemList.RC_Rail_Adv.set(GT_ModHandler.getModItem(Railcraft.ID, "part.rail", 1L, 1));
+ ItemList.RC_Rail_Wooden.set(GT_ModHandler.getModItem(Railcraft.ID, "part.rail", 1L, 2));
+ ItemList.RC_Rail_HS.set(GT_ModHandler.getModItem(Railcraft.ID, "part.rail", 1L, 3));
+ ItemList.RC_Rail_Reinforced.set(GT_ModHandler.getModItem(Railcraft.ID, "part.rail", 1L, 4));
+ ItemList.RC_Rail_Electric.set(GT_ModHandler.getModItem(Railcraft.ID, "part.rail", 1L, 5));
+ ItemList.RC_Tie_Wood.set(GT_ModHandler.getModItem(Railcraft.ID, "part.tie", 1L, 0));
+ ItemList.RC_Tie_Stone.set(GT_ModHandler.getModItem(Railcraft.ID, "part.tie", 1L, 1));
+ ItemList.RC_Bed_Wood.set(GT_ModHandler.getModItem(Railcraft.ID, "part.railbed", 1L, 0));
+ ItemList.RC_Bed_Stone.set(GT_ModHandler.getModItem(Railcraft.ID, "part.railbed", 1L, 1));
+ ItemList.RC_Rebar.set(GT_ModHandler.getModItem(Railcraft.ID, "part.rebar", 1L));
+ ItemList.TC_Thaumometer.set(GT_ModHandler.getModItem(Thaumcraft.ID, "ItemThaumometer", 1L, 0));
+ ItemList.Tool_Sword_Steel.set(GT_ModHandler.getModItem(Railcraft.ID, "tool.steel.sword", 1L));
+ ItemList.Tool_Pickaxe_Steel.set(GT_ModHandler.getModItem(Railcraft.ID, "tool.steel.pickaxe", 1L));
+ ItemList.Tool_Shovel_Steel.set(GT_ModHandler.getModItem(Railcraft.ID, "tool.steel.shovel", 1L));
+ ItemList.Tool_Axe_Steel.set(GT_ModHandler.getModItem(Railcraft.ID, "tool.steel.axe", 1L));
+ ItemList.Tool_Hoe_Steel.set(GT_ModHandler.getModItem(Railcraft.ID, "tool.steel.hoe", 1L));
+
+ ItemList.TF_LiveRoot.set(GT_ModHandler.getModItem(TwilightForest.ID, "item.liveRoot", 1L, 0));
+ ItemList.TF_Vial_FieryBlood.set(GT_ModHandler.getModItem(TwilightForest.ID, "item.fieryBlood", 1L));
+ ItemList.TF_Vial_FieryTears.set(GT_ModHandler.getModItem(TwilightForest.ID, "item.fieryTears", 1L));
+
+ ItemList.FR_Lemon.set(GT_ModHandler.getModItem(Forestry.ID, "fruits", 1L, 3));
+ ItemList.FR_Mulch.set(GT_ModHandler.getModItem(Forestry.ID, "mulch", 1L));
+ ItemList.FR_Fertilizer.set(GT_ModHandler.getModItem(Forestry.ID, "fertilizerCompound", 1L));
+ ItemList.FR_Compost.set(GT_ModHandler.getModItem(Forestry.ID, "fertilizerBio", 1L));
+ ItemList.FR_Silk.set(GT_ModHandler.getModItem(Forestry.ID, "craftingMaterial", 1L, 2));
+ ItemList.FR_Wax.set(GT_ModHandler.getModItem(Forestry.ID, "beeswax", 1L));
+ ItemList.FR_WaxCapsule.set(GT_ModHandler.getModItem(Forestry.ID, "waxCapsule", 1L));
+ ItemList.FR_RefractoryWax.set(GT_ModHandler.getModItem(Forestry.ID, "refractoryWax", 1L));
+ ItemList.FR_RefractoryCapsule.set(GT_ModHandler.getModItem(Forestry.ID, "refractoryEmpty", 1L));
+ ItemList.FR_Bee_Drone.set(GT_ModHandler.getModItem(Forestry.ID, "beeDroneGE", 1L));
+ ItemList.FR_Bee_Princess.set(GT_ModHandler.getModItem(Forestry.ID, "beePrincessGE", 1L));
+ ItemList.FR_Bee_Queen.set(GT_ModHandler.getModItem(Forestry.ID, "beeQueenGE", 1L));
+ ItemList.FR_Tree_Sapling.set(
+ GT_ModHandler
+ .getModItem(Forestry.ID, "sapling", 1L, GT_ModHandler.getModItem(Forestry.ID, "saplingGE", 1L)));
+ ItemList.FR_Butterfly.set(GT_ModHandler.getModItem(Forestry.ID, "butterflyGE", 1L));
+ ItemList.FR_Larvae.set(GT_ModHandler.getModItem(Forestry.ID, "beeLarvaeGE", 1L));
+ ItemList.FR_Serum.set(GT_ModHandler.getModItem(Forestry.ID, "serumGE", 1L));
+ ItemList.FR_Caterpillar.set(GT_ModHandler.getModItem(Forestry.ID, "caterpillarGE", 1L));
+ ItemList.FR_PollenFertile.set(GT_ModHandler.getModItem(Forestry.ID, "pollenFertile", 1L));
+ ItemList.FR_Stick.set(GT_ModHandler.getModItem(Forestry.ID, "oakStick", 1L));
+ ItemList.FR_Casing_Impregnated.set(GT_ModHandler.getModItem(Forestry.ID, "impregnatedCasing", 1L));
+ ItemList.FR_Casing_Sturdy.set(GT_ModHandler.getModItem(Forestry.ID, "sturdyMachine", 1L));
+ ItemList.FR_Casing_Hardened.set(GT_ModHandler.getModItem(Forestry.ID, "hardenedMachine", 1L));
+
+ ItemList.Bottle_Empty.set(new ItemStack(Items.glass_bottle, 1));
+
+ ItemList.Cell_Universal_Fluid.set(GT_ModHandler.getIC2Item("FluidCell", 1L));
+ ItemList.Cell_Empty.set(
+ GT_ModHandler.getIC2Item(
+ "cell",
+ 1L,
+ GT_ModHandler.getIC2Item("cellEmpty", 1L, GT_ModHandler.getIC2Item("emptyCell", 1L))));
+ ItemList.Cell_Water.set(GT_ModHandler.getIC2Item("waterCell", 1L, GT_ModHandler.getIC2Item("cellWater", 1L)));
+ ItemList.Cell_Lava.set(GT_ModHandler.getIC2Item("lavaCell", 1L, GT_ModHandler.getIC2Item("cellLava", 1L)));
+ ItemList.Cell_Air.set(
+ GT_ModHandler.getIC2Item(
+ "airCell",
+ 1L,
+ GT_ModHandler.getIC2Item("cellAir", 1L, GT_ModHandler.getIC2Item("cellOxygen", 1L))));
+
+ ItemList.IC2_Item_Casing_Iron.set(GT_ModHandler.getIC2Item("casingiron", 1L));
+ ItemList.IC2_Item_Casing_Gold.set(GT_ModHandler.getIC2Item("casinggold", 1L));
+ ItemList.IC2_Item_Casing_Bronze.set(GT_ModHandler.getIC2Item("casingbronze", 1L));
+ ItemList.IC2_Item_Casing_Copper.set(GT_ModHandler.getIC2Item("casingcopper", 1L));
+ ItemList.IC2_Item_Casing_Tin.set(GT_ModHandler.getIC2Item("casingtin", 1L));
+ ItemList.IC2_Item_Casing_Lead.set(GT_ModHandler.getIC2Item("casinglead", 1L));
+ ItemList.IC2_Item_Casing_Steel.set(GT_ModHandler.getIC2Item("casingadviron", 1L));
+ ItemList.IC2_Spray_WeedEx.set(GT_ModHandler.getIC2Item("weedEx", 1L));
+ ItemList.IC2_Mixed_Metal_Ingot.set(GT_ModHandler.getIC2Item("mixedMetalIngot", 1L));
+ ItemList.IC2_Fertilizer.set(GT_ModHandler.getIC2Item("fertilizer", 1L));
+ ItemList.IC2_CoffeeBeans.set(GT_ModHandler.getIC2Item("coffeeBeans", 1L));
+ ItemList.IC2_CoffeePowder.set(GT_ModHandler.getIC2Item("coffeePowder", 1L));
+ ItemList.IC2_Hops.set(GT_ModHandler.getIC2Item("hops", 1L));
+ ItemList.IC2_Resin.set(GT_ModHandler.getIC2Item("resin", 1L));
+ ItemList.IC2_Plantball.set(GT_ModHandler.getIC2Item("plantBall", 1L));
+ ItemList.IC2_PlantballCompressed
+ .set(GT_ModHandler.getIC2Item("compressedPlantBall", 1L, ItemList.IC2_Plantball.get(1L)));
+ ItemList.IC2_Crop_Seeds.set(GT_ModHandler.getIC2Item("cropSeed", 1L));
+ ItemList.IC2_Grin_Powder.set(GT_ModHandler.getIC2Item("grinPowder", 1L));
+ ItemList.IC2_Energium_Dust.set(GT_ModHandler.getIC2Item("energiumDust", 1L));
+ ItemList.IC2_Scrap.set(GT_ModHandler.getIC2Item("scrap", 1L));
+ ItemList.IC2_Scrapbox.set(GT_ModHandler.getIC2Item("scrapBox", 1L));
+ ItemList.IC2_Fuel_Rod_Empty.set(GT_ModHandler.getIC2Item("fuelRod", 1L));
+ ItemList.IC2_Food_Can_Empty.set(GT_ModHandler.getIC2Item("tinCan", 1L));
+ ItemList.IC2_Food_Can_Filled.set(GT_ModHandler.getIC2Item("filledTinCan", 1L, 0));
+ ItemList.IC2_Food_Can_Spoiled.set(GT_ModHandler.getIC2Item("filledTinCan", 1L, 1));
+ ItemList.IC2_Industrial_Diamond
+ .set(GT_ModHandler.getIC2Item("industrialDiamond", 1L, new ItemStack(Items.diamond, 1)));
+ ItemList.IC2_Compressed_Coal_Ball.set(GT_ModHandler.getIC2Item("compressedCoalBall", 1L));
+ ItemList.IC2_Compressed_Coal_Chunk.set(GT_ModHandler.getIC2Item("coalChunk", 1L));
+ ItemList.IC2_ShaftIron.set(GT_ModHandler.getIC2Item("ironshaft", 1L));
+ ItemList.IC2_ShaftSteel.set(GT_ModHandler.getIC2Item("steelshaft", 1L));
+
+ ItemList.IC2_SuBattery.set(GT_ModHandler.getIC2Item("suBattery", 1L));
+ ItemList.IC2_ReBattery.set(GT_ModHandler.getIC2Item("reBattery", 1L));
+ ItemList.IC2_AdvBattery.set(GT_ModHandler.getIC2Item("advBattery", 1L));
+ ItemList.IC2_EnergyCrystal.set(GT_ModHandler.getIC2Item("energyCrystal", 1L));
+ ItemList.IC2_LapotronCrystal.set(GT_ModHandler.getIC2Item("lapotronCrystal", 1L));
+
+ ItemList.Tool_Sword_Bronze.set(GT_ModHandler.getIC2Item("bronzeSword", 1L));
+ ItemList.Tool_Pickaxe_Bronze.set(GT_ModHandler.getIC2Item("bronzePickaxe", 1L));
+ ItemList.Tool_Shovel_Bronze.set(GT_ModHandler.getIC2Item("bronzeShovel", 1L));
+ ItemList.Tool_Axe_Bronze.set(GT_ModHandler.getIC2Item("bronzeAxe", 1L));
+ ItemList.Tool_Hoe_Bronze.set(GT_ModHandler.getIC2Item("bronzeHoe", 1L));
+ ItemList.IC2_ForgeHammer.set(GT_ModHandler.getIC2Item("ForgeHammer", 1L));
+ ItemList.IC2_WireCutter.set(GT_ModHandler.getIC2Item("cutter", 1L));
+
+ ItemList.Credit_Iron.set(GT_ModHandler.getIC2Item("coin", 1L));
+
+ ItemList.Circuit_Basic.set(GT_ModHandler.getIC2Item("electronicCircuit", 1L));
+ ItemList.Circuit_Advanced.set(GT_ModHandler.getIC2Item("advancedCircuit", 1L));
+
+ ItemList.Upgrade_Overclocker.set(GT_ModHandler.getIC2Item("overclockerUpgrade", 1L));
+ ItemList.Upgrade_Battery.set(GT_ModHandler.getIC2Item("energyStorageUpgrade", 1L));
+
+ ItemList.Dye_Bonemeal.set(new ItemStack(Items.dye, 1, 15));
+ ItemList.Dye_SquidInk.set(new ItemStack(Items.dye, 1, 0));
+ ItemList.Dye_Cocoa.set(new ItemStack(Items.dye, 1, 3));
+
+ ItemList.Book_Written_00.set(new ItemStack(Items.written_book, 1, 0));
+
+ ItemList.Food_Baked_Bread.set(new ItemStack(Items.bread, 1, 0));
+ ItemList.Food_Raw_Potato.set(new ItemStack(Items.potato, 1, 0));
+ ItemList.Food_Baked_Potato.set(new ItemStack(Items.baked_potato, 1, 0));
+ ItemList.Food_Poisonous_Potato.set(new ItemStack(Items.poisonous_potato, 1, 0));
+
+ OrePrefixes.bottle.mContainerItem = ItemList.Bottle_Empty.get(1L);
+ OrePrefixes.bucket.mContainerItem = new ItemStack(Items.bucket, 1);
+ OrePrefixes.cellPlasma.mContainerItem = ItemList.Cell_Empty.get(1L);
+ OrePrefixes.cellMolten.mContainerItem = ItemList.Cell_Empty.get(1L);
+ OrePrefixes.cell.mContainerItem = ItemList.Cell_Empty.get(1L);
+
+ GT_ModHandler.sNonReplaceableItems.add(new ItemStack(Items.bow, 1, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(new ItemStack(Items.fishing_rod, 1, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(ItemList.IC2_ForgeHammer.getWithDamage(1L, 32767L));
+ GT_ModHandler.sNonReplaceableItems.add(ItemList.IC2_WireCutter.getWithDamage(1L, 32767L));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getIC2Item("painter", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getIC2Item("blackPainter", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getIC2Item("redPainter", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getIC2Item("greenPainter", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getIC2Item("brownPainter", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getIC2Item("bluePainter", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getIC2Item("purplePainter", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getIC2Item("cyanPainter", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getIC2Item("lightGreyPainter", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getIC2Item("darkGreyPainter", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getIC2Item("pinkPainter", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getIC2Item("limePainter", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getIC2Item("yellowPainter", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getIC2Item("cloudPainter", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getIC2Item("magentaPainter", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getIC2Item("orangePainter", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getIC2Item("whitePainter", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getIC2Item("cfPack", 1L, 32767));
+ // GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getIC2Item("jetpack", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getIC2Item("treetap", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getIC2Item("weedEx", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getIC2Item("staticBoots", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getIC2Item("compositeArmor", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getIC2Item("hazmatHelmet", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getIC2Item("hazmatChestplate", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getIC2Item("hazmatLeggings", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getIC2Item("hazmatBoots", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getModItem(Railcraft.ID, "part.turbine.disk", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getModItem(Railcraft.ID, "part.turbine.blade", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getModItem(Railcraft.ID, "part.turbine.rotor", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getModItem(Railcraft.ID, "borehead.diamond", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getModItem(Railcraft.ID, "borehead.steel", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getModItem(Railcraft.ID, "borehead.iron", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems
+ .add(GT_ModHandler.getModItem(TwilightForest.ID, "item.plateNaga", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getModItem(TwilightForest.ID, "item.legsNaga", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems
+ .add(GT_ModHandler.getModItem(TwilightForest.ID, "item.arcticHelm", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems
+ .add(GT_ModHandler.getModItem(TwilightForest.ID, "item.arcticPlate", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems
+ .add(GT_ModHandler.getModItem(TwilightForest.ID, "item.arcticLegs", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems
+ .add(GT_ModHandler.getModItem(TwilightForest.ID, "item.arcticBoots", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getModItem(TwilightForest.ID, "item.yetiHelm", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems
+ .add(GT_ModHandler.getModItem(TwilightForest.ID, "item.yetiPlate", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getModItem(TwilightForest.ID, "item.yetiLegs", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems
+ .add(GT_ModHandler.getModItem(TwilightForest.ID, "item.yetiBoots", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems
+ .add(GT_ModHandler.getModItem(AppliedEnergistics2.ID, "item.ToolCertusQuartzCuttingKnife", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems
+ .add(GT_ModHandler.getModItem(AppliedEnergistics2.ID, "item.ToolNetherQuartzCuttingKnife", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getModItem(Forestry.ID, "apiaristHelmet", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getModItem(Forestry.ID, "apiaristChest", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getModItem(Forestry.ID, "apiaristLegs", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getModItem(Forestry.ID, "apiaristBoots", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getModItem(Forestry.ID, "frameUntreated", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getModItem(Forestry.ID, "frameImpregnated", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getModItem(Forestry.ID, "frameProven", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems.add(GT_ModHandler.getModItem(Forestry.ID, "waxCast", 1L, 32767));
+ GT_ModHandler.sNonReplaceableItems
+ .add(GT_ModHandler.getModItem(GalacticraftCore.ID, "item.sensorGlasses", 1L, 32767));
+
+ RecipeSorter.register(
+ "gregtech:shaped",
+ GT_Shaped_Recipe.class,
+ RecipeSorter.Category.SHAPED,
+ "after:minecraft:shaped before:minecraft:shapeless");
+ RecipeSorter.register(
+ "gregtech:shapeless",
+ GT_Shapeless_Recipe.class,
+ RecipeSorter.Category.SHAPELESS,
+ "after:minecraft:shapeless");
+
+ // Register chunk manager with Forge
+ GT_ChunkManager.init();
+ }
+
+ public void onLoad() {
+ GT_Log.out.println("GT_Mod: Beginning Load-Phase.");
+ GT_Log.ore.println("GT_Mod: Beginning Load-Phase.");
+ if (MagicalCrops.isModLoaded()) {
+ GT_OreDictUnificator.registerOre(
+ "cropChilipepper",
+ GT_ModHandler.getModItem(MagicalCrops.ID, "magicalcrops_CropProduce", 1L, 2));
+ GT_OreDictUnificator.registerOre(
+ "cropTomato",
+ GT_ModHandler.getModItem(MagicalCrops.ID, "magicalcrops_CropProduce", 1L, 8));
+ GT_OreDictUnificator
+ .registerOre("cropGrape", GT_ModHandler.getModItem(MagicalCrops.ID, "magicalcrops_CropProduce", 1L, 4));
+ }
+ if (GanysSurface.isModLoaded()) {
+ GT_OreDictUnificator.registerOre("cropTea", GT_ModHandler.getModItem(GanysSurface.ID, "teaLeaves", 1L, 0));
+ }
+
+ // Clay buckets, which don't get registered until Iguana Tweaks pre-init
+ if (IguanaTweaksTinkerConstruct.isModLoaded()) {
+ OrePrefixes.bucketClay.mContainerItem = GT_ModHandler
+ .getModItem(IguanaTweaksTinkerConstruct.ID, "clayBucketFired", 1L, 0);
+ GT_OreDictUnificator.set(
+ OrePrefixes.bucketClay,
+ Materials.Empty,
+ GT_ModHandler.getModItem(IguanaTweaksTinkerConstruct.ID, "clayBucketFired", 1L, 0));
+ GT_OreDictUnificator.set(
+ OrePrefixes.bucketClay,
+ Materials.Water,
+ GT_ModHandler.getModItem(IguanaTweaksTinkerConstruct.ID, "clayBucketWater", 1L, 0));
+ GT_OreDictUnificator.set(
+ OrePrefixes.bucketClay,
+ Materials.Lava,
+ GT_ModHandler.getModItem(IguanaTweaksTinkerConstruct.ID, "clayBucketLava", 1L, 0));
+ GT_OreDictUnificator.set(
+ OrePrefixes.bucketClay,
+ Materials.Milk,
+ GT_ModHandler.getModItem(IguanaTweaksTinkerConstruct.ID, "clayBucketMilk", 1L, 0));
+
+ FluidContainerRegistry.registerFluidContainer(
+ new FluidContainerRegistry.FluidContainerData(
+ Materials.Milk.getFluid(1000L),
+ GT_OreDictUnificator.get(OrePrefixes.bucketClay, Materials.Milk, 1L),
+ GT_OreDictUnificator.get(OrePrefixes.bucketClay, Materials.Empty, 1L)));
+ }
+
+ if (!GT_Mod.gregtechproxy.enableUndergroundGravelGen)
+ PREVENTED_ORES.add(OreGenEvent.GenerateMinable.EventType.GRAVEL);
+ if (!GT_Mod.gregtechproxy.enableUndergroundDirtGen)
+ PREVENTED_ORES.add(OreGenEvent.GenerateMinable.EventType.DIRT);
+
+ MinecraftForge.EVENT_BUS.register(new SpaceProjectWorldSavedData());
+ MinecraftForge.EVENT_BUS.register(new GlobalEnergyWorldSavedData(""));
+ MinecraftForge.EVENT_BUS.register(new GT_Worldgenerator.OregenPatternSavedData(""));
+ MinecraftForge.EVENT_BUS.register(new GlobalMetricsCoverDatabase());
+ FMLCommonHandler.instance()
+ .bus()
+ .register(new GT_Worldgenerator.OregenPatternSavedData(""));
+
+ // IC2 Hazmat
+ addFullHazmatToIC2Item("hazmatHelmet");
+ addFullHazmatToIC2Item("hazmatChestplate");
+ addFullHazmatToIC2Item("hazmatLeggings");
+ addFullHazmatToIC2Item("hazmatBoots");
+ addFullHazmatToIC2Item("nanoHelmet");
+ addFullHazmatToIC2Item("nanoBoots");
+ addFullHazmatToIC2Item("nanoLeggings");
+ addFullHazmatToIC2Item("nanoBodyarmor");
+ addFullHazmatToIC2Item("quantumHelmet");
+ addFullHazmatToIC2Item("quantumBodyarmor");
+ addFullHazmatToIC2Item("quantumLeggings");
+ addFullHazmatToIC2Item("quantumBoots");
+
+ // GT++ Hazmat
+ addFullHazmatToGeneralItem(GTPlusPlus.ID, "itemArmorHazmatHelmetEx", 1);
+ addFullHazmatToGeneralItem(GTPlusPlus.ID, "itemArmorHazmatChestplateEx", 1);
+ addFullHazmatToGeneralItem(GTPlusPlus.ID, "itemArmorHazmatLeggingsEx", 1);
+ addFullHazmatToGeneralItem(GTPlusPlus.ID, "itemArmorRubBootsEx", 1);
+
+ // GraviSuite Hazmat
+ addFullHazmatToGeneralItem(GraviSuite.ID, "graviChestPlate", 1L);
+ addFullHazmatToGeneralItem(GraviSuite.ID, "advNanoChestPlate", 1L);
+
+ // EMT Hazmat
+ addFullHazmatToGeneralItem(ElectroMagicTools.ID, "itemArmorQuantumChestplate", 1L);
+ addFullHazmatToGeneralItem(ElectroMagicTools.ID, "NanoBootsTraveller", 1L);
+ addFullHazmatToGeneralItem(ElectroMagicTools.ID, "NanosuitGogglesRevealing", 1L);
+ addFullHazmatToGeneralItem(ElectroMagicTools.ID, "QuantumBootsTraveller", 1L);
+ addFullHazmatToGeneralItem(ElectroMagicTools.ID, "QuantumGogglesRevealing", 1L);
+ addFullHazmatToGeneralItem(ElectroMagicTools.ID, "SolarHelmetRevealing", 1L);
+ addFullHazmatToGeneralItem(ElectroMagicTools.ID, "NanosuitWing", 1L);
+ addFullHazmatToGeneralItem(ElectroMagicTools.ID, "QuantumWing", 1L);
+
+ // Thaumic Boots Hazmat
+ addFullHazmatToGeneralItem(ThaumicBoots.ID, "item.ItemQuantumVoid", 1L);
+ addFullHazmatToGeneralItem(ThaumicBoots.ID, "item.ItemQuantumMeteor", 1L);
+ addFullHazmatToGeneralItem(ThaumicBoots.ID, "item.ItemQuantumComet", 1L);
+ addFullHazmatToGeneralItem(ThaumicBoots.ID, "item.ItemNanoVoid", 1L);
+ addFullHazmatToGeneralItem(ThaumicBoots.ID, "item.ItemNanoMeteor", 1L);
+ addFullHazmatToGeneralItem(ThaumicBoots.ID, "item.ItemNanoComet", 1L);
+ addFullHazmatToGeneralItem(ThaumicBoots.ID, "item.ItemElectricVoid", 1L);
+ addFullHazmatToGeneralItem(ThaumicBoots.ID, "item.ItemVoidMeteor", 1L);
+ addFullHazmatToGeneralItem(ThaumicBoots.ID, "item.ItemVoidComet", 1L);
+
+ // DraconicEvolution Hazmat
+ addFullHazmatToGeneralItem(DraconicEvolution.ID, "draconicBoots", 1L, 0);
+ addFullHazmatToGeneralItem(DraconicEvolution.ID, "draconicHelm", 1L, 0);
+ addFullHazmatToGeneralItem(DraconicEvolution.ID, "draconicLeggs", 1L, 0);
+ addFullHazmatToGeneralItem(DraconicEvolution.ID, "draconicChest", 1L, 0);
+ addFullHazmatToGeneralItem(DraconicEvolution.ID, "wyvernBoots", 1L, 0);
+ addFullHazmatToGeneralItem(DraconicEvolution.ID, "wyvernHelm", 1L, 0);
+ addFullHazmatToGeneralItem(DraconicEvolution.ID, "wyvernLeggs", 1L, 0);
+ addFullHazmatToGeneralItem(DraconicEvolution.ID, "wyvernChest", 1L, 0);
+
+ // AdvancedSolarPanel
+ addFullHazmatToGeneralItem(AdvancedSolarPanel.ID, "advanced_solar_helmet", 1L);
+ addFullHazmatToGeneralItem(AdvancedSolarPanel.ID, "hybrid_solar_helmet", 1L);
+ addFullHazmatToGeneralItem(AdvancedSolarPanel.ID, "ultimate_solar_helmet", 1L);
+
+ // TaintedMagic Hazmat
+ addFullHazmatToGeneralItem(TaintedMagic.ID, "ItemVoidwalkerBoots", 1L);
+ addFullHazmatToGeneralItem(TaintedMagic.ID, "ItemShadowFortressHelmet", 1L);
+ addFullHazmatToGeneralItem(TaintedMagic.ID, "ItemShadowFortressChestplate", 1L);
+ addFullHazmatToGeneralItem(TaintedMagic.ID, "ItemShadowFortressLeggings", 1L);
+ addFullHazmatToGeneralItem(TaintedMagic.ID, "ItemVoidFortressHelmet", 1L);
+ addFullHazmatToGeneralItem(TaintedMagic.ID, "ItemVoidFortressChestplate", 1L);
+ addFullHazmatToGeneralItem(TaintedMagic.ID, "ItemVoidFortressLeggings", 1L);
+ addFullHazmatToGeneralItem(TaintedMagic.ID, "ItemVoidmetalGoggles", 1L);
+
+ // WitchingGadgets Hazmat
+ addFullHazmatToGeneralItem(WitchingGadgets.ID, "item.WG_PrimordialHelm", 1L);
+ addFullHazmatToGeneralItem(WitchingGadgets.ID, "item.WG_PrimordialChest", 1L);
+ addFullHazmatToGeneralItem(WitchingGadgets.ID, "item.WG_PrimordialLegs", 1L);
+ addFullHazmatToGeneralItem(WitchingGadgets.ID, "item.WG_PrimordialBoots", 1L);
+
+ // ThaumicTinkerer Hazmat
+ addFullHazmatToGeneralItem(ThaumicTinkerer.ID, "ichorclothChestGem", 1L);
+ addFullHazmatToGeneralItem(ThaumicTinkerer.ID, "ichorclothBootsGem", 1L);
+ addFullHazmatToGeneralItem(ThaumicTinkerer.ID, "ichorclothHelmGem", 1L);
+ addFullHazmatToGeneralItem(ThaumicTinkerer.ID, "ichorclothLegsGem", 1L);
+
+ // GalaxySpace Hazmat
+ addFullHazmatToGeneralItem(GalaxySpace.ID, "item.spacesuit_helmet", 1L);
+ addFullHazmatToGeneralItem(GalaxySpace.ID, "item.spacesuit_helmetglasses", 1L);
+ addFullHazmatToGeneralItem(GalaxySpace.ID, "item.spacesuit_plate", 1L);
+ addFullHazmatToGeneralItem(GalaxySpace.ID, "item.spacesuit_jetplate", 1L);
+ addFullHazmatToGeneralItem(GalaxySpace.ID, "item.spacesuit_leg", 1L);
+ addFullHazmatToGeneralItem(GalaxySpace.ID, "item.spacesuit_boots", 1L);
+ addFullHazmatToGeneralItem(GalaxySpace.ID, "item.spacesuit_gravityboots", 1L);
+
+ // Extra Hazmat
+ GregTech_API.sElectroHazmatList.add(new ItemStack(Items.chainmail_helmet, 1, W));
+ GregTech_API.sElectroHazmatList.add(new ItemStack(Items.chainmail_chestplate, 1, W));
+ GregTech_API.sElectroHazmatList.add(new ItemStack(Items.chainmail_leggings, 1, W));
+ GregTech_API.sElectroHazmatList.add(new ItemStack(Items.chainmail_boots, 1, W));
+
+ // Infinity Hazmat
+ addFullHazmatToGeneralItem(Avaritia.ID, "Infinity_Helm", 1L);
+ addFullHazmatToGeneralItem(Avaritia.ID, "Infinity_Chest", 1L);
+ addFullHazmatToGeneralItem(Avaritia.ID, "Infinity_Pants", 1L);
+ addFullHazmatToGeneralItem(Avaritia.ID, "Infinity_Shoes", 1L);
+
+ // EnderIO Hazmat
+ addFullHazmatToGeneralItem(EnderIO.ID, "item.endSteel_helmet", 1L);
+ addFullHazmatToGeneralItem(EnderIO.ID, "item.endSteel_chestplate", 1L);
+ addFullHazmatToGeneralItem(EnderIO.ID, "item.endSteel_leggings", 1L);
+ addFullHazmatToGeneralItem(EnderIO.ID, "item.endSteel_boots", 1L);
+ addFullHazmatToGeneralItem(EnderIO.ID, "item.stellar_helmet", 1L);
+ addFullHazmatToGeneralItem(EnderIO.ID, "item.stellar_chestplate", 1L);
+ addFullHazmatToGeneralItem(EnderIO.ID, "item.stellar_leggings", 1L);
+ addFullHazmatToGeneralItem(EnderIO.ID, "item.stellar_boots", 1L);
+
+ GregTech_API.sLoadStarted = true;
+ for (FluidContainerRegistry.FluidContainerData tData : FluidContainerRegistry
+ .getRegisteredFluidContainerData()) {
+ if ((tData.filledContainer.getItem() == Items.potionitem) && (tData.filledContainer.getItemDamage() == 0)) {
+ tData.fluid.amount = 0;
+ break;
+ }
+ }
+ GT_LanguageManager.writePlaceholderStrings();
+ }
+
+ public static long tBits = GT_ModHandler.RecipeBits.DO_NOT_CHECK_FOR_COLLISIONS | GT_ModHandler.RecipeBits.BUFFERED
+ | GT_ModHandler.RecipeBits.ONLY_ADD_IF_RESULT_IS_NOT_NULL
+ | GT_ModHandler.RecipeBits.NOT_REMOVABLE;
+
+ public void onPostLoad() {
+ GT_Log.out.println("GT_Mod: Beginning PostLoad-Phase.");
+ GT_Log.ore.println("GT_Mod: Beginning PostLoad-Phase.");
+ if (GT_Log.pal != null) {
+ final Thread playerActivityLogger = new Thread(new GT_PlayerActivityLogger());
+ playerActivityLogger.setDaemon(true);
+ playerActivityLogger.setName("GT5U Player activity logger");
+ playerActivityLogger.start();
+ }
+ GregTech_API.sPostloadStarted = true;
+
+ // This needs to happen late enough that all of the fluids we need have been registered.
+ // onLoad() seems to be too early, as the New Horizons Core Mod registers some fluids in post-load.
+ GT_MetaGenerated_Item_98.init();
+
+ GT_OreDictUnificator.addItemData(new ItemStack(Items.iron_door, 1), new ItemData(Materials.Iron, 21772800L));
+ GT_OreDictUnificator
+ .addItemData(new ItemStack(Items.wooden_door, 1, 32767), new ItemData(Materials.Wood, 21772800L));
+ for (FluidContainerRegistry.FluidContainerData tData : FluidContainerRegistry
+ .getRegisteredFluidContainerData()) {
+ if ((tData.filledContainer.getItem() == Items.potionitem) && (tData.filledContainer.getItemDamage() == 0)) {
+ tData.fluid.amount = 0;
+ break;
+ }
+ }
+ GT_Log.out.println("GT_Mod: Adding Configs specific for MetaTileEntities");
+ try {
+ for (int i = 1; i < GregTech_API.METATILEENTITIES.length; i++) {
+ for (; i < GregTech_API.METATILEENTITIES.length; i++) {
+ if (GregTech_API.METATILEENTITIES[i] != null) {
+ GregTech_API.METATILEENTITIES[i].onConfigLoad(GregTech_API.sMachineFile);
+ }
+ }
+ }
+ } catch (Throwable e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ GT_Log.out.println("GT_Mod: Adding Tool Usage Crafting Recipes for OreDict Items.");
+ for (Materials aMaterial : Materials.values()) {
+ if ((aMaterial.mUnificatable) && (aMaterial.mMaterialInto == aMaterial)) {
+ GT_ModHandler.addCraftingRecipe(
+ GT_OreDictUnificator.get(OrePrefixes.dust, aMaterial.mMacerateInto, 1L),
+ tBits,
+ new Object[] { "h", "X", 'X', OrePrefixes.crushedCentrifuged.get(aMaterial) });
+ GT_ModHandler.addCraftingRecipe(
+ GT_OreDictUnificator.get(OrePrefixes.dust, aMaterial.mMacerateInto, 1L),
+ tBits,
+ new Object[] { "h", "X", 'X', OrePrefixes.crystalline.get(aMaterial) });
+ GT_ModHandler.addCraftingRecipe(
+ GT_OreDictUnificator.get(OrePrefixes.dust, aMaterial.mMacerateInto, 1L),
+ tBits,
+ new Object[] { "h", "X", 'X', OrePrefixes.crystal.get(aMaterial) });
+ GT_ModHandler.addCraftingRecipe(
+ GT_OreDictUnificator.get(OrePrefixes.dustPure, aMaterial.mMacerateInto, 1L),
+ tBits,
+ new Object[] { "h", "X", 'X', OrePrefixes.crushedPurified.get(aMaterial) });
+ GT_ModHandler.addCraftingRecipe(
+ GT_OreDictUnificator.get(OrePrefixes.dustPure, aMaterial.mMacerateInto, 1L),
+ tBits,
+ new Object[] { "h", "X", 'X', OrePrefixes.cleanGravel.get(aMaterial) });
+ GT_ModHandler.addCraftingRecipe(
+ GT_OreDictUnificator.get(OrePrefixes.dustPure, aMaterial.mMacerateInto, 1L),
+ tBits,
+ new Object[] { "h", "X", 'X', OrePrefixes.reduced.get(aMaterial) });
+ GT_ModHandler.addCraftingRecipe(
+ GT_OreDictUnificator.get(OrePrefixes.dustImpure, aMaterial.mMacerateInto, 1L),
+ tBits,
+ new Object[] { "h", "X", 'X', OrePrefixes.clump.get(aMaterial) });
+ GT_ModHandler.addCraftingRecipe(
+ GT_OreDictUnificator.get(OrePrefixes.dustImpure, aMaterial.mMacerateInto, 1L),
+ tBits,
+ new Object[] { "h", "X", 'X', OrePrefixes.shard.get(aMaterial) });
+ GT_ModHandler.addCraftingRecipe(
+ GT_OreDictUnificator.get(OrePrefixes.dustImpure, aMaterial.mMacerateInto, 1L),
+ tBits,
+ new Object[] { "h", "X", 'X', OrePrefixes.crushed.get(aMaterial) });
+ GT_ModHandler.addCraftingRecipe(
+ GT_OreDictUnificator.get(OrePrefixes.dustImpure, aMaterial.mMacerateInto, 1L),
+ tBits,
+ new Object[] { "h", "X", 'X', OrePrefixes.dirtyGravel.get(aMaterial) });
+ GT_ModHandler.addCraftingRecipe(
+ GT_OreDictUnificator.get(OrePrefixes.dustSmall, aMaterial, 4L),
+ tBits,
+ new Object[] { " X ", 'X', OrePrefixes.dust.get(aMaterial) });
+ GT_ModHandler.addCraftingRecipe(
+ GT_OreDictUnificator.get(OrePrefixes.dustTiny, aMaterial, 9L),
+ tBits,
+ new Object[] { "X ", 'X', OrePrefixes.dust.get(aMaterial) });
+ GT_ModHandler.addCraftingRecipe(
+ GT_OreDictUnificator.get(OrePrefixes.dust, aMaterial, 1L),
+ tBits,
+ new Object[] { "XX", "XX", 'X', OrePrefixes.dustSmall.get(aMaterial) });
+ GT_ModHandler.addCraftingRecipe(
+ GT_OreDictUnificator.get(OrePrefixes.dust, aMaterial, 1L),
+ tBits,
+ new Object[] { "XXX", "XXX", "XXX", 'X', OrePrefixes.dustTiny.get(aMaterial) });
+ }
+ }
+ }
+
+ public void onLoadComplete() {}
+
+ public void onServerAboutToStart() {
+ dimensionWisePollution.clear(); // !!! IMPORTANT for map switching...
+ GT_ChunkAssociatedData.clearAll();
+ }
+
+ public void onServerStarting() {
+ GT_Log.out.println("GT_Mod: ServerStarting-Phase started!");
+ GT_Log.ore.println("GT_Mod: ServerStarting-Phase started!");
+
+ this.mUniverse = null;
+ this.isFirstServerWorldTick = true;
+ for (FluidContainerRegistry.FluidContainerData tData : FluidContainerRegistry
+ .getRegisteredFluidContainerData()) {
+ if ((tData.filledContainer.getItem() == Items.potionitem) && (tData.filledContainer.getItemDamage() == 0)) {
+ tData.fluid.amount = 0;
+ break;
+ }
+ }
+ try {
+ for (int i = 1; i < GregTech_API.METATILEENTITIES.length; i++) {
+ for (; i < GregTech_API.METATILEENTITIES.length; i++) {
+ if (GregTech_API.METATILEENTITIES[i] != null) {
+ GregTech_API.METATILEENTITIES[i].onServerStart();
+ }
+ }
+ }
+ } catch (Throwable e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ }
+
+ public void onServerStarted() {
+ GregTech_API.sWirelessRedstone.clear();
+ GT_MetaTileEntity_DroneCentre.getCentreMap()
+ .clear();
+ GT_Log.out.println(
+ "GT_Mod: Cleaning up all OreDict Crafting Recipes, which have an empty List in them, since they are never meeting any Condition.");
+ List<IRecipe> tList = CraftingManager.getInstance()
+ .getRecipeList();
+ for (int i = 0; i < tList.size(); i++) {
+ if ((tList.get(i) instanceof ShapedOreRecipe)) {
+ for (Object tObject : ((ShapedOreRecipe) tList.get(i)).getInput()) {
+ if (((tObject instanceof List)) && (((List<?>) tObject).isEmpty())) {
+ tList.remove(i--);
+ break;
+ }
+ }
+ } else if ((tList.get(i) instanceof ShapelessOreRecipe)) {
+ for (Object tObject : ((ShapelessOreRecipe) tList.get(i)).getInput()) {
+ if (((tObject instanceof List)) && (((List<?>) tObject).isEmpty())) {
+ tList.remove(i--);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ public void onServerStopping() {
+ File tSaveDirectory = getSaveDirectory();
+ GregTech_API.sWirelessRedstone.clear();
+ if (tSaveDirectory != null) {
+ try {
+ for (int i = 1; i < GregTech_API.METATILEENTITIES.length; i++) {
+ for (; i < GregTech_API.METATILEENTITIES.length; i++) {
+ if (GregTech_API.METATILEENTITIES[i] != null) {
+ GregTech_API.METATILEENTITIES[i].onWorldSave(tSaveDirectory);
+ }
+ }
+ }
+ } catch (Throwable e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ }
+ this.mUniverse = null;
+ // GT_ChunkAssociatedData.saveAll(); todo: figure out if this is needed
+
+ }
+
+ @SubscribeEvent
+ public void onClientConnectedToServerEvent(FMLNetworkEvent.ClientConnectedToServerEvent aEvent) {}
+
+ /**
+ * Tells {@link gregtech.nei.GT_NEI_DefaultHandler} to reload recipes.
+ */
+ public void reloadNEICache() {}
+
+ /**
+ * Logging in to server or {@link #reloadNEICache} being called increases the count.
+ */
+ public int getNEIReloadCount() {
+ return 0;
+ }
+
+ @SubscribeEvent
+ public void onArrowNockEvent(ArrowNockEvent aEvent) {
+ if ((!aEvent.isCanceled()) && (GT_Utility.isStackValid(aEvent.result))
+ && (GT_Utility.getProjectile(SubTag.PROJECTILE_ARROW, aEvent.entityPlayer.inventory) != null)) {
+ aEvent.entityPlayer.setItemInUse(
+ aEvent.result,
+ aEvent.result.getItem()
+ .getMaxItemUseDuration(aEvent.result));
+ aEvent.setCanceled(true);
+ }
+ }
+
+ @SubscribeEvent
+ public void onArrowLooseEvent(ArrowLooseEvent aEvent) {
+ ItemStack aArrow = GT_Utility.getProjectile(SubTag.PROJECTILE_ARROW, aEvent.entityPlayer.inventory);
+ if ((!aEvent.isCanceled()) && (GT_Utility.isStackValid(aEvent.bow))
+ && (aArrow != null)
+ && ((aEvent.bow.getItem() instanceof ItemBow))) {
+ float tSpeed = aEvent.charge / 20.0F;
+ tSpeed = (tSpeed * tSpeed + tSpeed * 2.0F) / 3.0F;
+ if (tSpeed < 0.1D) {
+ return;
+ }
+ if (tSpeed > 1.0D) {
+ tSpeed = 1.0F;
+ }
+ EntityArrow tArrowEntity = ((IProjectileItem) aArrow.getItem()).getProjectile(
+ SubTag.PROJECTILE_ARROW,
+ aArrow,
+ aEvent.entityPlayer.worldObj,
+ aEvent.entityPlayer,
+ tSpeed * 2.0F);
+ if (tSpeed >= 1.0F) {
+ tArrowEntity.setIsCritical(true);
+ }
+ int tLevel = EnchantmentHelper.getEnchantmentLevel(Enchantment.power.effectId, aEvent.bow);
+ if (tLevel > 0) {
+ tArrowEntity.setDamage(tArrowEntity.getDamage() + tLevel * 0.5D + 0.5D);
+ }
+ tLevel = EnchantmentHelper.getEnchantmentLevel(Enchantment.punch.effectId, aEvent.bow);
+ if (tLevel > 0) {
+ tArrowEntity.setKnockbackStrength(tLevel);
+ }
+ tLevel = EnchantmentHelper.getEnchantmentLevel(Enchantment.flame.effectId, aEvent.bow);
+ if (tLevel > 0) {
+ tArrowEntity.setFire(tLevel * 100);
+ }
+ aEvent.bow.damageItem(1, aEvent.entityPlayer);
+ aEvent.bow.getItem();
+
+ new WorldSpawnedEventBuilder.SoundAtEntityEventBuilder().setPitch(0.64893958288F + tSpeed * 0.5F)
+ .setVolume(1f)
+ .setIdentifier(SoundResource.RANDOM_BOW)
+ .setEntity(aEvent.entityPlayer)
+ .setWorld(aEvent.entityPlayer.worldObj)
+ .run();
+
+ tArrowEntity.canBePickedUp = 1;
+ if (!aEvent.entityPlayer.capabilities.isCreativeMode) {
+ aArrow.stackSize -= 1;
+ }
+ if (aArrow.stackSize == 0) {
+ GT_Utility.removeNullStacksFromInventory(aEvent.entityPlayer.inventory);
+ }
+ if (!aEvent.entityPlayer.worldObj.isRemote) {
+ aEvent.entityPlayer.worldObj.spawnEntityInWorld(tArrowEntity);
+ }
+ aEvent.setCanceled(true);
+ }
+ }
+
+ @SubscribeEvent
+ public void onEndermanTeleportEvent(EnderTeleportEvent aEvent) {
+ if (((aEvent.entityLiving instanceof EntityEnderman))
+ && (aEvent.entityLiving.getActivePotionEffect(Potion.weakness) != null)) {
+ aEvent.setCanceled(true);
+ }
+ }
+
+ @SubscribeEvent
+ public void onEntitySpawningEvent(EntityJoinWorldEvent aEvent) {
+ if ((aEvent.entity != null) && (!aEvent.entity.worldObj.isRemote)) {
+ if ((aEvent.entity instanceof EntityItem)) {
+ ((EntityItem) aEvent.entity).setEntityItemStack(
+ GT_OreDictUnificator.get(true, ((EntityItem) aEvent.entity).getEntityItem(), true));
+ }
+ if ((this.mSkeletonsShootGTArrows > 0) && (aEvent.entity.getClass() == EntityArrow.class)
+ && (aEvent.entity.worldObj.rand.nextInt(this.mSkeletonsShootGTArrows) == 0)
+ && ((((EntityArrow) aEvent.entity).shootingEntity instanceof EntitySkeleton))) {
+ aEvent.entity.worldObj.spawnEntityInWorld(
+ new GT_Entity_Arrow(
+ (EntityArrow) aEvent.entity,
+ OrePrefixes.arrowGtWood.mPrefixedItems
+ .get(aEvent.entity.worldObj.rand.nextInt(OrePrefixes.arrowGtWood.mPrefixedItems.size()))));
+ aEvent.entity.setDead();
+ }
+ }
+ }
+
+ @SubscribeEvent
+ public void onOreGenEvent(OreGenEvent.GenerateMinable aGenerator) {
+ if ((this.mDisableVanillaOres) && ((aGenerator.generator instanceof WorldGenMinable))
+ && (PREVENTED_ORES.contains(aGenerator.type))) {
+ aGenerator.setResult(Result.DENY);
+ }
+ }
+
+ private String getDataAndTime() {
+ return this.mDateFormat.format(new Date());
+ }
+
+ @SubscribeEvent
+ public void onPlayerInteraction(PlayerInteractEvent aEvent) {
+ if ((aEvent.entityPlayer == null) || (aEvent.entityPlayer.worldObj == null)
+ || (aEvent.action == null)
+ || (aEvent.world.provider == null)) {
+ return;
+ }
+ if ((!aEvent.entityPlayer.worldObj.isRemote) && (aEvent.action != PlayerInteractEvent.Action.RIGHT_CLICK_AIR)
+ && (GT_Log.pal != null)) {
+ this.mBufferedPlayerActivity.offer(
+ getDataAndTime() + ";"
+ + aEvent.action.name()
+ + ";"
+ + aEvent.entityPlayer.getDisplayName()
+ + ";DIM:"
+ + aEvent.world.provider.dimensionId
+ + ";"
+ + aEvent.x
+ + ";"
+ + aEvent.y
+ + ";"
+ + aEvent.z
+ + ";|;"
+ + aEvent.x / 10
+ + ";"
+ + aEvent.y / 10
+ + ";"
+ + aEvent.z / 10);
+ }
+ ItemStack aStack = aEvent.entityPlayer.getCurrentEquippedItem();
+ if ((aStack != null) && (aEvent.action == PlayerInteractEvent.Action.RIGHT_CLICK_BLOCK)
+ && (aStack.getItem() == Items.flint_and_steel)) {
+ if ((!aEvent.world.isRemote) && (!aEvent.entityPlayer.capabilities.isCreativeMode)
+ && (aEvent.world.rand.nextInt(100) >= this.mFlintChance)) {
+ aEvent.setCanceled(true);
+ aStack.damageItem(1, aEvent.entityPlayer);
+ if (aStack.getItemDamage() >= aStack.getMaxDamage()) {
+ aStack.stackSize -= 1;
+ }
+ if (aStack.stackSize <= 0) {
+ ForgeEventFactory.onPlayerDestroyItem(aEvent.entityPlayer, aStack);
+ }
+ }
+ }
+ }
+
+ @SubscribeEvent
+ public void onBlockBreakingEvent(BlockEvent.BreakEvent event) {
+ EntityPlayer player = event.getPlayer();
+ if (player == null) return;
+
+ ItemStack item = event.getPlayer()
+ .getCurrentEquippedItem();
+ if (item == null) return;
+
+ if (!(item.getItem() instanceof GT_MetaGenerated_Tool tool)) return;
+
+ IToolStats stats = tool.getToolStats(item);
+ if (stats == null) return;
+
+ TileEntity tile = event.world.getTileEntity(event.x, event.y, event.z);
+ stats.onBreakBlock(player, event.x, event.y, event.z, event.block, (byte) event.blockMetadata, tile, event);
+ }
+
+ @SubscribeEvent
+ public void onBlockHarvestingEvent(BlockEvent.HarvestDropsEvent aEvent) {
+ if (aEvent.harvester == null) return;
+
+ if ((!aEvent.world.isRemote) && (GT_Log.pal != null)) {
+ this.mBufferedPlayerActivity.offer(
+ getDataAndTime() + ";HARVEST_BLOCK;"
+ + aEvent.harvester.getDisplayName()
+ + ";DIM:"
+ + aEvent.world.provider.dimensionId
+ + ";"
+ + aEvent.x
+ + ";"
+ + aEvent.y
+ + ";"
+ + aEvent.z
+ + ";|;"
+ + aEvent.x / 10
+ + ";"
+ + aEvent.y / 10
+ + ";"
+ + aEvent.z / 10);
+ }
+
+ ItemStack aStack = aEvent.harvester.getCurrentEquippedItem();
+ if (aStack == null) return;
+
+ if ((aStack.getItem() instanceof GT_MetaGenerated_Tool tool)) {
+ tool.onHarvestBlockEvent(
+ aEvent.drops,
+ aStack,
+ aEvent.harvester,
+ aEvent.block,
+ aEvent.x,
+ aEvent.y,
+ aEvent.z,
+ (byte) aEvent.blockMetadata,
+ aEvent.fortuneLevel,
+ aEvent.isSilkTouching,
+ aEvent);
+ }
+ if (EnchantmentHelper.getEnchantmentLevel(Enchantment.fireAspect.effectId, aStack) > 2) {
+ try {
+ for (ItemStack tDrop : aEvent.drops) {
+ ItemStack tSmeltingOutput = GT_ModHandler.getSmeltingOutput(tDrop, false, null);
+ if (tSmeltingOutput != null) {
+ tDrop.stackSize *= tSmeltingOutput.stackSize;
+ tSmeltingOutput.stackSize = tDrop.stackSize;
+ GT_Utility.setStack(tDrop, tSmeltingOutput);
+ }
+ }
+ } catch (Throwable e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ }
+
+ }
+
+ @SubscribeEvent
+ public void registerOre(OreDictionary.OreRegisterEvent aEvent) {
+ ModContainer tContainer = Loader.instance()
+ .activeModContainer();
+ String aMod = tContainer == null ? "UNKNOWN" : tContainer.getModId();
+ String aOriginalMod = aMod;
+ if (GT_OreDictUnificator.isRegisteringOres()) {
+ aMod = GregTech.ID;
+ } else if (aMod.equals(GregTech.ID)) {
+ aMod = "UNKNOWN";
+ }
+ if ((aEvent == null) || (aEvent.Ore == null)
+ || (aEvent.Ore.getItem() == null)
+ || (aEvent.Name == null)
+ || (aEvent.Name.isEmpty())
+ || (aEvent.Name.replaceAll("_", "")
+ .length() - aEvent.Name.length() == 9)) {
+ if (aOriginalMod.equals(GregTech.ID)) {
+ aOriginalMod = "UNKNOWN";
+ }
+ GT_Log.ore.println(
+ aOriginalMod
+ + " did something very bad! The registration is too invalid to even be shown properly. This happens only if you register null, invalid Items, empty Strings or even nonexisting Events to the OreDict.");
+ throw new IllegalArgumentException(
+ aOriginalMod
+ + " did something very bad! The registration is too invalid to even be shown properly. This happens only if you register null, invalid Items, empty Strings or even nonexisting Events to the OreDict.");
+ }
+ try {
+ aEvent.Ore.stackSize = 1;
+ if (this.mIgnoreTcon || aEvent.Ore.getUnlocalizedName()
+ .startsWith("item.oreberry")) {
+ if ((aOriginalMod.toLowerCase(Locale.ENGLISH)
+ .contains("xycraft"))
+ || (aOriginalMod.toLowerCase(Locale.ENGLISH)
+ .contains("tconstruct"))
+ || ((aOriginalMod.toLowerCase(Locale.ENGLISH)
+ .contains("natura"))
+ && (!aOriginalMod.toLowerCase(Locale.ENGLISH)
+ .contains("natural")))) {
+ if (GT_Values.D1) {
+ GT_Log.ore.println(aMod + " -> " + aEvent.Name + " is getting ignored, because of racism. :P");
+ }
+ return;
+ }
+ }
+ String tModToName = aMod + " -> " + aEvent.Name;
+ if ((this.mOreDictActivated) || (GregTech_API.sPostloadStarted)
+ || ((this.mSortToTheEnd) && (GregTech_API.sLoadFinished))) {
+ tModToName = aOriginalMod + " --Late--> " + aEvent.Name;
+ }
+ if (((aEvent.Ore.getItem() instanceof ItemBlock))
+ || (GT_Utility.getBlockFromStack(aEvent.Ore) != Blocks.air)) {
+ GT_OreDictUnificator.addToBlacklist(aEvent.Ore);
+ }
+ this.mRegisteredOres.add(aEvent.Ore);
+ if (this.mIgnoredItems.contains(aEvent.Name)) {
+ if ((aEvent.Name.startsWith("item"))) {
+ GT_Log.ore.println(tModToName);
+ if (aEvent.Name.equals("itemCopperWire")) {
+ GT_OreDictUnificator.registerOre(OreDictNames.craftingWireCopper, aEvent.Ore);
+ }
+ if (aEvent.Name.equals("itemRubber")) {
+ GT_OreDictUnificator.registerOre(OrePrefixes.ingot, Materials.Rubber, aEvent.Ore);
+ }
+ return;
+ }
+ } else if (this.mIgnoredNames.contains(aEvent.Name)) {
+ GT_Log.ore.println(tModToName + " is getting ignored via hardcode.");
+ return;
+ } else if (aEvent.Name.equals("stone")) {
+ GT_OreDictUnificator.registerOre("stoneSmooth", aEvent.Ore);
+ return;
+ } else if (aEvent.Name.equals("cobblestone")) {
+ GT_OreDictUnificator.registerOre("stoneCobble", aEvent.Ore);
+ return;
+ } else if ((aEvent.Name.contains("|")) || (aEvent.Name.contains("*"))
+ || (aEvent.Name.contains(":"))
+ || (aEvent.Name.contains("."))
+ || (aEvent.Name.contains("$"))) {
+ GT_Log.ore
+ .println(tModToName + " is using a private Prefix and is therefor getting ignored properly.");
+ return;
+ } else if (aEvent.Name.equals("copperWire")) {
+ GT_OreDictUnificator.registerOre(OreDictNames.craftingWireCopper, aEvent.Ore);
+ } else if (aEvent.Name.equals("oreHeeEndrium")) {
+ GT_OreDictUnificator.registerOre(OrePrefixes.ore, Materials.HeeEndium, aEvent.Ore);
+ } else if (aEvent.Name.equals("sheetPlastic")) {
+ GT_OreDictUnificator.registerOre(OrePrefixes.plate, Materials.Plastic, aEvent.Ore);
+ } else if (aEvent.Name.startsWith("shard")) {
+ switch (aEvent.Name) {
+ case "shardAir" -> {
+ GT_OreDictUnificator.registerOre(OrePrefixes.gem, Materials.InfusedAir, aEvent.Ore);
+ return;
+ }
+ case "shardWater" -> {
+ GT_OreDictUnificator.registerOre(OrePrefixes.gem, Materials.InfusedWater, aEvent.Ore);
+ return;
+ }
+ case "shardFire" -> {
+ GT_OreDictUnificator.registerOre(OrePrefixes.gem, Materials.InfusedFire, aEvent.Ore);
+ return;
+ }
+ case "shardEarth" -> {
+ GT_OreDictUnificator.registerOre(OrePrefixes.gem, Materials.InfusedEarth, aEvent.Ore);
+ return;
+ }
+ case "shardOrder" -> {
+ GT_OreDictUnificator.registerOre(OrePrefixes.gem, Materials.InfusedOrder, aEvent.Ore);
+ return;
+ }
+ case "shardEntropy" -> {
+ GT_OreDictUnificator.registerOre(OrePrefixes.gem, Materials.InfusedEntropy, aEvent.Ore);
+ return;
+ }
+ }
+ } else if (aEvent.Name.equals("fieryIngot")) {
+ GT_OreDictUnificator.registerOre(OrePrefixes.ingot, Materials.FierySteel, aEvent.Ore);
+ return;
+ } else if (aEvent.Name.equals("ironwood")) {
+ GT_OreDictUnificator.registerOre(OrePrefixes.ingot, Materials.IronWood, aEvent.Ore);
+ return;
+ } else if (aEvent.Name.equals("steeleaf")) {
+ GT_OreDictUnificator.registerOre(OrePrefixes.ingot, Materials.Steeleaf, aEvent.Ore);
+ return;
+ } else if (aEvent.Name.equals("knightmetal")) {
+ GT_OreDictUnificator.registerOre(OrePrefixes.ingot, Materials.Knightmetal, aEvent.Ore);
+ return;
+ } else if (aEvent.Name.equals("compressedAluminum")) {
+ GT_OreDictUnificator.registerOre(OrePrefixes.compressed, Materials.Aluminium, aEvent.Ore);
+ return;
+ } else if (aEvent.Name.contains(" ")) {
+ GT_Log.ore.println(
+ tModToName + " is getting re-registered because the OreDict Name containing invalid spaces.");
+ GT_OreDictUnificator
+ .registerOre(aEvent.Name.replaceAll(" ", ""), GT_Utility.copyAmount(1, aEvent.Ore));
+ aEvent.Ore.setStackDisplayName("Invalid OreDictionary Tag");
+ return;
+ } else if (this.mInvalidNames.contains(aEvent.Name)) {
+ GT_Log.ore.println(tModToName + " is wrongly registered and therefor getting ignored.");
+
+ return;
+ }
+ OrePrefixes aPrefix = OrePrefixes.getOrePrefix(aEvent.Name);
+ Materials aMaterial = Materials._NULL;
+ if ((aPrefix == OrePrefixes.nugget) && (aMod.equals(Thaumcraft.ID))
+ && (aEvent.Ore.getItem()
+ .getUnlocalizedName()
+ .contains("ItemResource"))) {
+ return;
+ }
+ if (aPrefix == null) {
+ if (aEvent.Name.toLowerCase()
+ .equals(aEvent.Name)) {
+ GT_Log.ore.println(tModToName + " is invalid due to being solely lowercased.");
+ return;
+ } else if (aEvent.Name.toUpperCase()
+ .equals(aEvent.Name)) {
+ GT_Log.ore.println(tModToName + " is invalid due to being solely uppercased.");
+ return;
+ } else if (Character.isUpperCase(aEvent.Name.charAt(0))) {
+ GT_Log.ore.println(tModToName + " is invalid due to the first character being uppercased.");
+ }
+ } else {
+ if (aPrefix.mDontUnificateActively) {
+ GT_OreDictUnificator.addToBlacklist(aEvent.Ore);
+ }
+ if (aPrefix != aPrefix.mPrefixInto) {
+ String tNewName = aEvent.Name.replaceFirst(aPrefix.toString(), aPrefix.mPrefixInto.toString());
+ if (!GT_OreDictUnificator.isRegisteringOres()) {
+ GT_Log.ore.println(
+ tModToName + " uses a depricated Prefix, and is getting re-registered as " + tNewName);
+ }
+ GT_OreDictUnificator.registerOre(tNewName, aEvent.Ore);
+ return;
+ }
+ String tName = aEvent.Name.replaceFirst(aPrefix.toString(), "");
+ if (tName.length() > 0) {
+ char firstChar = tName.charAt(0);
+ if (Character.isUpperCase(firstChar) || Character.isLowerCase(firstChar)
+ || firstChar == '_'
+ || Character.isDigit(firstChar)) {
+ if (aPrefix.mIsMaterialBased) {
+ aMaterial = Materials.get(tName);
+ if (aMaterial != aMaterial.mMaterialInto) {
+ GT_OreDictUnificator.registerOre(aPrefix, aMaterial.mMaterialInto, aEvent.Ore);
+ if (!GT_OreDictUnificator.isRegisteringOres()) {
+ GT_Log.ore.println(
+ tModToName + " uses a deprecated Material and is getting re-registered as "
+ + aPrefix.get(aMaterial.mMaterialInto));
+ }
+ return;
+ }
+ if (!aPrefix.isIgnored(aMaterial)) {
+ aPrefix.add(GT_Utility.copyAmount(1, aEvent.Ore));
+ }
+ if (aMaterial != Materials._NULL) {
+ Materials tReRegisteredMaterial;
+ for (Iterator<Materials> i$ = aMaterial.mOreReRegistrations.iterator(); i$
+ .hasNext(); GT_OreDictUnificator
+ .registerOre(aPrefix, tReRegisteredMaterial, aEvent.Ore)) {
+ tReRegisteredMaterial = i$.next();
+ }
+ aMaterial.add(GT_Utility.copyAmount(1, aEvent.Ore));
+
+ if (GregTech_API.sThaumcraftCompat != null && aPrefix.doGenerateItem(aMaterial)
+ && !aPrefix.isIgnored(aMaterial)) {
+ List<TC_AspectStack> tAspects = new ArrayList<>();
+ for (TC_AspectStack tAspect : aPrefix.mAspects) tAspect.addToAspectList(tAspects);
+ if (aPrefix.mMaterialAmount >= 3628800 || aPrefix.mMaterialAmount < 0)
+ for (TC_AspectStack tAspect : aMaterial.mAspects)
+ tAspect.addToAspectList(tAspects);
+ GregTech_API.sThaumcraftCompat.registerThaumcraftAspectsToItem(
+ GT_Utility.copyAmount(1, aEvent.Ore),
+ tAspects,
+ aEvent.Name);
+ }
+
+ switch (aPrefix) {
+ case crystal -> {
+ if ((aMaterial == Materials.CertusQuartz)
+ || (aMaterial == Materials.NetherQuartz)
+ || (aMaterial == Materials.Fluix)) {
+ GT_OreDictUnificator.registerOre(OrePrefixes.gem, aMaterial, aEvent.Ore);
+ }
+ }
+ case gem -> {
+ if (aMaterial == Materials.Lapis || aMaterial == Materials.Sodalite) {
+ GT_OreDictUnificator.registerOre(Dyes.dyeBlue, aEvent.Ore);
+ } else if (aMaterial == Materials.Lazurite) {
+ GT_OreDictUnificator.registerOre(Dyes.dyeCyan, aEvent.Ore);
+ } else
+ if (aMaterial == Materials.InfusedAir || aMaterial == Materials.InfusedWater
+ || aMaterial == Materials.InfusedFire
+ || aMaterial == Materials.InfusedEarth
+ || aMaterial == Materials.InfusedOrder
+ || aMaterial == Materials.InfusedEntropy) {
+ GT_OreDictUnificator.registerOre(
+ aMaterial.mName.replaceFirst("Infused", "shard"),
+ aEvent.Ore);
+ } else if (aMaterial == Materials.Chocolate) {
+ GT_OreDictUnificator.registerOre(Dyes.dyeBrown, aEvent.Ore);
+ } else if (aMaterial == Materials.CertusQuartz
+ || aMaterial == Materials.NetherQuartz) {
+ GT_OreDictUnificator
+ .registerOre(OrePrefixes.item.get(aMaterial), aEvent.Ore);
+ GT_OreDictUnificator
+ .registerOre(OrePrefixes.crystal, aMaterial, aEvent.Ore);
+ GT_OreDictUnificator
+ .registerOre(OreDictNames.craftingQuartz, aEvent.Ore);
+ } else
+ if (aMaterial == Materials.Fluix || aMaterial == Materials.Quartz
+ || aMaterial == Materials.Quartzite) {
+ GT_OreDictUnificator.registerOre(
+ OrePrefixes.crystal,
+ aMaterial,
+ aEvent.Ore);
+ GT_OreDictUnificator
+ .registerOre(OreDictNames.craftingQuartz, aEvent.Ore);
+ }
+ }
+ case cableGt01 -> {
+ if (aMaterial == Materials.Tin) {
+ GT_OreDictUnificator.registerOre(OreDictNames.craftingWireTin, aEvent.Ore);
+ } else if (aMaterial == Materials.AnyCopper) {
+ GT_OreDictUnificator
+ .registerOre(OreDictNames.craftingWireCopper, aEvent.Ore);
+ } else if (aMaterial == Materials.Gold) {
+ GT_OreDictUnificator.registerOre(OreDictNames.craftingWireGold, aEvent.Ore);
+ } else if (aMaterial == Materials.AnyIron) {
+ GT_OreDictUnificator.registerOre(OreDictNames.craftingWireIron, aEvent.Ore);
+ }
+ }
+ case lens -> {
+ if ((aMaterial.contains(SubTag.TRANSPARENT))
+ && (aMaterial.mColor != Dyes._NULL)) {
+ GT_OreDictUnificator.registerOre(
+ "craftingLens" + aMaterial.mColor.toString()
+ .replaceFirst("dye", ""),
+ aEvent.Ore);
+ }
+ }
+ case plate -> {
+ if ((aMaterial == Materials.Plastic) || (aMaterial == Materials.Rubber)) {
+ GT_OreDictUnificator.registerOre(OrePrefixes.sheet, aMaterial, aEvent.Ore);
+ } else if (aMaterial == Materials.Silicon) {
+ GT_OreDictUnificator.registerOre(OrePrefixes.item, aMaterial, aEvent.Ore);
+ } else if (aMaterial == Materials.Wood) {
+ GT_OreDictUnificator.addToBlacklist(aEvent.Ore);
+ GT_OreDictUnificator.registerOre(OrePrefixes.plank, aMaterial, aEvent.Ore);
+ }
+ }
+ case cell -> {
+ if (aMaterial == Materials.Empty) {
+ GT_OreDictUnificator.addToBlacklist(aEvent.Ore);
+ }
+ }
+ case gearGt -> GT_OreDictUnificator
+ .registerOre(OrePrefixes.gear, aMaterial, aEvent.Ore);
+ case stick -> {
+ if (!GT_RecipeRegistrator.sRodMaterialList.contains(aMaterial)) {
+ GT_RecipeRegistrator.sRodMaterialList.add(aMaterial);
+ } else if (aMaterial == Materials.Wood) {
+ GT_OreDictUnificator.addToBlacklist(aEvent.Ore);
+ } else if ((aMaterial == Materials.Tin) || (aMaterial == Materials.Lead)
+ || (aMaterial == Materials.SolderingAlloy)) {
+ GT_OreDictUnificator
+ .registerOre(ToolDictNames.craftingToolSolderingMetal, aEvent.Ore);
+ }
+ }
+ case dust -> {
+ if (aMaterial == Materials.Salt) {
+ GT_OreDictUnificator.registerOre("itemSalt", aEvent.Ore);
+ } else if (aMaterial == Materials.Wood) {
+ GT_OreDictUnificator.registerOre("pulpWood", aEvent.Ore);
+ } else if (aMaterial == Materials.Wheat) {
+ GT_OreDictUnificator.registerOre("foodFlour", aEvent.Ore);
+ } else if (aMaterial == Materials.Lapis) {
+ GT_OreDictUnificator.registerOre(Dyes.dyeBlue, aEvent.Ore);
+ } else if (aMaterial == Materials.Lazurite) {
+ GT_OreDictUnificator.registerOre(Dyes.dyeCyan, aEvent.Ore);
+ } else if (aMaterial == Materials.Sodalite) {
+ GT_OreDictUnificator.registerOre(Dyes.dyeBlue, aEvent.Ore);
+ } else if (aMaterial == Materials.Cocoa) {
+ GT_OreDictUnificator.registerOre(Dyes.dyeBrown, aEvent.Ore);
+ GT_OreDictUnificator.registerOre("foodCocoapowder", aEvent.Ore);
+ } else if (aMaterial == Materials.Coffee) {
+ GT_OreDictUnificator.registerOre(Dyes.dyeBrown, aEvent.Ore);
+ } else if (aMaterial == Materials.BrownLimonite) {
+ GT_OreDictUnificator.registerOre(Dyes.dyeBrown, aEvent.Ore);
+ } else if (aMaterial == Materials.YellowLimonite) {
+ GT_OreDictUnificator.registerOre(Dyes.dyeYellow, aEvent.Ore);
+ }
+ }
+ case ingot -> {
+ if (aMaterial == Materials.Rubber) {
+ GT_OreDictUnificator.registerOre("itemRubber", aEvent.Ore);
+ } else if (aMaterial == Materials.FierySteel) {
+ GT_OreDictUnificator.registerOre("fieryIngot", aEvent.Ore);
+ } else if (aMaterial == Materials.IronWood) {
+ GT_OreDictUnificator.registerOre("ironwood", aEvent.Ore);
+ } else if (aMaterial == Materials.Steeleaf) {
+ GT_OreDictUnificator.registerOre("steeleaf", aEvent.Ore);
+ } else if (aMaterial == Materials.Knightmetal) {
+ GT_OreDictUnificator.registerOre("knightmetal", aEvent.Ore);
+ } else if ((aMaterial == Materials.Brass) && (aEvent.Ore.getItemDamage() == 2)
+ && (aEvent.Ore.getUnlocalizedName()
+ .equals("item.ingotBrass"))
+ && (new ItemStack(aEvent.Ore.getItem(), 1, 0).getUnlocalizedName()
+ .contains("red"))) {
+ GT_OreDictUnificator.set(
+ OrePrefixes.ingot,
+ Materials.RedAlloy,
+ new ItemStack(aEvent.Ore.getItem(), 1, 0));
+ GT_OreDictUnificator.set(
+ OrePrefixes.ingot,
+ Materials.BlueAlloy,
+ new ItemStack(aEvent.Ore.getItem(), 1, 1));
+ GT_OreDictUnificator.set(
+ OrePrefixes.ingot,
+ Materials.Brass,
+ new ItemStack(aEvent.Ore.getItem(), 1, 2));
+ if (!mDisableIC2Cables) {
+ GT_Values.RA.stdBuilder()
+ .itemInputs(GT_ModHandler.getIC2Item("copperCableItem", 3L))
+ .itemOutputs(new ItemStack(aEvent.Ore.getItem(), 1, 8))
+ .duration(20 * SECONDS)
+ .eut(1)
+ .addTo(wiremillRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(GT_ModHandler.getIC2Item("ironCableItem", 6L))
+ .itemOutputs(new ItemStack(aEvent.Ore.getItem(), 1, 9))
+ .duration(20 * SECONDS)
+ .eut(2)
+ .addTo(wiremillRecipes);
+ }
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(new ItemStack(aEvent.Ore.getItem(), 1, 3))
+ .itemOutputs(new ItemStack(aEvent.Ore.getItem(), 16, 4))
+ .duration(20 * SECONDS)
+ .eut(8)
+ .addTo(cutterRecipes);
+ }
+ }
+ default -> {}
+ }
+ if (aPrefix.mIsUnificatable && !aMaterial.mUnificatable) {
+ return;
+ }
+ } else {
+ for (Dyes tDye : Dyes.VALUES) {
+ if (aEvent.Name.endsWith(
+ tDye.name()
+ .replaceFirst("dye", ""))) {
+ GT_OreDictUnificator.addToBlacklist(aEvent.Ore);
+ GT_Log.ore.println(
+ tModToName
+ + " Oh man, why the fuck would anyone need a OreDictified Color for this, that is even too much for GregTech... do not report this, this is just a random Comment about how ridiculous this is.");
+ return;
+ }
+ }
+ // GT_FML_LOGGER.info("Material Name: "+aEvent.Name+ "
+ // !!!Unknown Material detected!!! Please report to GregTech Intergalactical for
+ // additional compatiblity. This is not an Error, an Issue nor a Lag Source, it is just
+ // an Information, which you should pass to me.");
+ // GT_Log.ore.println(tModToName + " uses an unknown
+ // Material. Report this to GregTech.");
+ return;
+ }
+ } else {
+ aPrefix.add(GT_Utility.copyAmount(1, aEvent.Ore));
+ }
+ }
+ } else if (aPrefix.mIsSelfReferencing) {
+ aPrefix.add(GT_Utility.copyAmount(1, aEvent.Ore));
+ } else {
+ GT_Log.ore.println(tModToName + " uses a Prefix as full OreDict Name, and is therefor invalid.");
+ aEvent.Ore.setStackDisplayName("Invalid OreDictionary Tag");
+ return;
+ }
+ switch (aPrefix) {
+ case dye -> {
+ if (GT_Utility.isStringValid(tName)) {
+ GT_OreDictUnificator.registerOre(OrePrefixes.dye, aEvent.Ore);
+ }
+ }
+ case stoneSmooth -> GT_OreDictUnificator.registerOre("stone", aEvent.Ore);
+ case stoneCobble -> GT_OreDictUnificator.registerOre("cobblestone", aEvent.Ore);
+ case plank -> {
+ if (tName.equals("Wood")) {
+ GT_OreDictUnificator.addItemData(aEvent.Ore, new ItemData(Materials.Wood, 3628800L));
+ }
+ }
+ case slab -> {
+ if (tName.equals("Wood")) {
+ GT_OreDictUnificator.addItemData(aEvent.Ore, new ItemData(Materials.Wood, 1814400L));
+ }
+ }
+ case sheet -> {
+ if (tName.equals("Plastic")) {
+ GT_OreDictUnificator.registerOre(OrePrefixes.plate, Materials.Plastic, aEvent.Ore);
+ } else if (tName.equals("Rubber")) {
+ GT_OreDictUnificator.registerOre(OrePrefixes.plate, Materials.Rubber, aEvent.Ore);
+ }
+ }
+ case crafting -> {
+ switch (tName) {
+ case "ToolSolderingMetal" -> GregTech_API.registerSolderingMetal(aEvent.Ore);
+ case "IndustrialDiamond" -> GT_OreDictUnificator.addToBlacklist(aEvent.Ore);
+ case "WireCopper" -> GT_OreDictUnificator
+ .registerOre(OrePrefixes.wire, Materials.Copper, aEvent.Ore);
+ }
+ }
+ case wood -> {
+ if (tName.equals("Rubber")) {
+ GT_OreDictUnificator.registerOre("logRubber", aEvent.Ore);
+ }
+ }
+ case food -> {
+ if (tName.equals("Cocoapowder")) {
+ GT_OreDictUnificator.registerOre(OrePrefixes.dust, Materials.Cocoa, aEvent.Ore);
+ }
+ }
+ default -> {}
+ }
+ }
+ GT_Log.ore.println(tModToName);
+
+ OreDictEventContainer tOre = new OreDictEventContainer(aEvent, aPrefix, aMaterial, aMod);
+ if ((!this.mOreDictActivated) || (!GregTech_API.sUnificationEntriesRegistered)) {
+ this.mEvents.add(tOre);
+ } else {
+ this.mEvents.clear();
+ }
+ if (this.mOreDictActivated) {
+ registerRecipes(tOre);
+ }
+ } catch (Throwable e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ }
+
+ @SuppressWarnings("deprecated")
+ public static void stepMaterialsVanilla(Collection<GT_Proxy.OreDictEventContainer> mEvents,
+ ProgressManager.ProgressBar progressBar) {
+ int size = 5;
+ int sizeStep = mEvents.size() / 20 - 1;
+ GT_Proxy.OreDictEventContainer tEvent;
+ for (Iterator<GT_Proxy.OreDictEventContainer> i$ = mEvents.iterator(); i$.hasNext(); GT_Proxy
+ .registerRecipes(tEvent)) {
+ tEvent = i$.next();
+ sizeStep--;
+ if (sizeStep == 0) {
+ GT_FML_LOGGER.info("Baking : " + size + "%", new Object[0]);
+ sizeStep = mEvents.size() / 20 - 1;
+ size += 5;
+ }
+ progressBar.step(tEvent.mMaterial == null ? "" : tEvent.mMaterial.toString());
+ }
+ ProgressManager.pop(progressBar);
+ }
+
+ @SubscribeEvent
+ public void onLivingUpdate(LivingUpdateEvent aEvent) {
+ if (aEvent.entityLiving.onGround) {
+ int tX = MathHelper.floor_double(aEvent.entityLiving.posX),
+ tY = MathHelper.floor_double(aEvent.entityLiving.boundingBox.minY - 0.001F),
+ tZ = MathHelper.floor_double(aEvent.entityLiving.posZ);
+ Block tBlock = aEvent.entityLiving.worldObj.getBlock(tX, tY, tZ);
+ if (tBlock instanceof IBlockOnWalkOver)
+ ((IBlockOnWalkOver) tBlock).onWalkOver(aEvent.entityLiving, aEvent.entityLiving.worldObj, tX, tY, tZ);
+ }
+ }
+
+ @SubscribeEvent
+ public void onFluidContainerRegistration(FluidContainerRegistry.FluidContainerRegisterEvent aFluidEvent) {
+ if ((aFluidEvent.data.filledContainer.getItem() == Items.potionitem)
+ && (aFluidEvent.data.filledContainer.getItemDamage() == 0)) {
+ aFluidEvent.data.fluid.amount = 0;
+ }
+ GT_OreDictUnificator.addToBlacklist(aFluidEvent.data.emptyContainer);
+ GT_OreDictUnificator.addToBlacklist(aFluidEvent.data.filledContainer);
+ GT_Utility.addFluidContainerData(aFluidEvent.data);
+ }
+
+ @SubscribeEvent
+ public void onServerTickEvent(TickEvent.ServerTickEvent aEvent) {
+ if (aEvent.side.isServer()) {
+ if (aEvent.phase == TickEvent.Phase.START) {
+ TICK_LOCK.lock();
+
+ } else {
+ TICK_LOCK.unlock();
+ }
+
+ // Making sure it is being freed up in order to prevent exploits or Garbage Collection mishaps.
+ LAST_BROKEN_TILEENTITY.set(null);
+ }
+ }
+
+ @SubscribeEvent
+ public void onWorldTickEvent(TickEvent.WorldTickEvent aEvent) {
+ if (aEvent.world.provider.dimensionId == 0) mTicksUntilNextCraftSound--;
+ if (isFirstWorldTick) {
+ for (Runnable runnable : GregTech_API.sFirstWorldTick) runnable.run();
+ isFirstWorldTick = false;
+ GT_Values.worldTickHappened = true;
+ }
+ if (aEvent.side.isServer()) {
+ if (this.mUniverse == null) {
+ this.mUniverse = aEvent.world;
+ }
+ if (this.isFirstServerWorldTick) {
+ File tSaveDiretory = getSaveDirectory();
+ if (tSaveDiretory != null) {
+ this.isFirstServerWorldTick = false;
+ try {
+ for (IMetaTileEntity tMetaTileEntity : GregTech_API.METATILEENTITIES) {
+ if (tMetaTileEntity != null) {
+ tMetaTileEntity.onWorldLoad(tSaveDiretory);
+ }
+ }
+ } catch (Throwable e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ }
+ }
+ if ((aEvent.world.getTotalWorldTime() % 100L == 0L)
+ && ((this.mItemDespawnTime != 6000) || (this.mMaxEqualEntitiesAtOneSpot > 0))) {
+ long startTime = System.nanoTime();
+ double oldX = 0, oldY = 0, oldZ = 0;
+ if (debugEntityCramming && (aEvent.world.loadedEntityList.size() != 0)) {
+ GT_Log.out.println("CRAM: Entity list size " + aEvent.world.loadedEntityList.size());
+ }
+ for (int i = 0; i < aEvent.world.loadedEntityList.size(); i++) {
+ if ((aEvent.world.loadedEntityList.get(i) instanceof Entity)) {
+ Entity tEntity = aEvent.world.loadedEntityList.get(i);
+ if (((tEntity instanceof EntityItem)) && (this.mItemDespawnTime != 6000)
+ && (((EntityItem) tEntity).lifespan == 6000)) {
+ ((EntityItem) tEntity).lifespan = this.mItemDespawnTime;
+ } else if (((tEntity instanceof EntityLivingBase)) && (this.mMaxEqualEntitiesAtOneSpot > 0)
+ && (!(tEntity instanceof EntityPlayer))
+ && (tEntity.canBePushed())
+ && (((EntityLivingBase) tEntity).getHealth() > 0.0F)) {
+ List<Entity> tList = tEntity.worldObj.getEntitiesWithinAABBExcludingEntity(
+ tEntity,
+ tEntity.boundingBox.expand(0.20000000298023224D, 0.0D, 0.20000000298023224D));
+ Class<? extends Entity> tClass = tEntity.getClass();
+ int tEntityCount = 1;
+ if (tList != null) {
+ for (Object o : tList) {
+ if ((o != null) && (o.getClass() == tClass)) {
+ tEntityCount++;
+ }
+ }
+ }
+ if (tEntityCount > this.mMaxEqualEntitiesAtOneSpot) {
+ if (debugEntityCramming) {
+ // Cheeseball way of not receiving a bunch of spam caused by 1 location
+ // obviously fails if there are crammed entities in more than one spot.
+ if (tEntity.posX != oldX && tEntity.posY != oldY && tEntity.posZ != oldZ) {
+ GT_Log.out.println(
+ "CRAM: Excess entities: " + tEntityCount
+ + " at X "
+ + tEntity.posX
+ + " Y "
+ + tEntity.posY
+ + " Z "
+ + tEntity.posZ);
+ oldX = tEntity.posX;
+ oldY = tEntity.posY;
+ oldZ = tEntity.posZ;
+ }
+ }
+ tEntity.attackEntityFrom(
+ DamageSource.inWall,
+ tEntityCount - this.mMaxEqualEntitiesAtOneSpot);
+ }
+ }
+ }
+ }
+ if (debugEntityCramming && (aEvent.world.loadedEntityList.size() != 0)) {
+ GT_Log.out.println(
+ "CRAM: Time spent checking " + (System.nanoTime() - startTime) / 1000 + " microseconds");
+ }
+ }
+
+ GT_Pollution.onWorldTick(aEvent);
+ }
+ }
+
+ @SubscribeEvent
+ public void onWorldUnload(WorldEvent.Unload event) {
+ for (TileEntity tileEntity : event.world.loadedTileEntityList) {
+ if (tileEntity instanceof IGregTechTileEntity) {
+ tileEntity.onChunkUnload();
+ }
+ }
+ }
+
+ public static void registerRecipes(GT_Proxy.OreDictEventContainer aOre) {
+ if ((aOre.mEvent.Ore == null) || (aOre.mEvent.Ore.getItem() == null)) {
+ return;
+ }
+ if (aOre.mEvent.Ore.stackSize != 1) {
+ aOre.mEvent.Ore.stackSize = 1;
+ }
+ if (aOre.mPrefix != null) {
+ if (!aOre.mPrefix.isIgnored(aOre.mMaterial)) {
+ aOre.mPrefix.processOre(
+ aOre.mMaterial == null ? Materials._NULL : aOre.mMaterial,
+ aOre.mEvent.Name,
+ aOre.mModID,
+ GT_Utility.copyAmount(1, aOre.mEvent.Ore));
+ }
+ } else {
+ // GT_FML_LOGGER.info("Thingy Name: "+ aOre.mEvent.Name+ " !!!Unknown 'Thingy' detected!!! This
+ // Object seems to probably not follow a valid OreDictionary Convention, or I missed a Convention. Please
+ // report to GregTech Intergalactical for additional compatiblity. This is not an Error, an Issue nor a Lag
+ // Source, it is just an Information, which you should pass to me.");
+ }
+ }
+
+ @SubscribeEvent
+ public void onPlayerTickEventServer(TickEvent.PlayerTickEvent aEvent) {
+ if ((aEvent.side.isServer()) && (aEvent.phase == TickEvent.Phase.END) && (!aEvent.player.isDead)) {
+ if ((aEvent.player.ticksExisted % 200 == 0) && (aEvent.player.capabilities.allowEdit)
+ && (!aEvent.player.capabilities.isCreativeMode)
+ && (this.mSurvivalIntoAdventure)) {
+ aEvent.player.setGameType(GameType.ADVENTURE);
+ aEvent.player.capabilities.allowEdit = false;
+ if (this.mAxeWhenAdventure) {
+ GT_Utility.sendChatToPlayer(
+ aEvent.player,
+ GT_LanguageManager.addStringLocalization(
+ "Interaction_DESCRIPTION_Index_097",
+ "It's dangerous to go alone! Take this."));
+ aEvent.player.worldObj.spawnEntityInWorld(
+ new EntityItem(
+ aEvent.player.worldObj,
+ aEvent.player.posX,
+ aEvent.player.posY,
+ aEvent.player.posZ,
+ GT_MetaGenerated_Tool_01.INSTANCE.getToolWithStats(
+ GT_MetaGenerated_Tool_01.AXE,
+ 1,
+ Materials.Flint,
+ Materials.Wood,
+ null)));
+ }
+ }
+ final boolean tHungerEffect = (this.mHungerEffect) && (aEvent.player.ticksExisted % 2400 == 1200);
+ if (aEvent.player.ticksExisted % 120 == 0) {
+ int tCount = 64;
+ for (int i = 0; i < 36; i++) {
+ final ItemStack tStack;
+ if ((tStack = aEvent.player.inventory.getStackInSlot(i)) != null) {
+ if (!aEvent.player.capabilities.isCreativeMode) {
+ GT_Utility.applyRadioactivity(
+ aEvent.player,
+ GT_Utility.getRadioactivityLevel(tStack),
+ tStack.stackSize);
+ final float tHeat = GT_Utility.getHeatDamageFromItem(tStack);
+ if (tHeat != 0.0F) {
+ if (tHeat > 0.0F) {
+ GT_Utility.applyHeatDamageFromItem(aEvent.player, tHeat, tStack);
+ } else {
+ GT_Utility.applyFrostDamage(aEvent.player, -tHeat);
+ }
+ }
+ }
+ if (tHungerEffect) {
+ tCount += tStack.stackSize * 64 / Math.max(1, tStack.getMaxStackSize());
+ }
+ if (this.mInventoryUnification) {
+ GT_OreDictUnificator.setStack(true, tStack);
+ }
+ }
+ }
+ for (int i = 0; i < 4; i++) {
+ final ItemStack tStack;
+ if ((tStack = aEvent.player.inventory.armorInventory[i]) != null) {
+ if (!aEvent.player.capabilities.isCreativeMode) {
+ GT_Utility.applyRadioactivity(
+ aEvent.player,
+ GT_Utility.getRadioactivityLevel(tStack),
+ tStack.stackSize);
+ final float tHeat = GT_Utility.getHeatDamageFromItem(tStack);
+ if (tHeat != 0.0F) {
+ if (tHeat > 0.0F) {
+ GT_Utility.applyHeatDamageFromItem(aEvent.player, tHeat, tStack);
+ } else {
+ GT_Utility.applyFrostDamage(aEvent.player, -tHeat);
+ }
+ }
+ }
+ if (tHungerEffect) {
+ tCount += 256;
+ }
+ }
+ }
+ if (tHungerEffect) {
+ aEvent.player.addExhaustion(Math.max(1.0F, tCount / 666.6F));
+ }
+ }
+ }
+ }
+
+ public GT_ClientPreference getClientPreference(UUID aPlayerID) {
+ return mClientPrefernces.get(aPlayerID);
+ }
+
+ public void setClientPreference(UUID aPlayerID, GT_ClientPreference aPreference) {
+ mClientPrefernces.put(aPlayerID, aPreference);
+ }
+
+ @Override
+ public Object getServerGuiElement(int aID, EntityPlayer aPlayer, World aWorld, int aX, int aY, int aZ) {
+ if (aID >= 1000) {
+ return null;
+ }
+ final TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if ((tTileEntity instanceof IGregTechTileEntity)) {
+ if (GUI_ID_COVER_SIDE_BASE <= aID && aID < GUI_ID_COVER_SIDE_BASE + 6) {
+ return null;
+ }
+ final IMetaTileEntity tMetaTileEntity = ((IGregTechTileEntity) tTileEntity).getMetaTileEntity();
+ if (tMetaTileEntity != null && !tMetaTileEntity.useModularUI()) {
+ return tMetaTileEntity.getServerGUI(aID, aPlayer.inventory, (IGregTechTileEntity) tTileEntity);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public Object getClientGuiElement(int aID, EntityPlayer aPlayer, World aWorld, int aX, int aY, int aZ) {
+ if (aID >= 1000) {
+ return null;
+ }
+ final TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if ((tTileEntity instanceof IGregTechTileEntity tile)) {
+
+ if (GUI_ID_COVER_SIDE_BASE <= aID && aID < GUI_ID_COVER_SIDE_BASE + 6) {
+ final ForgeDirection side = ForgeDirection
+ .getOrientation((byte) (aID - GT_Proxy.GUI_ID_COVER_SIDE_BASE));
+ GT_CoverBehaviorBase<?> cover = tile.getCoverBehaviorAtSideNew(side);
+
+ if (cover.hasCoverGUI() && !cover.useModularUI()) {
+ return cover.getClientGUI(
+ side,
+ tile.getCoverIDAtSide(side),
+ tile.getComplexCoverDataAtSide(side),
+ tile,
+ aPlayer,
+ aWorld);
+ }
+ return null;
+ }
+ final IMetaTileEntity tMetaTileEntity = tile.getMetaTileEntity();
+ if (tMetaTileEntity != null && !tMetaTileEntity.useModularUI()) {
+ return tMetaTileEntity.getClientGUI(aID, aPlayer.inventory, tile);
+ }
+ }
+ return null;
+ }
+
+ private static List<String> getOreDictNames(ItemStack stack) {
+ return Arrays.stream(OreDictionary.getOreIDs(stack))
+ .mapToObj(OreDictionary::getOreName)
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public int getBurnTime(ItemStack aFuel) {
+ if ((aFuel == null) || (aFuel.getItem() == null)) {
+ return 0;
+ }
+ int rFuelValue = 0;
+ if ((aFuel.getItem() instanceof GT_MetaGenerated_Item)) {
+ final Short tFuelValue = ((GT_MetaGenerated_Item) aFuel.getItem()).mBurnValues
+ .get((short) aFuel.getItemDamage());
+ if (tFuelValue != null) {
+ rFuelValue = Math.max(rFuelValue, tFuelValue);
+ }
+ }
+ final NBTTagCompound tNBT = aFuel.getTagCompound();
+ if (tNBT != null) {
+ // See if we have something defined by NBT
+ final short tValue = tNBT.getShort("GT.ItemFuelValue");
+ rFuelValue = Math.max(rFuelValue, tValue);
+ } else {
+ // If not check the ore dict
+ rFuelValue = Math.max(
+ rFuelValue,
+ getOreDictNames(aFuel).stream()
+ .mapToInt(f -> oreDictBurnTimes.getOrDefault(f, 0))
+ .max()
+ .orElse(0));
+ }
+
+ // If we have something from the GT MetaGenerated_Item, ItemFuelValue, or OreDict return
+ if (rFuelValue > 0) return rFuelValue;
+
+ // Otherwise, a few more checks
+ if (GT_Utility.areStacksEqual(aFuel, new ItemStack(Blocks.wooden_button, 1))) return 150;
+ else if (GT_Utility.areStacksEqual(aFuel, new ItemStack(Blocks.ladder, 1))) return 100;
+ else if (GT_Utility.areStacksEqual(aFuel, new ItemStack(Items.sign, 1))) return 600;
+ else if (GT_Utility.areStacksEqual(aFuel, new ItemStack(Items.wooden_door, 1))) return 600;
+ else if (GT_Utility.areStacksEqual(aFuel, ItemList.Block_MSSFUEL.get(1))) return 150000;
+ else if (GT_Utility.areStacksEqual(aFuel, ItemList.Block_SSFUEL.get(1))) return 100000;
+
+ return 0;
+ }
+
+ // ------------------------ Adds all fluids corresponding to materials ------------------------
+
+ public Fluid addAutoGeneratedCorrespondingFluid(Materials aMaterial) {
+ // If the fluid is registered as custom inside the Material's constructor then to add custom fluid
+ // textures go to blocks/fluids and place the .png. File should be called fluid.fluid.{unlocalised_name}.png.
+ // All lower case.
+ final String fluidTexture = aMaterial.mIconSet.is_custom ? "fluid." + aMaterial.mName.toLowerCase()
+ : "autogenerated";
+
+ return GT_FluidFactory.builder(aMaterial.mName.toLowerCase(Locale.ENGLISH))
+ .withLocalizedName(aMaterial.mDefaultLocalName)
+ .withTextureName(fluidTexture)
+ .withColorRGBA(aMaterial.mRGBa)
+ .withStateAndTemperature(LIQUID, aMaterial.getLiquidTemperature())
+ .buildAndRegister()
+ .configureMaterials(aMaterial)
+ .registerBContainers(GT_OreDictUnificator.get(OrePrefixes.cell, aMaterial, 1L), ItemList.Cell_Empty.get(1L))
+ .asFluid();
+ }
+
+ public Fluid addAutoGeneratedCorrespondingGas(Materials aMaterial) {
+ // If the fluid is registered as custom inside the Material's constructor then to add custom fluid
+ // textures go to blocks/fluids and place the .png. File should be called fluid.gas.{unlocalised_name}.png. All
+ // lower case.
+ final String fluidTexture = aMaterial.mIconSet.is_custom ? ("gas." + aMaterial.mName.toLowerCase())
+ : "autogenerated";
+
+ return GT_FluidFactory.builder(aMaterial.mName.toLowerCase(Locale.ENGLISH))
+ .withLocalizedName(aMaterial.mDefaultLocalName)
+ .withTextureName(fluidTexture)
+ .withColorRGBA(aMaterial.mRGBa)
+ .withStateAndTemperature(GAS, aMaterial.getGasTemperature())
+ .buildAndRegister()
+ .configureMaterials(aMaterial)
+ .registerBContainers(GT_OreDictUnificator.get(OrePrefixes.cell, aMaterial, 1L), ItemList.Cell_Empty.get(1L))
+ .asFluid();
+ }
+
+ public Fluid addAutogeneratedPlasmaFluid(Materials aMaterial) {
+ // If the fluid is registered as custom inside the Material's constructor then to add custom fluid
+ // textures go to blocks/fluids and place the .png. File should be called fluid.plasma.{unlocalised_name}.png.
+ // All lower case.
+ final String fluidTexture = aMaterial.mIconSet.is_custom ? ("plasma." + aMaterial.mName.toLowerCase())
+ : "plasma.autogenerated";
+
+ return GT_FluidFactory.builder("plasma." + aMaterial.mName.toLowerCase(Locale.ENGLISH))
+ .withLocalizedName(aMaterial.mDefaultLocalName + " Plasma")
+ .withTextureName(fluidTexture)
+ .withColorRGBA(aMaterial.mMoltenRGBa)
+ .withStateAndTemperature(PLASMA, 10000)
+ .buildAndRegister()
+ .configureMaterials(aMaterial)
+ .registerContainers(
+ GT_OreDictUnificator.get(OrePrefixes.cellPlasma, aMaterial, 1L),
+ ItemList.Cell_Empty.get(1L),
+ aMaterial.getMolten(1) != null ? 144 : 1000)
+ .asFluid();
+ }
+
+ public Fluid addAutogeneratedMoltenFluid(Materials aMaterial) {
+ // If the fluid is registered as custom inside the Material's constructor then to add custom fluid
+ // textures go to blocks/fluids and place the .png. File should be called fluid.molten.{unlocalised_name}.png.
+ // All lower case.
+ final String fluidTexture = aMaterial.mIconSet.is_custom ? ("molten." + aMaterial.mName.toLowerCase())
+ : "molten.autogenerated";
+
+ return GT_FluidFactory.builder("molten." + aMaterial.mName.toLowerCase(Locale.ENGLISH))
+ .withLocalizedName("Molten " + aMaterial.mDefaultLocalName)
+ .withTextureName(fluidTexture)
+ .withColorRGBA(aMaterial.mMoltenRGBa)
+ .withStateAndTemperature(MOLTEN, aMaterial.mMeltingPoint < 0 ? 1000 : aMaterial.mMeltingPoint)
+ .buildAndRegister()
+ .configureMaterials(aMaterial)
+ .registerContainers(
+ GT_OreDictUnificator.get(OrePrefixes.cellMolten, aMaterial, 1L),
+ ItemList.Cell_Empty.get(1L),
+ 144)
+ .asFluid();
+ }
+
+ // ------------------------------------------------------------------------------------------------------------
+
+ public void addAutoGeneratedHydroCrackedFluids(Materials aMaterial) {
+ Fluid[] crackedFluids = new Fluid[3];
+ String[] namePrefixes = { "lightlyhydrocracked.", "moderatelyhydrocracked.", "severelyhydrocracked." };
+ OrePrefixes[] orePrefixes = { OrePrefixes.cellHydroCracked1, OrePrefixes.cellHydroCracked2,
+ OrePrefixes.cellHydroCracked3 };
+ final Fluid uncrackedFluid;
+ if (aMaterial.mFluid != null) {
+ uncrackedFluid = aMaterial.mFluid;
+ } else if (aMaterial.mGas != null) {
+ uncrackedFluid = aMaterial.mGas;
+ } else return;
+ for (int i = 0; i < 3; i++) {
+ crackedFluids[i] = GT_FluidFactory.builder(namePrefixes[i] + aMaterial.mName.toLowerCase(Locale.ENGLISH))
+ .withIconsFrom(uncrackedFluid)
+ .withLocalizedName(orePrefixes[i].mLocalizedMaterialPre + aMaterial.mDefaultLocalName)
+ .withColorRGBA(aMaterial.mRGBa)
+ .withStateAndTemperature(GAS, 775)
+ .buildAndRegister()
+ .registerBContainers(
+ GT_OreDictUnificator.get(orePrefixes[i], aMaterial, 1L),
+ ItemList.Cell_Empty.get(1L))
+ .asFluid();
+
+ int hydrogenAmount = 2 * i + 2;
+ GT_Values.RA.stdBuilder()
+ .itemInputs(GT_Utility.getIntegratedCircuit(i + 1))
+ .fluidInputs(new FluidStack(uncrackedFluid, 1000), Materials.Hydrogen.getGas(hydrogenAmount * 800))
+ .fluidOutputs(new FluidStack(crackedFluids[i], 1000))
+ .duration((1 + i) * SECONDS)
+ .eut(240)
+ .addTo(crackingRecipes);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(Materials.Hydrogen.getCells(hydrogenAmount), GT_Utility.getIntegratedCircuit(i + 1))
+ .itemOutputs(Materials.Empty.getCells(hydrogenAmount))
+ .fluidInputs(new FluidStack(uncrackedFluid, 1000))
+ .fluidOutputs(new FluidStack(crackedFluids[i], 800))
+ .duration((8 + 4 * i) * SECONDS)
+ .eut(TierEU.RECIPE_LV)
+ .addTo(UniversalChemical);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(aMaterial.getCells(1), GT_Utility.getIntegratedCircuit(i + 1))
+ .itemOutputs(Materials.Empty.getCells(1))
+ .fluidInputs(Materials.Hydrogen.getGas(hydrogenAmount * 1000))
+ .fluidOutputs(new FluidStack(crackedFluids[i], 800))
+ .duration((8 + 4 * i) * SECONDS)
+ .eut(TierEU.RECIPE_LV)
+ .addTo(UniversalChemical);
+ }
+ aMaterial.setHydroCrackedFluids(crackedFluids);
+ }
+
+ public void addAutoGeneratedSteamCrackedFluids(Materials aMaterial) {
+ Fluid[] crackedFluids = new Fluid[3];
+ String[] namePrefixes = { "lightlysteamcracked.", "moderatelysteamcracked.", "severelysteamcracked." };
+ OrePrefixes[] orePrefixes = { OrePrefixes.cellSteamCracked1, OrePrefixes.cellSteamCracked2,
+ OrePrefixes.cellSteamCracked3 };
+ final Fluid uncrackedFluid;
+ if (aMaterial.mFluid != null) {
+ uncrackedFluid = aMaterial.mFluid;
+ } else if (aMaterial.mGas != null) {
+ uncrackedFluid = aMaterial.mGas;
+ } else return;
+ for (int i = 0; i < 3; i++) {
+ crackedFluids[i] = GT_FluidFactory.builder(namePrefixes[i] + aMaterial.mName.toLowerCase(Locale.ENGLISH))
+ .withIconsFrom(uncrackedFluid)
+ .withLocalizedName(orePrefixes[i].mLocalizedMaterialPre + aMaterial.mDefaultLocalName)
+ .withColorRGBA(aMaterial.mRGBa)
+ .withStateAndTemperature(GAS, 775)
+ .buildAndRegister()
+ .registerBContainers(
+ GT_OreDictUnificator.get(orePrefixes[i], aMaterial, 1L),
+ ItemList.Cell_Empty.get(1L))
+ .asFluid();
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(GT_Utility.getIntegratedCircuit(i + 1))
+ .fluidInputs(new FluidStack(uncrackedFluid, 1000), GT_ModHandler.getSteam(1000))
+ .fluidOutputs(new FluidStack(crackedFluids[i], 1200))
+ .duration((1 + i) * SECONDS)
+ .eut(240)
+ .addTo(crackingRecipes);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(GT_ModHandler.getIC2Item("steamCell", 1L), GT_Utility.getIntegratedCircuit(i + 1))
+ .itemOutputs(Materials.Empty.getCells(1))
+ .fluidInputs(new FluidStack(uncrackedFluid, 1000))
+ .fluidOutputs(new FluidStack(crackedFluids[i], 800))
+ .duration((8 + 4 * i) * SECONDS)
+ .eut(TierEU.RECIPE_LV)
+ .addTo(UniversalChemical);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(aMaterial.getCells(1), GT_Utility.getIntegratedCircuit(i + 1))
+ .itemOutputs(Materials.Empty.getCells(1))
+ .fluidInputs(GT_ModHandler.getSteam(1000))
+ .fluidOutputs(new FluidStack(crackedFluids[i], 800))
+ .duration((8 + 4 * i) * SECONDS)
+ .eut(TierEU.RECIPE_LV)
+ .addTo(UniversalChemical);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(aMaterial.getCells(1), GT_Utility.getIntegratedCircuit(i + 1))
+ .itemOutputs(Materials.Empty.getCells(1))
+ .fluidInputs(getFluidStack("ic2steam", 1000))
+ .fluidOutputs(new FluidStack(crackedFluids[i], 800))
+ .duration((8 + 4 * i) * SECONDS)
+ .eut(TierEU.RECIPE_LV)
+ .addTo(UniversalChemical);
+ }
+ aMaterial.setSteamCrackedFluids(crackedFluids);
+ }
+
+ /**
+ * @see GT_FluidFactory#of(String, String, Materials, FluidState, int)
+ * @see GT_FluidFactory#of(String, String, FluidState, int)
+ * @deprecated use {@link GT_FluidFactory#builder}
+ */
+ @Deprecated
+ public Fluid addFluid(String aName, String aLocalized, Materials aMaterial, int aState, int aTemperatureK) {
+ return GT_FluidFactory.of(aName, aLocalized, aMaterial, FluidState.VALID_STATES[aState], aTemperatureK);
+ }
+
+ /**
+ * @deprecated use {@link GT_FluidFactory#builder}
+ */
+ @SuppressWarnings({ "MethodWithTooManyParameters" }) // Deprecated method
+ @Deprecated
+ public Fluid addFluid(String aName, String aLocalized, Materials aMaterial, int aState, int aTemperatureK,
+ ItemStack aFullContainer, ItemStack aEmptyContainer, int aFluidAmount) {
+ return GT_FluidFactory.builder(aName)
+ .withLocalizedName(aLocalized)
+ .withStateAndTemperature(FluidState.fromValue(aState), aTemperatureK)
+ .buildAndRegister()
+ .configureMaterials(aMaterial)
+ .registerContainers(aFullContainer, aEmptyContainer, aFluidAmount)
+ .asFluid();
+ }
+
+ /**
+ * @deprecated use {@link GT_FluidFactory#builder}
+ */
+ @Deprecated
+ @SuppressWarnings({ "MethodWithTooManyParameters" }) // Deprecated method
+ public Fluid addFluid(String aName, String aTexture, String aLocalized, Materials aMaterial, short[] aRGBa,
+ int aState, int aTemperatureK, ItemStack aFullContainer, ItemStack aEmptyContainer, int aFluidAmount) {
+ return GT_FluidFactory.builder(aName)
+ .withLocalizedName(aLocalized)
+ .withStillIconResourceLocation(new ResourceLocation(GregTech.ID, "fluids/fluid." + aTexture))
+ .withColorRGBA(aRGBa)
+ .withStateAndTemperature(FluidState.fromValue(aState), aTemperatureK)
+ .buildAndRegister()
+ .configureMaterials(aMaterial)
+ .registerContainers(aFullContainer, aEmptyContainer, aFluidAmount)
+ .asFluid();
+ }
+
+ public File getSaveDirectory() {
+ return this.mUniverse == null ? null
+ : this.mUniverse.getSaveHandler()
+ .getWorldDirectory();
+ }
+
+ public long getAnimationTicks() {
+ return 0L;
+ }
+
+ public float getPartialRenderTicks() {
+ return 0;
+ }
+
+ public void registerUnificationEntries() {
+ GregTech_API.sUnification.mConfig.save();
+ GregTech_API.sUnification.mConfig.load();
+ GT_OreDictUnificator.resetUnificationEntries();
+ for (OreDictEventContainer tOre : this.mEvents) {
+ if ((!(tOre.mEvent.Ore.getItem() instanceof GT_MetaGenerated_Item)) && (tOre.mPrefix != null)
+ && (tOre.mPrefix.mIsUnificatable)
+ && (tOre.mMaterial != null)) {
+ boolean checkModID = tOre.mModID != null;
+
+ if (checkModID) {
+ switch (tOre.mModID) {
+ case Names.ENDER_I_O -> {
+ if (tOre.mPrefix == OrePrefixes.ingot && tOre.mMaterial == Materials.DarkSteel) {
+ GT_OreDictUnificator
+ .addAssociation(tOre.mPrefix, tOre.mMaterial, tOre.mEvent.Ore, false);
+ GT_OreDictUnificator.set(
+ tOre.mPrefix,
+ tOre.mMaterial,
+ tOre.mEvent.Ore,
+ (GregTech_API.sUnification.get(
+ ConfigCategories.specialunificationtargets + "." + tOre.mModID,
+ tOre.mEvent.Name,
+ true)),
+ true);
+ continue;
+ }
+ }
+ case Names.THERMAL_FONDATION -> {
+ if (tOre.mPrefix == OrePrefixes.dust && tOre.mMaterial == Materials.Blizz) {
+ GT_OreDictUnificator
+ .addAssociation(tOre.mPrefix, tOre.mMaterial, tOre.mEvent.Ore, false);
+ GT_OreDictUnificator.set(
+ tOre.mPrefix,
+ tOre.mMaterial,
+ tOre.mEvent.Ore,
+ (GregTech_API.sUnification.get(
+ ConfigCategories.specialunificationtargets + "." + tOre.mModID,
+ tOre.mEvent.Name,
+ true)),
+ true);
+ continue;
+ } else if (tOre.mPrefix == OrePrefixes.dust && tOre.mMaterial == Materials.Pyrotheum) {
+ GT_OreDictUnificator
+ .addAssociation(tOre.mPrefix, tOre.mMaterial, tOre.mEvent.Ore, false);
+ GT_OreDictUnificator.set(
+ tOre.mPrefix,
+ tOre.mMaterial,
+ tOre.mEvent.Ore,
+ (GregTech_API.sUnification.get(
+ ConfigCategories.specialunificationtargets + "." + tOre.mModID,
+ tOre.mEvent.Name,
+ true)),
+ true);
+ continue;
+ }
+ }
+ case Names.ARS_MAGICA2 -> {
+ if (tOre.mPrefix == OrePrefixes.dust && tOre.mMaterial == Materials.Vinteum) {
+ GT_OreDictUnificator
+ .addAssociation(tOre.mPrefix, tOre.mMaterial, tOre.mEvent.Ore, false);
+ GT_OreDictUnificator.set(
+ tOre.mPrefix,
+ tOre.mMaterial,
+ tOre.mEvent.Ore,
+ (GregTech_API.sUnification.get(
+ ConfigCategories.specialunificationtargets + "." + tOre.mModID,
+ tOre.mEvent.Name,
+ true)),
+ true);
+ continue;
+ } else if (tOre.mPrefix == OrePrefixes.gem && tOre.mMaterial == Materials.BlueTopaz) {
+ GT_OreDictUnificator
+ .addAssociation(tOre.mPrefix, tOre.mMaterial, tOre.mEvent.Ore, false);
+ GT_OreDictUnificator.set(
+ tOre.mPrefix,
+ tOre.mMaterial,
+ tOre.mEvent.Ore,
+ (GregTech_API.sUnification.get(
+ ConfigCategories.specialunificationtargets + "." + tOre.mModID,
+ tOre.mEvent.Name,
+ true)),
+ true);
+ continue;
+ } else if (tOre.mPrefix == OrePrefixes.gem && tOre.mMaterial == Materials.Chimerite) {
+ GT_OreDictUnificator
+ .addAssociation(tOre.mPrefix, tOre.mMaterial, tOre.mEvent.Ore, false);
+ GT_OreDictUnificator.set(
+ tOre.mPrefix,
+ tOre.mMaterial,
+ tOre.mEvent.Ore,
+ (GregTech_API.sUnification.get(
+ ConfigCategories.specialunificationtargets + "." + tOre.mModID,
+ tOre.mEvent.Name,
+ true)),
+ true);
+ continue;
+ } else if (tOre.mPrefix == OrePrefixes.gem && tOre.mMaterial == Materials.Moonstone) {
+ GT_OreDictUnificator
+ .addAssociation(tOre.mPrefix, tOre.mMaterial, tOre.mEvent.Ore, false);
+ GT_OreDictUnificator.set(
+ tOre.mPrefix,
+ tOre.mMaterial,
+ tOre.mEvent.Ore,
+ (GregTech_API.sUnification.get(
+ ConfigCategories.specialunificationtargets + "." + tOre.mModID,
+ tOre.mEvent.Name,
+ true)),
+ true);
+ continue;
+ } else if (tOre.mPrefix == OrePrefixes.gem && tOre.mMaterial == Materials.Sunstone) {
+ GT_OreDictUnificator
+ .addAssociation(tOre.mPrefix, tOre.mMaterial, tOre.mEvent.Ore, false);
+ GT_OreDictUnificator.set(
+ tOre.mPrefix,
+ tOre.mMaterial,
+ tOre.mEvent.Ore,
+ (GregTech_API.sUnification.get(
+ ConfigCategories.specialunificationtargets + "." + tOre.mModID,
+ tOre.mEvent.Name,
+ true)),
+ true);
+ continue;
+ }
+ }
+ case Names.ROTARY_CRAFT -> {
+ if (tOre.mPrefix == OrePrefixes.ingot && tOre.mMaterial == Materials.HSLA) {
+ GT_OreDictUnificator
+ .addAssociation(tOre.mPrefix, tOre.mMaterial, tOre.mEvent.Ore, false);
+ GT_OreDictUnificator.set(
+ tOre.mPrefix,
+ tOre.mMaterial,
+ tOre.mEvent.Ore,
+ (GregTech_API.sUnification.get(
+ ConfigCategories.specialunificationtargets + "." + tOre.mModID,
+ tOre.mEvent.Name,
+ true)),
+ true);
+ continue;
+ }
+ }
+ case Names.APPLIED_ENERGISTICS2 -> {
+ if (tOre.mPrefix == OrePrefixes.gem && tOre.mMaterial == Materials.CertusQuartz) {
+ GT_OreDictUnificator
+ .addAssociation(tOre.mPrefix, tOre.mMaterial, tOre.mEvent.Ore, false);
+ GT_OreDictUnificator.set(
+ tOre.mPrefix,
+ tOre.mMaterial,
+ tOre.mEvent.Ore,
+ (GregTech_API.sUnification.get(
+ ConfigCategories.specialunificationtargets + "." + tOre.mModID,
+ tOre.mEvent.Name,
+ true)),
+ true);
+ continue;
+ } else if (tOre.mPrefix == OrePrefixes.dust && tOre.mMaterial == Materials.CertusQuartz) {
+ GT_OreDictUnificator
+ .addAssociation(tOre.mPrefix, tOre.mMaterial, tOre.mEvent.Ore, false);
+ GT_OreDictUnificator.set(
+ tOre.mPrefix,
+ tOre.mMaterial,
+ tOre.mEvent.Ore,
+ (GregTech_API.sUnification.get(
+ ConfigCategories.specialunificationtargets + "." + tOre.mModID,
+ tOre.mEvent.Name,
+ true)),
+ true);
+ continue;
+ }
+ }
+ default -> {}
+ }
+ }
+ if (GT_OreDictUnificator.isBlacklisted(tOre.mEvent.Ore)) {
+ GT_OreDictUnificator.addAssociation(tOre.mPrefix, tOre.mMaterial, tOre.mEvent.Ore, true);
+ } else {
+ GT_OreDictUnificator.addAssociation(tOre.mPrefix, tOre.mMaterial, tOre.mEvent.Ore, false);
+ GT_OreDictUnificator.set(
+ tOre.mPrefix,
+ tOre.mMaterial,
+ tOre.mEvent.Ore,
+ (checkModID) && (GregTech_API.sUnification.get(
+ ConfigCategories.specialunificationtargets + "." + tOre.mModID,
+ tOre.mEvent.Name,
+ false)),
+ true);
+ }
+ }
+ }
+
+ for (OreDictEventContainer tOre : this.mEvents) {
+ if (((tOre.mEvent.Ore.getItem() instanceof GT_MetaGenerated_Item)) && (tOre.mPrefix != null)
+ && (tOre.mPrefix.mIsUnificatable)
+ && (tOre.mMaterial != null)) {
+ if (GT_OreDictUnificator.isBlacklisted(tOre.mEvent.Ore)) {
+ GT_OreDictUnificator.addAssociation(tOre.mPrefix, tOre.mMaterial, tOre.mEvent.Ore, true);
+ } else {
+ GT_OreDictUnificator.addAssociation(tOre.mPrefix, tOre.mMaterial, tOre.mEvent.Ore, false);
+ GT_OreDictUnificator.set(
+ tOre.mPrefix,
+ tOre.mMaterial,
+ tOre.mEvent.Ore,
+ (tOre.mModID != null) && (GregTech_API.sUnification.get(
+ new StringBuilder().append(ConfigCategories.specialunificationtargets)
+ .append(".")
+ .append(tOre.mModID),
+ tOre.mEvent.Name,
+ false)),
+ true);
+ }
+ }
+ }
+ GregTech_API.sUnificationEntriesRegistered = true;
+ GregTech_API.sUnification.mConfig.save();
+ GT_Recipe.reInit();
+ }
+
+ @SuppressWarnings("deprecation")
+ public void activateOreDictHandler() {
+ this.mOreDictActivated = true;
+ ProgressManager.ProgressBar progressBar = ProgressManager.push("Register materials", mEvents.size());
+
+ if (BetterLoadingScreen.isModLoaded()) {
+ GT_Values.cls_enabled = true;
+ try {
+ GT_CLS_Compat.stepMaterialsCLS(mEvents, progressBar);
+ } catch (IllegalAccessException e) {
+ GT_FML_LOGGER.catching(e);
+ }
+ } else GT_Proxy.stepMaterialsVanilla(this.mEvents, progressBar);
+ }
+
+ @Deprecated
+ public static final HashMap<Integer, HashMap<ChunkCoordIntPair, int[]>> dimensionWiseChunkData = new HashMap<>(16); // stores
+ // chunk
+ // data
+ // that
+ // is
+ // loaded/saved
+
+ public static final HashMap<Integer, GT_Pollution> dimensionWisePollution = new HashMap<>(16); // stores
+ // GT_Polluttors
+ // objects
+ public static final byte GTOIL = 3, GTOILFLUID = 2, GTPOLLUTION = 1, GTMETADATA = 0, NOT_LOADED = 0, LOADED = 1; // consts
+
+ // TO get default's fast
+ @Deprecated
+ public static int[] getDefaultChunkDataOnCreation() {
+ return new int[] { NOT_LOADED, 0, -1, -1 };
+ }
+
+ @Deprecated
+ public static int[] getDefaultChunkDataOnLoad() {
+ return new int[] { LOADED, 0, -1, -1 };
+ }
+
+ @SubscribeEvent
+ public void handleChunkLoadEvent(ChunkDataEvent.Load event) {
+ GT_UndergroundOil.migrate(event);
+ GT_Pollution.migrate(event);
+ }
+
+ @SubscribeEvent
+ public void onBlockBreakSpeedEvent(PlayerEvent.BreakSpeed aEvent) {
+ if (aEvent.entityPlayer != null) {
+ ItemStack aStack = aEvent.entityPlayer.getCurrentEquippedItem();
+ if ((aStack != null) && ((aStack.getItem() instanceof GT_MetaGenerated_Tool))) {
+ aEvent.newSpeed = ((GT_MetaGenerated_Tool) aStack.getItem()).onBlockBreakSpeedEvent(
+ aEvent.newSpeed,
+ aStack,
+ aEvent.entityPlayer,
+ aEvent.block,
+ aEvent.x,
+ aEvent.y,
+ aEvent.z,
+ (byte) aEvent.metadata,
+ aEvent);
+ }
+ }
+ }
+
+ public static class OreDictEventContainer {
+
+ public final OreDictionary.OreRegisterEvent mEvent;
+ public final OrePrefixes mPrefix;
+ public final Materials mMaterial;
+ public final String mModID;
+
+ public OreDictEventContainer(OreDictionary.OreRegisterEvent aEvent, OrePrefixes aPrefix, Materials aMaterial,
+ String aModID) {
+ this.mEvent = aEvent;
+ this.mPrefix = aPrefix;
+ this.mMaterial = aMaterial;
+ this.mModID = ((aModID == null) || (aModID.equals("UNKNOWN")) ? null : aModID);
+ }
+ }
+
+ @SubscribeEvent
+ public void onBlockEvent(BlockEvent event) {
+ if (event.block.getUnlocalizedName()
+ .equals("blockAlloyGlass")) GregTech_API.causeMachineUpdate(event.world, event.x, event.y, event.z);
+ }
+
+ public static void addFullHazmatToGeneralItem(String aModID, String aItem, long aAmount, int aMeta) {
+ ItemStack item = GT_ModHandler.getModItem(aModID, aItem, aAmount, aMeta);
+ addItemToHazmatLists(item);
+ }
+
+ public static void addFullHazmatToGeneralItem(String aModID, String aItem, long aAmount) {
+ ItemStack item = GT_ModHandler.getModItem(aModID, aItem, aAmount, W);
+ addItemToHazmatLists(item);
+ }
+
+ public static void addFullHazmatToIC2Item(String aItem) {
+ ItemStack item = GT_ModHandler.getIC2Item(aItem, 1L, W);
+ addItemToHazmatLists(item);
+ }
+
+ private static void addItemToHazmatLists(ItemStack item) {
+ GregTech_API.sGasHazmatList.add(item);
+ GregTech_API.sBioHazmatList.add(item);
+ GregTech_API.sFrostHazmatList.add(item);
+ GregTech_API.sHeatHazmatList.add(item);
+ GregTech_API.sRadioHazmatList.add(item);
+ GregTech_API.sElectroHazmatList.add(item);
+ }
+
+ public static boolean providesProtection(ItemStack aStack) {
+
+ if (GT_Utility.hasHazmatEnchant(aStack)) return true;
+
+ boolean isGas = GT_Utility.isStackInList(aStack, GregTech_API.sGasHazmatList);
+ boolean isBio = GT_Utility.isStackInList(aStack, GregTech_API.sBioHazmatList);
+ boolean isFrost = GT_Utility.isStackInList(aStack, GregTech_API.sFrostHazmatList);
+ boolean isHeat = GT_Utility.isStackInList(aStack, GregTech_API.sHeatHazmatList);
+ boolean isRadio = GT_Utility.isStackInList(aStack, GregTech_API.sRadioHazmatList);
+ boolean isElectro = GT_Utility.isStackInList(aStack, GregTech_API.sElectroHazmatList);
+ return isGas && isBio && isFrost && isHeat && isRadio && isElectro;
+ }
+
+ @SubscribeEvent
+ public void onItemTooltip(ItemTooltipEvent event) {
+ if (event.itemStack != null) {
+ ItemStack aStackTemp = event.itemStack;
+ GT_ItemStack aStack = new GT_ItemStack(aStackTemp);
+ if (providesProtection(aStackTemp)) {
+ event.toolTip.add(EnumChatFormatting.LIGHT_PURPLE + "Provides full hazmat protection.");
+ }
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/GT_RecipeAdder.java b/src/main/java/gregtech/common/GT_RecipeAdder.java
new file mode 100644
index 0000000000..d236bbc4f2
--- /dev/null
+++ b/src/main/java/gregtech/common/GT_RecipeAdder.java
@@ -0,0 +1,3245 @@
+package gregtech.common;
+
+import static gregtech.GT_Mod.GT_FML_LOGGER;
+import static gregtech.api.enums.Mods.GTPlusPlus;
+import static gregtech.api.enums.Mods.Railcraft;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Objects;
+
+import net.minecraft.init.Blocks;
+import net.minecraft.init.Items;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidStack;
+import net.minecraftforge.oredict.OreDictionary;
+
+import cpw.mods.fml.common.registry.GameRegistry;
+import gregtech.GT_Mod;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.interfaces.internal.IGT_RecipeAdder;
+import gregtech.api.objects.ItemData;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.util.GT_AssemblyLineUtils;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_OreDictUnificator;
+import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.GT_Recipe.GT_Recipe_AssemblyLine;
+import gregtech.api.util.GT_RecipeBuilder;
+import gregtech.api.util.GT_RecipeConstants;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.extensions.ArrayExt;
+import ic2.core.init.MainConfig;
+import ic2.core.util.ConfigUtil;
+import mods.railcraft.common.blocks.aesthetics.cube.EnumCube;
+import mods.railcraft.common.items.RailcraftToolItems;
+
+public class GT_RecipeAdder implements IGT_RecipeAdder {
+
+ @Override
+ @Deprecated
+ public boolean addFusionReactorRecipe(ItemStack aInput1, ItemStack aInput2, ItemStack aOutput1, int aDuration,
+ int aEUt, int aStartEU) {
+ return false;
+ }
+
+ @Deprecated
+ @Override // Really?
+ public boolean addFusionReactorRecipe(FluidStack aInput1, FluidStack aInput2, FluidStack aOutput1, int aDuration,
+ int aEUt, int aStartEU) {
+ if (aInput1 == null || aInput2 == null || aOutput1 == null || aDuration < 1 || aEUt < 1 || aStartEU < 1) {
+ return false;
+ }
+ RecipeMaps.fusionRecipes.addRecipe(
+ null,
+ new FluidStack[] { aInput1, aInput2 },
+ new FluidStack[] { aOutput1 },
+ aDuration,
+ aEUt,
+ aStartEU);
+ return true;
+ }
+
+ @Deprecated
+ @Override
+ public boolean addFusionReactorRecipe(FluidStack[] FluidInputArray, FluidStack[] FluidOutputArray,
+ int aFusionDurationInTicks, int aFusionEnergyPerTick, int aEnergyNeededForStartingFusion) {
+ if (FluidInputArray.length == 0) return false;
+
+ if (FluidOutputArray.length == 0) return false;
+
+ RecipeMaps.fusionRecipes.addRecipe(
+ null,
+ FluidInputArray,
+ FluidOutputArray,
+ aFusionDurationInTicks,
+ aFusionEnergyPerTick,
+ aEnergyNeededForStartingFusion);
+ return true;
+ }
+
+ @Deprecated
+ @Override
+ public boolean addCentrifugeRecipe(ItemStack aInput1, int aInput2, ItemStack aOutput1, ItemStack aOutput2,
+ ItemStack aOutput3, ItemStack aOutput4, ItemStack aOutput5, ItemStack aOutput6, int aDuration) {
+ return addCentrifugeRecipe(
+ aInput1,
+ aInput2 < 0 ? null : aInput2 > 0 ? ItemList.Cell_Empty.get(aInput2) : null,
+ null,
+ null,
+ aOutput1,
+ aOutput2,
+ aOutput3,
+ aOutput4,
+ aOutput5,
+ aOutput6,
+ null,
+ aDuration,
+ 5);
+ }
+
+ @Deprecated
+ @Override
+ public boolean addCentrifugeRecipe(ItemStack aInput1, int aInput2, ItemStack aOutput1, ItemStack aOutput2,
+ ItemStack aOutput3, ItemStack aOutput4, ItemStack aOutput5, ItemStack aOutput6, int aDuration, int aEUt) {
+ return addCentrifugeRecipe(
+ aInput1,
+ aInput2 < 0 ? null : aInput2 > 0 ? ItemList.Cell_Empty.get(aInput2) : null,
+ null,
+ null,
+ aOutput1,
+ aOutput2,
+ aOutput3,
+ aOutput4,
+ aOutput5,
+ aOutput6,
+ null,
+ aDuration,
+ aEUt);
+ }
+
+ @Deprecated
+ @Override
+ public boolean addCentrifugeRecipe(ItemStack aInput1, ItemStack aInput2, FluidStack aFluidInput,
+ FluidStack aFluidOutput, ItemStack aOutput1, ItemStack aOutput2, ItemStack aOutput3, ItemStack aOutput4,
+ ItemStack aOutput5, ItemStack aOutput6, int[] aChances, int aDuration, int aEUt) {
+ return addCentrifugeRecipe(
+ aInput1,
+ aInput2,
+ aFluidInput,
+ aFluidOutput,
+ aOutput1,
+ aOutput2,
+ aOutput3,
+ aOutput4,
+ aOutput5,
+ aOutput6,
+ aChances,
+ aDuration,
+ aEUt,
+ false);
+ }
+
+ @Deprecated
+ @Override
+ public boolean addCentrifugeRecipe(ItemStack aInput1, ItemStack aInput2, FluidStack aFluidInput,
+ FluidStack aFluidOutput, ItemStack aOutput1, ItemStack aOutput2, ItemStack aOutput3, ItemStack aOutput4,
+ ItemStack aOutput5, ItemStack aOutput6, int[] aChances, int aDuration, int aEUt, boolean aCleanroom) {
+ if (((aInput1 == null) && (aFluidInput == null)) || ((aOutput1 == null) && (aFluidOutput == null))) {
+ return false;
+ }
+ if ((aInput1 != null) && (aDuration <= 0)) {
+ return false;
+ }
+ if ((aFluidInput != null) && (aDuration <= 0)) {
+ return false;
+ }
+ if (!GT_Mod.gregtechproxy.mEnableCleanroom) {
+ aCleanroom = false;
+ }
+ RecipeMaps.centrifugeRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput1, aInput2 },
+ new ItemStack[] { aOutput1, aOutput2, aOutput3, aOutput4, aOutput5, aOutput6, },
+ null,
+ aChances,
+ new FluidStack[] { aFluidInput },
+ new FluidStack[] { aFluidOutput },
+ aDuration,
+ aEUt,
+ aCleanroom ? -100 : 0);
+ ItemStack[] itemInputs = { aInput1, aInput2 };
+ ItemStack[] itemOutputs = { aOutput1, aOutput2, aOutput3, aOutput4, aOutput5, aOutput6 };
+ FluidStack[] fluidInputs = { aFluidInput, null, null };
+ FluidStack[] fluidOutputs = { aFluidOutput, null, null, null, null, null, null };
+
+ byte iNumber = 0;
+ byte oNumber = 0;
+
+ for (ItemStack item : itemInputs) {
+ if (item != null) {
+ if (GT_Utility.getFluidForFilledItem(aInput1, true) != null || GT_Utility.isCellEmpty(item)) {
+ fluidInputs[iNumber + 1] = GT_Utility.convertCellToFluid(item);
+ itemInputs[iNumber] = null;
+ }
+ }
+ iNumber++;
+ }
+
+ for (ItemStack item : itemOutputs) {
+ if (item != null) {
+ if (GT_Utility.getFluidForFilledItem(item, true) != null || GT_Utility.isCellEmpty(item)) {
+ fluidOutputs[oNumber + 1] = GT_Utility.convertCellToFluid(item);
+ itemOutputs[oNumber] = null;
+ }
+ }
+ oNumber++;
+ }
+
+ RecipeMaps.centrifugeNonCellRecipes.addRecipe(
+ false,
+ itemInputs,
+ itemOutputs,
+ null,
+ aChances,
+ fluidInputs,
+ fluidOutputs,
+ aDuration,
+ aEUt,
+ aCleanroom ? -100 : 0);
+ return true;
+ }
+
+ @Deprecated
+ @Override
+ public boolean addCompressorRecipe(ItemStack aInput1, ItemStack aOutput1, int aDuration, int aEUt) {
+ if ((aInput1 == null) || (aOutput1 == null)) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ RecipeMaps.compressorRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput1 },
+ new ItemStack[] { aOutput1 },
+ null,
+ null,
+ null,
+ aDuration,
+ aEUt,
+ 0);
+ return true;
+ }
+
+ @Deprecated
+ @Override
+ public boolean addElectrolyzerRecipe(ItemStack aInput1, int aInput2, ItemStack aOutput1, ItemStack aOutput2,
+ ItemStack aOutput3, ItemStack aOutput4, ItemStack aOutput5, ItemStack aOutput6, int aDuration, int aEUt) {
+ return addElectrolyzerRecipe(
+ aInput1,
+ aInput2 < 0 ? null : aInput2 > 0 ? ItemList.Cell_Empty.get(aInput2) : null,
+ null,
+ null,
+ aOutput1,
+ aOutput2,
+ aOutput3,
+ aOutput4,
+ aOutput5,
+ aOutput6,
+ null,
+ aDuration,
+ aEUt);
+ }
+
+ @Deprecated
+ @Override
+ public boolean addElectrolyzerRecipe(ItemStack aInput1, ItemStack aInput2, FluidStack aFluidInput,
+ FluidStack aFluidOutput, ItemStack aOutput1, ItemStack aOutput2, ItemStack aOutput3, ItemStack aOutput4,
+ ItemStack aOutput5, ItemStack aOutput6, int[] aChances, int aDuration, int aEUt) {
+ if (((aInput1 == null) && (aFluidInput == null)) || ((aOutput1 == null) && (aFluidOutput == null))) {
+ return false;
+ }
+ if ((aInput1 != null) && (aDuration <= 0)) {
+ return false;
+ }
+ if ((aFluidInput != null) && (aDuration <= 0)) {
+ return false;
+ }
+ RecipeMaps.electrolyzerRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput1, aInput2 },
+ new ItemStack[] { aOutput1, aOutput2, aOutput3, aOutput4, aOutput5, aOutput6 },
+ null,
+ aChances,
+ new FluidStack[] { aFluidInput },
+ new FluidStack[] { aFluidOutput },
+ aDuration,
+ aEUt,
+ 0);
+ ItemStack[] itemInputs = { aInput1, aInput2 };
+ ItemStack[] itemOutputs = { aOutput1, aOutput2, aOutput3, aOutput4, aOutput5, aOutput6 };
+ FluidStack[] fluidInputs = { aFluidInput, null, null };
+ FluidStack[] fluidOutputs = { aFluidOutput, null, null, null, null, null, null };
+
+ byte iNumber = 0;
+ byte oNumber = 0;
+
+ for (ItemStack item : itemInputs) {
+ if (item != null) {
+ if (GT_Utility.getFluidForFilledItem(item, true) != null || GT_Utility.isCellEmpty(item)
+ || GT_Utility.isAnyIntegratedCircuit(item)) {
+ fluidInputs[iNumber + 1] = GT_Utility.convertCellToFluid(item);
+ itemInputs[iNumber] = null;
+ }
+ }
+ iNumber++;
+ }
+
+ for (ItemStack item : itemOutputs) {
+ if (item != null) {
+ if (GT_Utility.getFluidForFilledItem(item, true) != null || GT_Utility.isCellEmpty(item)) {
+ fluidOutputs[oNumber + 1] = GT_Utility.convertCellToFluid(item);
+ itemOutputs[oNumber] = null;
+ }
+ }
+ oNumber++;
+ }
+
+ RecipeMaps.electrolyzerNonCellRecipes
+ .addRecipe(false, itemInputs, itemOutputs, null, aChances, fluidInputs, fluidOutputs, aDuration, aEUt, 0);
+ return true;
+ }
+
+ @Deprecated
+ @Override
+ public boolean addChemicalRecipe(ItemStack aInput1, ItemStack aInput2, ItemStack aOutput, int aDuration) {
+ return addChemicalRecipe(aInput1, aInput2, null, null, aOutput, aDuration);
+ }
+
+ @Deprecated
+ @Override
+ public boolean addChemicalRecipe(ItemStack aInput1, ItemStack aInput2, ItemStack aOutput, int aDuration, int aEUt) {
+ return addChemicalRecipe(aInput1, aInput2, null, null, aOutput, aDuration, aEUt);
+ }
+
+ @Deprecated
+ @Override
+ public boolean addChemicalRecipe(ItemStack aInput1, ItemStack aInput2, FluidStack aFluidInput,
+ FluidStack aFluidOutput, ItemStack aOutput, int aDuration) {
+ return addChemicalRecipe(aInput1, aInput2, aFluidInput, aFluidOutput, aOutput, aDuration, 30);
+ }
+
+ @Deprecated
+ @Override
+ public boolean addChemicalRecipe(ItemStack aInput1, ItemStack aInput2, FluidStack aFluidInput,
+ FluidStack aFluidOutput, ItemStack aOutput, ItemStack aOutput2, int aDuration) {
+ return addChemicalRecipe(aInput1, aInput2, aFluidInput, aFluidOutput, aOutput, aOutput2, aDuration, 30);
+ }
+
+ @Deprecated
+ @Override
+ public boolean addChemicalRecipe(ItemStack aInput1, ItemStack aInput2, FluidStack aFluidInput,
+ FluidStack aFluidOutput, ItemStack aOutput, int aDuration, int aEUTick) {
+ return addChemicalRecipe(
+ aInput1,
+ aInput2,
+ aFluidInput,
+ aFluidOutput,
+ aOutput,
+ GT_Values.NI,
+ aDuration,
+ aEUTick);
+ }
+
+ @Deprecated
+ @Override
+ public boolean addChemicalRecipe(ItemStack aInput1, ItemStack aInput2, FluidStack aFluidInput,
+ FluidStack aFluidOutput, ItemStack aOutput, ItemStack aOutput2, int aDuration, int aEUtick) {
+ return addChemicalRecipe(
+ aInput1,
+ aInput2,
+ aFluidInput,
+ aFluidOutput,
+ aOutput,
+ aOutput2,
+ aDuration,
+ aEUtick,
+ false);
+ }
+
+ @Deprecated
+ @Override
+ public boolean addChemicalRecipe(ItemStack aInput1, ItemStack aInput2, FluidStack aFluidInput,
+ FluidStack aFluidOutput, ItemStack aOutput, ItemStack aOutput2, int aDuration, int aEUtick,
+ boolean aCleanroom) {
+ if (((aInput1 == null) && (aFluidInput == null))
+ || ((aOutput == null) && (aOutput2 == null) && (aFluidOutput == null))) {
+ return false;
+ }
+ if ((aOutput != null || aOutput2 != null) && (aDuration <= 0)) {
+ return false;
+ }
+ if ((aFluidOutput != null) && (aDuration <= 0)) {
+ return false;
+ }
+ if (aEUtick <= 0) {
+ return false;
+ }
+ if (!GT_Mod.gregtechproxy.mEnableCleanroom) {
+ aCleanroom = false;
+ }
+ GT_RecipeBuilder builder = stdBuilder()
+ .itemInputs(ArrayExt.withoutNulls(new ItemStack[] { aInput1, aInput2 }, ItemStack[]::new))
+ .itemOutputs(ArrayExt.withoutNulls(new ItemStack[] { aOutput, aOutput2 }, ItemStack[]::new));
+ if (aFluidInput != null) builder.fluidInputs(aFluidInput);
+ if (aFluidOutput != null) builder.fluidOutputs(aFluidOutput);
+ builder.duration(aDuration)
+ .eut(aEUtick)
+ .metadata(GT_RecipeConstants.CLEANROOM, aCleanroom)
+ .addTo(GT_RecipeConstants.UniversalChemical);
+ return true;
+ }
+
+ @Deprecated
+ @Override
+ public boolean addMultiblockChemicalRecipe(ItemStack[] aInputs, FluidStack[] aFluidInputs,
+ FluidStack[] aFluidOutputs, ItemStack[] aOutputs, int aDuration, int aEUtick) {
+ if (areItemsAndFluidsBothNull(aInputs, aFluidInputs) || areItemsAndFluidsBothNull(aOutputs, aFluidOutputs)) {
+ return false;
+ }
+ if (aEUtick <= 0) {
+ return false;
+ }
+ RecipeMaps.multiblockChemicalReactorRecipes
+ .addRecipe(false, aInputs, aOutputs, null, null, aFluidInputs, aFluidOutputs, aDuration, aEUtick, 0);
+ return true;
+ }
+
+ @Deprecated
+ @Override
+ public boolean addChemicalRecipeForBasicMachineOnly(ItemStack aInput1, ItemStack aInput2, FluidStack aFluidInput,
+ FluidStack aFluidOutput, ItemStack aOutput, ItemStack aOutput2, int aDuration, int aEUtick) {
+ if (((aInput1 == null) && (aFluidInput == null))
+ || ((aOutput == null) && (aOutput2 == null) && (aFluidOutput == null))) {
+ return false;
+ }
+ if ((aOutput != null || aOutput2 != null) && (aDuration <= 0)) {
+ return false;
+ }
+ if ((aFluidOutput != null) && (aDuration <= 0)) {
+ return false;
+ }
+ if (aEUtick <= 0) {
+ return false;
+ }
+ RecipeMaps.chemicalReactorRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput1, aInput2 },
+ new ItemStack[] { aOutput, aOutput2 },
+ null,
+ null,
+ new FluidStack[] { aFluidInput },
+ new FluidStack[] { aFluidOutput },
+ aDuration,
+ aEUtick,
+ 0);
+ return true;
+ }
+
+ @Deprecated
+ @Override
+ public void addDefaultPolymerizationRecipes(Fluid aBasicMaterial, ItemStack aBasicMaterialCell, Fluid aPolymer) {
+ // Oxygen/Titaniumtetrafluoride -> +50% Output each
+ addChemicalRecipe(
+ ItemList.Cell_Air.get(1),
+ GT_Utility.getIntegratedCircuit(1),
+ new FluidStack(aBasicMaterial, 144),
+ new FluidStack(aPolymer, 144),
+ Materials.Empty.getCells(1),
+ 160);
+ addChemicalRecipe(
+ Materials.Oxygen.getCells(1),
+ GT_Utility.getIntegratedCircuit(1),
+ new FluidStack(aBasicMaterial, 144),
+ new FluidStack(aPolymer, 216),
+ Materials.Empty.getCells(1),
+ 160);
+ addChemicalRecipe(
+ aBasicMaterialCell,
+ GT_Utility.getIntegratedCircuit(1),
+ Materials.Air.getGas(14000),
+ new FluidStack(aPolymer, 1000),
+ Materials.Empty.getCells(1),
+ 1120);
+ addChemicalRecipe(
+ aBasicMaterialCell,
+ GT_Utility.getIntegratedCircuit(1),
+ Materials.Oxygen.getGas(7000),
+ new FluidStack(aPolymer, 1500),
+ Materials.Empty.getCells(1),
+ 1120);
+ addMultiblockChemicalRecipe(
+ new ItemStack[] { GT_Utility.getIntegratedCircuit(2) },
+ new FluidStack[] { new FluidStack(aBasicMaterial, 2160), Materials.Air.getGas(7500),
+ Materials.Titaniumtetrachloride.getFluid(100) },
+ new FluidStack[] { new FluidStack(aPolymer, 3240) },
+ null,
+ 800,
+ 30);
+ addMultiblockChemicalRecipe(
+ new ItemStack[] { GT_Utility.getIntegratedCircuit(2) },
+ new FluidStack[] { new FluidStack(aBasicMaterial, 2160), Materials.Oxygen.getGas(7500),
+ Materials.Titaniumtetrachloride.getFluid(100) },
+ new FluidStack[] { new FluidStack(aPolymer, 4320) },
+ null,
+ 800,
+ 30);
+ }
+
+ @Deprecated
+ @Override
+ public boolean addBlastRecipe(ItemStack aInput1, ItemStack aInput2, ItemStack aOutput1, ItemStack aOutput2,
+ int aDuration, int aEUt, int aLevel) {
+ return addBlastRecipe(aInput1, aInput2, null, null, aOutput1, aOutput2, aDuration, aEUt, aLevel);
+ }
+
+ @Override
+ @Deprecated
+ public boolean addBlastRecipe(ItemStack aInput1, ItemStack aInput2, FluidStack aFluidInput, FluidStack aFluidOutput,
+ ItemStack aOutput1, ItemStack aOutput2, int aDuration, int aEUt, int aLevel) {
+ if ((aInput1 == null) || (aOutput1 == null)) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ RecipeMaps.blastFurnaceRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput1, aInput2 },
+ new ItemStack[] { aOutput1, aOutput2 },
+ null,
+ null,
+ new FluidStack[] { aFluidInput },
+ new FluidStack[] { aFluidOutput },
+ aDuration,
+ aEUt,
+ aLevel);
+ return true;
+ }
+
+ @Deprecated
+ public boolean addBlastRecipe(ItemStack aInput1, ItemStack aInput2, ItemStack aInput3, ItemStack aInput4,
+ FluidStack aFluidInput, FluidStack aFluidOutput, ItemStack aOutput1, ItemStack aOutput2, ItemStack aOutput3,
+ ItemStack aOutput4, int aDuration, int aEUt, int aLevel) {
+ if ((aInput1 == null) || (aOutput1 == null)) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ RecipeMaps.blastFurnaceRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput1, aInput2, aInput3, aInput4 },
+ new ItemStack[] { aOutput1, aOutput2, aOutput3, aOutput4 },
+ null,
+ null,
+ new FluidStack[] { aFluidInput },
+ new FluidStack[] { aFluidOutput },
+ aDuration,
+ aEUt,
+ aLevel);
+ return true;
+ }
+
+ @Deprecated
+ @Override
+ public boolean addPlasmaForgeRecipe(ItemStack[] ItemInputArray, FluidStack[] FluidInputArray,
+ ItemStack[] OutputItemArray, FluidStack[] FluidOutputArray, int aDuration, int aEUt, int coil_heat_level) {
+ RecipeMaps.plasmaForgeRecipes.addRecipe(
+ false,
+ ItemInputArray,
+ OutputItemArray,
+ null,
+ null,
+ FluidInputArray,
+ FluidOutputArray,
+ aDuration,
+ aEUt,
+ coil_heat_level);
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addPrimitiveBlastRecipe(ItemStack aInput1, ItemStack aInput2, int aCoalAmount, ItemStack aOutput1,
+ ItemStack aOutput2, int aDuration) {
+ if ((aInput1 == null && aInput2 == null) || (aOutput1 == null && aOutput2 == null)) {
+ return false;
+ }
+ if (aCoalAmount <= 0) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ Materials[] coals = new Materials[] { Materials.Coal, Materials.Charcoal };
+ for (Materials coal : coals) {
+ RecipeMaps.primitiveBlastRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput1, aInput2, coal.getGems(aCoalAmount) },
+ new ItemStack[] { aOutput1, aOutput2, Materials.DarkAsh.getDustTiny(aCoalAmount) },
+ null,
+ null,
+ null,
+ null,
+ aDuration,
+ 0,
+ 0);
+ RecipeMaps.primitiveBlastRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput1, aInput2, coal.getDust(aCoalAmount) },
+ new ItemStack[] { aOutput1, aOutput2, Materials.DarkAsh.getDustTiny(aCoalAmount) },
+ null,
+ null,
+ null,
+ null,
+ aDuration,
+ 0,
+ 0);
+ }
+ if (Railcraft.isModLoaded()) {
+ RecipeMaps.primitiveBlastRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput1, aInput2, RailcraftToolItems.getCoalCoke(aCoalAmount / 2) },
+ new ItemStack[] { aOutput1, aOutput2, Materials.Ash.getDustTiny(aCoalAmount / 2) },
+ null,
+ null,
+ null,
+ null,
+ aDuration * 2 / 3,
+ 0,
+ 0);
+ }
+ if (GTPlusPlus.isModLoaded()) {
+ RecipeMaps.primitiveBlastRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput1, aInput2,
+ GT_ModHandler.getModItem(GTPlusPlus.ID, "itemCactusCoke", (aCoalAmount * 2L)) },
+ new ItemStack[] { aOutput1, aOutput2, Materials.Ash.getDustTiny(aCoalAmount * 2) },
+ null,
+ null,
+ null,
+ null,
+ aDuration * 2 / 3,
+ 0,
+ 0);
+ RecipeMaps.primitiveBlastRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput1, aInput2,
+ GT_ModHandler.getModItem(GTPlusPlus.ID, "itemSugarCoke", (aCoalAmount * 2L)) },
+ new ItemStack[] { aOutput1, aOutput2, Materials.Ash.getDustTiny(aCoalAmount * 2) },
+ null,
+ null,
+ null,
+ null,
+ aDuration * 2 / 3,
+ 0,
+ 0);
+ }
+ if ((aInput1 == null || aInput1.stackSize <= 6) && (aInput2 == null || aInput2.stackSize <= 6)
+ && (aOutput1 == null || aOutput1.stackSize <= 6)
+ && (aOutput2 == null || aOutput2.stackSize <= 6)) {
+ aInput1 = aInput1 == null ? null : GT_Utility.copyAmount(aInput1.stackSize * 10, aInput1);
+ aInput2 = aInput2 == null ? null : GT_Utility.copyAmount(aInput2.stackSize * 10, aInput2);
+ aOutput1 = aOutput1 == null ? null : GT_Utility.copyAmount(aOutput1.stackSize * 10, aOutput1);
+ aOutput2 = aOutput2 == null ? null : GT_Utility.copyAmount(aOutput2.stackSize * 10, aOutput2);
+ for (Materials coal : coals) {
+ RecipeMaps.primitiveBlastRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput1, aInput2, coal.getBlocks(aCoalAmount) },
+ new ItemStack[] { aOutput1, aOutput2, Materials.DarkAsh.getDust(aCoalAmount) },
+ null,
+ null,
+ null,
+ null,
+ aDuration * 10,
+ 0,
+ 0);
+ RecipeMaps.primitiveBlastRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput1, aInput2, coal.getBlocks(aCoalAmount) },
+ new ItemStack[] { aOutput1, aOutput2, Materials.DarkAsh.getDust(aCoalAmount) },
+ null,
+ null,
+ null,
+ null,
+ aDuration * 10,
+ 0,
+ 0);
+ }
+ if (Railcraft.isModLoaded()) {
+ RecipeMaps.primitiveBlastRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput1, aInput2, EnumCube.COKE_BLOCK.getItem(aCoalAmount / 2) },
+ new ItemStack[] { aOutput1, aOutput2, Materials.Ash.getDust(aCoalAmount / 2) },
+ null,
+ null,
+ null,
+ null,
+ aDuration * 20 / 3,
+ 0,
+ 0);
+ }
+ }
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addCannerRecipe(ItemStack aInput1, ItemStack aInput2, ItemStack aOutput1, ItemStack aOutput2,
+ int aDuration, int aEUt) {
+ if ((aInput1 == null) || (aOutput1 == null)) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ RecipeMaps.cannerRecipes.addRecipe(
+ true,
+ aInput2 == null ? new ItemStack[] { aInput1 } : new ItemStack[] { aInput1, aInput2 },
+ new ItemStack[] { aOutput1, aOutput2 },
+ null,
+ null,
+ null,
+ null,
+ aDuration,
+ Math.max(aEUt, 1),
+ 0);
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addAlloySmelterRecipe(ItemStack aInput1, ItemStack aInput2, ItemStack aOutput1, int aDuration,
+ int aEUt) {
+ return addAlloySmelterRecipe(aInput1, aInput2, aOutput1, aDuration, aEUt, false);
+ }
+
+ @Override
+ @Deprecated
+ public boolean addAlloySmelterRecipe(ItemStack aInput1, ItemStack aInput2, ItemStack aOutput1, int aDuration,
+ int aEUt, boolean hidden) {
+ if ((aInput1 == null) || (aOutput1 == null || Materials.Graphite.contains(aInput1))) {
+ return false;
+ }
+ if ((aInput2 == null) && ((OrePrefixes.ingot.contains(aInput1)) || (OrePrefixes.dust.contains(aInput1))
+ || (OrePrefixes.gem.contains(aInput1)))) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ GT_Recipe tRecipe = new GT_Recipe(
+ true,
+ aInput2 == null ? new ItemStack[] { aInput1 } : new ItemStack[] { aInput1, aInput2 },
+ new ItemStack[] { aOutput1 },
+ null,
+ null,
+ null,
+ null,
+ aDuration,
+ Math.max(aEUt, 1),
+ 0);
+ if (hidden) {
+ tRecipe.mHidden = true;
+ }
+ RecipeMaps.alloySmelterRecipes.addRecipe(tRecipe);
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addLatheRecipe(ItemStack aInput1, ItemStack aOutput1, ItemStack aOutput2, int aDuration, int aEUt) {
+ if ((aInput1 == null) || (aOutput1 == null)) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ RecipeMaps.latheRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput1 },
+ new ItemStack[] { aOutput1, aOutput2 },
+ null,
+ null,
+ null,
+ null,
+ aDuration,
+ aEUt,
+ 0);
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addCutterRecipe(ItemStack aInput, FluidStack aLubricant, ItemStack aOutput1, ItemStack aOutput2,
+ int aDuration, int aEUt) {
+ if ((aInput == null) || (aLubricant == null) || (aOutput1 == null)) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ RecipeMaps.cutterRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput },
+ new ItemStack[] { aOutput1, aOutput2 },
+ null,
+ new FluidStack[] { aLubricant },
+ null,
+ aDuration,
+ aEUt,
+ 0);
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addCutterRecipe(ItemStack aInput, ItemStack aOutput1, ItemStack aOutput2, int aDuration, int aEUt,
+ boolean aCleanroom) {
+ return addCutterRecipe(aInput, null, aOutput1, aOutput2, aDuration, aEUt, aCleanroom);
+ }
+
+ @Deprecated
+ public boolean addCutterRecipe(ItemStack aInput, int aCircuit, ItemStack aOutput1, ItemStack aOutput2,
+ int aDuration, int aEUt) {
+ return addCutterRecipe(aInput, aCircuit, aOutput1, aOutput2, aDuration, aEUt, false);
+ }
+
+ @Deprecated
+ public boolean addCutterRecipe(ItemStack aInput, int aCircuit, ItemStack aOutput1, ItemStack aOutput2,
+ int aDuration, int aEUt, boolean aCleanroom) {
+ return addCutterRecipe(
+ aInput,
+ GT_Utility.getIntegratedCircuit(aCircuit),
+ aOutput1,
+ aOutput2,
+ aDuration,
+ aEUt,
+ aCleanroom);
+ }
+
+ @Override
+ @Deprecated
+ public boolean addCutterRecipe(ItemStack aInput, ItemStack aOutput1, ItemStack aOutput2, int aDuration, int aEUt) {
+ return addCutterRecipe(aInput, aOutput1, aOutput2, aDuration, aEUt, false);
+ }
+
+ @Override
+ @Deprecated
+ public boolean addCutterRecipe(ItemStack aInput, ItemStack aCircuit, ItemStack aOutput1, ItemStack aOutput2,
+ int aDuration, int aEUt) {
+ return addCutterRecipe(aInput, aCircuit, aOutput1, aOutput2, aDuration, aEUt, false);
+ }
+
+ @Override
+ @Deprecated
+ public boolean addCutterRecipe(ItemStack aInput, ItemStack aCircuit, ItemStack aOutput1, ItemStack aOutput2,
+ int aDuration, int aEUt, boolean aCleanroom) {
+ return addCutterRecipe(
+ new ItemStack[] { aInput, aCircuit },
+ new ItemStack[] { aOutput1, aOutput2 },
+ aDuration,
+ aEUt,
+ aCleanroom ? -200 : 0);
+ }
+
+ @Deprecated
+ public boolean addCutterRecipe(ItemStack[] aInputs, ItemStack[] aOutputs, int aDuration, int aEUt,
+ boolean aCleanroom) {
+ return addCutterRecipe(aInputs, aOutputs, aDuration, aEUt, aCleanroom ? -200 : 0);
+ }
+
+ @Override
+ @Deprecated
+ public boolean addCutterRecipe(ItemStack[] aInputs, ItemStack[] aOutputs, int aDuration, int aEUt, int aSpecial) {
+ if ((aInputs == null) || (aOutputs == null) || aInputs.length == 0 || aOutputs.length == 0) {
+ return false;
+ }
+ if (Arrays.stream(aOutputs)
+ .noneMatch(Objects::nonNull)) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ if (!GT_Mod.gregtechproxy.mEnableCleanroom && aSpecial == -200) {
+ aSpecial = 0;
+ }
+ RecipeMaps.cutterRecipes.addRecipe(
+ true,
+ aInputs,
+ aOutputs,
+ null,
+ new FluidStack[] { Materials.Water.getFluid(Math.max(4, Math.min(1000, aDuration * aEUt / 320))) },
+ null,
+ aDuration * 2,
+ aEUt,
+ aSpecial);
+ RecipeMaps.cutterRecipes.addRecipe(
+ true,
+ aInputs,
+ aOutputs,
+ null,
+ new FluidStack[] { GT_ModHandler.getDistilledWater(Math.max(3, Math.min(750, aDuration * aEUt / 426))) },
+ null,
+ aDuration * 2,
+ aEUt,
+ aSpecial);
+ RecipeMaps.cutterRecipes.addRecipe(
+ true,
+ aInputs,
+ aOutputs,
+ null,
+ new FluidStack[] { Materials.Lubricant.getFluid(Math.max(1, Math.min(250, aDuration * aEUt / 1280))) },
+ null,
+ aDuration,
+ aEUt,
+ aSpecial);
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addAssemblerRecipe(ItemStack aInput1, Object aOreDict, int aAmount, FluidStack aFluidInput,
+ ItemStack aOutput1, int aDuration, int aEUt) {
+ for (ItemStack tStack : GT_OreDictUnificator.getOresImmutable(aOreDict)) {
+ if (GT_Utility.isStackValid(tStack)) addAssemblerRecipe(
+ aInput1,
+ GT_Utility.copyAmount(aAmount, tStack),
+ aFluidInput,
+ aOutput1,
+ aDuration,
+ aEUt);
+ }
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addAssemblerRecipe(ItemStack[] aInputs, Object aOreDict, int aAmount, FluidStack aFluidInput,
+ ItemStack aOutput1, int aDuration, int aEUt) {
+ for (ItemStack tStack : GT_OreDictUnificator.getOresImmutable(aOreDict)) {
+ if (GT_Utility.isStackValid(tStack)) {
+ ItemStack[] extendedInputs = new ItemStack[aInputs.length + 1];
+ System.arraycopy(aInputs, 0, extendedInputs, 0, aInputs.length);
+ extendedInputs[aInputs.length] = GT_Utility.copyAmount(aAmount, tStack);
+ addAssemblerRecipe(extendedInputs, aFluidInput, aOutput1, aDuration, aEUt);
+ }
+ }
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addAssemblerRecipe(ItemStack aInput1, ItemStack aInput2, ItemStack aOutput1, int aDuration,
+ int aEUt) {
+ return addAssemblerRecipe(
+ new ItemStack[] { aInput1, aInput2 == null ? aInput1 : aInput2 },
+ null,
+ aOutput1,
+ aDuration,
+ aEUt,
+ false);
+ }
+
+ @Override
+ @Deprecated
+ public boolean addAssemblerRecipe(ItemStack aInput1, ItemStack aInput2, FluidStack aFluidInput, ItemStack aOutput1,
+ int aDuration, int aEUt) {
+ return addAssemblerRecipe(new ItemStack[] { aInput1, aInput2 }, aFluidInput, aOutput1, aDuration, aEUt);
+ }
+
+ @Override
+ @Deprecated
+ public boolean addAssemblerRecipe(ItemStack[] aInputs, FluidStack aFluidInput, ItemStack aOutput1, int aDuration,
+ int aEUt) {
+ return addAssemblerRecipe(aInputs, aFluidInput, aOutput1, aDuration, aEUt, false);
+ }
+
+ @Override
+ @Deprecated
+ public boolean addAssemblerRecipe(ItemStack aInput1, ItemStack aInput2, FluidStack aFluidInput, ItemStack aOutput1,
+ int aDuration, int aEUt, boolean aCleanroom) {
+ if (aInput2 == null)
+ return addAssemblerRecipe(new ItemStack[] { aInput1 }, aFluidInput, aOutput1, aDuration, aEUt, aCleanroom);
+ return addAssemblerRecipe(
+ new ItemStack[] { aInput1, aInput2 },
+ aFluidInput,
+ aOutput1,
+ aDuration,
+ aEUt,
+ aCleanroom);
+ }
+
+ @Override
+ @Deprecated
+ public boolean addAssemblerRecipe(ItemStack[] aInputs, FluidStack aFluidInput, ItemStack aOutput1, int aDuration,
+ int aEUt, boolean aCleanroom) {
+
+ if (areItemsAndFluidsBothNull(aInputs, new FluidStack[] { aFluidInput })) {
+ return false;
+ }
+
+ if (aDuration <= 0) {
+ return false;
+ }
+
+ if (!GT_Mod.gregtechproxy.mEnableCleanroom) {
+ aCleanroom = false;
+ }
+
+ if (!GT_Utility.isStackValid(aOutput1)) {
+ return false;
+ }
+
+ for (int oreID : OreDictionary.getOreIDs(aOutput1)) {
+ if (OreDictionary.getOreName(oreID)
+ .startsWith("circuit")) {
+ return this.addAssemblerRecipeNonOD(aInputs, aFluidInput, aOutput1, aDuration, aEUt, aCleanroom);
+ }
+ }
+
+ for (ItemStack aInput : aInputs) {
+ if (!GT_Utility.isStackValid(aInput)) {
+ GT_FML_LOGGER.debug("GT_RecipeAdder: Invalid input for (" + aOutput1 + ")");
+ }
+ }
+
+ RecipeMaps.assemblerRecipes.addRecipe(
+ true,
+ aInputs,
+ new ItemStack[] { aOutput1 },
+ null,
+ new FluidStack[] { aFluidInput },
+ null,
+ aDuration,
+ aEUt,
+ aCleanroom ? -200 : 0);
+
+ return true;
+ }
+
+ @Deprecated
+ public boolean addAssemblerRecipeNonOD(ItemStack[] aInputs, FluidStack aFluidInput, ItemStack aOutput1,
+ int aDuration, int aEUt, boolean aCleanroom) {
+ if (areItemsAndFluidsBothNull(aInputs, new FluidStack[] { aFluidInput })) {
+ return false;
+ }
+
+ if (aDuration <= 0) {
+ return false;
+ }
+
+ if (!GT_Mod.gregtechproxy.mEnableCleanroom) {
+ aCleanroom = false;
+ }
+
+ if (!GT_Utility.isStackValid(aOutput1)) {
+ return false;
+ }
+
+ RecipeMaps.assemblerRecipes.addRecipe(
+ true,
+ aInputs,
+ new ItemStack[] { aOutput1 },
+ null,
+ new FluidStack[] { aFluidInput },
+ null,
+ aDuration,
+ aEUt,
+ aCleanroom ? -200 : 0);
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addWiremillRecipe(ItemStack aInput, ItemStack aOutput, int aDuration, int aEUt) {
+ if ((aInput == null) || (aOutput == null)) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ RecipeMaps.wiremillRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput },
+ new ItemStack[] { aOutput },
+ null,
+ null,
+ null,
+ aDuration,
+ aEUt,
+ 0);
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addWiremillRecipe(ItemStack aInput, ItemStack aCircuit, ItemStack aOutput, int aDuration, int aEUt) {
+ if ((aInput == null) || (aOutput == null)) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ RecipeMaps.wiremillRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput, aCircuit },
+ new ItemStack[] { aOutput },
+ null,
+ null,
+ null,
+ aDuration,
+ aEUt,
+ 0);
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addPolarizerRecipe(ItemStack aInput, ItemStack aOutput, int aDuration, int aEUt) {
+ if ((aInput == null) || (aOutput == null)) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ RecipeMaps.polarizerRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput },
+ new ItemStack[] { aOutput },
+ null,
+ null,
+ null,
+ aDuration,
+ aEUt,
+ 0);
+ return true;
+ }
+
+ @Deprecated
+ @Override
+ public boolean addBenderRecipe(ItemStack aInput1, ItemStack aOutput1, int aDuration, int aEUt) {
+ if ((aInput1 == null) || (aOutput1 == null)) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ RecipeMaps.benderRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput1, ItemList.Circuit_Integrated.getWithDamage(0, aInput1.stackSize) },
+ new ItemStack[] { aOutput1 },
+ null,
+ null,
+ null,
+ null,
+ aDuration,
+ Math.max(aEUt, 1),
+ 0);
+ return true;
+ }
+
+ @Deprecated
+ @Override
+ public boolean addBenderRecipe(ItemStack aInput1, ItemStack aCircuit, ItemStack aOutput1, int aDuration, int aEUt) {
+ if ((aInput1 == null) || (aOutput1 == null)) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ GT_Recipe tRecipe = new GT_Recipe(
+ new ItemStack[] { aInput1, aCircuit },
+ new ItemStack[] { aOutput1 },
+ null,
+ null,
+ null,
+ null,
+ aDuration,
+ Math.max(aEUt, 1),
+ 0);
+ RecipeMaps.benderRecipes.addRecipe(tRecipe);
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addExtruderRecipe(ItemStack aInput, ItemStack aShape, ItemStack aOutput, int aDuration, int aEUt) {
+ if ((aInput == null) || (aShape == null) || (aOutput == null)) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ RecipeMaps.extruderRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput, aShape },
+ new ItemStack[] { aOutput },
+ null,
+ null,
+ null,
+ aDuration,
+ aEUt,
+ 0);
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addSlicerRecipe(ItemStack aInput, ItemStack aShape, ItemStack aOutput, int aDuration, int aEUt) {
+ if ((aInput == null) || (aShape == null) || (aOutput == null)) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ RecipeMaps.slicerRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput, aShape },
+ new ItemStack[] { aOutput },
+ null,
+ null,
+ null,
+ aDuration,
+ aEUt,
+ 0);
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addOreWasherRecipe(ItemStack aInput, ItemStack aOutput1, ItemStack aOutput2, ItemStack aOutput3,
+ FluidStack aFluidInput, int aDuration, int aEUt) {
+ if ((aInput == null) || (aFluidInput == null)
+ || ((aOutput1 == null) || (aOutput2 == null) || (aOutput3 == null))) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ RecipeMaps.oreWasherRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput },
+ new ItemStack[] { aOutput1, aOutput2, aOutput3 },
+ null,
+ new FluidStack[] { aFluidInput },
+ null,
+ aDuration,
+ aEUt,
+ 0);
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addOreWasherRecipe(ItemStack aInput, ItemStack aOutput1, ItemStack aOutput2, ItemStack aOutput3,
+ FluidStack aFluidInput, int[] aChances, int aDuration, int aEUt) {
+ if ((aInput == null) || (aFluidInput == null)
+ || ((aOutput1 == null) || (aOutput2 == null) || (aOutput3 == null))) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ RecipeMaps.oreWasherRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput },
+ new ItemStack[] { aOutput1, aOutput2, aOutput3 },
+ null,
+ aChances,
+ new FluidStack[] { aFluidInput },
+ null,
+ aDuration,
+ aEUt,
+ 0);
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addImplosionRecipe(ItemStack aInput1, int aInput2, ItemStack aOutput1, ItemStack aOutput2) {
+ if ((aInput1 == null) || (aOutput1 == null)) {
+ return false;
+ }
+ if (aInput2 <= 0) {
+ return false;
+ }
+ int tExplosives = Math.min(aInput2, 64);
+ int tGunpowder = tExplosives << 1; // Worst
+ int tDynamite = Math.max(1, tExplosives >> 1); // good
+ @SuppressWarnings("UnnecessaryLocalVariable")
+ int tTNT = tExplosives; // Slightly better
+ int tITNT = Math.max(1, tExplosives >> 2); // the best
+ // new GT_Recipe(aInput1, aInput2, aOutput1, aOutput2);
+ if (tGunpowder < 65) {
+ RecipeMaps.implosionRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput1, ItemList.Block_Powderbarrel.get(tGunpowder) },
+ new ItemStack[] { aOutput1, aOutput2 },
+ null,
+ null,
+ null,
+ null,
+ 20,
+ 30,
+ 0);
+ }
+ if (tDynamite < 17) {
+ RecipeMaps.implosionRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput1, GT_ModHandler.getIC2Item("dynamite", tDynamite, null) },
+ new ItemStack[] { aOutput1, aOutput2 },
+ null,
+ null,
+ null,
+ null,
+ 20,
+ 30,
+ 0);
+ }
+ RecipeMaps.implosionRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput1, new ItemStack(Blocks.tnt, tTNT) },
+ new ItemStack[] { aOutput1, aOutput2 },
+ null,
+ null,
+ null,
+ null,
+ 20,
+ 30,
+ 0);
+ RecipeMaps.implosionRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput1, GT_ModHandler.getIC2Item("industrialTnt", tITNT, null) },
+ new ItemStack[] { aOutput1, aOutput2 },
+ null,
+ null,
+ null,
+ null,
+ 20,
+ 30,
+ 0);
+
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addDistillationRecipe(ItemStack aInput1, int aInput2, ItemStack aOutput1, ItemStack aOutput2,
+ ItemStack aOutput3, ItemStack aOutput4, int aDuration, int aEUt) {
+ return false;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addUniversalDistillationRecipe(FluidStack aInput, FluidStack[] aOutputs, ItemStack aOutput2,
+ int aDuration, int aEUt) {
+ for (int i = 0; i < Math.min(aOutputs.length, 11); i++) {
+ addDistilleryRecipe(i + 1, aInput, aOutputs[i], aOutput2, aDuration * 2, aEUt / 4, false);
+ }
+
+ return addDistillationTowerRecipe(aInput, aOutputs, aOutput2, aDuration, aEUt);
+ }
+
+ @Override
+ @Deprecated
+ public boolean addDistillationTowerRecipe(FluidStack aInput, FluidStack[] aOutputs, ItemStack aOutput2,
+ int aDuration, int aEUt) {
+ if (aInput == null || aOutputs == null || aOutputs.length < 1 || aOutputs.length > 11) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ RecipeMaps.distillationTowerRecipes.addRecipe(
+ false,
+ null,
+ new ItemStack[] { aOutput2 },
+ null,
+ new FluidStack[] { aInput },
+ aOutputs,
+ aDuration,
+ Math.max(1, aEUt),
+ 0);
+ return false;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addDistillationTowerRecipe(FluidStack aInput, ItemStack[] aCircuit, FluidStack[] aOutputs,
+ ItemStack aOutput2, int aDuration, int aEUt) {
+ if (aInput == null || aOutputs == null || aOutputs.length < 1 || aOutputs.length > 11) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ RecipeMaps.distillationTowerRecipes.addRecipe(
+ false,
+ aCircuit,
+ new ItemStack[] { aOutput2 },
+ null,
+ new FluidStack[] { aInput },
+ aOutputs,
+ aDuration,
+ Math.max(1, aEUt),
+ 0);
+ return false;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addUniversalDistillationRecipewithCircuit(FluidStack aInput, ItemStack[] aCircuit,
+ FluidStack[] aOutputs, ItemStack aOutput2, int aDuration, int aEUt) {
+ for (int i = 0; i < Math.min(aOutputs.length, 11); i++) {
+ addDistilleryRecipe(i + 1, aInput, aOutputs[i], aOutput2, aDuration * 2, aEUt / 4, false);
+ }
+ return addDistillationTowerRecipe(aInput, aCircuit, aOutputs, aOutput2, aDuration, aEUt);
+ }
+
+ @Override
+ @Deprecated
+ public boolean addVacuumFreezerRecipe(ItemStack aInput1, ItemStack aOutput1, int aDuration, int aEUt) {
+ if ((aInput1 == null) || (aOutput1 == null)) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ RecipeMaps.vacuumFreezerRecipes.addRecipe(
+ false,
+ new ItemStack[] { aInput1 },
+ new ItemStack[] { aOutput1 },
+ null,
+ null,
+ null,
+ aDuration,
+ aEUt,
+ 0);
+ FluidStack tInputFluid = GT_Utility.getFluidForFilledItem(aInput1, true);
+ FluidStack tOutputFluid = GT_Utility.getFluidForFilledItem(aOutput1, true);
+ if (tInputFluid != null && tOutputFluid != null) {
+ addVacuumFreezerRecipe(tInputFluid, tOutputFluid, aDuration, aEUt);
+ }
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addVacuumFreezerRecipe(ItemStack aInput1, ItemStack aOutput1, int aDuration) {
+ if ((aInput1 == null) || (aOutput1 == null)) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ addVacuumFreezerRecipe(aInput1, aOutput1, aDuration, 120);
+ FluidStack tInputFluid = GT_Utility.getFluidForFilledItem(aInput1, true);
+ FluidStack tOutputFluid = GT_Utility.getFluidForFilledItem(aOutput1, true);
+ if (tInputFluid != null && tOutputFluid != null) {
+ addVacuumFreezerRecipe(tInputFluid, tOutputFluid, aDuration, 120);
+ }
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addVacuumFreezerRecipe(FluidStack aInput1, FluidStack aOutput1, int aDuration, int aEUt) {
+ if ((aInput1 == null) || (aOutput1 == null)) {
+ return false;
+ }
+ RecipeMaps.vacuumFreezerRecipes.addRecipe(
+ false,
+ null,
+ null,
+ null,
+ new FluidStack[] { aInput1 },
+ new FluidStack[] { aOutput1 },
+ Math.max(1, aDuration),
+ aEUt,
+ 0);
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addVacuumFreezerRecipe(ItemStack[] aItemInput, FluidStack[] aFluidInput, ItemStack[] aItemOutput,
+ FluidStack[] aFluidOutput, int aDuration, int aEUt) {
+ RecipeMaps.vacuumFreezerRecipes.addRecipe(
+ false,
+ aItemInput,
+ aItemOutput,
+ null,
+ aFluidInput,
+ aFluidOutput,
+ Math.max(1, aDuration),
+ Math.max(1, aEUt),
+ 0);
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addGrinderRecipe(ItemStack aInput1, ItemStack aInput2, ItemStack aOutput1, ItemStack aOutput2,
+ ItemStack aOutput3, ItemStack aOutput4) {
+ return false;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addFuel(ItemStack aInput1, ItemStack aOutput1, int aEU, int aType) {
+ if (aInput1 == null) {
+ return false;
+ }
+ new GT_Recipe(aInput1, aOutput1, null, null, null, aEU, aType);
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addSonictronSound(ItemStack aItemStack, String aSoundName) {
+ if ((aItemStack == null) || (aSoundName == null) || (aSoundName.equals(""))) {
+ return false;
+ }
+ GT_Mod.gregtechproxy.mSoundItems.add(aItemStack);
+ GT_Mod.gregtechproxy.mSoundNames.add(aSoundName);
+ if (aSoundName.startsWith("note.")) {
+ GT_Mod.gregtechproxy.mSoundCounts.add(25);
+ } else {
+ GT_Mod.gregtechproxy.mSoundCounts.add(1);
+ }
+ return true;
+ }
+
+ @Deprecated
+ @Override
+ public boolean addChemicalBathRecipe(ItemStack aInput, FluidStack aBathingFluid, ItemStack aOutput1,
+ ItemStack aOutput2, ItemStack aOutput3, FluidStack aFluidOutput, int[] aChances, int aDuration, int aEUt) {
+ return false;
+ }
+
+ @Deprecated
+ @Override
+ public boolean addForgeHammerRecipe(ItemStack aInput1, ItemStack aOutput1, int aDuration, int aEUt) {
+ if ((aInput1 == null) || (aOutput1 == null)) {
+ return false;
+ }
+ RecipeMaps.hammerRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput1 },
+ new ItemStack[] { aOutput1 },
+ null,
+ null,
+ null,
+ aDuration,
+ aEUt,
+ 0);
+ return true;
+ }
+
+ @Deprecated
+ @Override
+ public boolean addForgeHammerRecipe(ItemStack[] ItemInputArray, FluidStack[] FluidInputArray,
+ ItemStack[] ItemOutputArray, FluidStack[] FluidOutputArray, int aDuration, int aEUt) {
+
+ RecipeMaps.hammerRecipes.addRecipe(
+ true,
+ ItemInputArray,
+ ItemOutputArray,
+ null,
+ FluidInputArray,
+ FluidOutputArray,
+ aDuration,
+ aEUt,
+ 0);
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addBoxingRecipe(ItemStack aContainedItem, ItemStack aEmptyBox, ItemStack aFullBox, int aDuration,
+ int aEUt) {
+ if ((aContainedItem == null) || (aFullBox == null)) {
+ return false;
+ }
+ RecipeMaps.packagerRecipes.addRecipe(
+ true,
+ new ItemStack[] { aContainedItem, aEmptyBox },
+ new ItemStack[] { aFullBox },
+ null,
+ null,
+ null,
+ aDuration,
+ aEUt,
+ 0);
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addUnboxingRecipe(ItemStack aFullBox, ItemStack aContainedItem, ItemStack aEmptyBox, int aDuration,
+ int aEUt) {
+ if ((aFullBox == null) || (aContainedItem == null)) {
+ return false;
+ }
+ RecipeMaps.unpackagerRecipes.addRecipe(
+ true,
+ new ItemStack[] { aFullBox },
+ new ItemStack[] { aContainedItem, aEmptyBox },
+ null,
+ null,
+ null,
+ aDuration,
+ aEUt,
+ 0);
+ return true;
+ }
+
+ @Deprecated
+ @Override
+ public boolean addThermalCentrifugeRecipe(ItemStack aInput, ItemStack aOutput1, ItemStack aOutput2,
+ ItemStack aOutput3, int aDuration, int aEUt) {
+ if ((aInput == null) || (aOutput1 == null)) {
+ return false;
+ }
+ RecipeMaps.thermalCentrifugeRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput },
+ new ItemStack[] { aOutput1, aOutput2, aOutput3 },
+ null,
+ null,
+ null,
+ aDuration,
+ aEUt,
+ 0);
+ return true;
+ }
+
+ @Deprecated
+ @Override
+ public boolean addThermalCentrifugeRecipe(ItemStack aInput, ItemStack aOutput1, ItemStack aOutput2,
+ ItemStack aOutput3, int[] aChances, int aDuration, int aEUt) {
+ if ((aInput == null) || (aOutput1 == null)) {
+ return false;
+ }
+ RecipeMaps.thermalCentrifugeRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput },
+ new ItemStack[] { aOutput1, aOutput2, aOutput3 },
+ null,
+ aChances,
+ null,
+ null,
+ aDuration,
+ aEUt,
+ 0);
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addAmplifier(ItemStack aAmplifierItem, int aDuration, int aAmplifierAmountOutputted) {
+ if ((aAmplifierItem == null) || (aAmplifierAmountOutputted <= 0)) {
+ return false;
+ }
+ RecipeMaps.amplifierRecipes.addRecipe(
+ true,
+ new ItemStack[] { aAmplifierItem },
+ null,
+ null,
+ null,
+ new FluidStack[] { Materials.UUAmplifier.getFluid(aAmplifierAmountOutputted) },
+ aDuration,
+ 30,
+ 0);
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addBrewingRecipe(ItemStack aIngredient, Fluid aInput, Fluid aOutput, int aDuration, int aEUt,
+ boolean aHidden) {
+ if ((aIngredient == null) || (aInput == null) || (aOutput == null)) {
+ return false;
+ }
+ GT_Recipe tRecipe = RecipeMaps.brewingRecipes.addRecipe(
+ false,
+ new ItemStack[] { aIngredient },
+ null,
+ null,
+ new FluidStack[] { new FluidStack(aInput, 750) },
+ new FluidStack[] { new FluidStack(aOutput, 750) },
+ aDuration,
+ aEUt,
+ 0);
+ if ((aHidden) && (tRecipe != null)) {
+ tRecipe.mHidden = true;
+ }
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addBrewingRecipe(ItemStack aIngredient, Fluid aInput, Fluid aOutput, boolean aHidden) {
+ return addBrewingRecipe(aIngredient, aInput, aOutput, 128, 4, aHidden);
+ }
+
+ @Override
+ @Deprecated
+ public boolean addBrewingRecipeCustom(ItemStack aIngredient, FluidStack aInput, FluidStack aOutput, int aDuration,
+ int aEUt, boolean aHidden) {
+ if ((aInput == null) || (aOutput == null)) {
+ return false;
+ }
+ GT_Recipe tRecipe = RecipeMaps.brewingRecipes.addRecipe(
+ false,
+ new ItemStack[] { aIngredient },
+ null,
+ null,
+ new FluidStack[] { aInput },
+ new FluidStack[] { aOutput },
+ aDuration,
+ aEUt,
+ 0);
+ if ((aHidden) && (tRecipe != null)) {
+ tRecipe.mHidden = true;
+ }
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addFermentingRecipe(FluidStack aInput, FluidStack aOutput, int aDuration, int aEUt,
+ boolean aHidden) {
+ if ((aInput == null) || (aOutput == null)) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ GT_Recipe tRecipe = RecipeMaps.fermentingRecipes.addRecipe(
+ false,
+ null,
+ null,
+ null,
+ new FluidStack[] { aInput },
+ new FluidStack[] { aOutput },
+ aDuration,
+ aEUt,
+ 0);
+ if ((aHidden) && (tRecipe != null)) {
+ tRecipe.mHidden = true;
+ }
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addFermentingRecipe(FluidStack aInput, FluidStack aOutput, int aDuration, boolean aHidden) {
+ return addFermentingRecipe(aInput, aOutput, aDuration, 2, aHidden);
+ }
+
+ @Override
+ @Deprecated
+ public boolean addDistilleryRecipe(ItemStack aCircuit, FluidStack aInput, FluidStack aOutput,
+ ItemStack aSolidOutput, int aDuration, int aEUt, boolean aHidden) {
+ if ((aInput == null) || (aOutput == null)) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ // reduce the batch size if fluid amount is exceeding
+ int tScale = (Math.max(aInput.amount, aOutput.amount) + 999) / 1000;
+ if (tScale <= 0) tScale = 1;
+ if (tScale > 1) {
+ // trying to find whether there is a better factor
+ for (int i = tScale; i <= 5; i++) {
+ if (aInput.amount % i == 0 && aDuration % i == 0) {
+ tScale = i;
+ break;
+ }
+ }
+ for (int i = tScale; i <= 5; i++) {
+ if (aInput.amount % i == 0 && aDuration % i == 0 && aOutput.amount % i == 0) {
+ tScale = i;
+ break;
+ }
+ }
+ aInput = new FluidStack(aInput.getFluid(), (aInput.amount + tScale - 1) / tScale);
+ aOutput = new FluidStack(aOutput.getFluid(), aOutput.amount / tScale);
+ if (aSolidOutput != null) {
+ ItemData tData = GT_OreDictUnificator.getItemData(aSolidOutput);
+ if (tData != null && (tData.mPrefix == OrePrefixes.dust
+ || OrePrefixes.dust.mFamiliarPrefixes.contains(tData.mPrefix))) {
+ aSolidOutput = GT_OreDictUnificator
+ .getDust(tData.mMaterial.mMaterial, tData.mMaterial.mAmount * aSolidOutput.stackSize / tScale);
+ } else {
+ if (aSolidOutput.stackSize / tScale == 0) aSolidOutput = GT_Values.NI;
+ else aSolidOutput = new ItemStack(aSolidOutput.getItem(), aSolidOutput.stackSize / tScale);
+ }
+ }
+ aDuration = (aDuration + tScale - 1) / tScale;
+ }
+
+ GT_Recipe tRecipe = RecipeMaps.distilleryRecipes.addRecipe(
+ true,
+ new ItemStack[] { aCircuit },
+ new ItemStack[] { aSolidOutput },
+ null,
+ new FluidStack[] { aInput },
+ new FluidStack[] { aOutput },
+ aDuration,
+ aEUt,
+ 0);
+ if ((aHidden) && (tRecipe != null)) {
+ tRecipe.mHidden = true;
+ }
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addDistilleryRecipe(ItemStack aCircuit, FluidStack aInput, FluidStack aOutput, int aDuration,
+ int aEUt, boolean aHidden) {
+ return addDistilleryRecipe(aCircuit, aInput, aOutput, null, aDuration, aEUt, aHidden);
+ }
+
+ @Override
+ @Deprecated
+ public boolean addDistilleryRecipe(int circuitConfig, FluidStack aInput, FluidStack aOutput, ItemStack aSolidOutput,
+ int aDuration, int aEUt, boolean aHidden) {
+ return addDistilleryRecipe(
+ GT_Utility.getIntegratedCircuit(circuitConfig),
+ aInput,
+ aOutput,
+ aSolidOutput,
+ aDuration,
+ aEUt,
+ aHidden);
+ }
+
+ @Override
+ @Deprecated
+ public boolean addDistilleryRecipe(int circuitConfig, FluidStack aInput, FluidStack aOutput, int aDuration,
+ int aEUt, boolean aHidden) {
+ return addDistilleryRecipe(
+ GT_Utility.getIntegratedCircuit(circuitConfig),
+ aInput,
+ aOutput,
+ aDuration,
+ aEUt,
+ aHidden);
+ }
+
+ @Override
+ @Deprecated
+ public boolean addFluidSolidifierRecipe(final ItemStack[] itemInputs, final FluidStack[] fluidInputs,
+ final ItemStack[] itemOutputs, final FluidStack[] fluidOutputs, final int EUPerTick,
+ final int aDurationInTicks) {
+ RecipeMaps.fluidSolidifierRecipes
+ .addRecipe(true, itemInputs, itemOutputs, null, fluidInputs, fluidOutputs, aDurationInTicks, EUPerTick, 0);
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addFluidSolidifierRecipe(ItemStack aMold, FluidStack aInput, ItemStack aOutput, int aDuration,
+ int aEUt) {
+ if ((aMold == null) || (aInput == null) || (aOutput == null)) {
+ return false;
+ }
+ if (aInput.isFluidEqual(Materials.PhasedGold.getMolten(144))) {
+ aInput = Materials.VibrantAlloy.getMolten(aInput.amount);
+ }
+ if (aInput.isFluidEqual(Materials.PhasedIron.getMolten(144))) {
+ aInput = Materials.PulsatingIron.getMolten(aInput.amount);
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ RecipeMaps.fluidSolidifierRecipes.addRecipe(
+ true,
+ new ItemStack[] { aMold },
+ new ItemStack[] { aOutput },
+ null,
+ new FluidStack[] { aInput },
+ null,
+ aDuration,
+ aEUt,
+ 0);
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addFluidSmelterRecipe(ItemStack aInput, ItemStack aRemains, FluidStack aOutput, int aChance,
+ int aDuration, int aEUt) {
+ return addFluidSmelterRecipe(aInput, aRemains, aOutput, aChance, aDuration, aEUt, false);
+ }
+
+ @Override
+ @Deprecated
+ public boolean addFluidSmelterRecipe(ItemStack aInput, ItemStack aRemains, FluidStack aOutput, int aChance,
+ int aDuration, int aEUt, boolean hidden) {
+ if ((aInput == null) || (aOutput == null)) {
+ return false;
+ }
+ if (aOutput.isFluidEqual(Materials.PhasedGold.getMolten(1))) {
+ aOutput = Materials.VibrantAlloy.getMolten(aOutput.amount);
+ }
+ if (aOutput.isFluidEqual(Materials.PhasedIron.getMolten(1))) {
+ aOutput = Materials.PulsatingIron.getMolten(aOutput.amount);
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ GT_Recipe tRecipe = RecipeMaps.fluidExtractionRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput },
+ new ItemStack[] { aRemains },
+ null,
+ new int[] { aChance },
+ null,
+ new FluidStack[] { aOutput },
+ aDuration,
+ aEUt,
+ 0);
+ if ((hidden) && (tRecipe != null)) {
+ tRecipe.mHidden = true;
+ }
+ return true;
+ }
+
+ @Deprecated
+ @Override
+ public boolean addFluidExtractionRecipe(ItemStack aInput, ItemStack aRemains, FluidStack aOutput, int aChance,
+ int aDuration, int aEUt) {
+ if ((aInput == null) || (aOutput == null)) {
+ return false;
+ }
+ if (aOutput.isFluidEqual(Materials.PhasedGold.getMolten(1))) {
+ aOutput = Materials.VibrantAlloy.getMolten(aOutput.amount);
+ }
+ if (aOutput.isFluidEqual(Materials.PhasedIron.getMolten(1))) {
+ aOutput = Materials.PulsatingIron.getMolten(aOutput.amount);
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ RecipeMaps.fluidExtractionRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput },
+ new ItemStack[] { aRemains },
+ null,
+ new int[] { aChance },
+ null,
+ new FluidStack[] { aOutput },
+ aDuration,
+ aEUt,
+ 0);
+ return true;
+ }
+
+ @Deprecated
+ @Override
+ public boolean addFluidCannerRecipe(ItemStack aInput, ItemStack aOutput, FluidStack aFluidInput,
+ FluidStack aFluidOutput) {
+ int aDuration = aFluidOutput == null ? aFluidInput.amount / 62 : aFluidOutput.amount / 62;
+
+ if (aInput == null || aOutput == null) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ RecipeMaps.fluidCannerRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput },
+ new ItemStack[] { aOutput },
+ null,
+ new FluidStack[] { aFluidInput },
+ new FluidStack[] { aFluidOutput },
+ aDuration,
+ 1,
+ 0);
+ return true;
+ }
+
+ @Deprecated
+ @Override
+ public boolean addFluidCannerRecipe(ItemStack aInput, ItemStack aOutput, FluidStack aFluidInput,
+ FluidStack aFluidOutput, int aDuration, int aEUt) {
+ if (aInput == null || aOutput == null) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ RecipeMaps.fluidCannerRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput },
+ new ItemStack[] { aOutput },
+ null,
+ new FluidStack[] { aFluidInput },
+ new FluidStack[] { aFluidOutput },
+ aDuration,
+ aEUt,
+ 0);
+ return true;
+ }
+
+ @Deprecated
+ @Override
+ public boolean addChemicalBathRecipe(ItemStack aInput, FluidStack aBathingFluid, ItemStack aOutput1,
+ ItemStack aOutput2, ItemStack aOutput3, int[] aChances, int aDuration, int aEUt) {
+ if ((aInput == null) || (aBathingFluid == null) || (aOutput1 == null)) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ RecipeMaps.chemicalBathRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput },
+ new ItemStack[] { aOutput1, aOutput2, aOutput3 },
+ null,
+ aChances,
+ new FluidStack[] { aBathingFluid },
+ null,
+ aDuration,
+ aEUt,
+ 0);
+ return true;
+ }
+
+ @Deprecated
+ @Override
+ public boolean addChemicalBathRecipe(ItemStack aInput, FluidStack aBathingFluid, FluidStack aFluidOutput,
+ ItemStack aOutput1, ItemStack aOutput2, ItemStack aOutput3, int[] aChances, int aDuration, int aEUt) {
+ if ((aInput == null) || (aBathingFluid == null) || (aOutput1 == null)) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ RecipeMaps.chemicalBathRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput },
+ new ItemStack[] { aOutput1, aOutput2, aOutput3 },
+ null,
+ aChances,
+ new FluidStack[] { aBathingFluid },
+ new FluidStack[] { aFluidOutput },
+ aDuration,
+ aEUt,
+ 0);
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addElectromagneticSeparatorRecipe(ItemStack aInput, ItemStack aOutput1, ItemStack aOutput2,
+ ItemStack aOutput3, int[] aChances, int aDuration, int aEUt) {
+ if ((aInput == null) || (aOutput1 == null)) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ RecipeMaps.electroMagneticSeparatorRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput },
+ new ItemStack[] { aOutput1, aOutput2, aOutput3 },
+ null,
+ aChances,
+ null,
+ null,
+ aDuration,
+ aEUt,
+ 0);
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addExtractorRecipe(ItemStack aInput, ItemStack aOutput, int aDuration, int aEUt) {
+ if ((aInput == null) || (aOutput == null)) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ RecipeMaps.extractorRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput },
+ new ItemStack[] { aOutput },
+ null,
+ null,
+ null,
+ aDuration,
+ aEUt,
+ 0);
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addPrinterRecipe(ItemStack aInput, FluidStack aFluid, ItemStack aSpecialSlot, ItemStack aOutput,
+ int aDuration, int aEUt) {
+ if ((aInput == null) || (aFluid == null) || (aOutput == null)) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ RecipeMaps.printerRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput },
+ new ItemStack[] { aOutput },
+ aSpecialSlot,
+ null,
+ new FluidStack[] { aFluid },
+ null,
+ aDuration,
+ aEUt,
+ 0);
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addAutoclaveRecipe(ItemStack aInput, FluidStack aFluid, ItemStack aOutput, int aChance,
+ int aDuration, int aEUt, boolean aCleanroom) {
+ return addAutoclaveRecipe(aInput, aFluid, aOutput, aChance, aDuration, aEUt);
+ }
+
+ @Override
+ @Deprecated
+ public boolean addAutoclaveRecipe(ItemStack aInput, FluidStack aFluid, ItemStack aOutput, int aChance,
+ int aDuration, int aEUt) {
+ return addAutoclaveRecipe(aInput, null, aFluid, aOutput, aChance, aDuration, aEUt, false);
+ }
+
+ @Deprecated
+ public boolean addAutoclaveRecipe(ItemStack aInput, ItemStack aCircuit, FluidStack aFluid, ItemStack aOutput,
+ int aChance, int aDuration, int aEUt) {
+ return addAutoclaveRecipe(aInput, aCircuit, aFluid, aOutput, aChance, aDuration, aEUt, false);
+ }
+
+ @Override
+ @Deprecated
+ public boolean addAutoclaveRecipe(ItemStack aInput, ItemStack aCircuit, FluidStack aFluidIn, ItemStack aOutput,
+ int aChance, int aDuration, int aEUt, boolean aCleanroom) {
+ return addAutoclaveRecipe(aInput, aCircuit, aFluidIn, null, aOutput, aChance, aDuration, aEUt, aCleanroom);
+ }
+
+ @Override
+ @Deprecated
+ public boolean addAutoclaveRecipe(ItemStack aInput, ItemStack aCircuit, FluidStack aFluidIn, FluidStack aFluidOut,
+ ItemStack aOutput, int aChance, int aDuration, int aEUt, boolean aCleanroom) {
+ if ((aInput == null) || (aFluidIn == null) || (aOutput == null)) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ if (!GT_Mod.gregtechproxy.mEnableCleanroom) {
+ aCleanroom = false;
+ }
+ RecipeMaps.autoclaveRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput, aCircuit },
+ new ItemStack[] { aOutput },
+ null,
+ new int[] { aChance },
+ new FluidStack[] { aFluidIn },
+ new FluidStack[] { aFluidOut },
+ aDuration,
+ aEUt,
+ aCleanroom ? -200 : 0);
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addAutoclaveSpaceRecipe(ItemStack aInput, FluidStack aFluid, ItemStack aOutput, int aChance,
+ int aDuration, int aEUt, boolean aCleanroom) {
+ return addAutoclaveRecipe(aInput, aFluid, aOutput, aChance, aDuration, aEUt, aCleanroom);
+ }
+
+ @Override
+ @Deprecated
+ public boolean addAutoclaveSpaceRecipe(ItemStack aInput, ItemStack aCircuit, FluidStack aFluid, ItemStack aOutput,
+ int aChance, int aDuration, int aEUt, boolean aCleanroom) {
+ if ((aInput == null) || (aFluid == null) || (aOutput == null)) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ if (!GT_Mod.gregtechproxy.mEnableCleanroom) {
+ aCleanroom = false;
+ }
+ RecipeMaps.autoclaveRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput, aCircuit },
+ new ItemStack[] { aOutput },
+ null,
+ new int[] { aChance },
+ new FluidStack[] { aFluid },
+ null,
+ aDuration,
+ aEUt,
+ aCleanroom ? -100 : 0);
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addAutoclave4Recipe(ItemStack aInput, ItemStack aCircuit, FluidStack aFluidIn, FluidStack aFluidOut,
+ ItemStack[] aOutputs, int[] aChances, int aDuration, int aEUt, boolean aCleanroom) {
+ if ((aInput == null) || (aFluidIn == null) || (aOutputs == null)) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ if (!GT_Mod.gregtechproxy.mEnableCleanroom) {
+ aCleanroom = false;
+ }
+ RecipeMaps.autoclaveRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput, aCircuit },
+ aOutputs,
+ null,
+ aChances,
+ new FluidStack[] { aFluidIn },
+ new FluidStack[] { aFluidOut },
+ aDuration,
+ aEUt,
+ aCleanroom ? -200 : 0);
+ return true;
+ }
+
+ @Deprecated
+ @Override
+ public boolean addMixerRecipe(ItemStack aInput1, ItemStack aInput2, ItemStack aInput3, ItemStack aInput4,
+ FluidStack aFluidInput, FluidStack aFluidOutput, ItemStack aOutput, int aDuration, int aEUt) {
+ return addMixerRecipe(
+ aInput1,
+ aInput2,
+ aInput3,
+ aInput4,
+ null,
+ null,
+ null,
+ null,
+ null,
+ aFluidInput,
+ aFluidOutput,
+ aOutput,
+ aDuration,
+ aEUt);
+ }
+
+ @Deprecated
+ @Override
+ public boolean addMixerRecipe(ItemStack aInput1, ItemStack aInput2, ItemStack aInput3, ItemStack aInput4,
+ ItemStack aInput5, ItemStack aInput6, FluidStack aFluidInput, FluidStack aFluidOutput, ItemStack aOutput,
+ int aDuration, int aEUt) {
+ return addMixerRecipe(
+ aInput1,
+ aInput2,
+ aInput3,
+ aInput4,
+ aInput5,
+ aInput6,
+ null,
+ null,
+ null,
+ aFluidInput,
+ aFluidOutput,
+ aOutput,
+ aDuration,
+ aEUt);
+ }
+
+ @Deprecated
+ @Override
+ public boolean addMixerRecipe(ItemStack aInput1, ItemStack aInput2, ItemStack aInput3, ItemStack aInput4,
+ ItemStack aInput5, ItemStack aInput6, ItemStack aInput7, ItemStack aInput8, ItemStack aInput9,
+ FluidStack aFluidInput, FluidStack aFluidOutput, ItemStack aOutput, int aDuration, int aEUt) {
+ if (((aInput1 == null) && (aFluidInput == null)) || ((aOutput == null) && (aFluidOutput == null))) {
+ return false;
+ }
+ if ((aOutput != null) && (aDuration <= 0)) {
+ return false;
+ }
+ if ((aFluidOutput != null) && (aDuration <= 0)) {
+ return false;
+ }
+ RecipeMaps.mixerRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput1, aInput2, aInput3, aInput4, aInput5, aInput6, aInput7, aInput8, aInput9 },
+ new ItemStack[] { aOutput },
+ null,
+ null,
+ new FluidStack[] { aFluidInput },
+ new FluidStack[] { aFluidOutput },
+ aDuration,
+ aEUt,
+ 0);
+ ItemStack[] itemInputs = { aInput1, aInput2, aInput3, aInput4, aInput5, aInput6, aInput7, aInput8, aInput9 };
+ ItemStack[] itemOutputs = { aOutput };
+ FluidStack[] fluidInputs = { aFluidInput, null, null, null, null, null, null, null, null, null };
+ FluidStack[] fluidOutputs = { aFluidOutput, null };
+
+ byte iNumber = 0;
+ byte oNumber = 0;
+
+ for (ItemStack item : itemInputs) {
+ if (item != null) {
+ if (GT_Utility.getFluidForFilledItem(aInput1, true) != null || GT_Utility.isCellEmpty(item)) {
+ fluidInputs[iNumber + 1] = GT_Utility.convertCellToFluid(item);
+ itemInputs[iNumber] = null;
+ }
+ }
+ iNumber++;
+ }
+
+ for (ItemStack item : itemOutputs) {
+ if (item != null) {
+ if (GT_Utility.getFluidForFilledItem(item, true) != null || GT_Utility.isCellEmpty(item)) {
+ fluidOutputs[oNumber + 1] = GT_Utility.convertCellToFluid(item);
+ itemOutputs[oNumber] = null;
+ }
+ }
+ oNumber++;
+ }
+
+ RecipeMaps.mixerNonCellRecipes
+ .addRecipe(false, itemInputs, itemOutputs, null, null, fluidInputs, fluidOutputs, aDuration, aEUt, 0);
+ return true;
+ }
+
+ @Deprecated
+ @Override
+ public boolean addMixerRecipe(ItemStack[] ItemInputArray, FluidStack[] FluidInputArray, ItemStack[] ItemOutputArray,
+ FluidStack[] FluidOutputArray, int aDuration, int aEUt) {
+ RecipeMaps.mixerRecipes.addRecipe(
+ false,
+ ItemInputArray,
+ ItemOutputArray,
+ null,
+ null,
+ FluidInputArray,
+ FluidOutputArray,
+ aDuration,
+ aEUt,
+ 0);
+ List<ItemStack> tItemInputList;
+ if (ItemInputArray == null) {
+ tItemInputList = new ArrayList<>(1);
+ } else {
+ tItemInputList = new ArrayList<>(Arrays.asList(ItemInputArray));
+ }
+ List<FluidStack> tFluidInputList;
+ if (FluidInputArray != null) {
+ tFluidInputList = new ArrayList<>(Arrays.asList(FluidInputArray));
+ } else {
+ tFluidInputList = new ArrayList<>(1);
+ }
+ for (int i = 0; i < tItemInputList.size(); i++) {
+ if (tItemInputList.get(i) != null) {
+ if (GT_Utility.getFluidForFilledItem(tItemInputList.get(i), true) != null
+ || GT_Utility.isCellEmpty(tItemInputList.get(i))) {
+ tFluidInputList.add(GT_Utility.convertCellToFluid(tItemInputList.get(i)));
+ tItemInputList.set(i, null);
+ }
+ }
+ }
+ List<ItemStack> tItemOutputList;
+ if (ItemOutputArray == null) {
+ tItemOutputList = new ArrayList<>(1);
+ } else {
+ tItemOutputList = new ArrayList<>(Arrays.asList(ItemOutputArray));
+ }
+ List<FluidStack> tFluidOutputList;
+ if (FluidOutputArray != null) {
+ tFluidOutputList = new ArrayList<>(Arrays.asList(FluidOutputArray));
+ } else {
+ tFluidOutputList = new ArrayList<>(1);
+ }
+ for (int i = 0; i < tItemOutputList.size(); i++) {
+ if (tItemOutputList.get(i) != null) {
+ if (GT_Utility.getFluidForFilledItem(tItemOutputList.get(i), true) != null
+ || GT_Utility.isCellEmpty(tItemOutputList.get(i))) {
+ tFluidInputList.add(GT_Utility.convertCellToFluid(tItemOutputList.get(i)));
+ tItemOutputList.set(i, null);
+ }
+ }
+ }
+
+ ItemStack[] tItemInputArray = new ItemStack[tItemInputList.size()];
+ for (int i = 0; i < tItemInputArray.length; i++) tItemInputArray[i] = tItemInputList.get(i);
+
+ FluidStack[] tFluidInputArray = new FluidStack[tFluidInputList.size()];
+ for (int i = 0; i < tFluidInputArray.length; i++) tFluidInputArray[i] = tFluidInputList.get(i);
+
+ ItemStack[] tItemOutputArray = new ItemStack[tItemOutputList.size()];
+ for (int i = 0; i < tItemOutputArray.length; i++) tItemOutputArray[i] = tItemOutputList.get(i);
+
+ FluidStack[] tFluidOutputArray = new FluidStack[tFluidOutputList.size()];
+ for (int i = 0; i < tFluidOutputArray.length; i++) tFluidOutputArray[i] = tFluidOutputList.get(i);
+
+ RecipeMaps.mixerNonCellRecipes.addRecipe(
+ false,
+ tItemInputArray,
+ tItemOutputArray,
+ null,
+ null,
+ tFluidInputArray,
+ tFluidOutputArray,
+ aDuration,
+ aEUt,
+ 0);
+ return true;
+ }
+
+ @Deprecated
+ @Override
+ public boolean addMixerRecipe(ItemStack aInput1, ItemStack aInput2, ItemStack aInput3, ItemStack aInput4,
+ ItemStack aInput5, ItemStack aInput6, ItemStack aInput7, ItemStack aInput8, ItemStack aInput9,
+ FluidStack aFluidInput, FluidStack aFluidOutput, ItemStack aOutput1, ItemStack aOutput2, ItemStack aOutput3,
+ ItemStack aOutput4, int aDuration, int aEUt) {
+ if (((aInput1 == null) && (aFluidInput == null)) || ((aOutput1 == null) && (aFluidOutput == null))) {
+ return false;
+ }
+ if ((aOutput1 != null) && (aDuration <= 0)) {
+ return false;
+ }
+ if ((aFluidOutput != null) && (aDuration <= 0)) {
+ return false;
+ }
+ RecipeMaps.mixerRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput1, aInput2, aInput3, aInput4, aInput5, aInput6, aInput7, aInput8, aInput9 },
+ new ItemStack[] { aOutput1, aOutput2, aOutput3, aOutput4 },
+ null,
+ null,
+ new FluidStack[] { aFluidInput },
+ new FluidStack[] { aFluidOutput },
+ aDuration,
+ aEUt,
+ 0);
+ ItemStack[] itemInputs = { aInput1, aInput2, aInput3, aInput4, aInput5, aInput6, aInput7, aInput8, aInput9 };
+ ItemStack[] itemOutputs = { aOutput1, aOutput2, aOutput3, aOutput4 };
+ FluidStack[] fluidInputs = { aFluidInput, null, null, null, null, null, null, null, null, null };
+ FluidStack[] fluidOutputs = { aFluidOutput, null, null, null, null };
+
+ byte iNumber = 0;
+ byte oNumber = 0;
+
+ for (ItemStack item : itemInputs) {
+ if (item != null) {
+ if (GT_Utility.getFluidForFilledItem(aInput1, true) != null || GT_Utility.isCellEmpty(item)) {
+ fluidInputs[iNumber + 1] = GT_Utility.convertCellToFluid(item);
+ itemInputs[iNumber] = null;
+ }
+ }
+ iNumber++;
+ }
+
+ for (ItemStack item : itemOutputs) {
+ if (item != null) {
+ if (GT_Utility.getFluidForFilledItem(item, true) != null || GT_Utility.isCellEmpty(item)) {
+ fluidOutputs[oNumber + 1] = GT_Utility.convertCellToFluid(item);
+ itemOutputs[oNumber] = null;
+ }
+ }
+ oNumber++;
+ }
+
+ RecipeMaps.mixerNonCellRecipes
+ .addRecipe(false, itemInputs, itemOutputs, null, null, fluidInputs, fluidOutputs, aDuration, aEUt, 0);
+ return true;
+ }
+
+ @Deprecated
+ @Override
+ public boolean addLaserEngraverRecipe(ItemStack aItemToEngrave, ItemStack aLens, ItemStack aEngravedItem,
+ int aDuration, int aEUt) {
+ return addLaserEngraverRecipe(aItemToEngrave, aLens, aEngravedItem, aDuration, aEUt, false);
+ }
+
+ @Deprecated
+ @Override
+ public boolean addLaserEngraverRecipe(ItemStack aItemToEngrave, ItemStack aLens, ItemStack aEngravedItem,
+ int aDuration, int aEUt, boolean aCleanroom) {
+ if ((aItemToEngrave == null) || (aLens == null) || (aEngravedItem == null)) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ if (!GT_Mod.gregtechproxy.mEnableCleanroom) {
+ aCleanroom = false;
+ }
+ RecipeMaps.laserEngraverRecipes.addRecipe(
+ true,
+ new ItemStack[] { aItemToEngrave, aLens },
+ new ItemStack[] { aEngravedItem },
+ null,
+ null,
+ null,
+ aDuration,
+ aEUt,
+ aCleanroom ? -200 : 0);
+ return true;
+ }
+
+ @Deprecated
+ @Override
+ public boolean addLaserEngraverRecipe(ItemStack[] ItemInputArray, FluidStack[] FluidInputArray,
+ ItemStack[] OutputItemArray, FluidStack[] FluidOutputArray, int aDuration, int aEUt, boolean aCleanroom) {
+ RecipeMaps.laserEngraverRecipes.addRecipe(
+ false,
+ ItemInputArray,
+ OutputItemArray,
+ null,
+ null,
+ FluidInputArray,
+ FluidOutputArray,
+ aDuration,
+ aEUt,
+ aCleanroom ? -200 : 0);
+ return true;
+ }
+
+ @Deprecated
+ @Override
+ public boolean addFormingPressRecipe(ItemStack aItemToImprint, ItemStack aForm, ItemStack aImprintedItem,
+ int aDuration, int aEUt) {
+ if ((aItemToImprint == null) || (aForm == null) || (aImprintedItem == null)) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ RecipeMaps.formingPressRecipes.addRecipe(
+ true,
+ new ItemStack[] { aItemToImprint, aForm },
+ new ItemStack[] { aImprintedItem },
+ null,
+ null,
+ null,
+ aDuration,
+ aEUt,
+ 0);
+ return true;
+ }
+
+ @Deprecated
+ @Override
+ public boolean addFormingPressRecipe(ItemStack[] ItemInputArray, ItemStack[] OutputItemArray, int aDuration,
+ int aEUt) {
+ if ((ItemInputArray == null) || (OutputItemArray == null)) {
+ return false;
+ }
+ RecipeMaps.formingPressRecipes
+ .addRecipe(true, ItemInputArray, OutputItemArray, null, null, null, aDuration, aEUt, 0);
+ return true;
+ }
+
+ @Deprecated
+ @Override
+ public boolean addFluidHeaterRecipe(ItemStack aItem, FluidStack aOutput, int aDuration, int aEUt) {
+ if ((aItem == null) || (aOutput == null)) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ RecipeMaps.fluidHeaterRecipes.addRecipe(
+ true,
+ new ItemStack[] { aItem },
+ null,
+ null,
+ null,
+ new FluidStack[] { aOutput },
+ aDuration,
+ aEUt,
+ 0);
+ return true;
+ }
+
+ @Deprecated
+ @Override
+ public boolean addFluidHeaterRecipe(ItemStack aCircuit, FluidStack aInput, FluidStack aOutput, int aDuration,
+ int aEUt) {
+ if ((aInput == null) || (aOutput == null)) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ RecipeMaps.fluidHeaterRecipes.addRecipe(
+ true,
+ new ItemStack[] { aCircuit },
+ null,
+ null,
+ new FluidStack[] { aInput },
+ new FluidStack[] { aOutput },
+ aDuration,
+ aEUt,
+ 0);
+ return true;
+ }
+
+ @Deprecated
+ @Override
+ public boolean addSifterRecipe(ItemStack aItemToSift, ItemStack[] aSiftedItems, int[] aChances, int aDuration,
+ int aEUt) {
+ if ((aItemToSift == null) || (aSiftedItems == null)) {
+ return false;
+ }
+ for (ItemStack tStack : aSiftedItems) {
+ if (tStack != null) {
+ if (aDuration <= 0) {
+ return false;
+ }
+ RecipeMaps.sifterRecipes.addRecipe(
+ true,
+ new ItemStack[] { aItemToSift },
+ aSiftedItems,
+ null,
+ aChances,
+ null,
+ null,
+ aDuration,
+ aEUt,
+ 0);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Deprecated
+ @Override
+ public boolean addSifterRecipe(ItemStack[] ItemInputArray, FluidStack[] FluidInputArray,
+ ItemStack[] OutputItemArray, FluidStack[] FluidOutputArray, int[] aChances, int aDuration, int aEUt,
+ boolean aCleanroom) {
+ RecipeMaps.sifterRecipes.addRecipe(
+ false,
+ ItemInputArray,
+ OutputItemArray,
+ null,
+ aChances,
+ FluidInputArray,
+ FluidOutputArray,
+ aDuration,
+ aEUt,
+ aCleanroom ? -200 : 0);
+ return true;
+ }
+
+ @Deprecated
+ @Override
+ public boolean addArcFurnaceRecipe(ItemStack aInput, ItemStack[] aOutputs, int[] aChances, int aDuration,
+ int aEUt) {
+ return addArcFurnaceRecipe(aInput, aOutputs, aChances, aDuration, aEUt, false);
+ }
+
+ @Deprecated
+ @Override
+ public boolean addArcFurnaceRecipe(ItemStack aInput, ItemStack[] aOutputs, int[] aChances, int aDuration, int aEUt,
+ boolean hidden) {
+ if ((aInput == null) || (aOutputs == null)) {
+ return false;
+ }
+ for (ItemStack tStack : aOutputs) {
+ if (tStack != null) {
+ if (aDuration <= 0) {
+ return false;
+ }
+ GT_Recipe sRecipe = RecipeMaps.arcFurnaceRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput },
+ aOutputs,
+ null,
+ aChances,
+ new FluidStack[] { Materials.Oxygen.getGas(aDuration) },
+ null,
+ aDuration,
+ Math.max(1, aEUt),
+ 0);
+ if ((hidden) && (sRecipe != null)) {
+ sRecipe.mHidden = true;
+ }
+ for (Materials tMaterial : new Materials[] { Materials.Argon, Materials.Nitrogen }) {
+ if (tMaterial.mPlasma != null) {
+ int tPlasmaAmount = (int) Math.max(1L, aDuration / (tMaterial.getMass() * 16L));
+ GT_Recipe tRecipe = RecipeMaps.plasmaArcFurnaceRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput },
+ aOutputs,
+ null,
+ aChances,
+ new FluidStack[] { tMaterial.getPlasma(tPlasmaAmount) },
+ new FluidStack[] { tMaterial.getGas(tPlasmaAmount) },
+ Math.max(1, aDuration / 16),
+ Math.max(1, aEUt / 3),
+ 0);
+ if ((hidden) && (tRecipe != null)) {
+ tRecipe.mHidden = true;
+ }
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addSimpleArcFurnaceRecipe(ItemStack aInput, FluidStack aFluidInput, ItemStack[] aOutputs,
+ int[] aChances, int aDuration, int aEUt) {
+ if ((aInput == null) || (aOutputs == null) || aFluidInput == null) {
+ return false;
+ }
+ for (ItemStack tStack : aOutputs) {
+ if (tStack != null) {
+ if (aDuration <= 0) {
+ return false;
+ }
+ RecipeMaps.arcFurnaceRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput },
+ aOutputs,
+ null,
+ aChances,
+ new FluidStack[] { aFluidInput },
+ null,
+ aDuration,
+ Math.max(1, aEUt),
+ 0);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addPlasmaArcFurnaceRecipe(ItemStack aInput, FluidStack aFluidInput, ItemStack[] aOutputs,
+ int[] aChances, int aDuration, int aEUt) {
+ if ((aInput == null) || (aOutputs == null) || aFluidInput == null) {
+ return false;
+ }
+ for (ItemStack tStack : aOutputs) {
+ if (tStack != null) {
+ if (aDuration <= 0) {
+ return false;
+ }
+ RecipeMaps.plasmaArcFurnaceRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput },
+ aOutputs,
+ null,
+ aChances,
+ new FluidStack[] { aFluidInput },
+ null,
+ aDuration,
+ Math.max(1, aEUt),
+ 0);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addPlasmaArcFurnaceRecipe(ItemStack aInput, FluidStack aFluidInput, ItemStack[] aOutputs,
+ FluidStack aFluidOutput, int[] aChances, int aDuration, int aEUt) {
+ if ((aInput == null) || (aOutputs == null) || aFluidInput == null) {
+ return false;
+ }
+ for (ItemStack tStack : aOutputs) {
+ if (tStack != null) {
+ if (aDuration <= 0) {
+ return false;
+ }
+ RecipeMaps.plasmaArcFurnaceRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput },
+ aOutputs,
+ null,
+ aChances,
+ new FluidStack[] { aFluidInput },
+ new FluidStack[] { aFluidOutput },
+ aDuration,
+ Math.max(1, aEUt),
+ 0);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Deprecated
+ @Override
+ public boolean addPulveriserRecipe(ItemStack aInput, ItemStack[] aOutputs, int[] aChances, int aDuration,
+ int aEUt) {
+ return addPulveriserRecipe(aInput, aOutputs, aChances, aDuration, aEUt, false);
+ }
+
+ @Deprecated
+ @Override
+ public boolean addPulveriserRecipe(ItemStack aInput, ItemStack[] aOutputs, int[] aChances, int aDuration, int aEUt,
+ boolean hidden) {
+ if ((aInput == null) || (aOutputs == null)) {
+ return false;
+ }
+ for (ItemStack tStack : aOutputs) {
+ if (tStack != null) {
+ if (aDuration <= 0) {
+ return false;
+ }
+ GT_Recipe tRecipe = RecipeMaps.maceratorRecipes.addRecipe(
+ true,
+ new ItemStack[] { aInput },
+ aOutputs,
+ null,
+ aChances,
+ null,
+ null,
+ aDuration,
+ aEUt,
+ 0);
+ if ((hidden) && (tRecipe != null)) {
+ tRecipe.mHidden = true;
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addPyrolyseRecipe(ItemStack aInput, FluidStack aFluidInput, int intCircuit, ItemStack aOutput,
+ FluidStack aFluidOutput, int aDuration, int aEUt) {
+ if (aInput == null) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ RecipeMaps.pyrolyseRecipes.addRecipe(
+ false,
+ new ItemStack[] { aInput, ItemList.Circuit_Integrated.getWithDamage(0L, intCircuit) },
+ new ItemStack[] { aOutput },
+ null,
+ null,
+ new FluidStack[] { aFluidInput },
+ new FluidStack[] { aFluidOutput },
+ aDuration,
+ aEUt,
+ 0);
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addCrackingRecipe(FluidStack aInput, FluidStack aOutput, int aDuration, int aEUt) {
+ return false;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addCrackingRecipe(int circuitConfig, FluidStack aInput, FluidStack aInput2, FluidStack aOutput,
+ int aDuration, int aEUt) {
+ if ((aInput == null && aInput2 == null) || (aOutput == null)) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ RecipeMaps.crackingRecipes.addRecipe(
+ false,
+ new ItemStack[] { GT_Utility.getIntegratedCircuit(circuitConfig) },
+ null,
+ null,
+ null,
+ new FluidStack[] { aInput, aInput2 },
+ new FluidStack[] { aOutput },
+ aDuration,
+ aEUt,
+ 0);
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addAssemblylineRecipe(ItemStack aResearchItem, int aResearchTime, ItemStack[] aInputs,
+ FluidStack[] aFluidInputs, ItemStack aOutput, int aDuration, int aEUt) {
+ if ((aResearchItem == null) || (aResearchTime <= 0)
+ || (aInputs == null)
+ || (aOutput == null)
+ || aInputs.length > 15
+ || aInputs.length < 4) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ for (ItemStack tItem : aInputs) {
+ if (tItem == null) {
+ GT_FML_LOGGER.info(
+ "addAssemblingLineRecipe " + aResearchItem.getDisplayName()
+ + " --> "
+ + aOutput.getUnlocalizedName()
+ + " there is some null item in that recipe");
+ }
+ }
+ RecipeMaps.scannerFakeRecipes.addFakeRecipe(
+ false,
+ new ItemStack[] { aResearchItem },
+ new ItemStack[] { aOutput },
+ new ItemStack[] { ItemList.Tool_DataStick.getWithName(1L, "Writes Research result") },
+ null,
+ null,
+ aResearchTime,
+ 30,
+ -201);
+ RecipeMaps.assemblylineVisualRecipes.addFakeRecipe(
+ false,
+ aInputs,
+ new ItemStack[] { aOutput },
+ new ItemStack[] { ItemList.Tool_DataStick.getWithName(1L, "Reads Research result") },
+ aFluidInputs,
+ null,
+ aDuration,
+ aEUt,
+ 0,
+ false);
+ GT_Recipe_AssemblyLine tRecipe = new GT_Recipe_AssemblyLine(
+ aResearchItem,
+ aResearchTime,
+ aInputs,
+ aFluidInputs,
+ aOutput,
+ aDuration,
+ aEUt);
+ GT_Recipe.GT_Recipe_AssemblyLine.sAssemblylineRecipes.add(tRecipe);
+ GT_AssemblyLineUtils.addRecipeToCache(tRecipe);
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addAssemblylineRecipe(ItemStack aResearchItem, int aResearchTime, Object[] aInputs,
+ FluidStack[] aFluidInputs, ItemStack aOutput, int aDuration, int aEUt) {
+ if ((aResearchItem == null) || (aResearchTime <= 0)
+ || (aInputs == null)
+ || (aOutput == null)
+ || aInputs.length > 15
+ || aInputs.length < 4) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ ItemStack[] tInputs = new ItemStack[aInputs.length];
+ ItemStack[][] tAlts = new ItemStack[aInputs.length][];
+ int tPersistentHash = 1;
+ for (int i = 0; i < aInputs.length; i++) {
+ Object obj = aInputs[i];
+ if (obj instanceof ItemStack) {
+ tInputs[i] = (ItemStack) obj;
+ tAlts[i] = null;
+ tPersistentHash = tPersistentHash * 31 + GT_Utility.persistentHash(tInputs[i], true, false);
+ continue;
+ } else if (obj instanceof ItemStack[]aStacks) {
+ if (aStacks.length > 0) {
+ tInputs[i] = aStacks[0];
+ tAlts[i] = Arrays.copyOf(aStacks, aStacks.length);
+ for (ItemStack tAlt : tAlts[i]) {
+ tPersistentHash = tPersistentHash * 31 + GT_Utility.persistentHash(tAlt, true, false);
+ }
+ tPersistentHash *= 31;
+ continue;
+ }
+ } else if (obj instanceof Object[]objs) {
+ List<ItemStack> tList;
+ if (objs.length >= 2 && !(tList = GT_OreDictUnificator.getOres(objs[0])).isEmpty()) {
+ try {
+ // sort the output, so the hash code is stable across launches
+ tList.sort(
+ Comparator
+ .<ItemStack, String>comparing(
+ s -> GameRegistry.findUniqueIdentifierFor(s.getItem()).modId)
+ .thenComparing(s -> GameRegistry.findUniqueIdentifierFor(s.getItem()).name)
+ .thenComparingInt(Items.feather::getDamage)
+ .thenComparingInt(s -> s.stackSize));
+ int tAmount = ((Number) objs[1]).intValue();
+ List<ItemStack> uList = new ArrayList<>();
+ for (ItemStack tStack : tList) {
+ ItemStack uStack = GT_Utility.copyAmount(tAmount, tStack);
+ if (GT_Utility.isStackValid(uStack)) {
+ uList.add(uStack);
+ if (tInputs[i] == null) tInputs[i] = uStack;
+ }
+ }
+ tAlts[i] = uList.toArray(new ItemStack[0]);
+ tPersistentHash = tPersistentHash * 31 + (objs[0] == null ? "" : objs[0].toString()).hashCode();
+ tPersistentHash = tPersistentHash * 31 + tAmount;
+ continue;
+ } catch (Exception ignored) {}
+ }
+ }
+ GT_FML_LOGGER.info(
+ "addAssemblingLineRecipe " + aResearchItem.getDisplayName()
+ + " --> "
+ + aOutput.getUnlocalizedName()
+ + " there is some null item in that recipe");
+ }
+ tPersistentHash = tPersistentHash * 31 + GT_Utility.persistentHash(aResearchItem, true, false);
+ tPersistentHash = tPersistentHash * 31 + GT_Utility.persistentHash(aOutput, true, false);
+ for (FluidStack tFluidInput : aFluidInputs) {
+ if (tFluidInput == null) continue;
+ tPersistentHash = tPersistentHash * 31 + GT_Utility.persistentHash(tFluidInput, true, false);
+ }
+ tPersistentHash = tPersistentHash * 31 + aResearchTime;
+ tPersistentHash = tPersistentHash * 31 + aDuration;
+ tPersistentHash = tPersistentHash * 31 + aEUt;
+ RecipeMaps.scannerFakeRecipes.addFakeRecipe(
+ false,
+ new ItemStack[] { aResearchItem },
+ new ItemStack[] { aOutput },
+ new ItemStack[] { ItemList.Tool_DataStick.getWithName(1L, "Writes Research result") },
+ null,
+ null,
+ aResearchTime,
+ 30,
+ -201);
+ RecipeMaps.assemblylineVisualRecipes.addFakeRecipe(
+ false,
+ tInputs,
+ new ItemStack[] { aOutput },
+ new ItemStack[] { ItemList.Tool_DataStick.getWithName(1L, "Reads Research result") },
+ aFluidInputs,
+ null,
+ aDuration,
+ aEUt,
+ 0,
+ tAlts,
+ false);
+ GT_Recipe_AssemblyLine tRecipe = new GT_Recipe_AssemblyLine(
+ aResearchItem,
+ aResearchTime,
+ tInputs,
+ aFluidInputs,
+ aOutput,
+ aDuration,
+ aEUt,
+ tAlts);
+ tRecipe.setPersistentHash(tPersistentHash);
+ GT_Recipe.GT_Recipe_AssemblyLine.sAssemblylineRecipes.add(tRecipe);
+ GT_AssemblyLineUtils.addRecipeToCache(tRecipe);
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addCircuitAssemblerRecipe(ItemStack[] aInputs, FluidStack aFluidInput, ItemStack aOutput,
+ int aDuration, int aEUt) {
+ return addCircuitAssemblerRecipe(aInputs, aFluidInput, aOutput, aDuration, aEUt, false);
+ }
+
+ @Override
+ @Deprecated
+ public boolean addCircuitAssemblerRecipe(ItemStack[] aInputs, FluidStack aFluidInput, ItemStack aOutput,
+ int aDuration, int aEUt, boolean aCleanroom) {
+
+ if (this.areItemsAndFluidsBothNull(aInputs, new FluidStack[] { aFluidInput })) {
+ return false;
+ }
+
+ if (aDuration <= 0) {
+ return false;
+ }
+
+ if (!GT_Mod.gregtechproxy.mEnableCleanroom) {
+ aCleanroom = false;
+ }
+
+ if (!GT_Utility.isStackValid(aOutput)) {
+ return false;
+ }
+
+ for (int oreID : OreDictionary.getOreIDs(aOutput)) {
+ if (OreDictionary.getOreName(oreID)
+ .startsWith("circuit")) {
+ return this
+ .addCircuitAssemblerRecipeNonOredicted(aInputs, aFluidInput, aOutput, aDuration, aEUt, aCleanroom);
+ }
+ }
+
+ RecipeMaps.circuitAssemblerRecipes.addRecipe(
+ true,
+ aInputs,
+ new ItemStack[] { aOutput },
+ null,
+ new FluidStack[] { aFluidInput },
+ null,
+ aDuration,
+ aEUt,
+ aCleanroom ? -200 : 0);
+ return true;
+ }
+
+ @Deprecated
+ public boolean addCircuitAssemblerRecipeNonOredicted(ItemStack[] aInputs, FluidStack aFluidInput, ItemStack aOutput,
+ int aDuration, int aEUt, boolean aCleanroom) {
+ if ((aInputs == null) || (aOutput == null) || aInputs.length > 6 || aInputs.length < 1) {
+ return false;
+ }
+ if (aDuration <= 0) {
+ return false;
+ }
+ if (!GT_Mod.gregtechproxy.mEnableCleanroom) {
+ aCleanroom = false;
+ }
+ RecipeMaps.circuitAssemblerRecipes.addRecipe(
+ true,
+ aInputs,
+ new ItemStack[] { aOutput },
+ null,
+ null,
+ new FluidStack[] { aFluidInput },
+ null,
+ aDuration,
+ aEUt,
+ aCleanroom ? -200 : 0);
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ public boolean addNanoForgeRecipe(ItemStack[] aInputs, FluidStack[] aFluidInputs, ItemStack[] aOutputs,
+ FluidStack[] aFluidOutputs, int[] aChances, int aDuration, int aEUt, int aSpecialValue) {
+ if (aInputs == null || aOutputs == null || aSpecialValue == 0) return false;
+
+ RecipeMaps.nanoForgeRecipes.addRecipe(
+ new GT_Recipe(
+ false,
+ aInputs,
+ aOutputs,
+ null,
+ aChances,
+ aFluidInputs,
+ aFluidOutputs,
+ aDuration,
+ aEUt,
+ aSpecialValue));
+ return true;
+ }
+
+ @Override
+ public GT_Recipe addIC2ReactorBreederCell(ItemStack input, ItemStack output, boolean reflector, int heatStep,
+ int heatMultiplier, int requiredPulses) {
+ return GT_Values.RA.stdBuilder()
+ .itemInputs(input)
+ .itemOutputs(output)
+ .setNEIDesc(
+ reflector ? "Neutron reflecting Breeder" : "Heat neutral Breeder",
+ String.format("Every %d reactor hull heat", heatStep),
+ String.format("increase speed by %d00%%", heatMultiplier),
+ String.format("Required pulses: %d", requiredPulses))
+ .duration(0)
+ .eut(0)
+ .addTo(RecipeMaps.ic2NuclearFakeRecipes)
+ .stream()
+ .findFirst()
+ .orElse(null);
+ }
+
+ @Override
+ public GT_Recipe addIC2ReactorFuelCell(ItemStack input, ItemStack output, boolean aMox, float aHeat, float aEnergy,
+ int aCells) {
+ // for the mysterious constant 5.0f,
+ // see ic2.core.block.reactor.tileentity.TileEntityNuclearReactorElectric.getOfferedEnergy
+ // don't ask, just accept
+ int pulses = aCells / 2 + 1;
+ float nukePowerMult = 5.0f * ConfigUtil.getFloat(MainConfig.get(), "balance/energy/generator/nuclear");
+ return GT_Values.RA.stdBuilder()
+ .itemInputs(input)
+ .itemOutputs(output)
+ .setNEIDesc(
+ aMox ? "MOX Model" : "Uranium Model",
+ "Neutron Pulse: " + aCells,
+ aCells == 1 ? String.format("Heat: %.1f * n1 * (n1 + 1)", aHeat / 2f)
+ : String.format("Heat: %.1f * (%d + n1) * (%d + n1)", aHeat * aCells / 2f, aCells, aCells + 1),
+ String.format(
+ "Energy: %.1f + n2 * %.1f EU/t",
+ aEnergy * aCells * pulses * nukePowerMult,
+ aEnergy * nukePowerMult))
+ .duration(0)
+ .eut(0)
+ .addTo(RecipeMaps.ic2NuclearFakeRecipes)
+ .stream()
+ .findFirst()
+ .orElse(null);
+ }
+
+ private boolean areItemsAndFluidsBothNull(ItemStack[] items, FluidStack[] fluids) {
+ boolean itemsNull = true;
+ if (items != null) {
+ for (ItemStack itemStack : items) {
+ if (itemStack != null) {
+ itemsNull = false;
+ break;
+ }
+ }
+ }
+ boolean fluidsNull = true;
+ if (fluids != null) {
+ for (FluidStack fluidStack : fluids) {
+ if (fluidStack != null) {
+ fluidsNull = false;
+ break;
+ }
+ }
+ }
+ return itemsNull && fluidsNull;
+ }
+
+ @Override
+ public GT_RecipeBuilder stdBuilder() {
+ return GT_RecipeBuilder.builder();
+ }
+}
diff --git a/src/main/java/gregtech/common/GT_Server.java b/src/main/java/gregtech/common/GT_Server.java
new file mode 100644
index 0000000000..1a2d8e6b5a
--- /dev/null
+++ b/src/main/java/gregtech/common/GT_Server.java
@@ -0,0 +1,36 @@
+package gregtech.common;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.world.World;
+
+public class GT_Server extends GT_Proxy {
+
+ @Override
+ public boolean isServerSide() {
+ return true;
+ }
+
+ @Override
+ public boolean isClientSide() {
+ return false;
+ }
+
+ @Override
+ public boolean isBukkitSide() {
+ return false;
+ }
+
+ @Override
+ public void doSonictronSound(ItemStack aStack, World aWorld, double aX, double aY, double aZ) {}
+
+ @Override
+ public int addArmor(String aPrefix) {
+ return 0;
+ }
+
+ @Override
+ public EntityPlayer getThePlayer() {
+ return null;
+ }
+}
diff --git a/src/main/java/gregtech/common/GT_ThaumcraftCompat.java b/src/main/java/gregtech/common/GT_ThaumcraftCompat.java
new file mode 100644
index 0000000000..43c3dce569
--- /dev/null
+++ b/src/main/java/gregtech/common/GT_ThaumcraftCompat.java
@@ -0,0 +1,285 @@
+package gregtech.common;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import net.minecraft.block.Block;
+import net.minecraft.enchantment.Enchantment;
+import net.minecraft.item.ItemStack;
+import net.minecraft.item.crafting.IRecipe;
+import net.minecraft.util.ResourceLocation;
+
+import gregtech.api.enums.TC_Aspects;
+import gregtech.api.interfaces.internal.IThaumcraftCompat;
+import gregtech.api.util.GT_LanguageManager;
+import gregtech.api.util.GT_Utility;
+import thaumcraft.api.ThaumcraftApi;
+import thaumcraft.api.ThaumcraftApiHelper;
+import thaumcraft.api.aspects.Aspect;
+import thaumcraft.api.aspects.AspectList;
+import thaumcraft.api.crafting.CrucibleRecipe;
+import thaumcraft.api.crafting.IArcaneRecipe;
+import thaumcraft.api.crafting.InfusionEnchantmentRecipe;
+import thaumcraft.api.crafting.InfusionRecipe;
+import thaumcraft.api.research.ResearchCategories;
+import thaumcraft.api.research.ResearchCategoryList;
+import thaumcraft.api.research.ResearchItem;
+import thaumcraft.api.research.ResearchPage;
+
+public class GT_ThaumcraftCompat implements IThaumcraftCompat {
+
+ public GT_ThaumcraftCompat() {
+ TC_Aspects.AER.mAspect = Aspect.AIR;
+ TC_Aspects.ALIENIS.mAspect = Aspect.ELDRITCH;
+ TC_Aspects.AQUA.mAspect = Aspect.WATER;
+ TC_Aspects.ARBOR.mAspect = Aspect.TREE;
+ TC_Aspects.AURAM.mAspect = Aspect.AURA;
+ TC_Aspects.BESTIA.mAspect = Aspect.BEAST;
+ TC_Aspects.COGNITIO.mAspect = Aspect.MIND;
+ TC_Aspects.CORPUS.mAspect = Aspect.FLESH;
+ TC_Aspects.EXANIMIS.mAspect = Aspect.UNDEAD;
+ TC_Aspects.FABRICO.mAspect = Aspect.CRAFT;
+ TC_Aspects.FAMES.mAspect = Aspect.HUNGER;
+ TC_Aspects.GELUM.mAspect = Aspect.COLD;
+ TC_Aspects.GRANUM.mAspect = Aspect.PLANT;
+ TC_Aspects.HERBA.mAspect = Aspect.PLANT;
+ TC_Aspects.HUMANUS.mAspect = Aspect.MAN;
+ TC_Aspects.IGNIS.mAspect = Aspect.FIRE;
+ TC_Aspects.INSTRUMENTUM.mAspect = Aspect.TOOL;
+ TC_Aspects.ITER.mAspect = Aspect.TRAVEL;
+ TC_Aspects.LIMUS.mAspect = Aspect.SLIME;
+ TC_Aspects.LUCRUM.mAspect = Aspect.GREED;
+ TC_Aspects.LUX.mAspect = Aspect.LIGHT;
+ TC_Aspects.MACHINA.mAspect = Aspect.MECHANISM;
+ TC_Aspects.MESSIS.mAspect = Aspect.CROP;
+ TC_Aspects.METALLUM.mAspect = Aspect.METAL;
+ TC_Aspects.METO.mAspect = Aspect.HARVEST;
+ TC_Aspects.MORTUUS.mAspect = Aspect.DEATH;
+ TC_Aspects.MOTUS.mAspect = Aspect.MOTION;
+ TC_Aspects.ORDO.mAspect = Aspect.ORDER;
+ TC_Aspects.PANNUS.mAspect = Aspect.CLOTH;
+ TC_Aspects.PERDITIO.mAspect = Aspect.ENTROPY;
+ TC_Aspects.PERFODIO.mAspect = Aspect.MINE;
+ TC_Aspects.PERMUTATIO.mAspect = Aspect.EXCHANGE;
+ TC_Aspects.POTENTIA.mAspect = Aspect.ENERGY;
+ TC_Aspects.PRAECANTATIO.mAspect = Aspect.MAGIC;
+ TC_Aspects.SANO.mAspect = Aspect.HEAL;
+ TC_Aspects.SENSUS.mAspect = Aspect.SENSES;
+ TC_Aspects.SPIRITUS.mAspect = Aspect.SOUL;
+ TC_Aspects.TELUM.mAspect = Aspect.WEAPON;
+ TC_Aspects.TERRA.mAspect = Aspect.EARTH;
+ TC_Aspects.TEMPESTAS.mAspect = Aspect.WEATHER;
+ TC_Aspects.TENEBRAE.mAspect = Aspect.DARKNESS;
+ TC_Aspects.TUTAMEN.mAspect = Aspect.ARMOR;
+ TC_Aspects.VACUOS.mAspect = Aspect.VOID;
+ TC_Aspects.VENENUM.mAspect = Aspect.POISON;
+ TC_Aspects.VICTUS.mAspect = Aspect.LIFE;
+ TC_Aspects.VINCULUM.mAspect = Aspect.TRAP;
+ TC_Aspects.VITIUM.mAspect = Aspect.TAINT;
+ TC_Aspects.VITREUS.mAspect = Aspect.CRYSTAL;
+ TC_Aspects.VOLATUS.mAspect = Aspect.FLIGHT;
+
+ TC_Aspects.STRONTIO.mAspect = new Aspect(
+ "strontio",
+ 0xEEC2B3,
+ new Aspect[] { Aspect.MIND, Aspect.ENTROPY },
+ new ResourceLocation("gregtech:textures/aspects/" + TC_Aspects.STRONTIO.name() + ".png"),
+ 1);
+ TC_Aspects.NEBRISUM.mAspect = new Aspect(
+ "nebrisum",
+ 0xEEEE7E,
+ new Aspect[] { Aspect.MINE, Aspect.GREED },
+ new ResourceLocation("gregtech:textures/aspects/" + TC_Aspects.NEBRISUM.name() + ".png"),
+ 1);
+ TC_Aspects.ELECTRUM.mAspect = new Aspect(
+ "electrum",
+ 0xC0EEEE,
+ new Aspect[] { Aspect.ENERGY, Aspect.MECHANISM },
+ new ResourceLocation("gregtech:textures/aspects/" + TC_Aspects.ELECTRUM.name() + ".png"),
+ 1);
+ TC_Aspects.MAGNETO.mAspect = new Aspect(
+ "magneto",
+ 0xC0C0C0,
+ new Aspect[] { Aspect.METAL, Aspect.TRAVEL },
+ new ResourceLocation("gregtech:textures/aspects/" + TC_Aspects.MAGNETO.name() + ".png"),
+ 1);
+ TC_Aspects.RADIO.mAspect = new Aspect(
+ "radio",
+ 0xC0FFC0,
+ new Aspect[] { Aspect.LIGHT, Aspect.ENERGY },
+ new ResourceLocation("gregtech:textures/aspects/" + TC_Aspects.RADIO.name() + ".png"),
+ 1);
+
+ GT_LanguageManager.addStringLocalization("tc.aspect.strontio", "Stupidness, Incompetence");
+ GT_LanguageManager.addStringLocalization("tc.aspect.nebrisum", "Cheatyness, Raiding");
+ GT_LanguageManager.addStringLocalization("tc.aspect.electrum", "Electricity, Lightning");
+ GT_LanguageManager.addStringLocalization("tc.aspect.magneto", "Magnetism, Attraction");
+ GT_LanguageManager.addStringLocalization("tc.aspect.radio", "Radiation");
+ }
+
+ private static AspectList getAspectList(List<TC_Aspects.TC_AspectStack> aAspects) {
+ AspectList rAspects = new AspectList();
+ TC_Aspects.TC_AspectStack tAspect;
+ for (Iterator<TC_Aspects.TC_AspectStack> i$ = aAspects.iterator(); i$.hasNext(); rAspects
+ .add((Aspect) tAspect.mAspect.mAspect, (int) tAspect.mAmount)) {
+ tAspect = i$.next();
+ }
+ return rAspects;
+ }
+
+ @Override
+ public Object addResearch(String aResearch, String aName, String aText, String[] aParentResearches,
+ String aCategory, ItemStack aIcon, int aComplexity, int aType, int aX, int aY,
+ List<TC_Aspects.TC_AspectStack> aAspects, ItemStack[] aResearchTriggers, Object[] aPages) {
+ ResearchCategoryList tCategory = ResearchCategories.getResearchList(aCategory);
+ if (tCategory == null) {
+ return null;
+ }
+ for (ResearchItem tResearch : tCategory.research.values()) {
+ if ((tResearch.displayColumn == aX) && (tResearch.displayRow == aY)) {
+ aX += (aX > 0 ? 5 : -5);
+ aY += (aY > 0 ? 5 : -5);
+ }
+ }
+ ResearchItem rResearch = new ResearchItem(
+ aResearch,
+ aCategory,
+ getAspectList(aAspects),
+ aX,
+ aY,
+ aComplexity,
+ aIcon);
+ ArrayList<ResearchPage> tPages = new ArrayList<>(aPages.length);
+ GT_LanguageManager.addStringLocalization("tc.research_name." + aResearch, aName);
+ GT_LanguageManager.addStringLocalization("tc.research_text." + aResearch, "[GT] " + aText);
+ for (Object tPage : aPages) {
+ if ((tPage instanceof String)) {
+ tPages.add(new ResearchPage((String) tPage));
+ } else if ((tPage instanceof IRecipe)) {
+ tPages.add(new ResearchPage((IRecipe) tPage));
+ } else if ((tPage instanceof IArcaneRecipe)) {
+ tPages.add(new ResearchPage((IArcaneRecipe) tPage));
+ } else if ((tPage instanceof CrucibleRecipe)) {
+ tPages.add(new ResearchPage((CrucibleRecipe) tPage));
+ } else if ((tPage instanceof InfusionRecipe)) {
+ tPages.add(new ResearchPage((InfusionRecipe) tPage));
+ } else if ((tPage instanceof InfusionEnchantmentRecipe)) {
+ tPages.add(new ResearchPage((InfusionEnchantmentRecipe) tPage));
+ }
+ }
+ if ((aType & 0x40) != 0) {
+ rResearch.setAutoUnlock();
+ }
+ if ((aType & 0x1) != 0) {
+ rResearch.setSecondary();
+ }
+ if ((aType & 0x20) != 0) {
+ rResearch.setSpecial();
+ }
+ if ((aType & 0x8) != 0) {
+ rResearch.setVirtual();
+ }
+ if ((aType & 0x4) != 0) {
+ rResearch.setHidden();
+ }
+ if ((aType & 0x10) != 0) {
+ rResearch.setRound();
+ }
+ if ((aType & 0x2) != 0) {
+ rResearch.setStub();
+ }
+ if (aParentResearches != null) {
+ ArrayList<String> tParentResearches = new ArrayList<>();
+ Collections.addAll(tParentResearches, aParentResearches);
+ if (tParentResearches.size() > 0) {
+ rResearch.setParents(tParentResearches.toArray(new String[0]));
+ rResearch.setConcealed();
+ }
+ }
+ if (aResearchTriggers != null) {
+ rResearch.setItemTriggers(aResearchTriggers);
+ rResearch.setHidden();
+ }
+ rResearch.setPages(tPages.toArray(new ResearchPage[0]));
+ return rResearch.registerResearchItem();
+ }
+
+ @Override
+ public Object addCrucibleRecipe(String aResearch, Object aInput, ItemStack aOutput,
+ List<TC_Aspects.TC_AspectStack> aAspects) {
+ if ((GT_Utility.isStringInvalid(aResearch)) || (aInput == null)
+ || (aOutput == null)
+ || (aAspects == null)
+ || (aAspects.isEmpty())) {
+ return null;
+ }
+ return ThaumcraftApi.addCrucibleRecipe(
+ aResearch,
+ GT_Utility.copyOrNull(aOutput),
+ ((aInput instanceof ItemStack)) || ((aInput instanceof ArrayList)) ? aInput : aInput.toString(),
+ getAspectList(aAspects));
+ }
+
+ @Override
+ public Object addInfusionRecipe(String aResearch, ItemStack aMainInput, ItemStack[] aSideInputs, ItemStack aOutput,
+ int aInstability, List<TC_Aspects.TC_AspectStack> aAspects) {
+ if ((GT_Utility.isStringInvalid(aResearch)) || (aMainInput == null)
+ || (aSideInputs == null)
+ || (aOutput == null)
+ || (aAspects == null)
+ || (aAspects.isEmpty())) {
+ return null;
+ }
+ return ThaumcraftApi.addInfusionCraftingRecipe(
+ aResearch,
+ GT_Utility.copyOrNull(aOutput),
+ aInstability,
+ getAspectList(aAspects),
+ aMainInput,
+ aSideInputs);
+ }
+
+ @Override
+ public Object addInfusionEnchantmentRecipe(String aResearch, Enchantment aEnchantment, int aInstability,
+ List<TC_Aspects.TC_AspectStack> aAspects, ItemStack[] aSideInputs) {
+ if ((GT_Utility.isStringInvalid(aResearch)) || (aSideInputs == null)
+ || (aAspects == null)
+ || (aEnchantment == null)
+ || (aAspects.isEmpty())) {
+ return null;
+ }
+ return ThaumcraftApi
+ .addInfusionEnchantmentRecipe(aResearch, aEnchantment, aInstability, getAspectList(aAspects), aSideInputs);
+ }
+
+ @Override
+ public boolean registerThaumcraftAspectsToItem(ItemStack aExampleStack, List<TC_Aspects.TC_AspectStack> aAspects,
+ String aOreDict) {
+ if (aAspects.isEmpty()) return false;
+ ThaumcraftApi.registerObjectTag(aOreDict, getAspectList(aAspects));
+ return true;
+ }
+
+ @Override
+ public boolean registerThaumcraftAspectsToItem(ItemStack aStack, List<TC_Aspects.TC_AspectStack> aAspects,
+ boolean aAdditive) {
+ if (aAspects.isEmpty()) return false;
+ if (aAdditive) {
+ ThaumcraftApi.registerComplexObjectTag(aStack, getAspectList(aAspects));
+ return true;
+ }
+ AspectList tAlreadyRegisteredAspects = ThaumcraftApiHelper.getObjectAspects(aStack);
+ if (tAlreadyRegisteredAspects == null || tAlreadyRegisteredAspects.size() <= 0) {
+ ThaumcraftApi.registerObjectTag(aStack, getAspectList(aAspects));
+ }
+ return true;
+ }
+
+ @Override
+ public boolean registerPortholeBlacklistedBlock(Block aBlock) {
+ ThaumcraftApi.portableHoleBlackList.add(aBlock);
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/common/GT_UndergroundOil.java b/src/main/java/gregtech/common/GT_UndergroundOil.java
new file mode 100644
index 0000000000..17a5662c09
--- /dev/null
+++ b/src/main/java/gregtech/common/GT_UndergroundOil.java
@@ -0,0 +1,339 @@
+package gregtech.common;
+
+import static gregtech.api.objects.XSTR.XSTR_INSTANCE;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.Objects;
+import java.util.WeakHashMap;
+
+import javax.annotation.Nullable;
+import javax.annotation.ParametersAreNonnullByDefault;
+
+import net.minecraft.world.World;
+import net.minecraft.world.chunk.Chunk;
+import net.minecraftforge.event.world.ChunkDataEvent;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidStack;
+
+import org.apache.commons.lang3.tuple.Pair;
+
+import gregtech.GT_Mod;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.objects.GT_UO_Dimension;
+import gregtech.api.objects.GT_UO_Fluid;
+import gregtech.api.objects.XSTR;
+import gregtech.api.util.GT_ChunkAssociatedData;
+
+/**
+ * Created by Tec on 29.04.2017.
+ */
+public class GT_UndergroundOil {
+
+ public static final short DIVIDER = 5000;
+ private static final GT_UndergroundOilStore STORAGE = new GT_UndergroundOilStore();
+ private static final ChunkData NIL_FLUID_STACK = new ChunkData(-1, null, null, false);
+
+ /**
+ * Effectively just call {@code undergroundOil(te, -1)} for you
+ *
+ * @see #undergroundOil(World, int, int, float)
+ */
+ public static FluidStack undergroundOilReadInformation(IGregTechTileEntity te) {
+ return undergroundOil(
+ te.getWorld()
+ .getChunkFromBlockCoords(te.getXCoord(), te.getZCoord()),
+ -1);
+ }
+
+ /**
+ * Effectively just call {@code undergroundOil(chunk, -1)} for you
+ *
+ * @see #undergroundOil(World, int, int, float)
+ */
+ public static FluidStack undergroundOilReadInformation(Chunk chunk) {
+ return undergroundOil(chunk, -1);
+ }
+
+ /** @see #undergroundOil(World, int, int, float) */
+ public static FluidStack undergroundOil(IGregTechTileEntity te, float readOrDrainCoefficient) {
+ return undergroundOil(
+ te.getWorld()
+ .getChunkFromBlockCoords(te.getXCoord(), te.getZCoord()),
+ readOrDrainCoefficient);
+ }
+
+ // Returns whole content for information purposes -> when drainSpeedCoefficient < 0
+ // Else returns extracted fluidStack if amount > 0, or null otherwise
+ /** @see #undergroundOil(World, int, int, float) */
+ public static FluidStack undergroundOil(Chunk chunk, float readOrDrainCoefficient) {
+ return undergroundOil(chunk.worldObj, chunk.xPosition, chunk.zPosition, readOrDrainCoefficient);
+ }
+
+ /**
+ * Pump fluid or read info.
+ *
+ * @param w a remote World. For a WorldClient it will always tell you null
+ * @param chunkX chunk coordinate X, i.e. blockX >> 4
+ * @param chunkZ chunk coordinate Z, i.e. blockZ >> 4
+ * @param readOrDrainCoefficient how fast to pump. The higher the faster. use negative to read expected current
+ * output
+ * @return null if nothing here, or depleted already, or a client side world
+ */
+ public static FluidStack undergroundOil(World w, int chunkX, int chunkZ, float readOrDrainCoefficient) {
+ if (w.isRemote) return null; // troublemakers go away
+ ChunkData chunkData = STORAGE.get(w, chunkX, chunkZ);
+ if (chunkData.getVein() == null || chunkData.getFluid() == null) // nothing here...
+ return null;
+ // do stuff on it if needed
+ FluidStack fluidInChunk = new FluidStack(chunkData.getFluid(), 0);
+ if (readOrDrainCoefficient >= 0) {
+ int fluidExtracted = (int) Math.floor(chunkData.getAmount() * (double) readOrDrainCoefficient / DIVIDER);
+ double averageDecrease = chunkData.getVein().DecreasePerOperationAmount * (double) readOrDrainCoefficient;
+ int decrease = (int) Math.ceil(averageDecrease);
+ if (fluidExtracted <= 0 || chunkData.amount <= decrease) { // decrease - here it is max value of extraction
+ // for easy check
+ chunkData.setAmount(0);
+ } else {
+ fluidInChunk.amount = fluidExtracted; // give appropriate amount
+ if (XSTR_INSTANCE.nextFloat() < (decrease - averageDecrease)) decrease--; // use XSTR_INSTANCE to
+ // "subtract double from int"
+ // ex.
+ // averageDecrease=3.9
+ // decrease= ceil from 3.9 = 4
+ // decrease-averageDecrease=0.1 -> chance to subtract 1
+ // if XSTR_INSTANCE is < chance then subtract 1
+ chunkData.changeAmount(-decrease); // diminish amount, "randomly" adjusted to double value
+ // (averageDecrease)
+ }
+ } else { // just get info
+ if (chunkData.amount <= DIVIDER) {
+ chunkData.setAmount(0);
+ } else {
+ // get the expected current output
+ fluidInChunk.amount = (int) Math
+ .floor(chunkData.getAmount() * (double) -readOrDrainCoefficient / DIVIDER);
+ }
+ }
+ return fluidInChunk;
+ }
+
+ /**
+ * Get the deposit as if it is never exploited
+ *
+ * @return UO fluid kind and amount, or null if nothing here.
+ */
+ public static Pair<GT_UO_Fluid, Integer> getPristineAmount(World world, int chunkX, int chunkZ) {
+ int dimensionId = world.provider.dimensionId;
+ GT_UO_Dimension dimension = GT_Mod.gregtechproxy.mUndergroundOil.GetDimension(dimensionId);
+ if (dimension == null) return null;
+ // prepare RNG
+ final XSTR tVeinRNG = new XSTR(world.getSeed() + dimensionId * 2L + (chunkX >> 3) + 8267L * (chunkZ >> 3));
+ GT_UO_Fluid uoFluid = dimension.getRandomFluid(tVeinRNG);
+ // nothing here :(
+ if (uoFluid == null || uoFluid.getFluid() == null) return null;
+ // offset each chunk's fluid amount by +-25%
+ // discard random values not for current chunk
+ int veinAverage = uoFluid.getRandomAmount(tVeinRNG);
+ for (int i = 0; i < (((chunkX & 0x7) << 3) | chunkZ & 0x7); i++) {
+ tVeinRNG.next(24);
+ }
+ int amount = (int) ((float) veinAverage * (0.75f + (tVeinRNG.nextFloat() / 2f)));
+ return Pair.of(uoFluid, amount);
+ }
+
+ static void migrate(ChunkDataEvent.Load e) {
+ if (e.getData()
+ .hasKey("GTOIL")
+ && e.getData()
+ .hasKey("GTOILFLUID")) {
+ ChunkData chunkData = STORAGE.get(e.getChunk());
+ Fluid fluid = chunkData.getFluid();
+ if (fluid != null && fluid.getID() == e.getData()
+ .getInteger("GTOILFLUID")) chunkData.setAmount(
+ Math.min(
+ chunkData.getAmount(),
+ e.getData()
+ .getInteger("GTOIL")));
+ }
+ }
+
+ /**
+ * Revamped UO store.
+ * <p>
+ * Primary functionality:
+ *
+ * <ul>
+ * <li>Decouple data storage with chunk, making it possible to pump oil from unloaded chunks</li>
+ * <li>Regen detection. If fluid generation config is changed, chunk fluid will be regenerated.</li>
+ * </ul>
+ *
+ * <h2>Serialized form</h2>
+ * <p>
+ * Since the exact file layout is controlled by the super class, here we only concern how each chunk's data is
+ * written.
+ * <h3>Form A: Empty Chunk</h3>
+ * <ol>
+ * <li>4 bytes of 0</li>
+ * </ol>
+ *
+ * <h3>Form B: Normal Chunk</h3>
+ * <ol>
+ * <li>4 bytes unsigned integer. Vein Hash.</li>
+ * <li>UTF string. Vein Key.</li>
+ * <li>4 bytes signed integer. Fluid amount.</li>
+ * </ol>
+ *
+ * @author glease
+ */
+ @ParametersAreNonnullByDefault
+ private static class GT_UndergroundOilStore extends GT_ChunkAssociatedData<ChunkData> {
+
+ private static final WeakHashMap<GT_UO_Fluid, Integer> hashes = new WeakHashMap<>();
+
+ private GT_UndergroundOilStore() {
+ super("UO", GT_UndergroundOil.ChunkData.class, 64, (byte) 0, false);
+ }
+
+ @Override
+ protected void writeElement(DataOutput output, ChunkData element, World world, int chunkX, int chunkZ)
+ throws IOException {
+ /* see class javadoc for explanation */
+ output.writeInt(element.getVeinHash());
+ if (element.getVeinKey() == null) return;
+ output.writeUTF(element.getVeinKey());
+ if (element.getAmount() > 0 && element.getFluid() != null) {
+ output.writeInt(element.getAmount());
+ } else {
+ output.writeInt(-1);
+ }
+ }
+
+ @Override
+ protected GT_UndergroundOil.ChunkData readElement(DataInput input, int version, World world, int chunkX,
+ int chunkZ) throws IOException {
+ /* see class javadoc for explanation */
+ if (version != 0) throw new IOException("Region file corrupted");
+ GT_UndergroundOil.ChunkData pristine = createElement(world, chunkX, chunkZ);
+ int hash = input.readInt();
+ String veinKey = hash != 0 ? input.readUTF() : null;
+ int amount = hash != 0 ? input.readInt() : -1;
+ if (hash != pristine.veinHash || !Objects.equals(veinKey, pristine.getVeinKey())) {
+ // vein config changed. use regen-ed data.
+ return pristine;
+ }
+ if (hash == 0) return NIL_FLUID_STACK;
+ return new GT_UndergroundOil.ChunkData(
+ amount,
+ GT_Mod.gregtechproxy.mUndergroundOil.GetDimension(world.provider.dimensionId)
+ .getUOFluid(veinKey),
+ veinKey);
+ }
+
+ @Override
+ protected GT_UndergroundOil.ChunkData createElement(World world, int chunkX, int chunkZ) {
+ Pair<GT_UO_Fluid, Integer> pristine = getPristineAmount(world, chunkX, chunkZ);
+ if (pristine == null) return NIL_FLUID_STACK;
+ int dimensionId = world.provider.dimensionId;
+ GT_UO_Dimension dimension = GT_Mod.gregtechproxy.mUndergroundOil.GetDimension(dimensionId);
+ return new GT_UndergroundOil.ChunkData(
+ pristine.getRight(),
+ pristine.getLeft(),
+ dimension.getUOFluidKey(pristine.getLeft()),
+ false);
+ }
+
+ private static int hash(@Nullable GT_UO_Fluid fluid) {
+ if (fluid == null) return 0;
+ int result = fluid.Registry.hashCode();
+ result = 31 * result + fluid.MaxAmount;
+ result = 31 * result + fluid.MinAmount;
+ result = 31 * result + fluid.Chance;
+ result = 31 * result + fluid.DecreasePerOperationAmount;
+ return result == 0 ? 1 : result;
+ }
+ }
+
+ /**
+ * Represent the amount of fluid in a given chunk.
+ */
+ private static final class ChunkData implements GT_ChunkAssociatedData.IData {
+
+ private final Fluid fluid;
+
+ @Nullable
+ private final GT_UO_Fluid vein;
+
+ private final String veinKey;
+ private final int veinHash;
+ private int amount;
+ private boolean dirty;
+
+ private ChunkData(int amount, GT_UO_Fluid veinKey, String veinID) {
+ this(amount, veinKey, veinID, true);
+ }
+
+ private ChunkData(int amount, @Nullable GT_UO_Fluid vein, @Nullable String veinKey, boolean dirty) {
+ this.amount = amount;
+ this.vein = vein;
+ this.dirty = dirty;
+ if (vein == null) {
+ fluid = null;
+ this.veinKey = null;
+ veinHash = 0;
+ } else {
+ fluid = vein.getFluid();
+ this.veinKey = veinKey;
+ veinHash = GT_UndergroundOilStore.hashes.computeIfAbsent(vein, GT_UndergroundOilStore::hash);
+ }
+ }
+
+ /**
+ * The current fluid type. {@code null} if vein is generated to be empty.
+ */
+ @Nullable
+ public Fluid getFluid() {
+ return fluid;
+ }
+
+ /**
+ * Current fluid amount. Might be 0 if empty. Cannot be negative
+ */
+ public int getAmount() {
+ return amount;
+ }
+
+ public void setAmount(int amount) {
+ if (this.amount != amount) dirty = true;
+ this.amount = Math.max(0, amount);
+ }
+
+ public void changeAmount(int delta) {
+ if (delta != 0) dirty = true;
+ this.amount = Math.max(amount + delta, 0);
+ }
+
+ @Nullable
+ public GT_UO_Fluid getVein() {
+ return vein;
+ }
+
+ /**
+ * The vein ID. Might be null if generated to be empty.
+ */
+ @Nullable
+ public String getVeinKey() {
+ return veinKey;
+ }
+
+ public int getVeinHash() {
+ return veinHash;
+ }
+
+ @Override
+ public boolean isSameAsDefault() {
+ return !dirty;
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/GT_Worldgen_GT_Ore_Layer.java b/src/main/java/gregtech/common/GT_Worldgen_GT_Ore_Layer.java
new file mode 100644
index 0000000000..fd260d73a4
--- /dev/null
+++ b/src/main/java/gregtech/common/GT_Worldgen_GT_Ore_Layer.java
@@ -0,0 +1,456 @@
+package gregtech.common;
+
+import static gregtech.api.enums.GT_Values.debugOrevein;
+import static gregtech.api.enums.GT_Values.oreveinPlacerOres;
+import static gregtech.api.enums.GT_Values.oreveinPlacerOresMultiplier;
+
+import java.util.ArrayList;
+import java.util.Random;
+
+import net.minecraft.block.Block;
+import net.minecraft.init.Blocks;
+import net.minecraft.util.MathHelper;
+import net.minecraft.world.World;
+import net.minecraft.world.chunk.IChunkProvider;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.Materials;
+import gregtech.api.util.GT_Log;
+import gregtech.api.world.GT_Worldgen;
+import gregtech.common.blocks.GT_TileEntity_Ores;
+
+public class GT_Worldgen_GT_Ore_Layer extends GT_Worldgen {
+
+ public static ArrayList<GT_Worldgen_GT_Ore_Layer> sList = new ArrayList<>();
+ public static int sWeight = 0;
+ public final short mMinY;
+ public final short mMaxY;
+ public final short mWeight;
+ public final short mDensity;
+ public final short mSize;
+ public final short mPrimaryMeta;
+ public final short mSecondaryMeta;
+ public final short mBetweenMeta;
+ public final short mSporadicMeta;
+ // public final String mBiome;
+ public final String mRestrictBiome;
+ public final boolean mOverworld;
+ public final boolean mNether;
+ public final boolean mEnd;
+ public final boolean mEndAsteroid;
+ public static final int WRONG_BIOME = 0;
+ public static final int WRONG_DIMENSION = 1;
+ public static final int NO_ORE_IN_BOTTOM_LAYER = 2;
+ public static final int NO_OVERLAP = 3;
+ public static final int ORE_PLACED = 4;
+ public static final int NO_OVERLAP_AIR_BLOCK = 5;
+
+ public final boolean mMoon = false, mMars = false, mAsteroid = false;
+ public final String aTextWorldgen = "worldgen.";
+
+ @Deprecated
+ public GT_Worldgen_GT_Ore_Layer(String aName, boolean aDefault, int aMinY, int aMaxY, int aWeight, int aDensity,
+ int aSize, boolean aOverworld, boolean aNether, boolean aEnd, boolean GC_UNUSED1, boolean GC_UNUSED2,
+ boolean GC_UNUSED3, Materials aPrimary, Materials aSecondary, Materials aBetween, Materials aSporadic) {
+ this(
+ aName,
+ aDefault,
+ aMinY,
+ aMaxY,
+ aWeight,
+ aDensity,
+ aSize,
+ aOverworld,
+ aNether,
+ aEnd,
+ aPrimary,
+ aSecondary,
+ aBetween,
+ aSporadic);
+ }
+
+ public GT_Worldgen_GT_Ore_Layer(String aName, boolean aDefault, int aMinY, int aMaxY, int aWeight, int aDensity,
+ int aSize, boolean aOverworld, boolean aNether, boolean aEnd, Materials aPrimary, Materials aSecondary,
+ Materials aBetween, Materials aSporadic) {
+ super(aName, sList, aDefault);
+ this.mOverworld = GregTech_API.sWorldgenFile.get(aTextWorldgen + this.mWorldGenName, "Overworld", aOverworld);
+ this.mNether = GregTech_API.sWorldgenFile.get(aTextWorldgen + this.mWorldGenName, "Nether", aNether);
+ this.mEnd = GregTech_API.sWorldgenFile.get(aTextWorldgen + this.mWorldGenName, "TheEnd", aEnd);
+ this.mEndAsteroid = GregTech_API.sWorldgenFile.get(aTextWorldgen + this.mWorldGenName, "EndAsteroid", aEnd);
+ this.mMinY = ((short) GregTech_API.sWorldgenFile.get(aTextWorldgen + this.mWorldGenName, "MinHeight", aMinY));
+ short mMaxY = ((short) GregTech_API.sWorldgenFile.get(aTextWorldgen + this.mWorldGenName, "MaxHeight", aMaxY));
+ if (mMaxY < (this.mMinY + 9)) {
+ GT_Log.out.println("Oremix " + this.mWorldGenName + " has invalid Min/Max heights!");
+ mMaxY = (short) (this.mMinY + 9);
+ }
+ this.mMaxY = mMaxY;
+ this.mWeight = ((short) GregTech_API.sWorldgenFile
+ .get(aTextWorldgen + this.mWorldGenName, "RandomWeight", aWeight));
+ this.mDensity = ((short) GregTech_API.sWorldgenFile
+ .get(aTextWorldgen + this.mWorldGenName, "Density", aDensity));
+ this.mSize = ((short) Math
+ .max(1, GregTech_API.sWorldgenFile.get(aTextWorldgen + this.mWorldGenName, "Size", aSize)));
+ this.mPrimaryMeta = ((short) GregTech_API.sWorldgenFile
+ .get(aTextWorldgen + this.mWorldGenName, "OrePrimaryLayer", aPrimary.mMetaItemSubID));
+ this.mSecondaryMeta = ((short) GregTech_API.sWorldgenFile
+ .get(aTextWorldgen + this.mWorldGenName, "OreSecondaryLayer", aSecondary.mMetaItemSubID));
+ this.mBetweenMeta = ((short) GregTech_API.sWorldgenFile
+ .get(aTextWorldgen + this.mWorldGenName, "OreSporadiclyInbetween", aBetween.mMetaItemSubID));
+ this.mSporadicMeta = ((short) GregTech_API.sWorldgenFile
+ .get(aTextWorldgen + this.mWorldGenName, "OreSporaticlyAround", aSporadic.mMetaItemSubID));
+ this.mRestrictBiome = GregTech_API.sWorldgenFile
+ .get(aTextWorldgen + this.mWorldGenName, "RestrictToBiomeName", "None");
+
+ if (this.mEnabled) {
+ sWeight += this.mWeight;
+ }
+ }
+
+ @Override
+ public int executeWorldgenChunkified(World aWorld, Random aRandom, String aBiome, int aDimensionType, int aChunkX,
+ int aChunkZ, int aSeedX, int aSeedZ, IChunkProvider aChunkGenerator, IChunkProvider aChunkProvider) {
+ if (mWorldGenName.equals("NoOresInVein")) {
+ if (debugOrevein) GT_Log.out.println(" NoOresInVein");
+ // Return a special empty orevein
+ return ORE_PLACED;
+ }
+ if (!isGenerationAllowed(
+ aWorld,
+ aDimensionType,
+ ((aDimensionType == -1) && (this.mNether)) || ((aDimensionType == 0) && (this.mOverworld))
+ || ((aDimensionType == 1) && (this.mEnd)) ? aDimensionType : ~aDimensionType)) {
+ // The following code can be used for debugging, but it spams in logs
+ // if (debugOrevein) { GT_Log.out.println( "Wrong dimension" ); }
+ return WRONG_DIMENSION;
+ }
+
+ if (!this.mRestrictBiome.equals("None") && !(this.mRestrictBiome.equals(aBiome))) {
+ return WRONG_BIOME;
+ }
+ // For optimal performance, this should be done upstream. Meh
+ String tDimensionName = aWorld.provider.getDimensionName();
+ boolean isUnderdark = tDimensionName.equals("Underdark");
+
+ int[] placeCount = new int[4];
+
+ int tMinY = mMinY + aRandom.nextInt(mMaxY - mMinY - 5);
+ // Determine West/East ends of orevein
+ int wXVein = aSeedX - aRandom.nextInt(mSize); // West side
+ int eXVein = aSeedX + 16 + aRandom.nextInt(mSize);
+ // Limit Orevein to only blocks present in current chunk
+ int wX = Math.max(wXVein, aChunkX + 2); // Bias placement by 2 blocks to prevent worldgen cascade.
+ int eX = Math.min(eXVein, aChunkX + 2 + 16);
+
+ // Get a block at the center of the chunk and the bottom of the orevein.
+ Block tBlock = aWorld.getBlock(aChunkX + 7, tMinY, aChunkZ + 9);
+
+ if (wX >= eX) { // No overlap between orevein and this chunk exists in X
+ if (tBlock.isReplaceableOreGen(aWorld, aChunkX + 7, tMinY, aChunkZ + 9, Blocks.stone)
+ || tBlock.isReplaceableOreGen(aWorld, aChunkX + 7, tMinY, aChunkZ + 9, Blocks.netherrack)
+ || tBlock.isReplaceableOreGen(aWorld, aChunkX + 7, tMinY, aChunkZ + 9, Blocks.end_stone)
+ || tBlock.isReplaceableOreGen(aWorld, aChunkX + 7, tMinY, aChunkZ + 9, GregTech_API.sBlockGranites)
+ || tBlock.isReplaceableOreGen(aWorld, aChunkX + 7, tMinY, aChunkZ + 9, GregTech_API.sBlockStones)) {
+ // Didn't reach, but could have placed. Save orevein for future use.
+ return NO_OVERLAP;
+ } else {
+ // Didn't reach, but couldn't place in test spot anywys, try for another orevein
+ return NO_OVERLAP_AIR_BLOCK;
+ }
+ }
+ // Determine North/Sound ends of orevein
+ int nZVein = aSeedZ - aRandom.nextInt(mSize);
+ int sZVein = aSeedZ + 16 + aRandom.nextInt(mSize);
+
+ int nZ = Math.max(nZVein, aChunkZ + 2); // Bias placement by 2 blocks to prevent worldgen cascade.
+ int sZ = Math.min(sZVein, aChunkZ + 2 + 16);
+ if (nZ >= sZ) { // No overlap between orevein and this chunk exists in Z
+ if (tBlock.isReplaceableOreGen(aWorld, aChunkX + 7, tMinY, aChunkZ + 9, Blocks.stone)
+ || tBlock.isReplaceableOreGen(aWorld, aChunkX + 7, tMinY, aChunkZ + 9, Blocks.netherrack)
+ || tBlock.isReplaceableOreGen(aWorld, aChunkX + 7, tMinY, aChunkZ + 9, Blocks.end_stone)
+ || tBlock.isReplaceableOreGen(aWorld, aChunkX + 7, tMinY, aChunkZ + 9, GregTech_API.sBlockGranites)
+ || tBlock.isReplaceableOreGen(aWorld, aChunkX + 7, tMinY, aChunkZ + 9, GregTech_API.sBlockStones)) {
+ // Didn't reach, but could have placed. Save orevein for future use.
+ return NO_OVERLAP;
+ } else {
+ // Didn't reach, but couldn't place in test spot anywys, try for another orevein
+ return NO_OVERLAP_AIR_BLOCK;
+ }
+ }
+
+ if (debugOrevein) {
+ GT_Log.out.print(
+ "Trying Orevein:" + this.mWorldGenName
+ + " Dimension="
+ + tDimensionName
+ + " mX="
+ + aChunkX / 16
+ + " mZ="
+ + aChunkZ / 16
+ + " oreseedX="
+ + aSeedX / 16
+ + " oreseedZ="
+ + aSeedZ / 16
+ + " cY="
+ + tMinY);
+ }
+ // Adjust the density down the more chunks we are away from the oreseed. The 5 chunks surrounding the seed
+ // should always be max density due to truncation of Math.sqrt().
+ int localDensity = Math.max(
+ 1,
+ this.mDensity / ((int) Math
+ .sqrt(2 + Math.pow(aChunkX / 16 - aSeedX / 16, 2) + Math.pow(aChunkZ / 16 - aSeedZ / 16, 2))));
+
+ // To allow for early exit due to no ore placed in the bottom layer (probably because we are in the sky), unroll
+ // 1 pass through the loop
+ // Now we do bottom-level-first oregen, and work our way upwards.
+ // Layer -1 Secondary and Sporadic
+ int level = tMinY - 1; // Dunno why, but the first layer is actually played one below tMinY. Go figure.
+ for (int tX = wX; tX < eX; tX++) {
+ int placeX = Math
+ .max(1, Math.max(MathHelper.abs_int(wXVein - tX), MathHelper.abs_int(eXVein - tX)) / localDensity);
+ for (int tZ = nZ; tZ < sZ; tZ++) {
+ int placeZ = Math
+ .max(1, Math.max(MathHelper.abs_int(sZVein - tZ), MathHelper.abs_int(nZVein - tZ)) / localDensity);
+ if (((aRandom.nextInt(placeZ) == 0) || (aRandom.nextInt(placeX) == 0)) && (this.mSecondaryMeta > 0)) {
+ if (GT_TileEntity_Ores
+ .setOreBlock(aWorld, tX, level, tZ, this.mSecondaryMeta, false, isUnderdark)) {
+ placeCount[1]++;
+ }
+ } else
+ if ((aRandom.nextInt(7) == 0) && ((aRandom.nextInt(placeZ) == 0) || (aRandom.nextInt(placeX) == 0))
+ && (this.mSporadicMeta > 0)) { // Sporadics are reduce by 1/7 to compensate
+ if (GT_TileEntity_Ores
+ .setOreBlock(aWorld, tX, level, tZ, this.mSporadicMeta, false, isUnderdark))
+ placeCount[3]++;
+ }
+ }
+ }
+ if ((placeCount[1] + placeCount[3]) == 0) {
+ if (debugOrevein) GT_Log.out.println(" No ore in bottom layer");
+ return NO_ORE_IN_BOTTOM_LAYER; // Exit early, didn't place anything in the bottom layer
+ }
+ // Layers 0 & 1 Secondary and Sporadic
+ for (level = tMinY; level < (tMinY + 2); level++) {
+ for (int tX = wX; tX < eX; tX++) {
+ int placeX = Math
+ .max(1, Math.max(MathHelper.abs_int(wXVein - tX), MathHelper.abs_int(eXVein - tX)) / localDensity);
+ for (int tZ = nZ; tZ < sZ; tZ++) {
+ int placeZ = Math.max(
+ 1,
+ Math.max(MathHelper.abs_int(sZVein - tZ), MathHelper.abs_int(nZVein - tZ)) / localDensity);
+ if (((aRandom.nextInt(placeZ) == 0) || (aRandom.nextInt(placeX) == 0))
+ && (this.mSecondaryMeta > 0)) {
+ if (GT_TileEntity_Ores
+ .setOreBlock(aWorld, tX, level, tZ, this.mSecondaryMeta, false, isUnderdark)) {
+ placeCount[1]++;
+ }
+ } else if ((aRandom.nextInt(7) == 0)
+ && ((aRandom.nextInt(placeZ) == 0) || (aRandom.nextInt(placeX) == 0))
+ && (this.mSporadicMeta > 0)) { // Sporadics are reduce by 1/7 to compensate
+ if (GT_TileEntity_Ores
+ .setOreBlock(aWorld, tX, level, tZ, this.mSporadicMeta, false, isUnderdark))
+ placeCount[3]++;
+ }
+ }
+ }
+ }
+ // Layer 2 is Secondary, in-between, and sporadic
+ for (int tX = wX; tX < eX; tX++) {
+ int placeX = Math
+ .max(1, Math.max(MathHelper.abs_int(wXVein - tX), MathHelper.abs_int(eXVein - tX)) / localDensity);
+ for (int tZ = nZ; tZ < sZ; tZ++) {
+ int placeZ = Math
+ .max(1, Math.max(MathHelper.abs_int(sZVein - tZ), MathHelper.abs_int(nZVein - tZ)) / localDensity);
+ if ((aRandom.nextInt(2) == 0) && ((aRandom.nextInt(placeZ) == 0) || (aRandom.nextInt(placeX) == 0))
+ && (this.mBetweenMeta > 0)) { // Between are reduce by 1/2 to compensate
+ if (GT_TileEntity_Ores.setOreBlock(aWorld, tX, level, tZ, this.mBetweenMeta, false, isUnderdark)) {
+ placeCount[2]++;
+ }
+ } else if (((aRandom.nextInt(placeZ) == 0) || (aRandom.nextInt(placeX) == 0))
+ && (this.mSecondaryMeta > 0)) {
+ if (GT_TileEntity_Ores
+ .setOreBlock(aWorld, tX, level, tZ, this.mSecondaryMeta, false, isUnderdark)) {
+ placeCount[1]++;
+ }
+ } else
+ if ((aRandom.nextInt(7) == 0) && ((aRandom.nextInt(placeZ) == 0) || (aRandom.nextInt(placeX) == 0))
+ && (this.mSporadicMeta > 0)) { // Sporadics are reduce by 1/7 to compensate
+ if (GT_TileEntity_Ores
+ .setOreBlock(aWorld, tX, level, tZ, this.mSporadicMeta, false, isUnderdark))
+ placeCount[3]++;
+ }
+ }
+ }
+ level++; // Increment level to next layer
+ // Layer 3 is In-between, and sporadic
+ for (int tX = wX; tX < eX; tX++) {
+ int placeX = Math
+ .max(1, Math.max(MathHelper.abs_int(wXVein - tX), MathHelper.abs_int(eXVein - tX)) / localDensity);
+ for (int tZ = nZ; tZ < sZ; tZ++) {
+ int placeZ = Math
+ .max(1, Math.max(MathHelper.abs_int(sZVein - tZ), MathHelper.abs_int(nZVein - tZ)) / localDensity);
+ if ((aRandom.nextInt(2) == 0) && ((aRandom.nextInt(placeZ) == 0) || (aRandom.nextInt(placeX) == 0))
+ && (this.mBetweenMeta > 0)) { // Between are reduce by 1/2 to compensate
+ if (GT_TileEntity_Ores.setOreBlock(aWorld, tX, level, tZ, this.mBetweenMeta, false, isUnderdark)) {
+ placeCount[2]++;
+ }
+ } else
+ if ((aRandom.nextInt(7) == 0) && ((aRandom.nextInt(placeZ) == 0) || (aRandom.nextInt(placeX) == 0))
+ && (this.mSporadicMeta > 0)) { // Sporadics are reduce by 1/7 to compensate
+ if (GT_TileEntity_Ores
+ .setOreBlock(aWorld, tX, level, tZ, this.mSporadicMeta, false, isUnderdark))
+ placeCount[3]++;
+ }
+ }
+ }
+ level++; // Increment level to next layer
+ // Layer 4 is In-between, Primary and sporadic
+ for (int tX = wX; tX < eX; tX++) {
+ int placeX = Math
+ .max(1, Math.max(MathHelper.abs_int(wXVein - tX), MathHelper.abs_int(eXVein - tX)) / localDensity);
+ for (int tZ = nZ; tZ < sZ; tZ++) {
+ int placeZ = Math
+ .max(1, Math.max(MathHelper.abs_int(sZVein - tZ), MathHelper.abs_int(nZVein - tZ)) / localDensity);
+ if ((aRandom.nextInt(2) == 0) && ((aRandom.nextInt(placeZ) == 0) || (aRandom.nextInt(placeX) == 0))
+ && (this.mBetweenMeta > 0)) { // Between are reduce by 1/2 to compensate
+ if (GT_TileEntity_Ores.setOreBlock(aWorld, tX, level, tZ, this.mBetweenMeta, false, isUnderdark)) {
+ placeCount[2]++;
+ }
+ } else
+ if (((aRandom.nextInt(placeZ) == 0) || (aRandom.nextInt(placeX) == 0)) && (this.mPrimaryMeta > 0)) {
+ if (GT_TileEntity_Ores
+ .setOreBlock(aWorld, tX, level, tZ, this.mPrimaryMeta, false, isUnderdark)) {
+ placeCount[1]++;
+ }
+ } else if ((aRandom.nextInt(7) == 0)
+ && ((aRandom.nextInt(placeZ) == 0) || (aRandom.nextInt(placeX) == 0))
+ && (this.mSporadicMeta > 0)) { // Sporadics are reduce by 1/7 to compensate
+ if (GT_TileEntity_Ores
+ .setOreBlock(aWorld, tX, level, tZ, this.mSporadicMeta, false, isUnderdark))
+ placeCount[3]++;
+ }
+ }
+ }
+ level++; // Increment level to next layer
+ // Layer 5 is In-between, Primary and sporadic
+ for (int tX = wX; tX < eX; tX++) {
+ int placeX = Math
+ .max(1, Math.max(MathHelper.abs_int(wXVein - tX), MathHelper.abs_int(eXVein - tX)) / localDensity);
+ for (int tZ = nZ; tZ < sZ; tZ++) {
+ int placeZ = Math
+ .max(1, Math.max(MathHelper.abs_int(sZVein - tZ), MathHelper.abs_int(nZVein - tZ)) / localDensity);
+ if ((aRandom.nextInt(2) == 0) && ((aRandom.nextInt(placeZ) == 0) || (aRandom.nextInt(placeX) == 0))
+ && (this.mBetweenMeta > 0)) { // Between are reduce by 1/2 to compensate
+ if (GT_TileEntity_Ores.setOreBlock(aWorld, tX, level, tZ, this.mBetweenMeta, false, isUnderdark)) {
+ placeCount[2]++;
+ }
+ } else
+ if (((aRandom.nextInt(placeZ) == 0) || (aRandom.nextInt(placeX) == 0)) && (this.mPrimaryMeta > 0)) {
+ if (GT_TileEntity_Ores
+ .setOreBlock(aWorld, tX, level, tZ, this.mPrimaryMeta, false, isUnderdark)) {
+ placeCount[1]++;
+ }
+ } else if ((aRandom.nextInt(7) == 0)
+ && ((aRandom.nextInt(placeZ) == 0) || (aRandom.nextInt(placeX) == 0))
+ && (this.mSporadicMeta > 0)) { // Sporadics are reduce by 1/7 to compensate
+ if (GT_TileEntity_Ores
+ .setOreBlock(aWorld, tX, level, tZ, this.mSporadicMeta, false, isUnderdark))
+ placeCount[3]++;
+ }
+ }
+ }
+ level++; // Increment level to next layer
+ // Layer 6 is Primary and sporadic
+ for (int tX = wX; tX < eX; tX++) {
+ int placeX = Math
+ .max(1, Math.max(MathHelper.abs_int(wXVein - tX), MathHelper.abs_int(eXVein - tX)) / localDensity);
+ for (int tZ = nZ; tZ < sZ; tZ++) {
+ int placeZ = Math
+ .max(1, Math.max(MathHelper.abs_int(sZVein - tZ), MathHelper.abs_int(nZVein - tZ)) / localDensity);
+ if (((aRandom.nextInt(placeZ) == 0) || (aRandom.nextInt(placeX) == 0)) && (this.mPrimaryMeta > 0)) {
+ if (GT_TileEntity_Ores.setOreBlock(aWorld, tX, level, tZ, this.mPrimaryMeta, false, isUnderdark)) {
+ placeCount[1]++;
+ }
+ } else
+ if ((aRandom.nextInt(7) == 0) && ((aRandom.nextInt(placeZ) == 0) || (aRandom.nextInt(placeX) == 0))
+ && (this.mSporadicMeta > 0)) { // Sporadics are reduce by 1/7 to compensate
+ if (GT_TileEntity_Ores
+ .setOreBlock(aWorld, tX, level, tZ, this.mSporadicMeta, false, isUnderdark))
+ placeCount[3]++;
+ }
+ }
+ }
+ level++; // Increment level to next layer
+ // Layer 7 is Primary and sporadic
+ for (int tX = wX; tX < eX; tX++) {
+ int placeX = Math
+ .max(1, Math.max(MathHelper.abs_int(wXVein - tX), MathHelper.abs_int(eXVein - tX)) / localDensity);
+ for (int tZ = nZ; tZ < sZ; tZ++) {
+ int placeZ = Math
+ .max(1, Math.max(MathHelper.abs_int(sZVein - tZ), MathHelper.abs_int(nZVein - tZ)) / localDensity);
+ if (((aRandom.nextInt(placeZ) == 0) || (aRandom.nextInt(placeX) == 0)) && (this.mPrimaryMeta > 0)) {
+ if (GT_TileEntity_Ores.setOreBlock(aWorld, tX, level, tZ, this.mPrimaryMeta, false, isUnderdark)) {
+ placeCount[1]++;
+ }
+ } else
+ if ((aRandom.nextInt(7) == 0) && ((aRandom.nextInt(placeZ) == 0) || (aRandom.nextInt(placeX) == 0))
+ && (this.mSporadicMeta > 0)) { // Sporadics are reduce by 1/7 to compensate
+ if (GT_TileEntity_Ores
+ .setOreBlock(aWorld, tX, level, tZ, this.mSporadicMeta, false, isUnderdark))
+ placeCount[3]++;
+ }
+ }
+ }
+ // Place small ores for the vein
+ if (oreveinPlacerOres) {
+ int nSmallOres = (eX - wX) * (sZ - nZ) * this.mDensity / 10 * oreveinPlacerOresMultiplier;
+ // Small ores are placed in the whole chunk in which the vein appears.
+ for (int nSmallOresCount = 0; nSmallOresCount < nSmallOres; nSmallOresCount++) {
+ int tX = aRandom.nextInt(16) + aChunkX + 2;
+ int tZ = aRandom.nextInt(16) + aChunkZ + 2;
+ int tY = aRandom.nextInt(160) + 10; // Y height can vary from 10 to 170 for small ores.
+ if (this.mPrimaryMeta > 0)
+ GT_TileEntity_Ores.setOreBlock(aWorld, tX, tY, tZ, this.mPrimaryMeta, true, isUnderdark);
+ tX = aRandom.nextInt(16) + aChunkX + 2;
+ tZ = aRandom.nextInt(16) + aChunkZ + 2;
+ tY = aRandom.nextInt(160) + 10; // Y height can vary from 10 to 170 for small ores.
+ if (this.mSecondaryMeta > 0)
+ GT_TileEntity_Ores.setOreBlock(aWorld, tX, tY, tZ, this.mSecondaryMeta, true, isUnderdark);
+ tX = aRandom.nextInt(16) + aChunkX + 2;
+ tZ = aRandom.nextInt(16) + aChunkZ + 2;
+ tY = aRandom.nextInt(160) + 10; // Y height can vary from 10 to 170 for small ores.
+ if (this.mBetweenMeta > 0)
+ GT_TileEntity_Ores.setOreBlock(aWorld, tX, tY, tZ, this.mBetweenMeta, true, isUnderdark);
+ tX = aRandom.nextInt(16) + aChunkX + 2;
+ tZ = aRandom.nextInt(16) + aChunkZ + 2;
+ tY = aRandom.nextInt(190) + 10; // Y height can vary from 10 to 200 for small ores.
+ if (this.mSporadicMeta > 0)
+ GT_TileEntity_Ores.setOreBlock(aWorld, tX, tY, tZ, this.mSporadicMeta, true, isUnderdark);
+ }
+ }
+ if (debugOrevein) {
+ GT_Log.out.println(
+ " wXVein" + wXVein
+ + " eXVein"
+ + eXVein
+ + " nZVein"
+ + nZVein
+ + " sZVein"
+ + sZVein
+ + " locDen="
+ + localDensity
+ + " Den="
+ + this.mDensity
+ + " Sec="
+ + placeCount[1]
+ + " Spo="
+ + placeCount[3]
+ + " Bet="
+ + placeCount[2]
+ + " Pri="
+ + placeCount[0]);
+ }
+ // Something (at least the bottom layer must have 1 block) must have been placed, return true
+ return ORE_PLACED;
+ }
+}
diff --git a/src/main/java/gregtech/common/GT_Worldgen_GT_Ore_SmallPieces.java b/src/main/java/gregtech/common/GT_Worldgen_GT_Ore_SmallPieces.java
new file mode 100644
index 0000000000..c8219e8361
--- /dev/null
+++ b/src/main/java/gregtech/common/GT_Worldgen_GT_Ore_SmallPieces.java
@@ -0,0 +1,115 @@
+package gregtech.common;
+
+import static gregtech.api.enums.GT_Values.debugSmallOres;
+
+import java.util.ArrayList;
+import java.util.Random;
+
+import net.minecraft.world.World;
+import net.minecraft.world.chunk.IChunkProvider;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.Materials;
+import gregtech.api.util.GT_Log;
+import gregtech.api.world.GT_Worldgen;
+import gregtech.common.blocks.GT_TileEntity_Ores;
+
+public class GT_Worldgen_GT_Ore_SmallPieces extends GT_Worldgen {
+
+ public final short mMinY;
+ public final short mMaxY;
+ public final short mAmount;
+ public final short mMeta;
+ public final boolean mOverworld;
+ public final boolean mNether;
+ public final boolean mEnd;
+ public final boolean mMoon = false, mMars = false, mAsteroid = false;
+ public final String mBiome;
+ public final String aTextWorldgen = "worldgen.";
+ public static ArrayList<GT_Worldgen_GT_Ore_SmallPieces> sList = new ArrayList<>();
+
+ // TODO CHECK IF INSTANTIATION IS CORRECT
+ public GT_Worldgen_GT_Ore_SmallPieces(String aName, boolean aDefault, int aMinY, int aMaxY, int aAmount,
+ boolean aOverworld, boolean aNether, boolean aEnd, Materials aPrimary) {
+ super(aName, GregTech_API.sWorldgenList, aDefault);
+ this.mOverworld = GregTech_API.sWorldgenFile.get(aTextWorldgen + this.mWorldGenName, "Overworld", aOverworld);
+ this.mNether = GregTech_API.sWorldgenFile.get(aTextWorldgen + this.mWorldGenName, "Nether", aNether);
+ this.mEnd = GregTech_API.sWorldgenFile.get(aTextWorldgen + this.mWorldGenName, "TheEnd", aEnd);
+ this.mMinY = ((short) GregTech_API.sWorldgenFile.get(aTextWorldgen + this.mWorldGenName, "MinHeight", aMinY));
+ this.mMaxY = ((short) Math.max(
+ this.mMinY + 1,
+ GregTech_API.sWorldgenFile.get(aTextWorldgen + this.mWorldGenName, "MaxHeight", aMaxY)));
+ this.mAmount = ((short) Math
+ .max(1, GregTech_API.sWorldgenFile.get(aTextWorldgen + this.mWorldGenName, "Amount", aAmount)));
+ this.mMeta = ((short) GregTech_API.sWorldgenFile
+ .get(aTextWorldgen + this.mWorldGenName, "Ore", aPrimary.mMetaItemSubID));
+ this.mBiome = GregTech_API.sWorldgenFile.get(aTextWorldgen + this.mWorldGenName, "BiomeName", "None");
+ sList.add(this);
+ }
+
+ public GT_Worldgen_GT_Ore_SmallPieces(String aName, boolean aDefault, int aMinY, int aMaxY, int aAmount,
+ boolean aOverworld, boolean aNether, boolean aEnd, boolean GC_UNUSED1, boolean GC_UNUSED2, boolean GC_UNUSED3,
+ Materials aPrimary) {
+ super(aName, GregTech_API.sWorldgenList, aDefault);
+ this.mOverworld = GregTech_API.sWorldgenFile.get(aTextWorldgen + this.mWorldGenName, "Overworld", aOverworld);
+ this.mNether = GregTech_API.sWorldgenFile.get(aTextWorldgen + this.mWorldGenName, "Nether", aNether);
+ this.mEnd = GregTech_API.sWorldgenFile.get(aTextWorldgen + this.mWorldGenName, "TheEnd", aEnd);
+ this.mMinY = ((short) GregTech_API.sWorldgenFile.get(aTextWorldgen + this.mWorldGenName, "MinHeight", aMinY));
+ this.mMaxY = ((short) Math.max(
+ this.mMinY + 1,
+ GregTech_API.sWorldgenFile.get(aTextWorldgen + this.mWorldGenName, "MaxHeight", aMaxY)));
+ this.mAmount = ((short) Math
+ .max(1, GregTech_API.sWorldgenFile.get(aTextWorldgen + this.mWorldGenName, "Amount", aAmount)));
+ this.mMeta = ((short) GregTech_API.sWorldgenFile
+ .get(aTextWorldgen + this.mWorldGenName, "Ore", aPrimary.mMetaItemSubID));
+ this.mBiome = GregTech_API.sWorldgenFile.get(aTextWorldgen + this.mWorldGenName, "BiomeName", "None");
+ sList.add(this);
+ }
+
+ @Override
+ public boolean executeWorldgen(World aWorld, Random aRandom, String aBiome, int aDimensionType, int aChunkX,
+ int aChunkZ, IChunkProvider aChunkGenerator, IChunkProvider aChunkProvider) {
+ if (!this.mBiome.equals("None") && !(this.mBiome.equals(aBiome))) {
+ return false; // Not the correct biome for ore mix
+ }
+ if (!isGenerationAllowed(
+ aWorld,
+ aDimensionType,
+ ((aDimensionType == -1) && (this.mNether)) || ((aDimensionType == 0) && (this.mOverworld))
+ || ((aDimensionType == 1) && (this.mEnd)) ? aDimensionType : ~aDimensionType)) {
+ return false;
+ }
+ int count = 0;
+ // For optimal performance, this should be done upstream. Meh
+ String tDimensionName = aWorld.provider.getDimensionName();
+ boolean isUnderdark = tDimensionName.equals("Underdark");
+
+ if (this.mMeta > 0) {
+ int j = Math.max(1, this.mAmount / 2 + aRandom.nextInt(this.mAmount) / 2);
+ for (int i = 0; i < j; i++) {
+ GT_TileEntity_Ores.setOreBlock(
+ aWorld,
+ aChunkX + 8 + aRandom.nextInt(16),
+ this.mMinY + aRandom.nextInt(Math.max(1, this.mMaxY - this.mMinY)),
+ aChunkZ + 8 + aRandom.nextInt(16),
+ this.mMeta,
+ true,
+ isUnderdark);
+ count++;
+ }
+ }
+ if (debugSmallOres) {
+ GT_Log.out.println(
+ "Small Ore:" + this.mWorldGenName
+ + " @ dim="
+ + aDimensionType
+ + " mX="
+ + aChunkX / 16
+ + " mZ="
+ + aChunkZ / 16
+ + " ore="
+ + count);
+ }
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/common/GT_Worldgen_Stone.java b/src/main/java/gregtech/common/GT_Worldgen_Stone.java
new file mode 100644
index 0000000000..835f9d5c67
--- /dev/null
+++ b/src/main/java/gregtech/common/GT_Worldgen_Stone.java
@@ -0,0 +1,295 @@
+package gregtech.common;
+
+import static gregtech.api.enums.GT_Values.debugStones;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Hashtable;
+import java.util.Random;
+
+import net.minecraft.block.Block;
+import net.minecraft.init.Blocks;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.world.World;
+import net.minecraft.world.chunk.IChunkProvider;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.objects.XSTR;
+import gregtech.api.util.GT_Log;
+import gregtech.api.world.GT_Worldgen_Ore;
+import gregtech.common.blocks.GT_Block_Ores_Abstract;
+import gregtech.common.blocks.GT_TileEntity_Ores;
+
+public class GT_Worldgen_Stone extends GT_Worldgen_Ore {
+
+ static final double[] sizeConversion = { 1, 1, 1.333333, 1.333333, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }; // Bias
+ // the
+ // sizes
+ // towards
+ // skinnier
+ // boulders,
+ // ie
+ // more
+ // "shafts"
+ // than
+ // dikes
+ // or
+ // sills.
+
+ public Hashtable<Long, StoneSeeds> validStoneSeeds = new Hashtable<>(1024);
+
+ static class StoneSeeds {
+
+ public boolean mExists;
+
+ StoneSeeds(boolean exists) {
+ mExists = exists;
+ }
+ }
+
+ static class ValidSeeds {
+
+ public int mX;
+ public int mZ;
+
+ ValidSeeds(int x, int z) {
+ this.mX = x;
+ this.mZ = z;
+ }
+ }
+
+ public GT_Worldgen_Stone(String aName, boolean aDefault, Block aBlock, int aBlockMeta, int aDimensionType,
+ int aAmount, int aSize, int aProbability, int aMinY, int aMaxY, Collection<String> aBiomeList,
+ boolean aAllowToGenerateinVoid) {
+ super(
+ aName,
+ aDefault,
+ aBlock,
+ aBlockMeta,
+ aDimensionType,
+ aAmount,
+ aSize,
+ aProbability,
+ aMinY,
+ aMaxY,
+ aBiomeList,
+ aAllowToGenerateinVoid);
+ }
+
+ @Override
+ public boolean executeWorldgen(World aWorld, Random aRandom, String aBiome, int aDimensionType, int aChunkX,
+ int aChunkZ, IChunkProvider aChunkGenerator, IChunkProvider aChunkProvider) {
+ XSTR stoneRNG = new XSTR();
+ ArrayList<ValidSeeds> stones = new ArrayList<>();
+
+ if (!isGenerationAllowed(aWorld, aDimensionType, this.mDimensionType)) {
+ return false;
+ }
+ if (!(this.mBiomeList.isEmpty() || this.mBiomeList.contains(aBiome))) {
+ return false;
+ }
+ // I think the real size of the balls is mSize/8, but the original code was difficult to understand.
+ // Overall there will be less GT stones since they aren't spheres any more. /16 since this code uses it as a
+ // radius.
+ double realSize = mSize / 16;
+ int windowWidth = ((int) realSize) / 16 + 1; // Width of chunks to check for a potential stoneseed
+ // Check stone seeds to see if they have been added
+ for (int x = aChunkX / 16 - windowWidth; x < (aChunkX / 16 + windowWidth + 1); x++) {
+ for (int z = aChunkZ / 16 - windowWidth; z < (aChunkZ / 16 + windowWidth + 1); z++) {
+ long hash = (((aWorld.provider.dimensionId & 0xffL) << 56) | (((long) x & 0x000000000fffffffL) << 28)
+ | ((long) z & 0x000000000fffffffL));
+ if (!validStoneSeeds.containsKey(hash)) {
+ // Determine if RNG says to add stone at this chunk
+ stoneRNG.setSeed(
+ aWorld.getSeed() ^ hash + Math.abs(mBlockMeta)
+ + Math.abs(mSize)
+ + ((GregTech_API.sBlockGranites == mBlock) ? (32768) : (0))); // Don't judge me.
+ // Want different
+ // values for
+ // different block
+ // types
+ if ((this.mProbability <= 1) || (stoneRNG.nextInt(this.mProbability) == 0)) {
+ // Add stone at this chunk
+ validStoneSeeds.put(hash, new StoneSeeds(true));
+ // Add to generation list
+ stones.add(new ValidSeeds(x, z));
+ if (debugStones) GT_Log.out.println(
+ "New stoneseed=" + mWorldGenName + " x=" + x + " z=" + z + " realSize=" + realSize);
+ } else {
+ validStoneSeeds.put(hash, new StoneSeeds(false));
+ }
+ } else {
+ // This chunk has already been checked, check to see if a boulder exists here
+ if (validStoneSeeds.get(hash).mExists) {
+ // Add to generation list
+ stones.add(new ValidSeeds(x, z));
+ }
+ }
+ }
+ }
+
+ boolean result = stones.size() != 0;
+ // Now process each oreseed vs this requested chunk
+ for (; stones.size() != 0; stones.remove(0)) {
+ int x = stones.get(0).mX * 16;
+ int z = stones.get(0).mZ * 16;
+
+ stoneRNG.setSeed(
+ aWorld.getSeed()
+ ^ (((aWorld.provider.dimensionId & 0xffL) << 56) | (((long) x & 0x000000000fffffffL) << 28)
+ | ((long) z & 0x000000000fffffffL)) + Math.abs(mBlockMeta)
+ + Math.abs(mSize)
+ + ((GregTech_API.sBlockGranites == mBlock) ? (32768) : (0))); // Don't judge me
+ for (int i = 0; i < this.mAmount; i++) { // Not sure why you would want more than one in a chunk! Left alone
+ // though.
+ // Locate the stoneseed XYZ. Original code would request an isAir at the seed location, causing a chunk
+ // generation request.
+ // To reduce potential worldgen cascade, we just always try to place a ball and use the check inside the
+ // for loop to prevent
+ // placement instead.
+ int tX = x + stoneRNG.nextInt(16);
+ int tY = mMinY + stoneRNG.nextInt(mMaxY - mMinY);
+ int tZ = z + stoneRNG.nextInt(16);
+
+ // Determine the XYZ sizes of the stoneseed
+ double xSize = sizeConversion[stoneRNG.nextInt(sizeConversion.length)];
+ double ySize = sizeConversion[stoneRNG.nextInt(sizeConversion.length) / 2]; // Skew the ySize towards
+ // the larger sizes, more
+ // long skinny pipes
+ double zSize = sizeConversion[stoneRNG.nextInt(sizeConversion.length)];
+
+ // Equation for an ellipsoid centered around 0,0,0
+ // Sx, Sy, and Sz are size controls (size = 1/S_)
+ // 1 = full size, 1.333 = 75%, 2 = 50%, 4 = 25%
+ // (x * Sx)^2 + (y * Sy)^2 + (z * sZ)^2 <= (mSize)^2
+
+ // So, we setup the intial boundaries to be the size of the boulder plus a block in each direction
+ int tMinX = tX - (int) (realSize / xSize - 1.0);
+ int tMaxX = tX + (int) (realSize / xSize + 2.0);
+ int tMinY = tY - (int) (realSize / ySize - 1.0);
+ int tMaxY = tY + (int) (realSize / ySize + 2.0);
+ int tMinZ = tZ - (int) (realSize / zSize - 1.0);
+ int tMaxZ = tZ + (int) (realSize / zSize + 2.0);
+
+ // If the (tY-ySize) of the stoneseed is air in the current chunk, mark the seed empty and move on.
+ if (aWorld.getBlock(aChunkX + 8, tMinY, aChunkZ + 8)
+ .isAir(aWorld, aChunkX + 8, tMinY, aChunkZ + 8)) {
+ if (debugStones) GT_Log.out.println(
+ mWorldGenName + " tX="
+ + tX
+ + " tY="
+ + tY
+ + " tZ="
+ + tZ
+ + " realSize="
+ + realSize
+ + " xSize="
+ + realSize / xSize
+ + " ySize="
+ + realSize / ySize
+ + " zSize="
+ + realSize / zSize
+ + " tMinY="
+ + tMinY
+ + " tMaxY="
+ + tMaxY
+ + " - Skipped because first requesting chunk would not contain this stone");
+ long hash = (((aWorld.provider.dimensionId & 0xffL) << 56)
+ | (((long) x & 0x000000000fffffffL) << 28)
+ | ((long) z & 0x000000000fffffffL));
+ validStoneSeeds.remove(hash);
+ validStoneSeeds.put(hash, new StoneSeeds(false));
+ }
+
+ // Chop the boundaries by the parts that intersect with the current chunk
+ int wX = Math.max(tMinX, aChunkX + 8);
+ int eX = Math.min(tMaxX, aChunkX + 8 + 16);
+
+ int sZ = Math.max(tMinZ, aChunkZ + 8);
+ int nZ = Math.min(tMaxZ, aChunkZ + 8 + 16);
+
+ if (debugStones) GT_Log.out.println(
+ mWorldGenName + " tX="
+ + tX
+ + " tY="
+ + tY
+ + " tZ="
+ + tZ
+ + " realSize="
+ + realSize
+ + " xSize="
+ + realSize / xSize
+ + " ySize="
+ + realSize / ySize
+ + " zSize="
+ + realSize / zSize
+ + " wX="
+ + wX
+ + " eX="
+ + eX
+ + " tMinY="
+ + tMinY
+ + " tMaxY="
+ + tMaxY
+ + " sZ="
+ + sZ
+ + " nZ="
+ + nZ);
+
+ double rightHandSide = realSize * realSize + 1; // Precalc the right hand side
+ for (int iY = tMinY; iY < tMaxY; iY++) { // Do placement from the bottom up layer up. Maybe better on
+ // cache usage?
+ double yCalc = ((double) (iY - tY) * ySize);
+ yCalc = yCalc * yCalc; // (y*Sy)^2
+ double leftHandSize = yCalc;
+ if (leftHandSize > rightHandSide) {
+ continue; // If Y alone is larger than the RHS, skip the rest of the loops
+ }
+ for (int iX = wX; iX < eX; iX++) {
+ double xCalc = ((double) (iX - tX) * xSize);
+ xCalc = xCalc * xCalc;
+ leftHandSize = yCalc + xCalc;
+ if (leftHandSize > rightHandSide) { // Again, if X and Y is larger than the RHS, skip to the
+ // next value
+ continue;
+ }
+ for (int iZ = sZ; iZ < nZ; iZ++) {
+ double zCalc = ((double) (iZ - tZ) * zSize);
+ zCalc = zCalc * zCalc;
+ leftHandSize = zCalc + xCalc + yCalc;
+ if (leftHandSize <= rightHandSide) {
+ // Yay! We can actually place a block now. (this part copied from original code)
+ Block tTargetedBlock = aWorld.getBlock(iX, iY, iZ);
+ if (tTargetedBlock instanceof GT_Block_Ores_Abstract) {
+ TileEntity tTileEntity = aWorld.getTileEntity(iX, iY, iZ);
+ if ((tTileEntity instanceof GT_TileEntity_Ores)) {
+ if (tTargetedBlock != GregTech_API.sBlockOres1) {
+ ((GT_TileEntity_Ores) tTileEntity).convertOreBlock(aWorld, iX, iY, iZ);
+ }
+ ((GT_TileEntity_Ores) tTileEntity)
+ .overrideOreBlockMaterial(this.mBlock, (byte) this.mBlockMeta);
+ }
+ } else if (((this.mAllowToGenerateinVoid) && (aWorld.getBlock(iX, iY, iZ)
+ .isAir(aWorld, iX, iY, iZ)))
+ || ((tTargetedBlock != null) && ((tTargetedBlock
+ .isReplaceableOreGen(aWorld, iX, iY, iZ, Blocks.stone))
+ || (tTargetedBlock
+ .isReplaceableOreGen(aWorld, iX, iY, iZ, Blocks.stained_hardened_clay))
+ || (tTargetedBlock.isReplaceableOreGen(aWorld, iX, iY, iZ, Blocks.cobblestone))
+ || (tTargetedBlock.isReplaceableOreGen(aWorld, iX, iY, iZ, Blocks.end_stone))
+ || (tTargetedBlock.isReplaceableOreGen(aWorld, iX, iY, iZ, Blocks.netherrack))
+ || (tTargetedBlock
+ .isReplaceableOreGen(aWorld, iX, iY, iZ, GregTech_API.sBlockGranites))
+ || (tTargetedBlock
+ .isReplaceableOreGen(aWorld, iX, iY, iZ, GregTech_API.sBlockStones))))) {
+ aWorld.setBlock(iX, iY, iZ, this.mBlock, this.mBlockMeta, 0);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return result;
+ }
+}
diff --git a/src/main/java/gregtech/common/GT_Worldgenerator.java b/src/main/java/gregtech/common/GT_Worldgenerator.java
new file mode 100644
index 0000000000..7357f42446
--- /dev/null
+++ b/src/main/java/gregtech/common/GT_Worldgenerator.java
@@ -0,0 +1,688 @@
+package gregtech.common;
+
+import static gregtech.api.enums.GT_Values.debugOrevein;
+import static gregtech.api.enums.GT_Values.debugWorldGen;
+import static gregtech.api.enums.GT_Values.oreveinAttempts;
+import static gregtech.api.enums.GT_Values.oreveinMaxPlacementAttempts;
+import static gregtech.api.enums.GT_Values.oreveinPercentage;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Random;
+
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.init.Blocks;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.MathHelper;
+import net.minecraft.world.World;
+import net.minecraft.world.WorldSavedData;
+import net.minecraft.world.chunk.Chunk;
+import net.minecraft.world.chunk.IChunkProvider;
+import net.minecraftforge.event.world.WorldEvent;
+
+import cpw.mods.fml.common.IWorldGenerator;
+import cpw.mods.fml.common.eventhandler.SubscribeEvent;
+import cpw.mods.fml.common.gameevent.PlayerEvent;
+import cpw.mods.fml.common.registry.GameRegistry;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.enums.Materials;
+import gregtech.api.net.GT_Packet_SendOregenPattern;
+import gregtech.api.objects.XSTR;
+import gregtech.api.util.GT_Log;
+import gregtech.api.world.GT_Worldgen;
+import gregtech.common.blocks.GT_TileEntity_Ores;
+
+public class GT_Worldgenerator implements IWorldGenerator {
+
+ private static int mEndAsteroidProbability = 300;
+ private static int mSize = 100;
+ private static int endMinSize = 50;
+ private static int endMaxSize = 200;
+ private static boolean endAsteroids = true;
+ public static List<Runnable> mList = new ArrayList<>();
+ public static HashSet<Long> ProcChunks = new HashSet<>();
+ // This is probably not going to work. Trying to create a fake orevein to put into hashtable when there will be no
+ // ores in a vein.
+ public static GT_Worldgen_GT_Ore_Layer noOresInVein = new GT_Worldgen_GT_Ore_Layer(
+ "NoOresInVein",
+ false,
+ 0,
+ 255,
+ 0,
+ 255,
+ 16,
+ false,
+ false,
+ false,
+ Materials.Aluminium,
+ Materials.Aluminium,
+ Materials.Aluminium,
+ Materials.Aluminium);
+ public static Hashtable<Long, GT_Worldgen_GT_Ore_Layer> validOreveins = new Hashtable<>(1024);
+ public boolean mIsGenerating = false;
+ public static final Object listLock = new Object();
+ public static OregenPattern oregenPattern = OregenPattern.AXISSYMMETRICAL;
+
+ public GT_Worldgenerator() {
+ endAsteroids = GregTech_API.sWorldgenFile.get("endasteroids", "GenerateAsteroids", true);
+ endMinSize = GregTech_API.sWorldgenFile.get("endasteroids", "AsteroidMinSize", 50);
+ endMaxSize = GregTech_API.sWorldgenFile.get("endasteroids", "AsteroidMaxSize", 200);
+ mEndAsteroidProbability = GregTech_API.sWorldgenFile.get("endasteroids", "AsteroidProbability", 300);
+ GameRegistry.registerWorldGenerator(this, 1073741823);
+ if (debugWorldGen) {
+ GT_Log.out.println("GT_Worldgenerator created");
+ }
+ }
+
+ @Override
+ public void generate(Random aRandom, int aX, int aZ, World aWorld, IChunkProvider aChunkGenerator,
+ IChunkProvider aChunkProvider) {
+ synchronized (listLock) {
+ mList.add(
+ new WorldGenContainer(
+ new XSTR(Math.abs(aRandom.nextInt()) + 1),
+ aX,
+ aZ,
+ aWorld.provider.dimensionId,
+ aWorld,
+ aChunkGenerator,
+ aChunkProvider,
+ aWorld.getBiomeGenForCoords(aX * 16 + 8, aZ * 16 + 8).biomeName));
+ if (debugWorldGen) GT_Log.out.println(
+ "ADD WorldSeed:" + aWorld.getSeed()
+ + " DimId"
+ + aWorld.provider.dimensionId
+ + " chunk x:"
+ + aX
+ + " z:"
+ + aZ
+ + " SIZE: "
+ + mList.size());
+ }
+
+ if (!this.mIsGenerating) {
+ this.mIsGenerating = true;
+ int mList_sS = mList.size();
+ mList_sS = Math.min(mList_sS, 5); // Run a maximum of 5 chunks at a time through worldgen. Extra chunks get
+ // done later.
+ for (int i = 0; i < mList_sS; i++) {
+ WorldGenContainer toRun = (WorldGenContainer) mList.get(0);
+ if (debugWorldGen) GT_Log.out.println(
+ "RUN WorldSeed:" + aWorld.getSeed()
+ + " DimId"
+ + aWorld.provider.dimensionId
+ + " chunk x:"
+ + toRun.mX
+ + " z:"
+ + toRun.mZ
+ + " SIZE: "
+ + mList.size()
+ + " i: "
+ + i);
+ synchronized (listLock) {
+ mList.remove(0);
+ }
+ toRun.run();
+ }
+ this.mIsGenerating = false;
+ }
+ }
+
+ public static boolean isOreChunk(int chunkX, int chunkZ) {
+ if (oregenPattern == OregenPattern.EQUAL_SPACING) {
+ return Math.floorMod(chunkX, 3) == 1 && Math.floorMod(chunkZ, 3) == 1;
+ }
+ // add next if statement here or convert to switch when expanding OregenPattern enum
+
+ // AXISSYMMETRICAL
+ return Math.abs(chunkX) % 3 == 1 && Math.abs(chunkZ) % 3 == 1;
+ }
+
+ public static class OregenPatternSavedData extends WorldSavedData {
+
+ private static final String NAME = "GregTech_OregenPattern";
+ private static final String KEY = "oregenPattern";
+
+ public OregenPatternSavedData(String p_i2141_1_) {
+ super(p_i2141_1_);
+ }
+
+ public static void loadData(World world) {
+ if (world.getWorldInfo()
+ .getWorldTotalTime() == 0L) {
+ // The world has just been created -> use newest pattern
+ oregenPattern = OregenPattern.values()[OregenPattern.values().length - 1];
+ } else {
+ // This is an old world. Use legacy pattern for now, readFromNBT may change this if
+ // GregTech_OregenPattern.dat is present
+ oregenPattern = OregenPattern.AXISSYMMETRICAL;
+ }
+
+ // load OregenPatternSavedData
+ WorldSavedData instance = world.mapStorage
+ .loadData(OregenPatternSavedData.class, OregenPatternSavedData.NAME);
+ if (instance == null) {
+ instance = new OregenPatternSavedData(NAME);
+ world.mapStorage.setData(OregenPatternSavedData.NAME, instance);
+ }
+ instance.markDirty();
+ }
+
+ @SubscribeEvent
+ public void onWorldLoad(WorldEvent.Load event) {
+ final World world = event.world;
+ if (!world.isRemote && world.provider.dimensionId == 0) {
+ loadData(world);
+ }
+ }
+
+ @SubscribeEvent
+ public void onPlayerLoggedIn(PlayerEvent.PlayerLoggedInEvent event) {
+ if (event.player instanceof EntityPlayerMP player) {
+ GT_Values.NW.sendToPlayer(new GT_Packet_SendOregenPattern(oregenPattern), player);
+ }
+ }
+
+ @Override
+ public void readFromNBT(NBTTagCompound p_76184_1_) {
+ if (p_76184_1_.hasKey(KEY)) {
+ int ordinal = p_76184_1_.getByte(KEY);
+ ordinal = MathHelper.clamp_int(ordinal, 0, OregenPattern.values().length - 1);
+ oregenPattern = OregenPattern.values()[ordinal];
+ }
+ }
+
+ @Override
+ public void writeToNBT(NBTTagCompound p_76187_1_) {
+ // If we have so many different OregenPatterns that byte isn't good enough something is wrong
+ p_76187_1_.setByte(KEY, (byte) oregenPattern.ordinal());
+ }
+
+ }
+
+ public enum OregenPattern {
+ // The last value is used when creating a new world
+ AXISSYMMETRICAL,
+ EQUAL_SPACING;
+ }
+
+ public static class WorldGenContainer implements Runnable {
+
+ public final Random mRandom;
+ public final int mX;
+ public final int mZ;
+ public final int mDimensionType;
+ public final World mWorld;
+ public final IChunkProvider mChunkGenerator;
+ public final IChunkProvider mChunkProvider;
+ public final String mBiome;
+ // Used for outputting orevein weights and bins
+ // static int test=0;
+
+ // Local class to track which orevein seeds must be checked when doing chunkified worldgen
+ static class NearbySeeds {
+
+ public int mX;
+ public int mZ;
+
+ NearbySeeds(int x, int z) {
+ this.mX = x;
+ this.mZ = z;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof NearbySeeds that)) return false;
+ if (this.mX != that.mX) return false;
+ return this.mZ == that.mZ;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = this.mX;
+ result = 31 * result + this.mZ;
+ return result;
+ }
+ }
+
+ public static ArrayList<GT_Worldgenerator.WorldGenContainer.NearbySeeds> seedList = new ArrayList<>();
+
+ // aX and aZ are now the by-chunk X and Z for the chunk of interest
+ public WorldGenContainer(Random aRandom, int aX, int aZ, int aDimensionType, World aWorld,
+ IChunkProvider aChunkGenerator, IChunkProvider aChunkProvider, String aBiome) {
+ this.mRandom = aRandom;
+ this.mX = aX;
+ this.mZ = aZ;
+ this.mDimensionType = aDimensionType;
+ this.mWorld = aWorld;
+ this.mChunkGenerator = aChunkGenerator;
+ this.mChunkProvider = aChunkProvider;
+ this.mBiome = aBiome;
+ }
+
+ // How to evaluate oregen distribution
+ // - Enable debugOreveins
+ // - Fly around for a while, or teleport jumping ~320 blocks at a time, with
+ // a 15-30s pause for worldgen to catch up
+ // - Do this across a large area, at least 2000x2000 blocks for good numbers
+ // - Open logs\gregtech.log
+ // - Using notepad++, do a Search | Find - enter "Added" for the search term
+ // - Select Find All In Current Document
+ // - In the Search window, right-click and Select All
+ // - Copy and paste to a new file
+ // - Delete extraneous stuff at top, and blank line at bottom. Line count is
+ // # of total oreveins
+ // - For simple spot checks, use Find All in Current Document for specific
+ // oremixes, ie ore.mix.diamond, to check how many appear in the list.
+ // - For more complex work, import file into Excel, and sort based on oremix
+ // column. Drag select the oremix names, in the bottom right will be how many
+ // entries to add in a seperate tab to calculate %ages.
+ //
+ // When using the ore weights, discount or remove the high altitude veins since
+ // their high weight are offset by their rareness. I usually just use zero for them.
+ // Actual spawn rates will vary based upon the average height of the stone layers
+ // in the dimension. For example veins that range above and below the average height
+ // will be less, and veins that are completely above the average height will be much less.
+
+ public void worldGenFindVein(int oreseedX, int oreseedZ) {
+ // Explanation of oreveinseed implementation.
+ // (long)this.mWorld.getSeed()<<16) Deep Dark does two oregen passes, one with getSeed set to +1 the
+ // original world seed. This pushes that +1 off the low bits of oreseedZ, so that the hashes are far apart
+ // for the two passes.
+ // ((this.mWorld.provider.dimensionId & 0xffL)<<56) Puts the dimension in the top bits of the hash, to
+ // make sure to get unique hashes per dimension
+ // ((long)oreseedX & 0x000000000fffffffL) << 28) Puts the chunk X in the bits 29-55. Cuts off the top few
+ // bits of the chunk so we have bits for dimension.
+ // ( (long)oreseedZ & 0x000000000fffffffL )) Puts the chunk Z in the bits 0-27. Cuts off the top few bits
+ // of the chunk so we have bits for dimension.
+ long oreveinSeed = (this.mWorld.getSeed() << 16)
+ ^ (((this.mWorld.provider.dimensionId & 0xffL) << 56) | (((long) oreseedX & 0x000000000fffffffL) << 28)
+ | ((long) oreseedZ & 0x000000000fffffffL)); // Use an RNG that is identical every time it is
+ // called for
+ // this oreseed.
+ XSTR oreveinRNG = new XSTR(oreveinSeed);
+ int oreveinPercentageRoll = oreveinRNG.nextInt(100); // Roll the dice, see if we get an orevein here at all
+ int noOrePlacedCount = 0;
+ String tDimensionName = "";
+ if (debugOrevein) {
+ tDimensionName = this.mWorld.provider.getDimensionName();
+ }
+
+ if (debugOrevein) GT_Log.out.println(
+ " Finding oreveins for oreveinSeed=" + oreveinSeed
+ + " mX="
+ + this.mX
+ + " mZ="
+ + this.mZ
+ + " oreseedX="
+ + oreseedX
+ + " oreseedZ="
+ + oreseedZ
+ + " worldSeed="
+ + this.mWorld.getSeed());
+
+ // Search for a valid orevein for this dimension
+ if (!validOreveins.containsKey(oreveinSeed)) {
+ if ((oreveinPercentageRoll < oreveinPercentage) && (GT_Worldgen_GT_Ore_Layer.sWeight > 0)
+ && (GT_Worldgen_GT_Ore_Layer.sList.size() > 0)) {
+ int placementAttempts = 0;
+ boolean oreveinFound = false;
+ int i;
+
+ // Used for outputting orevein weights and bins
+ /*
+ * if( test==0 ) { test = 1; GT_Log.out.println( "sWeight = " + GT_Worldgen_GT_Ore_Layer.sWeight );
+ * for (GT_Worldgen_GT_Ore_Layer tWorldGen : GT_Worldgen_GT_Ore_Layer.sList) { GT_Log.out.println( (
+ * tWorldGen).mWorldGenName + " mWeight = " + ( tWorldGen).mWeight + " mSize = " + (tWorldGen).mSize
+ * ); } }
+ */
+ for (i = 0; (i < oreveinAttempts) && (!oreveinFound)
+ && (placementAttempts < oreveinMaxPlacementAttempts); i++) {
+ int tRandomWeight = oreveinRNG.nextInt(GT_Worldgen_GT_Ore_Layer.sWeight);
+ for (GT_Worldgen_GT_Ore_Layer tWorldGen : GT_Worldgen_GT_Ore_Layer.sList) {
+ tRandomWeight -= (tWorldGen).mWeight;
+ if (tRandomWeight <= 0) {
+ try {
+ // Adjust the seed so that this layer has a series of unique random numbers.
+ // Otherwise multiple attempts at this same oreseed will get the same offset and X/Z
+ // values. If an orevein failed, any orevein with the
+ // same minimum heights would fail as well. This prevents that, giving each orevein
+ // a unique height each pass through here.
+ int placementResult = tWorldGen.executeWorldgenChunkified(
+ this.mWorld,
+ new XSTR(oreveinSeed ^ (tWorldGen.mPrimaryMeta)),
+ this.mBiome,
+ this.mDimensionType,
+ this.mX * 16,
+ this.mZ * 16,
+ oreseedX * 16,
+ oreseedZ * 16,
+ this.mChunkGenerator,
+ this.mChunkProvider);
+ switch (placementResult) {
+ case GT_Worldgen_GT_Ore_Layer.ORE_PLACED -> {
+ if (debugOrevein) GT_Log.out.println(
+ " Added near oreveinSeed=" + oreveinSeed
+ + " "
+ + (tWorldGen).mWorldGenName
+ + " tries at oremix="
+ + i
+ + " placementAttempts="
+ + placementAttempts
+ + " dimensionName="
+ + tDimensionName);
+ validOreveins.put(oreveinSeed, tWorldGen);
+ oreveinFound = true;
+ }
+ case GT_Worldgen_GT_Ore_Layer.NO_ORE_IN_BOTTOM_LAYER -> placementAttempts++;
+
+ // SHould do retry in this case until out of chances
+ case GT_Worldgen_GT_Ore_Layer.NO_OVERLAP -> {
+ if (debugOrevein) GT_Log.out.println(
+ " Added far oreveinSeed=" + oreveinSeed
+ + " "
+ + (tWorldGen).mWorldGenName
+ + " tries at oremix="
+ + i
+ + " placementAttempts="
+ + placementAttempts
+ + " dimensionName="
+ + tDimensionName);
+ validOreveins.put(oreveinSeed, tWorldGen);
+ oreveinFound = true;
+ }
+ case GT_Worldgen_GT_Ore_Layer.NO_OVERLAP_AIR_BLOCK -> {
+ if (debugOrevein) GT_Log.out.println(
+ " No overlap and air block in test spot=" + oreveinSeed
+ + " "
+ + (tWorldGen).mWorldGenName
+ + " tries at oremix="
+ + i
+ + " placementAttempts="
+ + placementAttempts
+ + " dimensionName="
+ + tDimensionName);
+ // SHould do retry in this case until out of chances
+ placementAttempts++;
+ }
+ }
+ break; // Try the next orevein
+ } catch (Throwable e) {
+ if (debugOrevein) GT_Log.out.println(
+ "Exception occurred on oreVein" + tWorldGen
+ + " oreveinSeed="
+ + oreveinSeed
+ + " mX="
+ + this.mX
+ + " mZ="
+ + this.mZ
+ + " oreseedX="
+ + oreseedX
+ + " oreseedZ="
+ + oreseedZ);
+ e.printStackTrace(GT_Log.err);
+ }
+ }
+ }
+ }
+ // Only add an empty orevein if unable to place a vein at the oreseed chunk.
+ if ((!oreveinFound) && (this.mX == oreseedX) && (this.mZ == oreseedZ)) {
+ if (debugOrevein) GT_Log.out.println(
+ " Empty oreveinSeed=" + oreveinSeed
+ + " mX="
+ + this.mX
+ + " mZ="
+ + this.mZ
+ + " oreseedX="
+ + oreseedX
+ + " oreseedZ="
+ + oreseedZ
+ + " tries at oremix="
+ + i
+ + " placementAttempts="
+ + placementAttempts
+ + " dimensionName="
+ + tDimensionName);
+ validOreveins.put(oreveinSeed, noOresInVein);
+ }
+ } else if (oreveinPercentageRoll >= oreveinPercentage) {
+ if (debugOrevein) GT_Log.out.println(
+ " Skipped oreveinSeed=" + oreveinSeed
+ + " mX="
+ + this.mX
+ + " mZ="
+ + this.mZ
+ + " oreseedX="
+ + oreseedX
+ + " oreseedZ="
+ + oreseedZ
+ + " RNG="
+ + oreveinPercentageRoll
+ + " %="
+ + oreveinPercentage
+ + " dimensionName="
+ + tDimensionName);
+ validOreveins.put(oreveinSeed, noOresInVein);
+ }
+ } else {
+ // oreseed is located in the previously processed table
+ if (debugOrevein) GT_Log.out
+ .print(" Valid oreveinSeed=" + oreveinSeed + " validOreveins.size()=" + validOreveins.size() + " ");
+ GT_Worldgen_GT_Ore_Layer tWorldGen = validOreveins.get(oreveinSeed);
+ oreveinRNG.setSeed(oreveinSeed ^ (tWorldGen.mPrimaryMeta)); // Reset RNG to only be based on oreseed X/Z
+ // and type of vein
+ int placementResult = tWorldGen.executeWorldgenChunkified(
+ this.mWorld,
+ oreveinRNG,
+ this.mBiome,
+ this.mDimensionType,
+ this.mX * 16,
+ this.mZ * 16,
+ oreseedX * 16,
+ oreseedZ * 16,
+ this.mChunkGenerator,
+ this.mChunkProvider);
+ switch (placementResult) {
+ case GT_Worldgen_GT_Ore_Layer.NO_ORE_IN_BOTTOM_LAYER -> {
+ if (debugOrevein) GT_Log.out.println(" No ore in bottom layer");
+ }
+ case GT_Worldgen_GT_Ore_Layer.NO_OVERLAP -> {
+ if (debugOrevein) GT_Log.out.println(" No overlap");
+ }
+ }
+ }
+ }
+
+ @Override
+ public void run() {
+ long startTime = System.nanoTime();
+ Chunk tChunk = this.mWorld.getChunkFromChunkCoords(this.mX, this.mZ);
+
+ int oreveinMaxSize;
+
+ // Do GT_Stones and GT_small_ores oregen for this chunk
+ try {
+ for (GT_Worldgen tWorldGen : GregTech_API.sWorldgenList) {
+ /*
+ * if (debugWorldGen) GT_Log.out.println( "tWorldGen.mWorldGenName="+tWorldGen.mWorldGenName );
+ */
+ tWorldGen.executeWorldgen(
+ this.mWorld,
+ this.mRandom,
+ this.mBiome,
+ this.mDimensionType,
+ this.mX * 16,
+ this.mZ * 16,
+ this.mChunkGenerator,
+ this.mChunkProvider);
+ }
+ } catch (Throwable e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ long leftOverTime = System.nanoTime();
+
+ // Determine bounding box on how far out to check for oreveins affecting this chunk
+ // For now, manually reducing oreveinMaxSize when not in the Underdark for performance
+ if (this.mWorld.provider.getDimensionName()
+ .equals("Underdark")) {
+ oreveinMaxSize = 32; // Leave Deep Dark/Underdark max oregen at 32, instead of 64
+ } else {
+ oreveinMaxSize = 32;
+ }
+
+ int wXbox = this.mX - (oreveinMaxSize / 16);
+ int eXbox = this.mX + (oreveinMaxSize / 16 + 1); // Need to add 1 since it is compared using a <
+ int nZbox = this.mZ - (oreveinMaxSize / 16);
+ int sZbox = this.mZ + (oreveinMaxSize / 16 + 1);
+
+ // Search for orevein seeds and add to the list;
+ for (int x = wXbox; x < eXbox; x++) {
+ for (int z = nZbox; z < sZbox; z++) {
+ // Determine if this X/Z is an orevein seed
+ if (isOreChunk(x, z)) {
+ if (debugWorldGen) GT_Log.out.println("Adding seed x=" + x + " z=" + z);
+ seedList.add(new NearbySeeds(x, z));
+ }
+ }
+ }
+
+ // Now process each oreseed vs this requested chunk
+ for (; seedList.size() != 0; seedList.remove(0)) {
+ if (debugWorldGen)
+ GT_Log.out.println("Processing seed x=" + seedList.get(0).mX + " z=" + seedList.get(0).mZ);
+ worldGenFindVein(seedList.get(0).mX, seedList.get(0).mZ);
+ }
+
+ long oregenTime = System.nanoTime();
+
+ // Asteroid Worldgen
+ int tDimensionType = this.mWorld.provider.dimensionId;
+ // String tDimensionName = this.mWorld.provider.getDimensionName();
+ // if (((tDimensionType == 1) && endAsteroids && ((mEndAsteroidProbability <= 1) ||
+ // (aRandom.nextInt(mEndAsteroidProbability) == 0))) || ((tDimensionName.equals("Asteroids")) && gcAsteroids
+ // && ((mGCAsteroidProbability <= 1) || (aRandom.nextInt(mGCAsteroidProbability) == 0)))) {
+ if ((tDimensionType == 1 /* the end */) && endAsteroids) {
+ XSTR random = new XSTR(
+ mWorld.getSeed() + mX * mX * 91777L + mZ * mZ * 137413L + mX * mZ * 1853L + mX * 3L + mZ * 17L);
+
+ if (mEndAsteroidProbability <= 1 || random.nextInt(mEndAsteroidProbability) == 0) {
+ generateAsteroid(mWorld, random, mX, mZ);
+ }
+ }
+
+ if (tChunk != null) {
+ tChunk.isModified = true;
+ }
+ long endTime = System.nanoTime();
+ long duration = (endTime - startTime);
+ if (debugWorldGen) {
+ GT_Log.out.println(
+ " Oregen took " + (oregenTime - leftOverTime)
+ + " Leftover gen took "
+ + (leftOverTime - startTime)
+ + " Worldgen took "
+ + duration
+ + " nanoseconds");
+ }
+ }
+
+ private void generateAsteroid(World world, Random random, int chunkX, int chunkZ) {
+ short primaryMeta = 0;
+ short secondaryMeta = 0;
+ short betweenMeta = 0;
+ short sporadicMeta = 0;
+ if ((GT_Worldgen_GT_Ore_Layer.sWeight > 0) && (GT_Worldgen_GT_Ore_Layer.sList.size() > 0)) {
+ boolean temp = true;
+ int tRandomWeight;
+ for (int i = 0; (i < oreveinAttempts) && (temp); i++) {
+ tRandomWeight = random.nextInt(GT_Worldgen_GT_Ore_Layer.sWeight);
+ for (GT_Worldgen_GT_Ore_Layer tWorldGen : GT_Worldgen_GT_Ore_Layer.sList) {
+ tRandomWeight -= tWorldGen.mWeight;
+ if (tRandomWeight <= 0) {
+ try {
+ if (tWorldGen.mEndAsteroid) {
+ primaryMeta = tWorldGen.mPrimaryMeta;
+ secondaryMeta = tWorldGen.mSecondaryMeta;
+ betweenMeta = tWorldGen.mBetweenMeta;
+ sporadicMeta = tWorldGen.mSporadicMeta;
+ temp = false;
+ break;
+ }
+ } catch (Throwable e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ }
+ }
+ }
+ }
+ // if(GT_Values.D1)GT_FML_LOGGER.info("do asteroid gen: "+this.mX+" "+this.mZ);
+ int tX = chunkX * 16 + random.nextInt(16);
+ int tY = 50 + random.nextInt(200 - 50);
+ int tZ = chunkZ * 16 + random.nextInt(16);
+ mSize = endMinSize + random.nextInt(endMaxSize - endMinSize + 1);
+
+ if ((world.getBlock(tX, tY, tZ)
+ .isAir(world, tX, tY, tZ))) {
+ float randomRadian = random.nextFloat() * (float) Math.PI;
+ double xBase = tX + 8 + MathHelper.sin(randomRadian) * mSize / 8.0F;
+ double xFactor = tX + 8 - MathHelper.sin(randomRadian) * mSize / 8.0F;
+ double zBase = tZ + 8 + MathHelper.cos(randomRadian) * mSize / 8.0F;
+ double zFactor = tZ + 8 - MathHelper.cos(randomRadian) * mSize / 8.0F;
+ double yBase = tY + random.nextInt(3) - 2;
+ double yFactor = tY + random.nextInt(3) - 2;
+
+ for (int i = 0; i <= mSize; i++) {
+ double xCenter = xBase + (xFactor - xBase) * i / mSize;
+ double yCenter = yBase + (yFactor - yBase) * i / mSize;
+ double zCenter = zBase + (zFactor - zBase) * i / mSize;
+ double randomDistance = random.nextDouble() * mSize / 16.0D;
+ double halfLength = (MathHelper.sin(i * (float) Math.PI / mSize) + 1.0F) * randomDistance + 1.0D;
+ double halfHeight = (MathHelper.sin(i * (float) Math.PI / mSize) + 1.0F) * randomDistance + 1.0D;
+ int tMinX = MathHelper.floor_double(xCenter - halfLength / 2.0D);
+ int tMinY = MathHelper.floor_double(yCenter - halfHeight / 2.0D);
+ int tMinZ = MathHelper.floor_double(zCenter - halfLength / 2.0D);
+ int tMaxX = MathHelper.floor_double(xCenter + halfLength / 2.0D);
+ int tMaxY = MathHelper.floor_double(yCenter + halfHeight / 2.0D);
+ int tMaxZ = MathHelper.floor_double(zCenter + halfLength / 2.0D);
+
+ for (int eX = tMinX; eX <= tMaxX; eX++) {
+ double xChance = (eX + 0.5D - xCenter) / (halfLength / 2.0D);
+ if (xChance * xChance < 1.0D) {
+ for (int eY = tMinY; eY <= tMaxY; eY++) {
+ double yChance = (eY + 0.5D - yCenter) / (halfHeight / 2.0D);
+ if (xChance * xChance + yChance * yChance < 1.0D) {
+ for (int eZ = tMinZ; eZ <= tMaxZ; eZ++) {
+ double zChance = (eZ + 0.5D - zCenter) / (halfLength / 2.0D);
+ if (xChance * xChance + yChance * yChance + zChance * zChance >= 1.0D) {
+ continue;
+ }
+ if (!world.getBlock(tX, tY, tZ)
+ .isAir(world, tX, tY, tZ)) {
+ continue;
+ }
+ int ranOre = random.nextInt(50);
+ if (ranOre < 3) {
+ GT_TileEntity_Ores.setOreBlock(world, eX, eY, eZ, primaryMeta, false);
+ } else if (ranOre < 6) {
+ GT_TileEntity_Ores.setOreBlock(world, eX, eY, eZ, secondaryMeta, false);
+ } else if (ranOre < 8) {
+ GT_TileEntity_Ores.setOreBlock(world, eX, eY, eZ, betweenMeta, false);
+ } else if (ranOre < 10) {
+ GT_TileEntity_Ores.setOreBlock(world, eX, eY, eZ, sporadicMeta, false);
+ } else {
+ world.setBlock(eX, eY, eZ, Blocks.end_stone, 0, 0);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/bees/GT_AlleleBeeSpecies.java b/src/main/java/gregtech/common/bees/GT_AlleleBeeSpecies.java
new file mode 100644
index 0000000000..b264737677
--- /dev/null
+++ b/src/main/java/gregtech/common/bees/GT_AlleleBeeSpecies.java
@@ -0,0 +1,53 @@
+package gregtech.common.bees;
+
+import java.awt.Color;
+
+import net.minecraft.init.Items;
+import net.minecraft.item.ItemStack;
+
+import forestry.api.apiculture.EnumBeeChromosome;
+import forestry.api.apiculture.IAlleleBeeSpeciesCustom;
+import forestry.api.genetics.AlleleManager;
+import forestry.api.genetics.IClassification;
+import forestry.apiculture.genetics.alleles.AlleleBeeSpecies;
+
+public class GT_AlleleBeeSpecies extends AlleleBeeSpecies {
+
+ public GT_AlleleBeeSpecies(String uid, boolean dominant, String unlocalizedName, String authority,
+ String unlocalizedDescription, IClassification branch, String binomial, Color primaryColor,
+ Color secondaryColor) {
+ super(
+ uid,
+ unlocalizedName,
+ authority,
+ unlocalizedDescription,
+ dominant,
+ branch,
+ binomial,
+ primaryColor.getRGB(),
+ secondaryColor.getRGB());
+ AlleleManager.alleleRegistry.registerAllele(this, EnumBeeChromosome.SPECIES);
+ }
+
+ @Override
+ public IAlleleBeeSpeciesCustom addProduct(ItemStack product, Float chance) {
+ if (product == null || product.getItem() == null) {
+ product = new ItemStack(Items.boat);
+ }
+ if (chance <= 0.0f || chance > 1.0f) {
+ chance = 0.1f;
+ }
+ return super.addProduct(product, chance);
+ }
+
+ @Override
+ public IAlleleBeeSpeciesCustom addSpecialty(ItemStack specialty, Float chance) {
+ if (specialty == null || specialty.getItem() == null) {
+ specialty = new ItemStack(Items.boat);
+ }
+ if (chance <= 0.0f || chance > 1.0f) {
+ chance = 0.1f;
+ }
+ return super.addSpecialty(specialty, chance);
+ }
+}
diff --git a/src/main/java/gregtech/common/bees/GT_AlleleHelper.java b/src/main/java/gregtech/common/bees/GT_AlleleHelper.java
new file mode 100644
index 0000000000..496aff29ca
--- /dev/null
+++ b/src/main/java/gregtech/common/bees/GT_AlleleHelper.java
@@ -0,0 +1,268 @@
+package gregtech.common.bees;
+
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.commons.lang3.reflect.FieldUtils;
+
+import forestry.api.apiculture.EnumBeeChromosome;
+import forestry.api.arboriculture.EnumTreeChromosome;
+import forestry.api.genetics.AlleleManager;
+import forestry.api.genetics.EnumTolerance;
+import forestry.api.genetics.IAllele;
+import forestry.api.genetics.IAlleleBoolean;
+import forestry.api.genetics.IAlleleInteger;
+import forestry.api.genetics.IAlleleTolerance;
+import forestry.api.genetics.IChromosomeType;
+import forestry.api.lepidopterology.EnumButterflyChromosome;
+import forestry.apiculture.flowers.FlowerProvider;
+import forestry.core.config.Constants;
+import forestry.core.genetics.alleles.AlleleBoolean;
+import forestry.core.genetics.alleles.AlleleHelper;
+import forestry.core.genetics.alleles.AlleleInteger;
+import forestry.core.genetics.alleles.AlleleTolerance;
+import forestry.core.genetics.alleles.EnumAllele;
+import forestry.core.genetics.alleles.IAlleleValue;
+import forestry.core.utils.vect.IVect;
+import forestry.plugins.PluginManager;
+import gregtech.GT_Mod;
+
+public class GT_AlleleHelper extends AlleleHelper {
+
+ private static final String modId = Constants.ID;
+
+ private Map<Class<?>, Map<?, ? extends IAllele>> alleleMaps = new HashMap<>();
+
+ @Override
+ public void init() {
+ if (PluginManager.Module.APICULTURE.isEnabled()) {
+ createAlleles(EnumAllele.Fertility.class, EnumBeeChromosome.FERTILITY);
+ createAlleles(EnumAllele.Flowering.class, EnumBeeChromosome.FLOWERING);
+ }
+
+ if (PluginManager.Module.APICULTURE.isEnabled() || PluginManager.Module.ARBORICULTURE.isEnabled()) {
+ createAlleles(EnumAllele.Territory.class, EnumBeeChromosome.TERRITORY, EnumTreeChromosome.TERRITORY);
+
+ AlleleManager.alleleRegistry
+ .registerDeprecatedAlleleReplacement("forestry.territoryDefault", get(EnumAllele.Territory.AVERAGE));
+ }
+
+ if (PluginManager.Module.APICULTURE.isEnabled() || PluginManager.Module.LEPIDOPTEROLOGY.isEnabled()) {
+ createAlleles(EnumAllele.Speed.class, EnumBeeChromosome.SPEED, EnumButterflyChromosome.SPEED);
+ createAlleles(EnumAllele.Lifespan.class, EnumBeeChromosome.LIFESPAN, EnumButterflyChromosome.LIFESPAN);
+ createAlleles(
+ EnumAllele.Tolerance.class,
+ EnumBeeChromosome.TEMPERATURE_TOLERANCE,
+ EnumBeeChromosome.HUMIDITY_TOLERANCE,
+ EnumButterflyChromosome.TEMPERATURE_TOLERANCE,
+ EnumButterflyChromosome.HUMIDITY_TOLERANCE);
+ createAlleles(
+ EnumAllele.Flowers.class,
+ EnumBeeChromosome.FLOWER_PROVIDER,
+ EnumButterflyChromosome.FLOWER_PROVIDER);
+
+ AlleleManager.alleleRegistry
+ .registerDeprecatedAlleleReplacement("forestry.speedNorm", get(EnumAllele.Speed.NORMAL));
+ }
+
+ if (PluginManager.Module.ARBORICULTURE.isEnabled()) {
+ createAlleles(EnumAllele.Height.class, EnumTreeChromosome.HEIGHT);
+ createAlleles(EnumAllele.Saplings.class, EnumTreeChromosome.FERTILITY);
+ createAlleles(EnumAllele.Yield.class, EnumTreeChromosome.YIELD);
+ createAlleles(EnumAllele.Fireproof.class, EnumTreeChromosome.FIREPROOF);
+ createAlleles(EnumAllele.Maturation.class, EnumTreeChromosome.MATURATION);
+ createAlleles(EnumAllele.Sappiness.class, EnumTreeChromosome.SAPPINESS);
+
+ AlleleManager.alleleRegistry
+ .registerDeprecatedAlleleReplacement("forestry.heightMax10", get(EnumAllele.Height.AVERAGE));
+ AlleleManager.alleleRegistry
+ .registerDeprecatedAlleleReplacement("forestry.saplingsDefault", get(EnumAllele.Saplings.AVERAGE));
+ AlleleManager.alleleRegistry
+ .registerDeprecatedAlleleReplacement("forestry.saplingsDouble", get(EnumAllele.Saplings.HIGH));
+ AlleleManager.alleleRegistry
+ .registerDeprecatedAlleleReplacement("forestry.saplingsTriple", get(EnumAllele.Saplings.HIGHER));
+ AlleleManager.alleleRegistry
+ .registerDeprecatedAlleleReplacement("forestry.yieldDefault", get(EnumAllele.Yield.AVERAGE));
+ AlleleManager.alleleRegistry
+ .registerDeprecatedAlleleReplacement("forestry.maturitySlowest", get(EnumAllele.Maturation.SLOWEST));
+ AlleleManager.alleleRegistry
+ .registerDeprecatedAlleleReplacement("forestry.maturitySlower", get(EnumAllele.Maturation.SLOWER));
+ AlleleManager.alleleRegistry
+ .registerDeprecatedAlleleReplacement("forestry.maturitySlow", get(EnumAllele.Maturation.SLOW));
+ AlleleManager.alleleRegistry
+ .registerDeprecatedAlleleReplacement("forestry.maturityAverage", get(EnumAllele.Maturation.AVERAGE));
+ AlleleManager.alleleRegistry
+ .registerDeprecatedAlleleReplacement("forestry.maturityFast", get(EnumAllele.Maturation.FAST));
+ AlleleManager.alleleRegistry
+ .registerDeprecatedAlleleReplacement("forestry.maturityFaster", get(EnumAllele.Maturation.FASTER));
+ AlleleManager.alleleRegistry
+ .registerDeprecatedAlleleReplacement("forestry.maturityFastest", get(EnumAllele.Maturation.FASTEST));
+ }
+
+ if (PluginManager.Module.LEPIDOPTEROLOGY.isEnabled()) {
+ createAlleles(EnumAllele.Size.class, EnumButterflyChromosome.SIZE);
+ }
+
+ Map<Integer, IAlleleInteger> integers = new HashMap<>();
+ for (int i = 1; i <= 10; i++) {
+ IAlleleInteger alleleInteger = new AlleleInteger(modId, "i", i + "d", i, true);
+ AlleleManager.alleleRegistry.registerAllele(
+ alleleInteger,
+ EnumTreeChromosome.GIRTH,
+ EnumButterflyChromosome.METABOLISM,
+ EnumButterflyChromosome.FERTILITY);
+ integers.put(i, alleleInteger);
+ }
+ alleleMaps.put(Integer.class, integers);
+
+ Map<Boolean, IAlleleBoolean> booleans = new HashMap<>();
+ booleans.put(true, new AlleleBoolean(modId, "bool", true, false));
+ booleans.put(false, new AlleleBoolean(modId, "bool", false, false));
+ for (IAlleleBoolean alleleBoolean : booleans.values()) {
+ AlleleManager.alleleRegistry.registerAllele(
+ alleleBoolean,
+ EnumBeeChromosome.NOCTURNAL,
+ EnumBeeChromosome.TOLERANT_FLYER,
+ EnumBeeChromosome.CAVE_DWELLING,
+ EnumButterflyChromosome.NOCTURNAL,
+ EnumButterflyChromosome.TOLERANT_FLYER,
+ EnumButterflyChromosome.FIRE_RESIST);
+ }
+ alleleMaps.put(Boolean.class, booleans);
+ }
+
+ @SuppressWarnings("unchecked")
+ public static void initialisation() {
+ GT_AlleleHelper helper = new GT_AlleleHelper();
+
+ try {
+ helper.alleleMaps = (Map<Class<?>, Map<?, ? extends IAllele>>) FieldUtils
+ .readField(FieldUtils.getField(AlleleHelper.class, "alleleMaps", true), AlleleHelper.instance, true);
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+
+ AlleleHelper.instance = helper;
+ // AlleleHelper.instance.init();
+ }
+
+ @Override
+ public <T extends Enum<T> & IChromosomeType> void set(IAllele[] alleles, T chromosomeType, IAllele allele) {
+
+ if (allele == null) {
+ GT_Mod.GT_FML_LOGGER.info("Allele is null!");
+ return;
+ }
+
+ if (!chromosomeType.getAlleleClass()
+ .isInstance(allele)) {
+ GT_Mod.GT_FML_LOGGER.info("chromosomeType is not an instance of allele!" + allele.getName());
+ return;
+ }
+
+ // TODO: uncomment this once all addon mods are using the allele registration with IChromosomeType
+ // Collection<IChromosomeType> validTypes = AlleleManager.alleleRegistry.getChromosomeTypes(allele);
+ // if (validTypes.size() > 0 && !validTypes.contains(chromosomeType)) {
+ // throw new IllegalArgumentException("Allele can't be applied to this Chromosome type. Expected: " + validTypes
+ // + " Got: " + chromosomeType);
+ // }
+
+ alleles[chromosomeType.ordinal()] = allele;
+ }
+
+ @Override
+ public <T extends Enum<T> & IChromosomeType> void set(IAllele[] alleles, T chromosomeType, IAlleleValue value) {
+ set(alleles, chromosomeType, get(value));
+ }
+
+ @Override
+ public <T extends Enum<T> & IChromosomeType> void set(IAllele[] alleles, T chromosomeType, boolean value) {
+ set(alleles, chromosomeType, get(value));
+ }
+
+ @Override
+ public <T extends Enum<T> & IChromosomeType> void set(IAllele[] alleles, T chromosomeType, int value) {
+ set(alleles, chromosomeType, get(value));
+ }
+
+ private IAllele get(Object value) {
+ Class<?> valueClass = value.getClass();
+ Map<?, ? extends IAllele> map = alleleMaps.get(valueClass);
+ if (map == null) {
+ throw new IllegalArgumentException("There is no IAllele type for: " + valueClass + ' ' + value);
+ }
+ IAllele allele = map.get(value);
+ if (allele == null) {
+ allele = new IAllele() {
+
+ @Override
+ public String getUID() {
+ return "NOT_FOUND";
+ }
+
+ @Override
+ public boolean isDominant() {
+ return false;
+ }
+
+ @Override
+ public String getName() {
+ return "NOT_FOUND";
+ }
+
+ @Override
+ public String getUnlocalizedName() {
+ return "NOT_FOUND";
+ }
+ };
+ }
+ return allele;
+ }
+
+ private <K extends Enum<K> & IAlleleValue<V>, V> void createAlleles(Class<K> enumClass, IChromosomeType... types) {
+ String category = enumClass.getSimpleName()
+ .toLowerCase(Locale.ENGLISH);
+ EnumMap<K, IAllele> map = new EnumMap<>(enumClass);
+ for (K enumValue : enumClass.getEnumConstants()) {
+ IAllele allele = createAllele(category, enumValue, types);
+ map.put(enumValue, allele);
+ }
+ alleleMaps.put(enumClass, map);
+ }
+
+ private static <K extends IAlleleValue<V>, V> IAllele createAllele(String category, K enumValue,
+ IChromosomeType... types) {
+ V value = enumValue.getValue();
+ boolean isDominant = enumValue.isDominant();
+ String name = enumValue.toString()
+ .toLowerCase(Locale.ENGLISH);
+
+ Class<?> valueClass = value.getClass();
+ if (Float.class.isAssignableFrom(valueClass)) {
+ return AlleleManager.alleleFactory.createFloat(modId, category, name, (Float) value, isDominant, types);
+ } else if (Integer.class.isAssignableFrom(valueClass)) {
+ return AlleleManager.alleleFactory.createInteger(modId, category, name, (Integer) value, isDominant, types);
+ } else if (IVect.class.isAssignableFrom(valueClass)) {
+ IVect area = (IVect) value;
+ return AlleleManager.alleleFactory
+ .createArea(modId, category, name, area.getX(), area.getY(), area.getZ(), isDominant, types);
+ } else if (Boolean.class.isAssignableFrom(valueClass)) {
+ return AlleleManager.alleleFactory.createBoolean(modId, category, (Boolean) value, isDominant, types);
+ } else if (EnumTolerance.class.isAssignableFrom(valueClass)) {
+ IAlleleTolerance alleleTolerance = new AlleleTolerance(
+ modId,
+ category,
+ name,
+ (EnumTolerance) value,
+ isDominant);
+ AlleleManager.alleleRegistry.registerAllele(alleleTolerance, types);
+ return alleleTolerance;
+ } else if (FlowerProvider.class.isAssignableFrom(valueClass)) {
+ return AlleleManager.alleleFactory
+ .createFlowers(modId, category, name, (FlowerProvider) value, isDominant, types);
+ }
+ throw new RuntimeException("could not create allele for category: " + category + " and value " + valueClass);
+ }
+}
diff --git a/src/main/java/gregtech/common/bees/GT_Bee_Mutation.java b/src/main/java/gregtech/common/bees/GT_Bee_Mutation.java
new file mode 100644
index 0000000000..e8b2d5b8c6
--- /dev/null
+++ b/src/main/java/gregtech/common/bees/GT_Bee_Mutation.java
@@ -0,0 +1,85 @@
+package gregtech.common.bees;
+
+import java.lang.reflect.Field;
+import java.util.List;
+
+import net.minecraft.util.ChunkCoordinates;
+import net.minecraft.world.World;
+
+import org.apache.commons.lang3.reflect.FieldUtils;
+
+import forestry.api.apiculture.BeeManager;
+import forestry.api.apiculture.IAlleleBeeSpecies;
+import forestry.api.apiculture.IBeeGenome;
+import forestry.api.apiculture.IBeeHousing;
+import forestry.api.apiculture.IBeeModifier;
+import forestry.api.core.IClimateProvider;
+import forestry.api.genetics.IAllele;
+import forestry.api.genetics.IGenome;
+import forestry.api.genetics.IMutationCondition;
+import forestry.apiculture.genetics.BeeMutation;
+import forestry.core.genetics.mutations.Mutation;
+
+public class GT_Bee_Mutation extends BeeMutation {
+
+ private final float split;
+
+ public GT_Bee_Mutation(IAlleleBeeSpecies bee0, IAlleleBeeSpecies bee1, IAllele[] result, int chance, float split) {
+ super(bee0, bee1, result, chance);
+ this.split = split;
+ BeeManager.beeRoot.registerMutation(this);
+ }
+
+ @Override
+ public float getBaseChance() {
+ return super.getBaseChance() / split;
+ }
+
+ @Override
+ public float getChance(IBeeHousing housing, IAlleleBeeSpecies allele0, IAlleleBeeSpecies allele1,
+ IBeeGenome genome0, IBeeGenome genome1) {
+ World world = housing != null ? housing.getWorld() : null;
+ ChunkCoordinates housingCoordinates = housing != null ? housing.getCoordinates() : null;
+ int x = housingCoordinates != null ? housingCoordinates.posX : 0;
+ int y = housingCoordinates != null ? housingCoordinates.posY : 0;
+ int z = housingCoordinates != null ? housingCoordinates.posZ : 0;
+
+ float processedChance = getBasicChance(world, x, y, z, allele0, allele1, genome0, genome1, housing);
+
+ if (processedChance <= 0f) {
+ return 0f;
+ }
+
+ IBeeModifier beeHousingModifier = BeeManager.beeRoot.createBeeHousingModifier(housing);
+ IBeeModifier beeModeModifier = BeeManager.beeRoot.getBeekeepingMode(world)
+ .getBeeModifier();
+
+ processedChance *= beeHousingModifier.getMutationModifier(genome0, genome1, processedChance);
+ processedChance *= beeModeModifier.getMutationModifier(genome0, genome1, processedChance);
+
+ return processedChance;
+ }
+
+ @SuppressWarnings("unchecked")
+ private float getBasicChance(World world, int x, int y, int z, IAllele allele0, IAllele allele1, IGenome genome0,
+ IGenome genome1, IClimateProvider climate) {
+ float mutationChance = this.getBaseChance();
+ List<IMutationCondition> mutationConditions = null;
+ Field f = FieldUtils.getDeclaredField(Mutation.class, "mutationConditions", true);
+ if (f == null) f = FieldUtils.getField(Mutation.class, "mutationConditions", true);
+ if (f == null) return mutationChance;
+ try {
+ mutationConditions = f.get(this) instanceof List ? (List<IMutationCondition>) f.get(this) : null;
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+
+ if (mutationConditions != null) for (IMutationCondition mutationCondition : mutationConditions) {
+ mutationChance *= mutationCondition.getChance(world, x, y, z, allele0, allele1, genome0, genome1, climate);
+ if (mutationChance == 0) {
+ return 0;
+ }
+ }
+ return mutationChance;
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Block_Casings1.java b/src/main/java/gregtech/common/blocks/GT_Block_Casings1.java
new file mode 100644
index 0000000000..897011eba9
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Block_Casings1.java
@@ -0,0 +1,108 @@
+package gregtech.common.blocks;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.IIcon;
+import net.minecraft.world.IBlockAccess;
+
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Textures;
+import gregtech.api.util.GT_LanguageManager;
+
+/**
+ * The casings are split into separate files because they are registered as regular blocks, and a regular block can have
+ * 16 subtypes at most.
+ */
+public class GT_Block_Casings1 extends GT_Block_Casings_Abstract {
+
+ /**
+ * Texture Index Information Textures.BlockIcons.casingTexturePages[0][0-63] - Gregtech
+ * Textures.BlockIcons.casingTexturePages[0][64-127] - GT++ Textures.BlockIcons.casingTexturePages[1][0-127] -
+ * Gregtech Textures.BlockIcons.casingTexturePages[2][0-127] - Free Textures.BlockIcons.casingTexturePages[3][0-127]
+ * - Free Textures.BlockIcons.casingTexturePages[4][0-127] - Free Textures.BlockIcons.casingTexturePages[5][0-127] -
+ * Free Textures.BlockIcons.casingTexturePages[6][0-127] - Free Textures.BlockIcons.casingTexturePages[7][0-127] -
+ * TecTech Textures.BlockIcons.casingTexturePages[8][0-127] - TecTech
+ */
+ public GT_Block_Casings1() {
+ super(GT_Item_Casings1.class, "gt.blockcasings", GT_Material_Casings.INSTANCE, 16);
+
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".0.name", "ULV Machine Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".1.name", "LV Machine Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".2.name", "MV Machine Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".3.name", "HV Machine Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".4.name", "EV Machine Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".5.name", "IV Machine Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".6.name", "LuV Machine Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".7.name", "ZPM Machine Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".8.name", "UV Machine Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".9.name", "UHV Machine Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".10.name", "Bronze Plated Bricks");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".11.name", "Heat Proof Machine Casing");
+ GT_LanguageManager
+ .addStringLocalization(getUnlocalizedName() + ".12.name", "Dimensionally Transcendent Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".13.name", "Dimensional Injection Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".14.name", "Dimensional Bridge");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".15.name", "Superconducting Coil Block");
+ ItemList.Casing_ULV.set(new ItemStack(this, 1, 0));
+ ItemList.Casing_LV.set(new ItemStack(this, 1, 1));
+ ItemList.Casing_MV.set(new ItemStack(this, 1, 2));
+ ItemList.Casing_HV.set(new ItemStack(this, 1, 3));
+ ItemList.Casing_EV.set(new ItemStack(this, 1, 4));
+ ItemList.Casing_IV.set(new ItemStack(this, 1, 5));
+ ItemList.Casing_LuV.set(new ItemStack(this, 1, 6));
+ ItemList.Casing_ZPM.set(new ItemStack(this, 1, 7));
+ ItemList.Casing_UV.set(new ItemStack(this, 1, 8));
+ ItemList.Casing_MAX.set(new ItemStack(this, 1, 9));
+ ItemList.Casing_BronzePlatedBricks.set(new ItemStack(this, 1, 10));
+ ItemList.Casing_HeatProof.set(new ItemStack(this, 1, 11));
+ ItemList.Casing_Dim_Trans.set(new ItemStack(this, 1, 12));
+ ItemList.Casing_Dim_Injector.set(new ItemStack(this, 1, 13));
+ ItemList.Casing_Dim_Bridge.set(new ItemStack(this, 1, 14));
+ ItemList.Casing_Coil_Superconductor.set(new ItemStack(this, 1, 15));
+ }
+
+ @Override
+ public int getTextureIndex(int aMeta) {
+ return aMeta;
+ }
+
+ @Override
+ public IIcon getIcon(int ordinalSide, int aMeta) {
+ if ((aMeta >= 0) && (aMeta < 16)) {
+ switch (aMeta) {
+ case 10 -> {
+ return Textures.BlockIcons.MACHINE_BRONZEPLATEDBRICKS.getIcon();
+ }
+ case 11 -> {
+ return Textures.BlockIcons.MACHINE_HEATPROOFCASING.getIcon();
+ }
+ case 12 -> {
+ return Textures.BlockIcons.MACHINE_DIM_TRANS_CASING.getIcon();
+ }
+ case 13 -> {
+ return Textures.BlockIcons.MACHINE_DIM_INJECTOR.getIcon();
+ }
+ case 14 -> {
+ return Textures.BlockIcons.MACHINE_DIM_BRIDGE.getIcon();
+ }
+ case 15 -> {
+ return Textures.BlockIcons.MACHINE_COIL_SUPERCONDUCTOR.getIcon();
+ }
+ }
+ if (ordinalSide == 0) {
+ return Textures.BlockIcons.MACHINECASINGS_BOTTOM[aMeta].getIcon();
+ }
+ if (ordinalSide == 1) {
+ return Textures.BlockIcons.MACHINECASINGS_TOP[aMeta].getIcon();
+ }
+ return Textures.BlockIcons.MACHINECASINGS_SIDE[aMeta].getIcon();
+ }
+ return Textures.BlockIcons.MACHINE_CASING_SOLID_STEEL.getIcon();
+ }
+
+ @Override
+ public int colorMultiplier(IBlockAccess aWorld, int aX, int aY, int aZ) {
+ return aWorld.getBlockMetadata(aX, aY, aZ) > 9 ? super.colorMultiplier(aWorld, aX, aY, aZ)
+ : gregtech.api.enums.Dyes.MACHINE_METAL.mRGBa[0] << 16 | gregtech.api.enums.Dyes.MACHINE_METAL.mRGBa[1] << 8
+ | gregtech.api.enums.Dyes.MACHINE_METAL.mRGBa[2];
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Block_Casings2.java b/src/main/java/gregtech/common/blocks/GT_Block_Casings2.java
new file mode 100644
index 0000000000..f1fbc30236
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Block_Casings2.java
@@ -0,0 +1,102 @@
+package gregtech.common.blocks;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.Entity;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.IIcon;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.enums.Dyes;
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Textures;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_LanguageManager;
+
+/**
+ * The casings are split into separate files because they are registered as regular blocks, and a regular block can have
+ * 16 subtypes at most.
+ */
+public class GT_Block_Casings2 extends GT_Block_Casings_Abstract {
+
+ public GT_Block_Casings2() {
+ super(GT_Item_Casings2.class, "gt.blockcasings2", GT_Material_Casings.INSTANCE, 96);
+ // Special handler for Pyrolyse Oven Casing on hatches...
+ Textures.BlockIcons.casingTexturePages[0][22] = TextureFactory.of(
+ Block.getBlockFromItem(
+ ItemList.Casing_ULV.get(1)
+ .getItem()),
+ 0,
+ ForgeDirection.UNKNOWN,
+ Dyes.MACHINE_METAL.mRGBa);
+
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".0.name", "Solid Steel Machine Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".1.name", "Frost Proof Machine Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".2.name", "Bronze Gear Box Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".3.name", "Steel Gear Box Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".4.name", "Titanium Gear Box Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".5.name", "Assembling Line Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".6.name", "Processor Machine Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".7.name", "Data Drive Machine Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".8.name", "Containment Field Machine Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".9.name", "Assembler Machine Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".10.name", "Pump Machine Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".11.name", "Motor Machine Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".12.name", "Bronze Pipe Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".13.name", "Steel Pipe Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".14.name", "Titanium Pipe Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".15.name", "Tungstensteel Pipe Casing");
+ ItemList.Casing_SolidSteel.set(new ItemStack(this, 1, 0));
+ ItemList.Casing_FrostProof.set(new ItemStack(this, 1, 1));
+ ItemList.Casing_Gearbox_Bronze.set(new ItemStack(this, 1, 2));
+ ItemList.Casing_Gearbox_Steel.set(new ItemStack(this, 1, 3));
+ ItemList.Casing_Gearbox_Titanium.set(new ItemStack(this, 1, 4));
+ ItemList.Casing_Gearbox_TungstenSteel.set(new ItemStack(this, 1, 5));
+ ItemList.Casing_Processor.set(new ItemStack(this, 1, 6));
+ ItemList.Casing_DataDrive.set(new ItemStack(this, 1, 7));
+ ItemList.Casing_ContainmentField.set(new ItemStack(this, 1, 8));
+ ItemList.Casing_Assembler.set(new ItemStack(this, 1, 9));
+ ItemList.Casing_Pump.set(new ItemStack(this, 1, 10));
+ ItemList.Casing_Motor.set(new ItemStack(this, 1, 11));
+ ItemList.Casing_Pipe_Bronze.set(new ItemStack(this, 1, 12));
+ ItemList.Casing_Pipe_Steel.set(new ItemStack(this, 1, 13));
+ ItemList.Casing_Pipe_Titanium.set(new ItemStack(this, 1, 14));
+ ItemList.Casing_Pipe_TungstenSteel.set(new ItemStack(this, 1, 15));
+ }
+
+ @Override
+ public int getTextureIndex(int aMeta) {
+ return aMeta == 6 ? ((1 << 7) + 96) : aMeta + 16;
+ }
+
+ @Override
+ public IIcon getIcon(int ordinalSide, int aMeta) {
+ return switch (aMeta) {
+ case 0 -> Textures.BlockIcons.MACHINE_CASING_SOLID_STEEL.getIcon();
+ case 1 -> Textures.BlockIcons.MACHINE_CASING_FROST_PROOF.getIcon();
+ case 2 -> Textures.BlockIcons.MACHINE_CASING_GEARBOX_BRONZE.getIcon();
+ case 3 -> Textures.BlockIcons.MACHINE_CASING_GEARBOX_STEEL.getIcon();
+ case 4 -> Textures.BlockIcons.MACHINE_CASING_GEARBOX_TITANIUM.getIcon();
+ case 5 -> Textures.BlockIcons.MACHINE_CASING_GEARBOX_TUNGSTENSTEEL.getIcon();
+ case 6 -> Textures.BlockIcons.MACHINE_CASING_PROCESSOR.getIcon();
+ case 7 -> Textures.BlockIcons.MACHINE_CASING_DATA_DRIVE.getIcon();
+ case 8 -> Textures.BlockIcons.MACHINE_CASING_CONTAINMENT_FIELD.getIcon();
+ case 9 -> Textures.BlockIcons.MACHINE_CASING_ASSEMBLER.getIcon();
+ case 10 -> Textures.BlockIcons.MACHINE_CASING_PUMP.getIcon();
+ case 11 -> Textures.BlockIcons.MACHINE_CASING_MOTOR.getIcon();
+ case 12 -> Textures.BlockIcons.MACHINE_CASING_PIPE_BRONZE.getIcon();
+ case 13 -> Textures.BlockIcons.MACHINE_CASING_PIPE_STEEL.getIcon();
+ case 14 -> Textures.BlockIcons.MACHINE_CASING_PIPE_TITANIUM.getIcon();
+ case 15 -> Textures.BlockIcons.MACHINE_CASING_PIPE_TUNGSTENSTEEL.getIcon();
+ default -> Textures.BlockIcons.MACHINE_CASING_SOLID_STEEL.getIcon();
+ };
+ }
+
+ @Override
+ public float getExplosionResistance(Entity aTNT, World aWorld, int aX, int aY, int aZ, double eX, double eY,
+ double eZ) {
+ return aWorld.getBlockMetadata(aX, aY, aZ) == 8 ? Blocks.bedrock.getExplosionResistance(aTNT)
+ : super.getExplosionResistance(aTNT, aWorld, aX, aY, aZ, eX, eY, eZ);
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Block_Casings3.java b/src/main/java/gregtech/common/blocks/GT_Block_Casings3.java
new file mode 100644
index 0000000000..ada77814c8
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Block_Casings3.java
@@ -0,0 +1,82 @@
+package gregtech.common.blocks;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.IIcon;
+
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Textures;
+import gregtech.api.util.GT_LanguageManager;
+
+/**
+ * The casings are split into separate files because they are registered as regular blocks, and a regular block can have
+ * 16 subtypes at most.
+ */
+public class GT_Block_Casings3 extends GT_Block_Casings_Abstract {
+
+ public GT_Block_Casings3() {
+ super(GT_Item_Casings3.class, "gt.blockcasings3", GT_Material_Casings.INSTANCE, 16);
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".0.name", "Yellow Stripes Block");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".1.name", "Yellow Stripes Block");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".2.name", "Radioactive Hazard Sign Block");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".3.name", "Bio Hazard Sign Block");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".4.name", "Explosion Hazard Sign Block");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".5.name", "Fire Hazard Sign Block");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".6.name", "Acid Hazard Sign Block");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".7.name", "Magic Hazard Sign Block");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".8.name", "Frost Hazard Sign Block");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".9.name", "Noise Hazard Sign Block");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".10.name", "Grate Machine Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".11.name", "Filter Machine Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".12.name", "Radiation Proof Machine Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".13.name", "Bronze Firebox Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".14.name", "Steel Firebox Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".15.name", "Tungstensteel Firebox Casing");
+ ItemList.Casing_Stripes_A.set(new ItemStack(this, 1, 0));
+ ItemList.Casing_Stripes_B.set(new ItemStack(this, 1, 1));
+ ItemList.Casing_RadioactiveHazard.set(new ItemStack(this, 1, 2));
+ ItemList.Casing_BioHazard.set(new ItemStack(this, 1, 3));
+ ItemList.Casing_ExplosionHazard.set(new ItemStack(this, 1, 4));
+ ItemList.Casing_FireHazard.set(new ItemStack(this, 1, 5));
+ ItemList.Casing_AcidHazard.set(new ItemStack(this, 1, 6));
+ ItemList.Casing_MagicHazard.set(new ItemStack(this, 1, 7));
+ ItemList.Casing_FrostHazard.set(new ItemStack(this, 1, 8));
+ ItemList.Casing_NoiseHazard.set(new ItemStack(this, 1, 9));
+ ItemList.Casing_Grate.set(new ItemStack(this, 1, 10));
+ ItemList.Casing_Vent.set(new ItemStack(this, 1, 11));
+ ItemList.Casing_RadiationProof.set(new ItemStack(this, 1, 12));
+ ItemList.Casing_Firebox_Bronze.set(new ItemStack(this, 1, 13));
+ ItemList.Casing_Firebox_Steel.set(new ItemStack(this, 1, 14));
+ ItemList.Casing_Firebox_TungstenSteel.set(new ItemStack(this, 1, 15));
+ }
+
+ @Override
+ public int getTextureIndex(int aMeta) {
+ return aMeta + 32;
+ }
+
+ @Override
+ public IIcon getIcon(int ordinalSide, int aMeta) {
+ return switch (aMeta) {
+ case 0 -> Textures.BlockIcons.MACHINE_CASING_STRIPES_A.getIcon();
+ case 1 -> Textures.BlockIcons.MACHINE_CASING_STRIPES_B.getIcon();
+ case 2 -> Textures.BlockIcons.MACHINE_CASING_RADIOACTIVEHAZARD.getIcon();
+ case 3 -> Textures.BlockIcons.MACHINE_CASING_BIOHAZARD.getIcon();
+ case 4 -> Textures.BlockIcons.MACHINE_CASING_EXPLOSIONHAZARD.getIcon();
+ case 5 -> Textures.BlockIcons.MACHINE_CASING_FIREHAZARD.getIcon();
+ case 6 -> Textures.BlockIcons.MACHINE_CASING_ACIDHAZARD.getIcon();
+ case 7 -> Textures.BlockIcons.MACHINE_CASING_MAGICHAZARD.getIcon();
+ case 8 -> Textures.BlockIcons.MACHINE_CASING_FROSTHAZARD.getIcon();
+ case 9 -> Textures.BlockIcons.MACHINE_CASING_NOISEHAZARD.getIcon();
+ case 10 -> Textures.BlockIcons.MACHINE_CASING_GRATE.getIcon();
+ case 11 -> Textures.BlockIcons.MACHINE_CASING_VENT.getIcon();
+ case 12 -> Textures.BlockIcons.MACHINE_CASING_RADIATIONPROOF.getIcon();
+ case 13 -> ordinalSide > 1 ? Textures.BlockIcons.MACHINE_CASING_FIREBOX_BRONZE.getIcon()
+ : Textures.BlockIcons.MACHINE_BRONZEPLATEDBRICKS.getIcon();
+ case 14 -> ordinalSide > 1 ? Textures.BlockIcons.MACHINE_CASING_FIREBOX_STEEL.getIcon()
+ : Textures.BlockIcons.MACHINE_CASING_SOLID_STEEL.getIcon();
+ case 15 -> ordinalSide > 1 ? Textures.BlockIcons.MACHINE_CASING_FIREBOX_TUNGSTENSTEEL.getIcon()
+ : Textures.BlockIcons.MACHINE_CASING_ROBUST_TUNGSTENSTEEL.getIcon();
+ default -> Textures.BlockIcons.MACHINE_CASING_SOLID_STEEL.getIcon();
+ };
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Block_Casings4.java b/src/main/java/gregtech/common/blocks/GT_Block_Casings4.java
new file mode 100644
index 0000000000..49c9c6c992
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Block_Casings4.java
@@ -0,0 +1,250 @@
+package gregtech.common.blocks;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.IIcon;
+import net.minecraft.world.IBlockAccess;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.GT_Mod;
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.util.GT_LanguageManager;
+import gregtech.api.util.GT_RenderingWorld;
+import gregtech.common.tileentities.machines.multi.GT_MetaTileEntity_LargeTurbine;
+
+/**
+ * The casings are split into separate files because they are registered as regular blocks, and a regular block can have
+ * 16 subtypes at most.
+ */
+public class GT_Block_Casings4 extends GT_Block_Casings_Abstract {
+
+ /**
+ * This mapping is used to look up which texture should be used to render the connected texture for fusion casings.
+ * <p>
+ * This mapping is computed from that giant if ladder from #getIcon in commit
+ * da3421547afadc49938b5b6a7f9a9679afa1d570 The exact meaning of these numbers are like black magic. Read the
+ * original getIcon implementation to understand why it is 0, 1, etc, if that if ladder is even intelligible.
+ */
+ private static final int[][] mapping = new int[][] {
+ { 7, 7, 7, 7, 0, 7, 0, 7, 1, 7, 1, 7, 8, 7, 8, 7, 0, 7, 0, 7, 0, 7, 0, 7, 9, 7, 9, 7, 3, 7, 3, 7, 1, 7, 1, 7,
+ 11, 7, 11, 7, 1, 7, 1, 7, 2, 7, 2, 7, 10, 7, 10, 7, 5, 7, 5, 7, 4, 7, 4, 7, 6, 7, 6, 7 },
+ { 7, 7, 7, 7, 0, 0, 7, 7, 1, 1, 7, 7, 8, 8, 7, 7, 0, 0, 7, 7, 0, 0, 7, 7, 9, 9, 7, 7, 3, 3, 7, 7, 1, 1, 7, 7,
+ 11, 11, 7, 7, 1, 1, 7, 7, 2, 2, 7, 7, 10, 10, 7, 7, 5, 5, 7, 7, 4, 4, 7, 7, 6, 6, 7, 7 },
+ { 7, 1, 1, 1, 0, 9, 10, 4, 7, 1, 1, 1, 0, 9, 10, 4, 0, 8, 11, 2, 0, 3, 5, 6, 0, 8, 11, 2, 0, 3, 5, 6, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 },
+ { 7, 1, 1, 1, 0, 8, 11, 2, 7, 7, 7, 7, 7, 7, 7, 7, 0, 9, 10, 4, 0, 3, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 1, 1, 1,
+ 0, 8, 11, 2, 7, 7, 7, 7, 7, 7, 7, 7, 0, 9, 10, 4, 0, 3, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7 },
+ { 7, 1, 1, 1, 7, 1, 1, 1, 0, 8, 11, 2, 0, 8, 11, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 9, 10, 4,
+ 0, 9, 10, 4, 0, 3, 5, 6, 0, 3, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 },
+ { 7, 1, 1, 1, 7, 7, 7, 7, 0, 9, 10, 4, 7, 7, 7, 7, 7, 1, 1, 1, 7, 7, 7, 7, 0, 9, 10, 4, 7, 7, 7, 7, 0, 8, 11, 2,
+ 7, 7, 7, 7, 0, 3, 5, 6, 7, 7, 7, 7, 0, 8, 11, 2, 7, 7, 7, 7, 0, 3, 5, 6, 7, 7, 7, 7 }, };
+
+ public static boolean mConnectedMachineTextures = true;
+
+ public GT_Block_Casings4() {
+ super(GT_Item_Casings4.class, "gt.blockcasings4", GT_Material_Casings.INSTANCE, 16);
+ GT_LanguageManager
+ .addStringLocalization(getUnlocalizedName() + ".0.name", "Robust Tungstensteel Machine Casing");
+ GT_LanguageManager
+ .addStringLocalization(getUnlocalizedName() + ".1.name", "Clean Stainless Steel Machine Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".2.name", "Stable Titanium Machine Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".3.name", "Titanium Firebox Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".6.name", "Fusion Machine Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".7.name", "Fusion Coil Block");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".8.name", "Fusion Machine Casing MK II");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".9.name", "Turbine Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".10.name", "Stainless Steel Turbine Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".11.name", "Titanium Turbine Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".12.name", "Tungstensteel Turbine Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".13.name", "Engine Intake Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".14.name", "Mining Osmiridium Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".15.name", "Firebricks");
+
+ ItemList.Casing_RobustTungstenSteel.set(new ItemStack(this, 1, 0));
+ ItemList.Casing_CleanStainlessSteel.set(new ItemStack(this, 1, 1));
+ ItemList.Casing_StableTitanium.set(new ItemStack(this, 1, 2));
+ ItemList.Casing_Firebox_Titanium.set(new ItemStack(this, 1, 3));
+ ItemList.Casing_Fusion.set(new ItemStack(this, 1, 6));
+ ItemList.Casing_Fusion_Coil.set(new ItemStack(this, 1, 7));
+ ItemList.Casing_Fusion2.set(new ItemStack(this, 1, 8));
+ ItemList.Casing_Turbine.set(new ItemStack(this, 1, 9));
+ ItemList.Casing_Turbine1.set(new ItemStack(this, 1, 10));
+ ItemList.Casing_Turbine2.set(new ItemStack(this, 1, 11));
+ ItemList.Casing_Turbine3.set(new ItemStack(this, 1, 12));
+ ItemList.Casing_EngineIntake.set(new ItemStack(this, 1, 13));
+ ItemList.Casing_MiningOsmiridium.set(new ItemStack(this, 1, 14));
+ ItemList.Casing_Firebricks.set(new ItemStack(this, 1, 15));
+
+ GT_Mod.gregtechproxy.mCTMBlockCache.put(this, (byte) 6, true);
+ GT_Mod.gregtechproxy.mCTMBlockCache.put(this, (byte) 8, true);
+ }
+
+ @Override
+ public int getTextureIndex(int aMeta) {
+ return aMeta + 48;
+ }
+
+ @Override
+ public IIcon getIcon(int ordinalSide, int aMeta) {
+ return switch (aMeta) {
+ case 0, 12 -> Textures.BlockIcons.MACHINE_CASING_ROBUST_TUNGSTENSTEEL.getIcon();
+ case 1, 10 -> Textures.BlockIcons.MACHINE_CASING_CLEAN_STAINLESSSTEEL.getIcon();
+ case 2, 11 -> Textures.BlockIcons.MACHINE_CASING_STABLE_TITANIUM.getIcon();
+ case 3 -> ordinalSide > 1 ? Textures.BlockIcons.MACHINE_CASING_FIREBOX_TITANIUM.getIcon()
+ : Textures.BlockIcons.MACHINE_CASING_STABLE_TITANIUM.getIcon();
+ case 4 ->
+ // Do not overwrite!
+ Textures.BlockIcons.MACHINE_CASING_FUSION_GLASS_YELLOW.getIcon();
+ case 5 ->
+ // Do not overwrite!
+ Textures.BlockIcons.MACHINE_CASING_FUSION_GLASS.getIcon();
+ case 6 -> Textures.BlockIcons.MACHINE_CASING_FUSION.getIcon();
+ case 7 -> Textures.BlockIcons.MACHINE_CASING_FUSION_COIL.getIcon();
+ case 8 -> Textures.BlockIcons.MACHINE_CASING_FUSION_2.getIcon();
+ case 9 -> Textures.BlockIcons.MACHINE_CASING_TURBINE.getIcon();
+ case 13 -> Textures.BlockIcons.MACHINE_CASING_ENGINE_INTAKE.getIcon();
+ case 14 -> Textures.BlockIcons.MACHINE_CASING_MINING_OSMIRIDIUM.getIcon();
+ case 15 -> Textures.BlockIcons.MACHINE_CASING_DENSEBRICKS.getIcon();
+ default -> Textures.BlockIcons.MACHINE_CASING_SOLID_STEEL.getIcon();
+ };
+ }
+
+ @Deprecated
+ public IIcon getTurbineCasing(int meta, int iconIndex, boolean active) {
+ return switch (meta) {
+ case 10 -> active ? Textures.BlockIcons.TURBINE_ACTIVE1[iconIndex].getIcon()
+ : Textures.BlockIcons.TURBINE1[iconIndex].getIcon();
+ case 11 -> active ? Textures.BlockIcons.TURBINE_ACTIVE2[iconIndex].getIcon()
+ : Textures.BlockIcons.TURBINE2[iconIndex].getIcon();
+ case 12 -> active ? Textures.BlockIcons.TURBINE_ACTIVE3[iconIndex].getIcon()
+ : Textures.BlockIcons.TURBINE3[iconIndex].getIcon();
+ default -> active ? Textures.BlockIcons.TURBINE_ACTIVE[iconIndex].getIcon()
+ : Textures.BlockIcons.TURBINE[iconIndex].getIcon();
+ };
+ }
+
+ @Deprecated
+ public IIcon getTurbineCasing(int meta, int iconIndex, boolean active, boolean hasTurbine) {
+ return switch (meta) {
+ case 10 -> active ? Textures.BlockIcons.TURBINE_ACTIVE1[iconIndex].getIcon()
+ : hasTurbine ? Textures.BlockIcons.TURBINE1[iconIndex].getIcon()
+ : Textures.BlockIcons.TURBINE_EMPTY1[iconIndex].getIcon();
+ case 11 -> active ? Textures.BlockIcons.TURBINE_ACTIVE2[iconIndex].getIcon()
+ : hasTurbine ? Textures.BlockIcons.TURBINE2[iconIndex].getIcon()
+ : Textures.BlockIcons.TURBINE_EMPTY2[iconIndex].getIcon();
+ case 12 -> active ? Textures.BlockIcons.TURBINE_ACTIVE3[iconIndex].getIcon()
+ : hasTurbine ? Textures.BlockIcons.TURBINE3[iconIndex].getIcon()
+ : Textures.BlockIcons.TURBINE_EMPTY3[iconIndex].getIcon();
+ default -> active ? Textures.BlockIcons.TURBINE_ACTIVE[iconIndex].getIcon()
+ : hasTurbine ? Textures.BlockIcons.TURBINE[iconIndex].getIcon()
+ : Textures.BlockIcons.TURBINE_EMPTY[iconIndex].getIcon();
+ };
+ }
+
+ private static int isTurbineControllerWithSide(IBlockAccess aWorld, int aX, int aY, int aZ, int ordinalSide) {
+ TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if (!(tTileEntity instanceof IGregTechTileEntity tTile)) return 0;
+ if (tTile.getMetaTileEntity() instanceof GT_MetaTileEntity_LargeTurbine turbine && tTile.getFrontFacing()
+ .ordinal() == ordinalSide) {
+ if (turbine.isNewStyleRendering()) return 0;
+ if (tTile.isActive()) return 1;
+ return turbine.hasTurbine() ? 2 : 3;
+ }
+ return 0;
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public IIcon getIcon(IBlockAccess aWorld, int xCoord, int yCoord, int zCoord, int ordinalSide) {
+ aWorld = GT_RenderingWorld.getInstance(aWorld);
+ int tMeta = aWorld.getBlockMetadata(xCoord, yCoord, zCoord);
+ if (tMeta != 6 && tMeta != 8 && tMeta != 9 && tMeta != 10 && tMeta != 11 && tMeta != 12
+ || !mConnectedMachineTextures) {
+ return getIcon(ordinalSide, tMeta);
+ }
+ // noinspection ConstantValue // tMeta < 13 should stay because mConnectedMachineTextures can be changed
+ if (tMeta > 8 && tMeta < 13) {
+ int tInvertLeftRightMod = ordinalSide % 2 * 2 - 1;
+ switch (ordinalSide / 2) {
+ case 0 -> {
+ for (int i = -1; i < 2; i++) {
+ for (int j = -1; j < 2; j++) {
+ if (i == 0 && j == 0) continue;
+ int tState;
+ if ((tState = isTurbineControllerWithSide(
+ aWorld,
+ xCoord + j,
+ yCoord,
+ zCoord + i,
+ ordinalSide)) != 0) {
+ return getTurbineCasing(tMeta, 4 - i * 3 - j, tState == 1, tState == 2);
+ }
+ }
+ }
+ }
+ case 1 -> {
+ for (int i = -1; i < 2; i++) {
+ for (int j = -1; j < 2; j++) {
+ if (i == 0 && j == 0) continue;
+ int tState;
+ if ((tState = isTurbineControllerWithSide(
+ aWorld,
+ xCoord + j,
+ yCoord + i,
+ zCoord,
+ ordinalSide)) != 0) {
+ return getTurbineCasing(
+ tMeta,
+ 4 + i * 3 - j * tInvertLeftRightMod,
+ tState == 1,
+ tState == 2);
+ }
+ }
+ }
+ }
+ case 2 -> {
+ for (int i = -1; i < 2; i++) {
+ for (int j = -1; j < 2; j++) {
+ if (i == 0 && j == 0) continue;
+ int tState;
+ if ((tState = isTurbineControllerWithSide(
+ aWorld,
+ xCoord,
+ yCoord + i,
+ zCoord + j,
+ ordinalSide)) != 0) {
+ return getTurbineCasing(
+ tMeta,
+ 4 + i * 3 + j * tInvertLeftRightMod,
+ tState == 1,
+ tState == 2);
+ }
+ }
+ }
+ }
+ }
+ return switch (tMeta) {
+ case 10 -> Textures.BlockIcons.MACHINE_CASING_CLEAN_STAINLESSSTEEL.getIcon();
+ case 11 -> Textures.BlockIcons.MACHINE_CASING_STABLE_TITANIUM.getIcon();
+ case 12 -> Textures.BlockIcons.MACHINE_CASING_ROBUST_TUNGSTENSTEEL.getIcon();
+ default -> Textures.BlockIcons.MACHINE_CASING_SOLID_STEEL.getIcon();
+ };
+ }
+ int tStartIndex = tMeta == 6 ? 1 : 13;
+ int tIndexIntoMapping = 0;
+ if (isSameBlock(aWorld, xCoord, yCoord - 1, zCoord, tMeta)) tIndexIntoMapping |= 1;
+ if (isSameBlock(aWorld, xCoord, yCoord + 1, zCoord, tMeta)) tIndexIntoMapping |= 1 << 1;
+ if (isSameBlock(aWorld, xCoord + 1, yCoord, zCoord, tMeta)) tIndexIntoMapping |= 1 << 2;
+ if (isSameBlock(aWorld, xCoord, yCoord, zCoord + 1, tMeta)) tIndexIntoMapping |= 1 << 3;
+ if (isSameBlock(aWorld, xCoord - 1, yCoord, zCoord, tMeta)) tIndexIntoMapping |= 1 << 4;
+ if (isSameBlock(aWorld, xCoord, yCoord, zCoord - 1, tMeta)) tIndexIntoMapping |= 1 << 5;
+ return Textures.BlockIcons.CONNECTED_HULLS[tStartIndex + mapping[ordinalSide][tIndexIntoMapping]].getIcon();
+ }
+
+ private boolean isSameBlock(IBlockAccess aWorld, int aX, int aY, int aZ, int aMeta) {
+ return aWorld.getBlock(aX, aY, aZ) == this && aWorld.getBlockMetadata(aX, aY, aZ) == aMeta;
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Block_Casings5.java b/src/main/java/gregtech/common/blocks/GT_Block_Casings5.java
new file mode 100644
index 0000000000..3a9efdbe71
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Block_Casings5.java
@@ -0,0 +1,159 @@
+package gregtech.common.blocks;
+
+import static gregtech.api.enums.HeatingCoilLevel.EV;
+import static gregtech.api.enums.HeatingCoilLevel.HV;
+import static gregtech.api.enums.HeatingCoilLevel.IV;
+import static gregtech.api.enums.HeatingCoilLevel.LV;
+import static gregtech.api.enums.HeatingCoilLevel.LuV;
+import static gregtech.api.enums.HeatingCoilLevel.MAX;
+import static gregtech.api.enums.HeatingCoilLevel.MV;
+import static gregtech.api.enums.HeatingCoilLevel.None;
+import static gregtech.api.enums.HeatingCoilLevel.UEV;
+import static gregtech.api.enums.HeatingCoilLevel.UHV;
+import static gregtech.api.enums.HeatingCoilLevel.UIV;
+import static gregtech.api.enums.HeatingCoilLevel.UMV;
+import static gregtech.api.enums.HeatingCoilLevel.UV;
+import static gregtech.api.enums.HeatingCoilLevel.UXV;
+import static gregtech.api.enums.HeatingCoilLevel.ZPM;
+
+import java.util.function.Consumer;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.IIcon;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.api.enums.HeatingCoilLevel;
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IHeatingCoil;
+import gregtech.api.util.GT_LanguageManager;
+
+/**
+ * The casings are split into separate files because they are registered as regular blocks, and a regular block can have
+ * 16 subtypes at most.
+ */
+public class GT_Block_Casings5 extends GT_Block_Casings_Abstract implements IHeatingCoil {
+
+ public GT_Block_Casings5() {
+ super(GT_Item_Casings5.class, "gt.blockcasings5", GT_Material_Casings.INSTANCE, 16);
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".0.name", "Cupronickel Coil Block");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".1.name", "Kanthal Coil Block");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".2.name", "Nichrome Coil Block");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".3.name", "TPV-Alloy Coil Block");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".4.name", "HSS-G Coil Block");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".5.name", "Naquadah Coil Block");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".6.name", "Naquadah Alloy Coil Block");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".7.name", "Electrum Flux Coil Block");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".8.name", "Awakened Draconium Coil Block");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".9.name", "HSS-S Coil Block");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".10.name", "Trinium Coil Block");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".11.name", "Infinity Coil Block");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".12.name", "Hypogen Coil Block");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".13.name", "Eternal Coil Block");
+
+ ItemList.Casing_Coil_Cupronickel.set(new ItemStack(this, 1, 0));
+ ItemList.Casing_Coil_Kanthal.set(new ItemStack(this, 1, 1));
+ ItemList.Casing_Coil_Nichrome.set(new ItemStack(this, 1, 2));
+ ItemList.Casing_Coil_TungstenSteel.set(new ItemStack(this, 1, 3));
+ ItemList.Casing_Coil_HSSG.set(new ItemStack(this, 1, 4));
+ ItemList.Casing_Coil_Naquadah.set(new ItemStack(this, 1, 5));
+ ItemList.Casing_Coil_NaquadahAlloy.set(new ItemStack(this, 1, 6));
+ ItemList.Casing_Coil_ElectrumFlux.set(new ItemStack(this, 1, 7));
+ ItemList.Casing_Coil_AwakenedDraconium.set(new ItemStack(this, 1, 8));
+ ItemList.Casing_Coil_HSSS.set(new ItemStack(this, 1, 9));
+ ItemList.Casing_Coil_Trinium.set(new ItemStack(this, 1, 10));
+ ItemList.Casing_Coil_Infinity.set(new ItemStack(this, 1, 11));
+ ItemList.Casing_Coil_Hypogen.set(new ItemStack(this, 1, 12));
+ ItemList.Casing_Coil_Eternal.set(new ItemStack(this, 1, 13));
+ }
+
+ @Override
+ public int getTextureIndex(int aMeta) {
+ return (1 << 7) | aMeta;
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public IIcon getIcon(int ordinalSide, int aMeta) {
+ return switch (aMeta) {
+ case 0 -> Textures.BlockIcons.MACHINE_COIL_CUPRONICKEL.getIcon();
+ case 1 -> Textures.BlockIcons.MACHINE_COIL_KANTHAL.getIcon();
+ case 2 -> Textures.BlockIcons.MACHINE_COIL_NICHROME.getIcon();
+ case 3 -> Textures.BlockIcons.MACHINE_COIL_TUNGSTENSTEEL.getIcon();
+ case 4 -> Textures.BlockIcons.MACHINE_COIL_HSSG.getIcon();
+ case 5 -> Textures.BlockIcons.MACHINE_COIL_NAQUADAH.getIcon();
+ case 6 -> Textures.BlockIcons.MACHINE_COIL_NAQUADAHALLOY.getIcon();
+ case 7 -> Textures.BlockIcons.MACHINE_COIL_ELECTRUMFLUX.getIcon();
+ case 8 -> Textures.BlockIcons.MACHINE_COIL_AWAKENEDDRACONIUM.getIcon();
+ case 9 -> Textures.BlockIcons.MACHINE_COIL_HSSS.getIcon();
+ case 10 -> Textures.BlockIcons.MACHINE_COIL_TRINIUM.getIcon();
+ case 11 -> Textures.BlockIcons.MACHINE_COIL_INFINITY.getIcon();
+ case 12 -> Textures.BlockIcons.MACHINE_COIL_HYPOGEN.getIcon();
+ case 13 -> Textures.BlockIcons.MACHINE_COIL_ETERNAL.getIcon();
+ default -> Textures.BlockIcons.MACHINE_COIL_CUPRONICKEL.getIcon();
+ };
+ }
+
+ /*--------------- COIL CHECK IMPL. ------------*/
+
+ public static HeatingCoilLevel getCoilHeatFromDamage(int meta) {
+ return switch (meta) {
+ case 0 -> LV;
+ case 1 -> MV;
+ case 2 -> HV;
+ case 3 -> EV;
+ case 4 -> IV;
+ case 5 -> ZPM;
+ case 6 -> UV;
+ case 7 -> UEV;
+ case 8 -> UIV;
+ case 9 -> LuV;
+ case 10 -> UHV;
+ case 11 -> UMV;
+ case 12 -> UXV;
+ case 13 -> MAX;
+ default -> None;
+ };
+ }
+
+ public static int getMetaFromCoilHeat(HeatingCoilLevel level) {
+ return switch (level) {
+ case LV -> 0;
+ case MV -> 1;
+ case HV -> 2;
+ case EV -> 3;
+ case IV -> 4;
+ case ZPM -> 5;
+ case UV -> 6;
+ case UEV -> 7;
+ case UIV -> 8;
+ case LuV -> 9;
+ case UHV -> 10;
+ case UMV -> 11;
+ case UXV -> 12;
+ case MAX -> 13;
+ default -> 0;
+ };
+ }
+
+ @Override
+ public HeatingCoilLevel getCoilHeat(int meta) {
+ getOnCoilCheck().accept(this);
+ return getCoilHeatFromDamage(meta);
+ }
+
+ /*--------------- CALLBACK ------------*/
+
+ private Consumer<IHeatingCoil> callback = coil -> {};
+
+ @Override
+ public void setOnCoilCheck(Consumer<IHeatingCoil> callback) {
+ this.callback = callback;
+ }
+
+ @Override
+ public Consumer<IHeatingCoil> getOnCoilCheck() {
+ return this.callback;
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Block_Casings6.java b/src/main/java/gregtech/common/blocks/GT_Block_Casings6.java
new file mode 100644
index 0000000000..9bdbf256cc
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Block_Casings6.java
@@ -0,0 +1,94 @@
+package gregtech.common.blocks;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.IIcon;
+import net.minecraft.world.IBlockAccess;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Textures;
+import gregtech.api.util.GT_LanguageManager;
+
+/**
+ * The casings are split into separate files because they are registered as regular blocks, and a regular block can have
+ * 16 subtypes at most.
+ */
+public class GT_Block_Casings6 extends GT_Block_Casings_Abstract {
+
+ public GT_Block_Casings6() {
+ super(GT_Item_Casings6.class, "gt.blockcasings6", GT_Material_Casings.INSTANCE, 16);
+
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".0.name", "Hermetic Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".1.name", "Hermetic Casing I");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".2.name", "Hermetic Casing II");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".3.name", "Hermetic Casing III");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".4.name", "Hermetic Casing IV");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".5.name", "Hermetic Casing V");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".6.name", "Hermetic Casing VI");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".7.name", "Hermetic Casing VII");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".8.name", "Hermetic Casing VIII");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".9.name", "Hermetic Casing IX");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".10.name", "Hermetic Casing X");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".11.name", "Hermetic Casing XI");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".12.name", "Hermetic Casing XII");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".13.name", "Hermetic Casing XIII");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".14.name", "Hermetic Casing XIV");
+
+ ItemList.Casing_Tank_0.set(new ItemStack(this, 1, 0));
+ ItemList.Casing_Tank_1.set(new ItemStack(this, 1, 1));
+ ItemList.Casing_Tank_2.set(new ItemStack(this, 1, 2));
+ ItemList.Casing_Tank_3.set(new ItemStack(this, 1, 3));
+ ItemList.Casing_Tank_4.set(new ItemStack(this, 1, 4));
+ ItemList.Casing_Tank_5.set(new ItemStack(this, 1, 5));
+ ItemList.Casing_Tank_6.set(new ItemStack(this, 1, 6));
+ ItemList.Casing_Tank_7.set(new ItemStack(this, 1, 7));
+ ItemList.Casing_Tank_8.set(new ItemStack(this, 1, 8));
+ ItemList.Casing_Tank_9.set(new ItemStack(this, 1, 9));
+ ItemList.Casing_Tank_10.set(new ItemStack(this, 1, 10));
+ ItemList.Casing_Tank_11.set(new ItemStack(this, 1, 11));
+ ItemList.Casing_Tank_12.set(new ItemStack(this, 1, 12));
+ ItemList.Casing_Tank_13.set(new ItemStack(this, 1, 13));
+ ItemList.Casing_Tank_14.set(new ItemStack(this, 1, 14));
+ }
+
+ @Override
+ public int getTextureIndex(int aMeta) {
+ return (8 << 7) | (aMeta + 112);
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public IIcon getIcon(int ordinalSide, int aMeta) {
+ if (ordinalSide == 0) {
+ return Textures.BlockIcons.MACHINECASINGS_BOTTOM[aMeta].getIcon();
+ }
+ if (ordinalSide == 1) {
+ return Textures.BlockIcons.MACHINECASINGS_TOP[aMeta].getIcon();
+ }
+ return switch (aMeta) {
+ case 1 -> Textures.BlockIcons.MACHINE_CASING_TANK_1.getIcon();
+ case 2 -> Textures.BlockIcons.MACHINE_CASING_TANK_2.getIcon();
+ case 3 -> Textures.BlockIcons.MACHINE_CASING_TANK_3.getIcon();
+ case 4 -> Textures.BlockIcons.MACHINE_CASING_TANK_4.getIcon();
+ case 5 -> Textures.BlockIcons.MACHINE_CASING_TANK_5.getIcon();
+ case 6 -> Textures.BlockIcons.MACHINE_CASING_TANK_6.getIcon();
+ case 7 -> Textures.BlockIcons.MACHINE_CASING_TANK_7.getIcon();
+ case 8 -> Textures.BlockIcons.MACHINE_CASING_TANK_8.getIcon();
+ case 9 -> Textures.BlockIcons.MACHINE_CASING_TANK_9.getIcon();
+ case 10 -> Textures.BlockIcons.MACHINE_CASING_TANK_10.getIcon();
+ case 11 -> Textures.BlockIcons.MACHINE_CASING_TANK_11.getIcon();
+ case 12 -> Textures.BlockIcons.MACHINE_CASING_TANK_12.getIcon();
+ case 13 -> Textures.BlockIcons.MACHINE_CASING_TANK_13.getIcon();
+ case 14 -> Textures.BlockIcons.MACHINE_CASING_TANK_14.getIcon();
+ default -> Textures.BlockIcons.MACHINE_CASING_TANK_0.getIcon();
+ };
+ }
+
+ @Override
+ public int colorMultiplier(IBlockAccess aWorld, int aX, int aY, int aZ) {
+ return gregtech.api.enums.Dyes.MACHINE_METAL.mRGBa[0] << 16
+ | gregtech.api.enums.Dyes.MACHINE_METAL.mRGBa[1] << 8
+ | gregtech.api.enums.Dyes.MACHINE_METAL.mRGBa[2];
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Block_Casings8.java b/src/main/java/gregtech/common/blocks/GT_Block_Casings8.java
new file mode 100644
index 0000000000..fdef0def82
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Block_Casings8.java
@@ -0,0 +1,199 @@
+package gregtech.common.blocks;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.IIcon;
+import net.minecraft.world.IBlockAccess;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.util.GT_LanguageManager;
+import gregtech.api.util.GT_RenderingWorld;
+import gregtech.common.tileentities.machines.multi.GT_MetaTileEntity_LargeTurbine;
+
+/**
+ * The casings are split into separate files because they are registered as regular blocks, and a regular block can have
+ * 16 subtypes at most.
+ */
+public class GT_Block_Casings8 extends GT_Block_Casings_Abstract {
+
+ public static boolean mConnectedMachineTextures = true;
+
+ // WATCH OUT FOR TEXTURE ID's
+ public GT_Block_Casings8() {
+ super(GT_Item_Casings8.class, "gt.blockcasings8", GT_Material_Casings.INSTANCE, 15);
+ /*
+ * DO NOT USE INDEX 15 ! USED HERE: https://github.com/GTNewHorizons/KubaTech/pull/101
+ */
+
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".0.name", "Chemically Inert Machine Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".1.name", "PTFE Pipe Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".2.name", "Mining Neutronium Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".3.name", "Mining Black Plutonium Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".4.name", "Extreme Engine Intake Casing");
+ GT_LanguageManager.addStringLocalization(
+ getUnlocalizedName() + ".5.name",
+ "Europium Reinforced Radiation Proof Machine Casing");
+ GT_LanguageManager.addStringLocalization(
+ getUnlocalizedName() + ".6.name",
+ "Advanced Rhodium Plated Palladium Machine Casing");
+ GT_LanguageManager
+ .addStringLocalization(getUnlocalizedName() + ".7.name", "Advanced Iridium Plated Machine Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".8.name", "Magical Machine Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".9.name", "HSS-S Turbine Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".10.name", "Radiant Naquadah Alloy Casing");
+ GT_LanguageManager
+ .addStringLocalization(getUnlocalizedName() + ".11.name", "Basic Photolithographic Framework Casing");
+ GT_LanguageManager
+ .addStringLocalization(getUnlocalizedName() + ".12.name", "Reinforced Photolithographic Framework Casing");
+ GT_LanguageManager.addStringLocalization(
+ getUnlocalizedName() + ".13.name",
+ "Radiation Proof Photolithographic Framework Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".14.name", "Infinity Cooled Casing");
+
+ ItemList.Casing_Chemically_Inert.set(new ItemStack(this, 1, 0));
+ ItemList.Casing_Pipe_Polytetrafluoroethylene.set(new ItemStack(this, 1, 1));
+ ItemList.Casing_MiningNeutronium.set(new ItemStack(this, 1, 2));
+ ItemList.Casing_MiningBlackPlutonium.set(new ItemStack(this, 1, 3));
+ ItemList.Casing_ExtremeEngineIntake.set(new ItemStack(this, 1, 4));
+ ItemList.Casing_AdvancedRadiationProof.set(new ItemStack(this, 1, 5));
+ ItemList.Casing_Advanced_Rhodium_Palladium.set(new ItemStack(this, 1, 6));
+ ItemList.Casing_Advanced_Iridium.set(new ItemStack(this, 1, 7));
+ ItemList.Casing_Magical.set(new ItemStack(this, 1, 8));
+ ItemList.Casing_TurbineGasAdvanced.set(new ItemStack(this, 1, 9));
+ ItemList.RadiantNaquadahAlloyCasing.set(new ItemStack(this, 1, 10));
+ ItemList.BasicPhotolithographicFrameworkCasing.set(new ItemStack(this, 1, 11));
+ ItemList.ReinforcedPhotolithographicFrameworkCasing.set(new ItemStack(this, 1, 12));
+ ItemList.RadiationProofPhotolithographicFrameworkCasing.set(new ItemStack(this, 1, 13));
+ ItemList.InfinityCooledCasing.set(new ItemStack(this, 1, 14));
+ }
+
+ @Override
+ public int getTextureIndex(int aMeta) {
+ return (1 << 7) | (aMeta + 48);
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public IIcon getIcon(int ordinalSide, int aMeta) {
+ return switch (aMeta) {
+ case 0 -> Textures.BlockIcons.MACHINE_CASING_CHEMICALLY_INERT.getIcon();
+ case 1 -> Textures.BlockIcons.MACHINE_CASING_PIPE_POLYTETRAFLUOROETHYLENE.getIcon();
+ case 2 -> Textures.BlockIcons.MACHINE_CASING_MINING_NEUTRONIUM.getIcon();
+ case 3 -> Textures.BlockIcons.MACHINE_CASING_MINING_BLACKPLUTONIUM.getIcon();
+ case 4 -> Textures.BlockIcons.MACHINE_CASING_EXTREME_ENGINE_INTAKE.getIcon(); // changed color in a
+ // terrible way
+ case 5 -> Textures.BlockIcons.MACHINE_CASING_ADVANCEDRADIATIONPROOF.getIcon();
+ case 6 -> Textures.BlockIcons.MACHINE_CASING_RHODIUM_PALLADIUM.getIcon();
+ case 7 -> Textures.BlockIcons.MACHINE_CASING_IRIDIUM.getIcon();
+ case 8 -> Textures.BlockIcons.MACHINE_CASING_MAGICAL.getIcon();
+ case 9 -> Textures.BlockIcons.MACHINE_CASING_ADVANCEDGAS.getIcon();
+ case 10 -> Textures.BlockIcons.MACHINE_CASING_RADIANT_NAQUADAH_ALLOY.getIcon();
+ case 11 -> Textures.BlockIcons.MACHINE_CASING_PCB_TIER_1.getIcon();
+ case 12 -> Textures.BlockIcons.MACHINE_CASING_PCB_TIER_2.getIcon();
+ case 13 -> Textures.BlockIcons.MACHINE_CASING_PCB_TIER_3.getIcon();
+ case 14 -> Textures.BlockIcons.INFINITY_COOLED_CASING.getIcon();
+ default -> Textures.BlockIcons.MACHINE_CASING_ROBUST_TUNGSTENSTEEL.getIcon();
+ };
+ }
+
+ @Deprecated
+ public IIcon getTurbineCasing(int meta, int iconIndex, boolean active) {
+ // noinspection SwitchStatementWithTooFewBranches // "if" is harder to edit
+ return switch (meta) {
+ case 9 -> active ? Textures.BlockIcons.TURBINE_ADVGASACTIVE[iconIndex].getIcon()
+ : Textures.BlockIcons.TURBINEADVGAS[iconIndex].getIcon();
+ default -> active ? Textures.BlockIcons.TURBINE_ACTIVE[iconIndex].getIcon()
+ : Textures.BlockIcons.TURBINE[iconIndex].getIcon();
+ };
+ }
+
+ public IIcon getTurbineCasing(int meta, int iconIndex, boolean active, boolean hasTurbine) {
+ // noinspection SwitchStatementWithTooFewBranches // "if" is harder to edit
+ return switch (meta) {
+ case 9 -> active ? Textures.BlockIcons.TURBINE_ADVGASACTIVE[iconIndex].getIcon()
+ : hasTurbine ? Textures.BlockIcons.TURBINEADVGAS[iconIndex].getIcon()
+ : Textures.BlockIcons.TURBINE_ADVGASEMPTY[iconIndex].getIcon();
+ default -> active ? Textures.BlockIcons.TURBINE_ACTIVE[iconIndex].getIcon()
+ : hasTurbine ? Textures.BlockIcons.TURBINE[iconIndex].getIcon()
+ : Textures.BlockIcons.TURBINE_EMPTY[iconIndex].getIcon();
+ };
+ }
+
+ private static int isTurbineControllerWithSide(IBlockAccess aWorld, int aX, int aY, int aZ, int ordinalSide) {
+ TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if (!(tTileEntity instanceof IGregTechTileEntity tTile)) return 0;
+ if (tTile.getMetaTileEntity() instanceof GT_MetaTileEntity_LargeTurbine turbine && tTile.getFrontFacing()
+ .ordinal() == ordinalSide) {
+ if (turbine.isNewStyleRendering()) return 0;
+ if (tTile.isActive()) return 1;
+ return turbine.hasTurbine() ? 2 : 3;
+ }
+ return 0;
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public IIcon getIcon(IBlockAccess aWorld, int xCoord, int yCoord, int zCoord, int ordinalSide) {
+ aWorld = GT_RenderingWorld.getInstance(aWorld);
+ final int tMeta = aWorld.getBlockMetadata(xCoord, yCoord, zCoord);
+
+ if (tMeta != 9 || !mConnectedMachineTextures) {
+ return getIcon(ordinalSide, tMeta);
+ }
+
+ int tInvertLeftRightMod = ordinalSide % 2 * 2 - 1;
+
+ switch (ordinalSide / 2) {
+ case 0 -> {
+ for (int i = -1; i < 2; i++) {
+ for (int j = -1; j < 2; j++) {
+ if (i == 0 && j == 0) continue;
+ int tState;
+ if ((tState = isTurbineControllerWithSide(aWorld, xCoord + j, yCoord, zCoord + i, ordinalSide))
+ != 0) {
+ return getTurbineCasing(tMeta, 4 - i * 3 - j, tState == 1, tState == 2);
+ }
+ }
+ }
+ }
+ case 1 -> {
+ for (int i = -1; i < 2; i++) {
+ for (int j = -1; j < 2; j++) {
+ if (i == 0 && j == 0) continue;
+ int tState;
+ if ((tState = isTurbineControllerWithSide(aWorld, xCoord + j, yCoord + i, zCoord, ordinalSide))
+ != 0) {
+ return getTurbineCasing(
+ tMeta,
+ 4 + i * 3 - j * tInvertLeftRightMod,
+ tState == 1,
+ tState == 2);
+ }
+ }
+ }
+ }
+ case 2 -> {
+ for (int i = -1; i < 2; i++) {
+ for (int j = -1; j < 2; j++) {
+ if (i == 0 && j == 0) continue;
+ int tState;
+ if ((tState = isTurbineControllerWithSide(aWorld, xCoord, yCoord + i, zCoord + j, ordinalSide))
+ != 0) {
+ return getTurbineCasing(
+ tMeta,
+ 4 + i * 3 + j * tInvertLeftRightMod,
+ tState == 1,
+ tState == 2);
+ }
+ }
+ }
+ }
+ }
+
+ return Textures.BlockIcons.MACHINE_CASING_SOLID_STEEL.getIcon();
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Block_Casings9.java b/src/main/java/gregtech/common/blocks/GT_Block_Casings9.java
new file mode 100644
index 0000000000..bc6aca6255
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Block_Casings9.java
@@ -0,0 +1,43 @@
+package gregtech.common.blocks;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.IIcon;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Textures;
+import gregtech.api.util.GT_LanguageManager;
+
+/**
+ * The casings are split into separate files because they are registered as regular blocks, and a regular block can have
+ * 16 subtypes at most.
+ */
+public class GT_Block_Casings9 extends GT_Block_Casings_Abstract {
+
+ public GT_Block_Casings9() {
+ super(GT_Item_Casings9.class, "gt.blockcasings9", GT_Material_Casings.INSTANCE, 2);
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".0.name", "PBI Pipe Casing");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".1.name", "Advanced Filter Casing");
+ GT_LanguageManager
+ .addStringLocalization(getUnlocalizedName() + ".1.tooltip", "Less than five 0.1μm particles per m^3");
+
+ ItemList.Casing_Pipe_Polybenzimidazole.set(new ItemStack(this, 1, 0));
+ ItemList.Casing_Vent_T2.set(new ItemStack(this, 1, 1));
+ }
+
+ @Override
+ public int getTextureIndex(int aMeta) {
+ return (1 << 7) | (aMeta + 64);
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public IIcon getIcon(int ordinalSide, int aMeta) {
+ return switch (aMeta) {
+ case 0 -> Textures.BlockIcons.MACHINE_CASING_PIPE_POLYBENZIMIDAZOLE.getIcon();
+ case 1 -> Textures.BlockIcons.MACHINE_CASING_VENT_T2.getIcon();
+ default -> Textures.BlockIcons.MACHINE_CASING_ROBUST_TUNGSTENSTEEL.getIcon();
+ };
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Block_Casings_Abstract.java b/src/main/java/gregtech/common/blocks/GT_Block_Casings_Abstract.java
new file mode 100644
index 0000000000..59144666df
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Block_Casings_Abstract.java
@@ -0,0 +1,144 @@
+package gregtech.common.blocks;
+
+import java.util.List;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.material.Material;
+import net.minecraft.client.renderer.texture.IIconRegister;
+import net.minecraft.creativetab.CreativeTabs;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.EnumCreatureType;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemBlock;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.StatCollector;
+import net.minecraft.world.IBlockAccess;
+import net.minecraft.world.World;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.Textures;
+import gregtech.api.items.GT_Generic_Block;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_LanguageManager;
+
+/**
+ * The base class for casings. Casings are the blocks that are mainly used to build multiblocks.
+ */
+public abstract class GT_Block_Casings_Abstract extends GT_Generic_Block
+ implements gregtech.api.interfaces.IHasIndexedTexture {
+
+ public GT_Block_Casings_Abstract(Class<? extends ItemBlock> aItemClass, String aName, Material aMaterial) {
+ super(aItemClass, aName, aMaterial);
+ setStepSound(soundTypeMetal);
+ setCreativeTab(GregTech_API.TAB_GREGTECH);
+ GregTech_API.registerMachineBlock(this, -1);
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + "." + 32767 + ".name", "Any Sub Block of this");
+ }
+
+ public GT_Block_Casings_Abstract(Class<? extends ItemBlock> aItemClass, String aName, Material aMaterial,
+ int aMaxMeta) {
+ this(aItemClass, aName, aMaterial);
+ for (int i = 0; i < aMaxMeta; i++) {
+ Textures.BlockIcons.setCasingTextureForId(getTextureIndex(i), TextureFactory.of(this, i));
+ }
+ }
+
+ @Override
+ public String getHarvestTool(int aMeta) {
+ return "wrench";
+ }
+
+ @Override
+ public int getHarvestLevel(int aMeta) {
+ return 2;
+ }
+
+ @Override
+ public float getBlockHardness(World aWorld, int aX, int aY, int aZ) {
+ return Blocks.iron_block.getBlockHardness(aWorld, aX, aY, aZ);
+ }
+
+ @Override
+ public float getExplosionResistance(Entity aTNT) {
+ return Blocks.iron_block.getExplosionResistance(aTNT);
+ }
+
+ @Override
+ protected boolean canSilkHarvest() {
+ return false;
+ }
+
+ @Override
+ public void onBlockAdded(World aWorld, int aX, int aY, int aZ) {
+ if (GregTech_API.isMachineBlock(this, aWorld.getBlockMetadata(aX, aY, aZ))) {
+ GregTech_API.causeMachineUpdate(aWorld, aX, aY, aZ);
+ }
+ }
+
+ @Override
+ public String getUnlocalizedName() {
+ return this.mUnlocalizedName;
+ }
+
+ @Override
+ public String getLocalizedName() {
+ return StatCollector.translateToLocal(this.mUnlocalizedName + ".name");
+ }
+
+ @Override
+ public boolean canBeReplacedByLeaves(IBlockAccess aWorld, int aX, int aY, int aZ) {
+ return false;
+ }
+
+ @Override
+ public boolean isNormalCube(IBlockAccess aWorld, int aX, int aY, int aZ) {
+ return true;
+ }
+
+ @Override
+ public void breakBlock(World aWorld, int aX, int aY, int aZ, Block aBlock, int aMetaData) {
+ if (GregTech_API.isMachineBlock(this, aWorld.getBlockMetadata(aX, aY, aZ))) {
+ GregTech_API.causeMachineUpdate(aWorld, aX, aY, aZ);
+ }
+ }
+
+ @Override
+ public boolean canCreatureSpawn(EnumCreatureType type, IBlockAccess world, int x, int y, int z) {
+ return false;
+ }
+
+ @Override
+ public int damageDropped(int metadata) {
+ return metadata;
+ }
+
+ @Override
+ public int getDamageValue(World aWorld, int aX, int aY, int aZ) {
+ return aWorld.getBlockMetadata(aX, aY, aZ);
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void registerBlockIcons(IIconRegister aIconRegister) {}
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void getSubBlocks(Item aItem, CreativeTabs aCreativeTab, List<ItemStack> aList) {
+ for (int i = 0; i < 16; i++) {
+ ItemStack aStack = new ItemStack(aItem, 1, i);
+ if (!aStack.getDisplayName()
+ .contains(".name")) aList.add(aStack);
+ }
+ }
+
+ /**
+ * Provide a fallback to subclasses in addons.
+ */
+ @Override
+ public int getTextureIndex(int aMeta) {
+ return Textures.BlockIcons.ERROR_TEXTURE_INDEX;
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Block_Concretes.java b/src/main/java/gregtech/common/blocks/GT_Block_Concretes.java
new file mode 100644
index 0000000000..c7b7e2bb04
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Block_Concretes.java
@@ -0,0 +1,83 @@
+package gregtech.common.blocks;
+
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.IIcon;
+import net.minecraft.world.World;
+
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.interfaces.IBlockOnWalkOver;
+import gregtech.api.util.GT_LanguageManager;
+import gregtech.api.util.GT_OreDictUnificator;
+
+public class GT_Block_Concretes extends GT_Block_Stones_Abstract implements IBlockOnWalkOver {
+
+ public GT_Block_Concretes() {
+ super(GT_Item_Concretes.class, "gt.blockconcretes");
+ setResistance(20.0F);
+ // this.slipperiness = 0.9F;
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".0.name", "Dark Concrete");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".1.name", "Dark Concrete Cobblestone");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".2.name", "Mossy Dark Concrete Cobblestone");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".3.name", "Dark Concrete Bricks");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".4.name", "Cracked Dark Concrete Bricks");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".5.name", "Mossy Dark Concrete Bricks");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".6.name", "Chiseled Dark Concrete");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".7.name", "Smooth Dark Concrete");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".8.name", "Light Concrete");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".9.name", "Light Concrete Cobblestone");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".10.name", "Mossy Light Concrete Cobblestone");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".11.name", "Light Concrete Bricks");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".12.name", "Cracked Light Concrete Bricks");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".13.name", "Mossy Light Concrete Bricks");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".14.name", "Chiseled Light Concrete");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".15.name", "Smooth Light Concrete");
+ GT_OreDictUnificator.registerOre(OrePrefixes.stone, Materials.Concrete, new ItemStack(this, 1, 0));
+ GT_OreDictUnificator.registerOre(OrePrefixes.stone, Materials.Concrete, new ItemStack(this, 1, 1));
+ GT_OreDictUnificator.registerOre(OrePrefixes.stone, Materials.Concrete, new ItemStack(this, 1, 2));
+ GT_OreDictUnificator.registerOre(OrePrefixes.stone, Materials.Concrete, new ItemStack(this, 1, 3));
+ GT_OreDictUnificator.registerOre(OrePrefixes.stone, Materials.Concrete, new ItemStack(this, 1, 4));
+ GT_OreDictUnificator.registerOre(OrePrefixes.stone, Materials.Concrete, new ItemStack(this, 1, 5));
+ GT_OreDictUnificator.registerOre(OrePrefixes.stone, Materials.Concrete, new ItemStack(this, 1, 6));
+ GT_OreDictUnificator.registerOre(OrePrefixes.stone, Materials.Concrete, new ItemStack(this, 1, 7));
+ GT_OreDictUnificator.registerOre(OrePrefixes.stone, Materials.Concrete, new ItemStack(this, 1, 8));
+ GT_OreDictUnificator.registerOre(OrePrefixes.stone, Materials.Concrete, new ItemStack(this, 1, 9));
+ GT_OreDictUnificator.registerOre(OrePrefixes.stone, Materials.Concrete, new ItemStack(this, 1, 10));
+ GT_OreDictUnificator.registerOre(OrePrefixes.stone, Materials.Concrete, new ItemStack(this, 1, 11));
+ GT_OreDictUnificator.registerOre(OrePrefixes.stone, Materials.Concrete, new ItemStack(this, 1, 12));
+ GT_OreDictUnificator.registerOre(OrePrefixes.stone, Materials.Concrete, new ItemStack(this, 1, 13));
+ GT_OreDictUnificator.registerOre(OrePrefixes.stone, Materials.Concrete, new ItemStack(this, 1, 14));
+ GT_OreDictUnificator.registerOre(OrePrefixes.stone, Materials.Concrete, new ItemStack(this, 1, 15));
+ }
+
+ @Override
+ public int getHarvestLevel(int aMeta) {
+ return 1;
+ }
+
+ @Override
+ public float getBlockHardness(World aWorld, int aX, int aY, int aZ) {
+ return this.blockHardness = Blocks.stone.getBlockHardness(aWorld, aX, aY, aZ);
+ }
+
+ @Override
+ public IIcon getIcon(int ordinalSide, int aMeta) {
+ if ((aMeta >= 0) && (aMeta < 16)) {
+ return gregtech.api.enums.Textures.BlockIcons.CONCRETES[aMeta].getIcon();
+ }
+ return gregtech.api.enums.Textures.BlockIcons.CONCRETES[0].getIcon();
+ }
+
+ @Override
+ public void onWalkOver(EntityLivingBase aEntity, World aWorld, int aX, int aY, int aZ) {
+ if ((aEntity.motionX != 0 || aEntity.motionZ != 0) && !aEntity.isInWater()
+ && !aEntity.isWet()
+ && !aEntity.isSneaking()) {
+ double tSpeed = (aWorld.getBlock(aX, aY - 1, aZ).slipperiness >= 0.8 ? 1.5 : 1.2);
+ aEntity.motionX *= tSpeed;
+ aEntity.motionZ *= tSpeed;
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Block_Drone.java b/src/main/java/gregtech/common/blocks/GT_Block_Drone.java
new file mode 100644
index 0000000000..81d1acc228
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Block_Drone.java
@@ -0,0 +1,65 @@
+package gregtech.common.blocks;
+
+import java.util.ArrayList;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.material.Material;
+import net.minecraft.client.renderer.texture.IIconRegister;
+import net.minecraft.item.ItemStack;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.world.World;
+
+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.common.tileentities.render.TileDrone;
+
+public class GT_Block_Drone extends Block {
+
+ public GT_Block_Drone() {
+ super(Material.iron);
+ this.setResistance(20f);
+ this.setHardness(-1.0f);
+ this.setCreativeTab(GregTech_API.TAB_GREGTECH);
+ this.setBlockName("gt.dronerender");
+ this.setLightLevel(100.0f);
+ GameRegistry.registerBlock(this, getUnlocalizedName());
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void registerBlockIcons(IIconRegister iconRegister) {
+ blockIcon = iconRegister.registerIcon("gregtech:iconsets/TRANSPARENT");
+ }
+
+ @Override
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ @Override
+ public boolean canRenderInPass(int a) {
+ return true;
+ }
+
+ @Override
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ @Override
+ public boolean hasTileEntity(int metadata) {
+ return true;
+ }
+
+ @Override
+ public TileEntity createTileEntity(World world, int metadata) {
+ return new TileDrone();
+ }
+
+ @Override
+ public ArrayList<ItemStack> getDrops(World world, int x, int y, int z, int meta, int fortune) {
+ return new ArrayList<>();
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Block_Granites.java b/src/main/java/gregtech/common/blocks/GT_Block_Granites.java
new file mode 100644
index 0000000000..69ebc2e733
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Block_Granites.java
@@ -0,0 +1,77 @@
+package gregtech.common.blocks;
+
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.boss.EntityWither;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.IIcon;
+import net.minecraft.world.IBlockAccess;
+import net.minecraft.world.World;
+
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.util.GT_LanguageManager;
+import gregtech.api.util.GT_OreDictUnificator;
+
+public class GT_Block_Granites extends GT_Block_Stones_Abstract {
+
+ public GT_Block_Granites() {
+ super(GT_Item_Granites.class, "gt.blockgranites");
+ setResistance(60.0F);
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".0.name", "Black Granite");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".1.name", "Black Granite Cobblestone");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".2.name", "Mossy Black Granite Cobblestone");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".3.name", "Black Granite Bricks");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".4.name", "Cracked Black Granite Bricks");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".5.name", "Mossy Black Granite Bricks");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".6.name", "Chiseled Black Granite");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".7.name", "Smooth Black Granite");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".8.name", "Red Granite");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".9.name", "Red Granite Cobblestone");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".10.name", "Mossy Red Granite Cobblestone");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".11.name", "Red Granite Bricks");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".12.name", "Cracked Red Granite Bricks");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".13.name", "Mossy Red Granite Bricks");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".14.name", "Chiseled Red Granite");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".15.name", "Smooth Red Granite");
+ GT_OreDictUnificator.registerOre(OrePrefixes.stone, Materials.GraniteBlack, new ItemStack(this, 1, 0));
+ GT_OreDictUnificator.registerOre(OrePrefixes.stone, Materials.GraniteBlack, new ItemStack(this, 1, 1));
+ GT_OreDictUnificator.registerOre(OrePrefixes.stone, Materials.GraniteBlack, new ItemStack(this, 1, 2));
+ GT_OreDictUnificator.registerOre(OrePrefixes.stone, Materials.GraniteBlack, new ItemStack(this, 1, 3));
+ GT_OreDictUnificator.registerOre(OrePrefixes.stone, Materials.GraniteBlack, new ItemStack(this, 1, 4));
+ GT_OreDictUnificator.registerOre(OrePrefixes.stone, Materials.GraniteBlack, new ItemStack(this, 1, 5));
+ GT_OreDictUnificator.registerOre(OrePrefixes.stone, Materials.GraniteBlack, new ItemStack(this, 1, 6));
+ GT_OreDictUnificator.registerOre(OrePrefixes.stone, Materials.GraniteBlack, new ItemStack(this, 1, 7));
+ GT_OreDictUnificator.registerOre(OrePrefixes.stone, Materials.GraniteRed, new ItemStack(this, 1, 8));
+ GT_OreDictUnificator.registerOre(OrePrefixes.stone, Materials.GraniteRed, new ItemStack(this, 1, 9));
+ GT_OreDictUnificator.registerOre(OrePrefixes.stone, Materials.GraniteRed, new ItemStack(this, 1, 10));
+ GT_OreDictUnificator.registerOre(OrePrefixes.stone, Materials.GraniteRed, new ItemStack(this, 1, 11));
+ GT_OreDictUnificator.registerOre(OrePrefixes.stone, Materials.GraniteRed, new ItemStack(this, 1, 12));
+ GT_OreDictUnificator.registerOre(OrePrefixes.stone, Materials.GraniteRed, new ItemStack(this, 1, 13));
+ GT_OreDictUnificator.registerOre(OrePrefixes.stone, Materials.GraniteRed, new ItemStack(this, 1, 14));
+ GT_OreDictUnificator.registerOre(OrePrefixes.stone, Materials.GraniteRed, new ItemStack(this, 1, 15));
+ }
+
+ @Override
+ public int getHarvestLevel(int aMeta) {
+ return 3;
+ }
+
+ @Override
+ public float getBlockHardness(World aWorld, int aX, int aY, int aZ) {
+ return this.blockHardness = Blocks.stone.getBlockHardness(aWorld, aX, aY, aZ) * 3.0F;
+ }
+
+ @Override
+ public IIcon getIcon(int ordinalSide, int aMeta) {
+ if ((aMeta >= 0) && (aMeta < 16)) {
+ return gregtech.api.enums.Textures.BlockIcons.GRANITES[aMeta].getIcon();
+ }
+ return gregtech.api.enums.Textures.BlockIcons.GRANITES[0].getIcon();
+ }
+
+ @Override
+ public boolean canEntityDestroy(IBlockAccess world, int x, int y, int z, Entity entity) {
+ return !(entity instanceof EntityWither);
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Block_Machines.java b/src/main/java/gregtech/common/blocks/GT_Block_Machines.java
new file mode 100644
index 0000000000..3d24799746
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Block_Machines.java
@@ -0,0 +1,703 @@
+package gregtech.common.blocks;
+
+import static gregtech.GT_Mod.GT_FML_LOGGER;
+import static gregtech.api.objects.XSTR.XSTR_INSTANCE;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.ITileEntityProvider;
+import net.minecraft.client.renderer.texture.IIconRegister;
+import net.minecraft.creativetab.CreativeTabs;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.EnumCreatureType;
+import net.minecraft.entity.item.EntityItem;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.AxisAlignedBB;
+import net.minecraft.util.IIcon;
+import net.minecraft.util.StatCollector;
+import net.minecraft.world.Explosion;
+import net.minecraft.world.IBlockAccess;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.cricketcraft.chisel.api.IFacade;
+
+import cpw.mods.fml.common.Optional;
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IDebugableBlock;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IColoredTileEntity;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.interfaces.tileentity.IDebugableTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.items.GT_Generic_Block;
+import gregtech.api.metatileentity.BaseMetaPipeEntity;
+import gregtech.api.metatileentity.BaseMetaTileEntity;
+import gregtech.api.metatileentity.BaseTileEntity;
+import gregtech.api.metatileentity.CoverableTileEntity;
+import gregtech.api.util.GT_BaseCrop;
+import gregtech.api.util.GT_Log;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.covers.CoverInfo;
+import gregtech.common.render.GT_Renderer_Block;
+import gregtech.common.tileentities.storage.GT_MetaTileEntity_QuantumChest;
+
+@Optional.Interface(iface = "com.cricketcraft.chisel.api.IFacade", modid = "ChiselAPI")
+public class GT_Block_Machines extends GT_Generic_Block implements IDebugableBlock, ITileEntityProvider, IFacade {
+
+ private static final ThreadLocal<IGregTechTileEntity> mTemporaryTileEntity = new ThreadLocal<>();
+ private boolean renderAsNormalBlock;
+
+ public GT_Block_Machines() {
+ super(GT_Item_Machines.class, "gt.blockmachines", new GT_Material_Machines());
+ GregTech_API.registerMachineBlock(this, -1);
+ setHardness(1.0F);
+ setResistance(10.0F);
+ setStepSound(soundTypeMetal);
+ setCreativeTab(GregTech_API.TAB_GREGTECH);
+ this.isBlockContainer = true;
+ this.renderAsNormalBlock = true;
+ this.useNeighborBrightness = true;
+ }
+
+ @Override
+ public String getHarvestTool(int aMeta) {
+ if (aMeta >= 8 && aMeta <= 11) {
+ return "cutter";
+ }
+ return "wrench";
+ }
+
+ @Override
+ public int getHarvestLevel(int aMeta) {
+ return aMeta % 4;
+ }
+
+ @Override
+ protected boolean canSilkHarvest() {
+ return false;
+ }
+
+ @Override
+ public void onNeighborChange(IBlockAccess aWorld, int aX, int aY, int aZ, int aTileX, int aTileY, int aTileZ) {
+ final TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if ((tTileEntity instanceof BaseTileEntity)) {
+ ((BaseTileEntity) tTileEntity).onAdjacentBlockChange(aTileX, aTileY, aTileZ);
+ }
+ }
+
+ @Override
+ public void onNeighborBlockChange(World aWorld, int aX, int aY, int aZ, Block aBlock) {
+ final TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if ((tTileEntity instanceof BaseMetaPipeEntity)) {
+ ((BaseMetaPipeEntity) tTileEntity).onNeighborBlockChange(aX, aY, aZ);
+ }
+ }
+
+ @Override
+ public void onBlockAdded(World aWorld, int aX, int aY, int aZ) {
+ super.onBlockAdded(aWorld, aX, aY, aZ);
+ if (GregTech_API.isMachineBlock(this, aWorld.getBlockMetadata(aX, aY, aZ))) {
+ GregTech_API.causeMachineUpdate(aWorld, aX, aY, aZ);
+ }
+ }
+
+ @Override
+ public String getUnlocalizedName() {
+ return "gt.blockmachines";
+ }
+
+ @Override
+ public String getLocalizedName() {
+ return StatCollector.translateToLocal(getUnlocalizedName() + ".name");
+ }
+
+ @Override
+ public int getFlammability(IBlockAccess aWorld, int aX, int aY, int aZ, ForgeDirection face) {
+ return 0;
+ }
+
+ @Override
+ public int getFireSpreadSpeed(IBlockAccess aWorld, int aX, int aY, int aZ, ForgeDirection face) {
+ return GregTech_API.sMachineFlammable && (aWorld.getBlockMetadata(aX, aY, aZ) == 0) ? 100 : 0;
+ }
+
+ @Override
+ public int getRenderType() {
+ if (GT_Renderer_Block.INSTANCE == null) {
+ return super.getRenderType();
+ }
+ return GT_Renderer_Block.INSTANCE.mRenderID;
+ }
+
+ @Override
+ public boolean isFireSource(World aWorld, int aX, int aY, int aZ, ForgeDirection side) {
+ return GregTech_API.sMachineFlammable && (aWorld.getBlockMetadata(aX, aY, aZ) == 0);
+ }
+
+ @Override
+ public boolean isFlammable(IBlockAccess aWorld, int aX, int aY, int aZ, ForgeDirection face) {
+ return GregTech_API.sMachineFlammable && (aWorld.getBlockMetadata(aX, aY, aZ) == 0);
+ }
+
+ @Override
+ public boolean canCreatureSpawn(EnumCreatureType type, IBlockAccess aWorld, int aX, int aY, int aZ) {
+ return false;
+ }
+
+ @Override
+ public boolean canConnectRedstone(IBlockAccess aWorld, int aX, int aY, int aZ, int ordinalSide) {
+ ForgeDirection forgeSide = switch (ordinalSide) {
+ case (-2) -> ForgeDirection.DOWN;
+ case (-1) -> ForgeDirection.UP;
+ case (0) -> ForgeDirection.NORTH;
+ case (2) -> ForgeDirection.SOUTH;
+ case (3) -> ForgeDirection.WEST;
+ case (1) -> ForgeDirection.EAST;
+ default -> ForgeDirection.UNKNOWN;
+ };
+ final TileEntity machineEntity = aWorld.getTileEntity(aX, aY, aZ);
+ return machineEntity instanceof CoverableTileEntity cte && cte.getCoverInfoAtSide(forgeSide)
+ .getCoverID() != 0;
+ }
+
+ @Override
+ public boolean canBeReplacedByLeaves(IBlockAccess aWorld, int aX, int aY, int aZ) {
+ return false;
+ }
+
+ @Override
+ public boolean isNormalCube(IBlockAccess aWorld, int aX, int aY, int aZ) {
+ return false;
+ }
+
+ @Override
+ public boolean hasTileEntity(int aMeta) {
+ return true;
+ }
+
+ @Override
+ public boolean hasComparatorInputOverride() {
+ return true;
+ }
+
+ @Override
+ public boolean renderAsNormalBlock() {
+ return renderAsNormalBlock;
+ }
+
+ public GT_Block_Machines setRenderAsNormalBlock(boolean aBool) {
+ renderAsNormalBlock = aBool;
+ return this;
+ }
+
+ @Override
+ public boolean canProvidePower() {
+ return true;
+ }
+
+ @Override
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ @Override
+ public TileEntity createNewTileEntity(World aWorld, int aMeta) {
+ return createTileEntity(aWorld, aMeta);
+ }
+
+ @SideOnly(Side.CLIENT)
+ @Override
+ public IIcon getIcon(IBlockAccess aIBlockAccess, int aX, int aY, int aZ, int ordinalSide) {
+ return Textures.BlockIcons.MACHINE_LV_SIDE.getIcon();
+ }
+
+ @SideOnly(Side.CLIENT)
+ @Override
+ public IIcon getIcon(int ordinalSide, int aMeta) {
+ return Textures.BlockIcons.MACHINE_LV_SIDE.getIcon();
+ }
+
+ @Override
+ public boolean onBlockEventReceived(World aWorld, int aX, int aY, int aZ, int aData1, int aData2) {
+ super.onBlockEventReceived(aWorld, aX, aY, aZ, aData1, aData2);
+ final TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ return tTileEntity != null && tTileEntity.receiveClientEvent(aData1, aData2);
+ }
+
+ @Override
+ public void addCollisionBoxesToList(World aWorld, int aX, int aY, int aZ, AxisAlignedBB inputAABB,
+ List<AxisAlignedBB> outputAABB, Entity collider) {
+ final TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if (tTileEntity instanceof IGregTechTileEntity
+ && ((IGregTechTileEntity) tTileEntity).getMetaTileEntity() != null) {
+ ((IGregTechTileEntity) tTileEntity)
+ .addCollisionBoxesToList(aWorld, aX, aY, aZ, inputAABB, outputAABB, collider);
+ return;
+ }
+ super.addCollisionBoxesToList(aWorld, aX, aY, aZ, inputAABB, outputAABB, collider);
+ }
+
+ @Override
+ public AxisAlignedBB getCollisionBoundingBoxFromPool(World aWorld, int aX, int aY, int aZ) {
+ final TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if (tTileEntity instanceof IGregTechTileEntity
+ && ((IGregTechTileEntity) tTileEntity).getMetaTileEntity() != null) {
+ return ((IGregTechTileEntity) tTileEntity).getCollisionBoundingBoxFromPool(aWorld, aX, aY, aZ);
+ }
+ return super.getCollisionBoundingBoxFromPool(aWorld, aX, aY, aZ);
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public AxisAlignedBB getSelectedBoundingBoxFromPool(World aWorld, int aX, int aY, int aZ) {
+ final TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if (tTileEntity instanceof IGregTechTileEntity
+ && ((IGregTechTileEntity) tTileEntity).getMetaTileEntity() != null) {
+ return ((IGregTechTileEntity) tTileEntity).getCollisionBoundingBoxFromPool(aWorld, aX, aY, aZ);
+ }
+ return super.getSelectedBoundingBoxFromPool(aWorld, aX, aY, aZ);
+ }
+
+ @Override // THIS
+ public void setBlockBoundsBasedOnState(IBlockAccess blockAccess, int aX, int aY, int aZ) {
+ final TileEntity tTileEntity = blockAccess.getTileEntity(aX, aY, aZ);
+ if (tTileEntity instanceof IGregTechTileEntity
+ && (((IGregTechTileEntity) tTileEntity).getMetaTileEntity() != null)) {
+ final AxisAlignedBB bbb = ((IGregTechTileEntity) tTileEntity)
+ .getCollisionBoundingBoxFromPool(((IGregTechTileEntity) tTileEntity).getWorld(), 0, 0, 0);
+ minX = bbb.minX; // This essentially sets block bounds
+ minY = bbb.minY;
+ minZ = bbb.minZ;
+ maxX = bbb.maxX;
+ maxY = bbb.maxY;
+ maxZ = bbb.maxZ;
+ return;
+ }
+ super.setBlockBoundsBasedOnState(blockAccess, aX, aY, aZ);
+ }
+
+ @Override
+ public void setBlockBoundsForItemRender() {
+ super.setBlockBounds(0, 0, 0, 1, 1, 1);
+ }
+
+ @Override
+ public void onEntityCollidedWithBlock(World aWorld, int aX, int aY, int aZ, Entity collider) {
+ final TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if (tTileEntity instanceof IGregTechTileEntity
+ && ((IGregTechTileEntity) tTileEntity).getMetaTileEntity() != null) {
+ ((IGregTechTileEntity) tTileEntity).onEntityCollidedWithBlock(aWorld, aX, aY, aZ, collider);
+ return;
+ }
+ super.onEntityCollidedWithBlock(aWorld, aX, aY, aZ, collider);
+ }
+
+ @SideOnly(Side.CLIENT)
+ @Override
+ public void registerBlockIcons(IIconRegister aIconRegister) {
+ if (!GregTech_API.sPostloadFinished) return;
+ GT_Log.out.println("GT_Mod: Setting up Icon Register for Blocks");
+ GregTech_API.setBlockIconRegister(aIconRegister);
+
+ GT_Log.out.println("GT_Mod: Registering MetaTileEntity specific Textures");
+ try {
+ for (IMetaTileEntity tMetaTileEntity : GregTech_API.METATILEENTITIES) {
+ if (tMetaTileEntity != null) {
+ tMetaTileEntity.registerIcons(aIconRegister);
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ GT_Log.out.println("GT_Mod: Registering Crop specific Textures");
+ try {
+ for (GT_BaseCrop tCrop : GT_BaseCrop.sCropList) {
+ tCrop.registerSprites(aIconRegister);
+ }
+ } catch (Exception e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ GT_Log.out.println("GT_Mod: Starting Block Icon Load Phase");
+ GT_FML_LOGGER.info("GT_Mod: Starting Block Icon Load Phase");
+ try {
+ for (Runnable tRunnable : GregTech_API.sGTBlockIconload) {
+ tRunnable.run();
+ }
+ } catch (Exception e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ GT_Log.out.println("GT_Mod: Finished Block Icon Load Phase");
+ GT_FML_LOGGER.info("GT_Mod: Finished Block Icon Load Phase");
+ }
+
+ @Override
+ public float getPlayerRelativeBlockHardness(EntityPlayer aPlayer, World aWorld, int aX, int aY, int aZ) {
+ final TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ return tTileEntity instanceof BaseMetaTileEntity && ((BaseMetaTileEntity) tTileEntity).privateAccess()
+ && !((BaseMetaTileEntity) tTileEntity).playerOwnsThis(aPlayer, true) ? -1.0F
+ : super.getPlayerRelativeBlockHardness(aPlayer, aWorld, aX, aY, aZ);
+ }
+
+ @Override
+ public boolean onBlockActivated(World aWorld, int aX, int aY, int aZ, EntityPlayer aPlayer, int ordinalSide,
+ float aOffsetX, float aOffsetY, float aOffsetZ) {
+ final TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if (tTileEntity == null) {
+ return false;
+ }
+ if (aPlayer.isSneaking()) {
+ final ItemStack tCurrentItem = aPlayer.inventory.getCurrentItem();
+ if (tCurrentItem != null && !GT_Utility.isStackInList(tCurrentItem, GregTech_API.sScrewdriverList)
+ && !GT_Utility.isStackInList(tCurrentItem, GregTech_API.sWrenchList)
+ && !GT_Utility.isStackInList(tCurrentItem, GregTech_API.sWireCutterList)
+ && !GT_Utility.isStackInList(tCurrentItem, GregTech_API.sSolderingToolList)
+ && !GT_Utility.isStackInList(tCurrentItem, GregTech_API.sJackhammerList)) return false;
+ }
+ if (tTileEntity instanceof IGregTechTileEntity gtTE) {
+ if (gtTE.getTimer() < 1L) {
+ return false;
+ }
+ if ((!aWorld.isRemote) && !gtTE.isUseableByPlayer(aPlayer)) {
+ return true;
+ }
+ return ((IGregTechTileEntity) tTileEntity)
+ .onRightclick(aPlayer, ForgeDirection.getOrientation(ordinalSide), aOffsetX, aOffsetY, aOffsetZ);
+ }
+ return false;
+ }
+
+ @Override
+ public void onBlockClicked(World aWorld, int aX, int aY, int aZ, EntityPlayer aPlayer) {
+ final TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if (tTileEntity instanceof IGregTechTileEntity gtTE) {
+ gtTE.onLeftclick(aPlayer);
+ }
+ }
+
+ @Override
+ public int getDamageValue(World aWorld, int aX, int aY, int aZ) {
+ final TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if (tTileEntity instanceof IGregTechTileEntity gtTE) {
+ return gtTE.getMetaTileID();
+ }
+ return 0;
+ }
+
+ @Override
+ public void onBlockExploded(World aWorld, int aX, int aY, int aZ, Explosion aExplosion) {
+ final TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if (tTileEntity instanceof BaseMetaTileEntity baseTE) {
+ GT_Log.exp.printf(
+ "Explosion at : %d | %d | %d DIMID: %s due to near explosion!%n",
+ aX,
+ aY,
+ aZ,
+ aWorld.provider.dimensionId);
+ baseTE.doEnergyExplosion();
+ }
+ super.onBlockExploded(aWorld, aX, aY, aZ, aExplosion);
+ }
+
+ @Override
+ public void breakBlock(World aWorld, int aX, int aY, int aZ, Block aBlock, int aMetadata) {
+ GregTech_API.causeMachineUpdate(aWorld, aX, aY, aZ);
+ final TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if (tTileEntity instanceof IGregTechTileEntity gtTE) {
+ gtTE.onBlockDestroyed();
+ mTemporaryTileEntity.set(gtTE);
+ if (!(gtTE.getMetaTileEntity() instanceof GT_MetaTileEntity_QuantumChest)) {
+ for (int i = 0; i < gtTE.getSizeInventory(); i++) {
+ final ItemStack tItem = gtTE.getStackInSlot(i);
+ if ((tItem != null) && (tItem.stackSize > 0) && (gtTE.isValidSlot(i)) && gtTE.shouldDropItemAt(i)) {
+ final EntityItem tItemEntity = new EntityItem(
+ aWorld,
+ aX + XSTR_INSTANCE.nextFloat() * 0.8F + 0.1F,
+ aY + XSTR_INSTANCE.nextFloat() * 0.8F + 0.1F,
+ aZ + XSTR_INSTANCE.nextFloat() * 0.8F + 0.1F,
+ new ItemStack(tItem.getItem(), tItem.stackSize, tItem.getItemDamage()));
+ if (tItem.hasTagCompound()) {
+ tItemEntity.getEntityItem()
+ .setTagCompound(
+ (NBTTagCompound) tItem.getTagCompound()
+ .copy());
+ }
+ tItemEntity.motionX = (XSTR_INSTANCE.nextGaussian() * 0.05D);
+ tItemEntity.motionY = (XSTR_INSTANCE.nextGaussian() * 0.25D);
+ tItemEntity.motionZ = (XSTR_INSTANCE.nextGaussian() * 0.05D);
+ aWorld.spawnEntityInWorld(tItemEntity);
+ tItem.stackSize = 0;
+ gtTE.setInventorySlotContents(i, null);
+ }
+ }
+ }
+ }
+ super.breakBlock(aWorld, aX, aY, aZ, aBlock, aMetadata);
+ aWorld.removeTileEntity(aX, aY, aZ);
+ }
+
+ @Override
+ public ArrayList<ItemStack> getDrops(World aWorld, int aX, int aY, int aZ, int aMeta, int aFortune) {
+ final TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if (tTileEntity instanceof IGregTechTileEntity gtTE) {
+ return gtTE.getDrops();
+ }
+ final IGregTechTileEntity tGregTechTileEntity = mTemporaryTileEntity.get();
+ final ArrayList<ItemStack> tDrops;
+ if (tGregTechTileEntity == null) {
+ tDrops = new ArrayList<>();
+ } else {
+ tDrops = tGregTechTileEntity.getDrops();
+ mTemporaryTileEntity.remove();
+ }
+ return tDrops;
+ }
+
+ @Override
+ public boolean removedByPlayer(World aWorld, EntityPlayer aPlayer, int aX, int aY, int aZ, boolean aWillHarvest) {
+ // This delays deletion of the block until after getDrops
+ return aWillHarvest || super.removedByPlayer(aWorld, aPlayer, aX, aY, aZ, false);
+ }
+
+ @Override
+ public void harvestBlock(World aWorld, EntityPlayer aPlayer, int aX, int aY, int aZ, int aMeta) {
+ super.harvestBlock(aWorld, aPlayer, aX, aY, aZ, aMeta);
+ aWorld.setBlockToAir(aX, aY, aZ);
+ }
+
+ @Override
+ public int getComparatorInputOverride(World aWorld, int aX, int aY, int aZ, int ordinalSide) {
+ final TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if (tTileEntity instanceof IGregTechTileEntity gtTE) {
+ return gtTE.getComparatorValue(ForgeDirection.getOrientation(ordinalSide));
+ }
+ return 0;
+ }
+
+ @Override
+ public int isProvidingWeakPower(IBlockAccess aWorld, int aX, int aY, int aZ, int ordinalSide) {
+ if (ordinalSide < 0 || ordinalSide > 5) {
+ return 0;
+ }
+ final TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if (tTileEntity instanceof IGregTechTileEntity gtTE) {
+ return gtTE.getOutputRedstoneSignal(
+ ForgeDirection.getOrientation(ordinalSide)
+ .getOpposite());
+ }
+ return 0;
+ }
+
+ @Override
+ public int isProvidingStrongPower(IBlockAccess aWorld, int aX, int aY, int aZ, int ordinalSide) {
+ if (ordinalSide < 0 || ordinalSide > 5) {
+ return 0;
+ }
+ final TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if (tTileEntity instanceof IGregTechTileEntity gtTE) {
+ return gtTE.getStrongOutputRedstoneSignal(
+ ForgeDirection.getOrientation(ordinalSide)
+ .getOpposite());
+ }
+ return 0;
+ }
+
+ @Override
+ public void dropBlockAsItemWithChance(World aWorld, int aX, int aY, int aZ, int aMetadata, float chance,
+ int aFortune) {
+ if (!aWorld.isRemote) {
+ final TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if (tTileEntity != null && (chance < 1.0F)) {
+ if (tTileEntity instanceof BaseMetaTileEntity bmte && (GregTech_API.sMachineNonWrenchExplosions)) {
+ GT_Log.exp.printf(
+ "Explosion at : %d | %d | %d DIMID: %s NonWrench picking/Rain!%n",
+ aX,
+ aY,
+ aZ,
+ aWorld.provider.dimensionId);
+ bmte.doEnergyExplosion();
+ }
+ } else {
+ super.dropBlockAsItemWithChance(aWorld, aX, aY, aZ, aMetadata, chance, aFortune);
+ }
+ }
+ }
+
+ @Override
+ public boolean isSideSolid(IBlockAccess aWorld, int aX, int aY, int aZ, ForgeDirection side) {
+ if (aWorld.getBlockMetadata(aX, aY, aZ) == 0) {
+ return true;
+ }
+ final TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if (tTileEntity != null) {
+ if (tTileEntity instanceof BaseMetaTileEntity) {
+ return true;
+ }
+ if (tTileEntity instanceof BaseMetaPipeEntity
+ && (((BaseMetaPipeEntity) tTileEntity).mConnections & 0xFFFFFFC0) != 0) {
+ return true;
+ }
+ return tTileEntity instanceof ICoverable && ((ICoverable) tTileEntity).getCoverIDAtSide(side) != 0;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean isBlockNormalCube() {
+ return true;
+ }
+
+ /**
+ * Returns the default ambient occlusion value based on block opacity
+ */
+ @SideOnly(Side.CLIENT)
+ @Override
+ public float getAmbientOcclusionLightValue() {
+ return this.renderAsNormalBlock() ? 0.2F : 0.5F;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void randomDisplayTick(World aWorld, int aX, int aY, int aZ, Random aRandom) {
+ final TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if (tTileEntity instanceof IGregTechTileEntity) {
+ ((IGregTechTileEntity) tTileEntity).onRandomDisplayTick();
+ }
+ }
+
+ @Override
+ public int getLightOpacity(IBlockAccess aWorld, int aX, int aY, int aZ) {
+ final TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if (tTileEntity instanceof IGregTechTileEntity) {
+ return ((IGregTechTileEntity) tTileEntity).getLightOpacity();
+ }
+ return aWorld.getBlockMetadata(aX, aY, aZ) == 0 ? 255 : 0;
+ }
+
+ @Override
+ public int getLightValue(IBlockAccess aWorld, int aX, int aY, int aZ) {
+ final TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if (tTileEntity instanceof BaseMetaTileEntity) {
+ return ((BaseMetaTileEntity) tTileEntity).getLightValue();
+ }
+ return 0;
+ }
+
+ @Override
+ public TileEntity createTileEntity(World aWorld, int aMeta) {
+ return GregTech_API.createTileEntity(aMeta);
+ }
+
+ @Override
+ public float getExplosionResistance(Entity entity, World aWorld, int aX, int aY, int aZ, double explosionX,
+ double explosionY, double explosionZ) {
+ final TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if (tTileEntity instanceof IGregTechTileEntity) {
+ return ((IGregTechTileEntity) tTileEntity).getBlastResistance(ForgeDirection.UNKNOWN);
+ }
+ return 10.0F;
+ }
+
+ @SideOnly(Side.CLIENT)
+ @Override
+ public void getSubBlocks(Item item, CreativeTabs aCreativeTab, List<ItemStack> outputSubBlocks) {
+ for (int i = 1; i < GregTech_API.METATILEENTITIES.length; i++) {
+ if (GregTech_API.METATILEENTITIES[i] != null) {
+ outputSubBlocks.add(new ItemStack(item, 1, i));
+ }
+ }
+ }
+
+ @Override
+ public void onBlockPlacedBy(World aWorld, int aX, int aY, int aZ, EntityLivingBase aPlayer, ItemStack aStack) {
+ final TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if (!(tTileEntity instanceof IGregTechTileEntity iGregTechTileEntity)) return;
+ iGregTechTileEntity.setFrontFacing(
+ BaseTileEntity.getSideForPlayerPlacing(aPlayer, ForgeDirection.UP, iGregTechTileEntity.getValidFacings()));
+ }
+
+ @Override
+ public ArrayList<String> getDebugInfo(EntityPlayer aPlayer, int aX, int aY, int aZ, int aLogLevel) {
+ final TileEntity tTileEntity = aPlayer.worldObj.getTileEntity(aX, aY, aZ);
+ if (tTileEntity instanceof IDebugableTileEntity) {
+ return ((IDebugableTileEntity) tTileEntity).getDebugInfo(aPlayer, aLogLevel);
+ }
+ return new ArrayList<>();
+ }
+
+ @Override
+ public boolean recolourBlock(World aWorld, int aX, int aY, int aZ, ForgeDirection side, int aColor) {
+ final TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if (tTileEntity instanceof IColoredTileEntity coloredTE) {
+ if (coloredTE.getColorization() == (byte) ((~aColor) & 0xF)) {
+ return false;
+ }
+ coloredTE.setColorization((byte) ((~aColor) & 0xF));
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public Block getFacade(IBlockAccess aWorld, int aX, int aY, int aZ, int ordinalSide) {
+ final TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if (tTileEntity instanceof CoverableTileEntity tile) {
+ final ForgeDirection dir = ForgeDirection.getOrientation(ordinalSide);
+ if (dir != ForgeDirection.UNKNOWN) {
+ final Block facadeBlock = tile.getCoverInfoAtSide(dir)
+ .getFacadeBlock();
+ if (facadeBlock != null) return facadeBlock;
+ } else {
+ // we do not allow more than one type of facade per block, so no need to check every side
+ // see comment in gregtech.common.covers.GT_Cover_FacadeBase.isCoverPlaceable
+ for (final ForgeDirection tSide : ForgeDirection.VALID_DIRECTIONS) {
+ final Block facadeBlock = tile.getCoverInfoAtSide(tSide)
+ .getFacadeBlock();
+ if (facadeBlock != null) {
+ return facadeBlock;
+ }
+ }
+ }
+ }
+ return Blocks.air;
+ }
+
+ @Override
+ public int getFacadeMetadata(IBlockAccess aWorld, int aX, int aY, int aZ, int ordinalSide) {
+ final TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if (tTileEntity instanceof CoverableTileEntity tile) {
+ final ForgeDirection dir = ForgeDirection.getOrientation(ordinalSide);
+ if (ordinalSide != -1) {
+ final CoverInfo coverInfo = tile.getCoverInfoAtSide(dir);
+ final Block facadeBlock = coverInfo.getFacadeBlock();
+ if (facadeBlock != null) return coverInfo.getFacadeMeta();
+ } else {
+ // we do not allow more than one type of facade per block, so no need to check every side
+ // see comment in gregtech.common.covers.GT_Cover_FacadeBase.isCoverPlaceable
+ for (final ForgeDirection d : ForgeDirection.VALID_DIRECTIONS) {
+ final CoverInfo coverInfo = tile.getCoverInfoAtSide(d);
+ final Block facadeBlock = coverInfo.getFacadeBlock();
+ if (facadeBlock != null) {
+ return coverInfo.getFacadeMeta();
+ }
+ }
+ }
+ }
+ return 0;
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Block_Metal.java b/src/main/java/gregtech/common/blocks/GT_Block_Metal.java
new file mode 100644
index 0000000000..753c590e51
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Block_Metal.java
@@ -0,0 +1,68 @@
+package gregtech.common.blocks;
+
+import static gregtech.api.enums.Mods.NotEnoughItems;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.material.Material;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.IIcon;
+import net.minecraft.world.World;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.util.GT_LanguageManager;
+import gregtech.api.util.GT_OreDictUnificator;
+
+public class GT_Block_Metal extends GT_Block_Storage {
+
+ public Materials[] mMats;
+ public OrePrefixes mPrefix;
+ public IIconContainer[] mBlockIcons;
+ public boolean mHideBlocks;
+ public static boolean mNEIisLoaded = NotEnoughItems.isModLoaded();
+
+ public GT_Block_Metal(String aName, Materials[] aMats, OrePrefixes aPrefix, IIconContainer[] aBlockIcons) {
+ super(GT_Item_Storage.class, aName, Material.iron);
+ mMats = aMats;
+ mPrefix = aPrefix;
+ mBlockIcons = aBlockIcons;
+ mHideBlocks = mNEIisLoaded;
+
+ for (int i = 0; i < aMats.length; i++) {
+ if (aMats[i].mMetaItemSubID > 0 && aMats[i].mHasParentMod) {
+ GT_LanguageManager.addStringLocalization(
+ getUnlocalizedName() + "." + i + ".name",
+ "Block of " + (GT_LanguageManager.i18nPlaceholder ? "%material" : aMats[i].mDefaultLocalName));
+ GT_OreDictUnificator.registerOre(aPrefix, aMats[i], new ItemStack(this, 1, i));
+ }
+ }
+ if (aMats.length < 16 && mNEIisLoaded) {
+ for (int i = aMats.length; i < 16; i++) codechicken.nei.api.API.hideItem(new ItemStack(this, 1, i));
+ }
+ }
+
+ @Override
+ public IIcon getIcon(int ordinalSide, int aMeta) {
+ if ((aMeta >= 0) && (aMeta < 16) && aMeta < mMats.length) {
+ return mBlockIcons[aMeta].getIcon();
+ }
+ return null;
+ }
+
+ @Override
+ public void onBlockAdded(World aWorld, int aX, int aY, int aZ) {
+ if (GregTech_API.isMachineBlock(this, aWorld.getBlockMetadata(aX, aY, aZ))) {
+ GregTech_API.causeMachineUpdate(aWorld, aX, aY, aZ);
+ }
+ }
+
+ @Override
+ public void breakBlock(World aWorld, int aX, int aY, int aZ, Block aBlock, int aMetaData) {
+ if (GregTech_API.isMachineBlock(this, aMetaData)) {
+ GregTech_API.causeMachineUpdate(aWorld, aX, aY, aZ);
+ }
+ }
+
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Block_Ores.java b/src/main/java/gregtech/common/blocks/GT_Block_Ores.java
new file mode 100644
index 0000000000..015baa2319
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Block_Ores.java
@@ -0,0 +1,154 @@
+package gregtech.common.blocks;
+
+import static gregtech.api.enums.Textures.BlockIcons.BASALT_STONE;
+import static gregtech.api.enums.Textures.BlockIcons.GRANITE_BLACK_STONE;
+import static gregtech.api.enums.Textures.BlockIcons.GRANITE_RED_STONE;
+import static gregtech.api.enums.Textures.BlockIcons.MARBLE_STONE;
+
+import java.util.Arrays;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.material.MapColor;
+import net.minecraft.block.material.Material;
+import net.minecraft.enchantment.EnchantmentHelper;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraft.util.IIcon;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.FakePlayer;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.GT_Mod;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.render.TextureFactory;
+
+public class GT_Block_Ores extends GT_Block_Ores_Abstract {
+
+ private static final String UNLOCALIZED_NAME = "gt.blockores";
+
+ public GT_Block_Ores() {
+ super(UNLOCALIZED_NAME, 7, false, Material.rock);
+ }
+
+ @Override
+ public String getUnlocalizedName() {
+ return UNLOCALIZED_NAME;
+ }
+
+ @Override
+ public OrePrefixes[] getProcessingPrefix() { // Must have 8 entries; an entry can be null to disable automatic
+ // recipes.
+ return new OrePrefixes[] { OrePrefixes.ore, OrePrefixes.oreNetherrack, OrePrefixes.oreEndstone,
+ OrePrefixes.oreBlackgranite, OrePrefixes.oreRedgranite, OrePrefixes.oreMarble, OrePrefixes.oreBasalt,
+ null };
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public IIcon getIcon(int ordinalSide, int meta) {
+ int index = ((meta / 1000) % 16);
+ return switch (index) {
+ case 1 -> Blocks.netherrack.getIcon(ordinalSide, 0);
+ case 2 -> Blocks.end_stone.getIcon(ordinalSide, 0);
+ case 3 -> GRANITE_BLACK_STONE.getIcon();
+ case 4 -> GRANITE_RED_STONE.getIcon();
+ case 5 -> MARBLE_STONE.getIcon();
+ case 6 -> BASALT_STONE.getIcon();
+ default -> Blocks.stone.getIcon(ordinalSide, 0);
+ };
+ }
+
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public boolean isFireSource(World world, int x, int y, int z, ForgeDirection side) {
+ return (side == ForgeDirection.UP && getDamageValue(world, x, y, z) / 1000 % 16 == 1);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public MapColor getMapColor(int meta) {
+ return meta == 1 ? MapColor.netherrackColor : MapColor.stoneColor;
+ }
+
+ @Override
+ public int getBaseBlockHarvestLevel(int aMeta) {
+ return switch (aMeta) {
+ case 3, 4 -> 3;
+ default -> 0;
+ };
+ }
+
+ @Override
+ public Block getDroppedBlock() {
+ return GregTech_API.sBlockOres1;
+ }
+
+ @Override
+ public Materials[] getDroppedDusts() { // Must have 8 entries; can be null.
+ return new Materials[] { Materials.Stone, Materials.Netherrack, Materials.Endstone, Materials.GraniteBlack,
+ Materials.GraniteRed, Materials.Marble, Materials.Basalt, Materials.Stone };
+ }
+
+ @Override
+ public boolean[] getEnabledMetas() {
+ return new boolean[] { true, true, true, GT_Mod.gregtechproxy.enableBlackGraniteOres,
+ GT_Mod.gregtechproxy.enableRedGraniteOres, GT_Mod.gregtechproxy.enableMarbleOres,
+ GT_Mod.gregtechproxy.enableBasaltOres, true };
+ }
+
+ @Override
+ public ITexture[] getTextureSet() {
+ final ITexture[] rTextures = new ITexture[16]; // Must have 16 entries.
+ Arrays.fill(rTextures, TextureFactory.of(Blocks.stone));
+ rTextures[1] = TextureFactory.of(Blocks.netherrack);
+ rTextures[2] = TextureFactory.of(Blocks.end_stone);
+ rTextures[3] = TextureFactory.builder()
+ .addIcon(GRANITE_BLACK_STONE)
+ .stdOrient()
+ .build();
+ rTextures[4] = TextureFactory.builder()
+ .addIcon(GRANITE_RED_STONE)
+ .stdOrient()
+ .build();
+ rTextures[5] = TextureFactory.builder()
+ .addIcon(MARBLE_STONE)
+ .stdOrient()
+ .build();
+ rTextures[6] = TextureFactory.builder()
+ .addIcon(BASALT_STONE)
+ .stdOrient()
+ .build();
+ return rTextures;
+ }
+
+ @Override
+ public void harvestBlock(World worldIn, EntityPlayer player, int x, int y, int z, int meta) {
+
+ if (EnchantmentHelper.getSilkTouchModifier(player)) {
+ GT_TileEntity_Ores.shouldSilkTouch = true;
+ super.harvestBlock(worldIn, player, x, y, z, meta);
+
+ if (GT_TileEntity_Ores.shouldSilkTouch) {
+ GT_TileEntity_Ores.shouldSilkTouch = false;
+ }
+ return;
+ }
+
+ if (!(player instanceof FakePlayer)) {
+ GT_TileEntity_Ores.shouldFortune = true;
+ }
+ super.harvestBlock(worldIn, player, x, y, z, meta);
+ if (GT_TileEntity_Ores.shouldFortune) {
+ GT_TileEntity_Ores.shouldFortune = false;
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Block_Ores_Abstract.java b/src/main/java/gregtech/common/blocks/GT_Block_Ores_Abstract.java
new file mode 100644
index 0000000000..8e68c5c39a
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Block_Ores_Abstract.java
@@ -0,0 +1,324 @@
+package gregtech.common.blocks;
+
+import static gregtech.api.enums.Mods.NotEnoughItems;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.ITileEntityProvider;
+import net.minecraft.block.material.Material;
+import net.minecraft.client.particle.EffectRenderer;
+import net.minecraft.client.renderer.texture.IIconRegister;
+import net.minecraft.creativetab.CreativeTabs;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.boss.EntityDragon;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.IIcon;
+import net.minecraft.util.MovingObjectPosition;
+import net.minecraft.util.StatCollector;
+import net.minecraft.world.IBlockAccess;
+import net.minecraft.world.World;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.GT_Mod;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.items.GT_Generic_Block;
+import gregtech.api.util.GT_LanguageManager;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_OreDictUnificator;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.render.GT_Renderer_Block;
+
+public abstract class GT_Block_Ores_Abstract extends GT_Generic_Block implements ITileEntityProvider {
+
+ private static final String DOT_NAME = ".name";
+ private static final String DOT_TOOLTIP = ".tooltip";
+ public static ThreadLocal<GT_TileEntity_Ores> mTemporaryTileEntity = new ThreadLocal<>();
+ public static boolean FUCKING_LOCK = false;
+ public static boolean tHideOres;
+ public static Set<Materials> aBlockedOres = new HashSet<>();
+
+ protected GT_Block_Ores_Abstract(String aUnlocalizedName, int aOreMetaCount, boolean aHideFirstMeta,
+ Material aMaterial) {
+ super(GT_Item_Ores.class, aUnlocalizedName, aMaterial);
+ this.isBlockContainer = true;
+ setStepSound(soundTypeStone);
+ setCreativeTab(GregTech_API.TAB_GREGTECH_ORES);
+ tHideOres = NotEnoughItems.isModLoaded() && GT_Mod.gregtechproxy.mHideUnusedOres;
+ if (aOreMetaCount > 8 || aOreMetaCount < 0) aOreMetaCount = 8;
+
+ for (int i = 0; i < 16; i++) {
+ GT_ModHandler.addValuableOre(this, i, 1);
+ }
+ for (int i = 1; i < GregTech_API.sGeneratedMaterials.length; i++) {
+ if (GregTech_API.sGeneratedMaterials[i] != null) {
+ for (int j = 0; j < aOreMetaCount; j++) {
+ if (!this.getEnabledMetas()[j]) continue;
+ GT_LanguageManager.addStringLocalization(
+ getUnlocalizedName() + "." + (i + (j * 1000)) + DOT_NAME,
+ GT_LanguageManager.i18nPlaceholder ? getLocalizedNameFormat(GregTech_API.sGeneratedMaterials[i])
+ : getLocalizedName(GregTech_API.sGeneratedMaterials[i]));
+ GT_LanguageManager.addStringLocalization(
+ getUnlocalizedName() + "." + (i + (j * 1000)) + DOT_TOOLTIP,
+ GregTech_API.sGeneratedMaterials[i].getToolTip());
+ GT_LanguageManager.addStringLocalization(
+ getUnlocalizedName() + "." + ((i + 16000) + (j * 1000)) + DOT_NAME,
+ "Small " + (GT_LanguageManager.i18nPlaceholder
+ ? getLocalizedNameFormat(GregTech_API.sGeneratedMaterials[i])
+ : getLocalizedName(GregTech_API.sGeneratedMaterials[i])));
+ GT_LanguageManager.addStringLocalization(
+ getUnlocalizedName() + "." + ((i + 16000) + (j * 1000)) + DOT_TOOLTIP,
+ GregTech_API.sGeneratedMaterials[i].getToolTip());
+ if ((GregTech_API.sGeneratedMaterials[i].mTypes & 0x8) != 0
+ && !aBlockedOres.contains(GregTech_API.sGeneratedMaterials[i])) {
+ GT_OreDictUnificator.registerOre(
+ this.getProcessingPrefix()[j] != null
+ ? this.getProcessingPrefix()[j].get(GregTech_API.sGeneratedMaterials[i])
+ : "",
+ new ItemStack(this, 1, i + (j * 1000)));
+ if (tHideOres) {
+ if (!(j == 0 && !aHideFirstMeta)) {
+ codechicken.nei.api.API.hideItem(new ItemStack(this, 1, i + (j * 1000)));
+ }
+ codechicken.nei.api.API.hideItem(new ItemStack(this, 1, (i + 16000) + (j * 1000)));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public int getBaseBlockHarvestLevel(int aMeta) {
+ return 0;
+ }
+
+ @Override
+ public void onNeighborChange(IBlockAccess aWorld, int aX, int aY, int aZ, int aTileX, int aTileY, int aTileZ) {
+ if (!FUCKING_LOCK) {
+ FUCKING_LOCK = true;
+ TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if ((tTileEntity instanceof GT_TileEntity_Ores)) {
+ ((GT_TileEntity_Ores) tTileEntity).onUpdated();
+ }
+ }
+ FUCKING_LOCK = false;
+ }
+
+ @Override
+ public void onNeighborBlockChange(World aWorld, int aX, int aY, int aZ, Block aBlock) {
+ if (!FUCKING_LOCK) {
+ FUCKING_LOCK = true;
+ TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if ((tTileEntity instanceof GT_TileEntity_Ores)) {
+ ((GT_TileEntity_Ores) tTileEntity).onUpdated();
+ }
+ }
+ FUCKING_LOCK = false;
+ }
+
+ public String getLocalizedNameFormat(Materials aMaterial) {
+ return switch (aMaterial.mName) {
+ case "InfusedAir", "InfusedDull", "InfusedEarth", "InfusedEntropy", "InfusedFire", "InfusedOrder", "InfusedVis", "InfusedWater" -> "%material Infused Stone";
+ case "Vermiculite", "Bentonite", "Kaolinite", "Talc", "BasalticMineralSand", "GraniticMineralSand", "GlauconiteSand", "CassiteriteSand", "GarnetSand", "QuartzSand", "Pitchblende", "FullersEarth" -> "%material";
+ default -> "%material" + OrePrefixes.ore.mLocalizedMaterialPost;
+ };
+ }
+
+ public String getLocalizedName(Materials aMaterial) {
+ return aMaterial.getDefaultLocalizedNameForItem(getLocalizedNameFormat(aMaterial));
+ }
+
+ @Override
+ public boolean onBlockActivated(World aWorld, int aX, int aY, int aZ, EntityPlayer aPlayer, int ordinalSide,
+ float aOffsetX, float aOffsetY, float aOffsetZ) {
+ if (!aPlayer.isSneaking() || !aPlayer.capabilities.isCreativeMode) {
+ return false;
+ }
+
+ TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if (!(tTileEntity instanceof GT_TileEntity_Ores)) {
+ return false;
+ }
+
+ boolean tNatural = (((GT_TileEntity_Ores) tTileEntity).mNatural = !((GT_TileEntity_Ores) tTileEntity).mNatural);
+ GT_Utility.sendChatToPlayer(aPlayer, "Ore \"mNatural\" flag set to: " + tNatural);
+ return true;
+ }
+
+ @Override
+ public boolean onBlockEventReceived(World p_149696_1_, int p_149696_2_, int p_149696_3_, int p_149696_4_,
+ int p_149696_5_, int p_149696_6_) {
+ super.onBlockEventReceived(p_149696_1_, p_149696_2_, p_149696_3_, p_149696_4_, p_149696_5_, p_149696_6_);
+ TileEntity tileentity = p_149696_1_.getTileEntity(p_149696_2_, p_149696_3_, p_149696_4_);
+ return tileentity != null && tileentity.receiveClientEvent(p_149696_5_, p_149696_6_);
+ }
+
+ @Override
+ public boolean canEntityDestroy(IBlockAccess world, int x, int y, int z, Entity entity) {
+ return (!(entity instanceof EntityDragon)) && (super.canEntityDestroy(world, x, y, z, entity));
+ }
+
+ @Override
+ public String getHarvestTool(int aMeta) {
+ return aMeta < 8 ? "pickaxe" : "shovel";
+ }
+
+ @Override
+ public int getHarvestLevel(int aMeta) {
+ return aMeta == 5 || aMeta == 6 ? 2 : aMeta % 8;
+ }
+
+ @Override
+ public float getBlockHardness(World aWorld, int aX, int aY, int aZ) {
+ return 1.0F + getHarvestLevel(aWorld.getBlockMetadata(aX, aY, aZ)) * 1.0F;
+ }
+
+ @Override
+ public float getExplosionResistance(Entity entity, World aWorld, int aX, int aY, int aZ, double explosionX,
+ double explosionY, double explosionZ) {
+ return 1.0F + getHarvestLevel(aWorld.getBlockMetadata(aX, aY, aZ)) * 1.0F;
+ }
+
+ @Override
+ protected boolean canSilkHarvest() {
+ return false;
+ }
+
+ @Override
+ public abstract String getUnlocalizedName();
+
+ @Override
+ public String getLocalizedName() {
+ return StatCollector.translateToLocal(getUnlocalizedName() + DOT_NAME);
+ }
+
+ @Override
+ public int getRenderType() {
+ if (GT_Renderer_Block.INSTANCE == null) {
+ return super.getRenderType();
+ }
+ return GT_Renderer_Block.INSTANCE.mRenderID;
+ }
+
+ @Override
+ public boolean canBeReplacedByLeaves(IBlockAccess aWorld, int aX, int aY, int aZ) {
+ return false;
+ }
+
+ @Override
+ public boolean isNormalCube(IBlockAccess aWorld, int aX, int aY, int aZ) {
+ return true;
+ }
+
+ @Override
+ public boolean hasTileEntity(int aMeta) {
+ return true;
+ }
+
+ @Override
+ public TileEntity createNewTileEntity(World aWorld, int aMeta) {
+ return createTileEntity(aWorld, aMeta);
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public IIcon getIcon(IBlockAccess aIBlockAccess, int aX, int aY, int aZ, int ordinalSide) {
+ return Blocks.stone.getIcon(0, 0);
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public IIcon getIcon(int ordinalSide, int aMeta) {
+ return Blocks.stone.getIcon(0, 0);
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void registerBlockIcons(IIconRegister aIconRegister) {}
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public boolean addHitEffects(World worldObj, MovingObjectPosition target, EffectRenderer effectRenderer) {
+ GT_Renderer_Block
+ .addHitEffects(effectRenderer, this, worldObj, target.blockX, target.blockY, target.blockZ, target.sideHit);
+ return true;
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public boolean addDestroyEffects(World world, int x, int y, int z, int meta, EffectRenderer effectRenderer) {
+ GT_Renderer_Block.addDestroyEffects(effectRenderer, this, world, x, y, z);
+ return true;
+ }
+
+ @Override
+ public int getDamageValue(World aWorld, int aX, int aY, int aZ) {
+ TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if (((tTileEntity instanceof GT_TileEntity_Ores))) {
+ return ((GT_TileEntity_Ores) tTileEntity).getMetaData();
+ }
+ return 0;
+ }
+
+ @Override
+ public void breakBlock(World aWorld, int aX, int aY, int aZ, Block aBlock, int aMetadata) {
+ TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if ((tTileEntity instanceof GT_TileEntity_Ores)) {
+ mTemporaryTileEntity.set((GT_TileEntity_Ores) tTileEntity);
+ }
+ super.breakBlock(aWorld, aX, aY, aZ, aBlock, aMetadata);
+ aWorld.removeTileEntity(aX, aY, aZ);
+ }
+
+ public abstract OrePrefixes[] getProcessingPrefix(); // Must have 8 entries; an entry can be null to disable
+ // automatic recipes.
+
+ public abstract boolean[] getEnabledMetas(); // Must have 8 entries.
+
+ public abstract Block getDroppedBlock();
+
+ public abstract Materials[] getDroppedDusts(); // Must have 8 entries; can be null.
+
+ @Override
+ public ArrayList<ItemStack> getDrops(World aWorld, int aX, int aY, int aZ, int aMeta, int aFortune) {
+ TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if ((tTileEntity instanceof GT_TileEntity_Ores)) {
+ return ((GT_TileEntity_Ores) tTileEntity).getDrops(getDroppedBlock(), aFortune);
+ }
+ return mTemporaryTileEntity.get() == null ? new ArrayList<>()
+ : mTemporaryTileEntity.get()
+ .getDrops(getDroppedBlock(), aFortune);
+ }
+
+ @Override
+ public TileEntity createTileEntity(World aWorld, int aMeta) {
+ return new GT_TileEntity_Ores();
+ }
+
+ public abstract ITexture[] getTextureSet(); // Must have 16 entries.
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void getSubBlocks(Item aItem, CreativeTabs aTab, List<ItemStack> aList) {
+ for (int i = 0; i < GregTech_API.sGeneratedMaterials.length; i++) {
+ Materials tMaterial = GregTech_API.sGeneratedMaterials[i];
+ if ((tMaterial != null) && ((tMaterial.mTypes & 0x8) != 0) && !aBlockedOres.contains(tMaterial)) {
+ for (int meta = i; meta < 23000 + i; meta += 1000) {
+ if (!(new ItemStack(aItem, 1, meta).getDisplayName()
+ .contains(DOT_NAME))) aList.add(new ItemStack(aItem, 1, meta));
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Block_Reinforced.java b/src/main/java/gregtech/common/blocks/GT_Block_Reinforced.java
new file mode 100644
index 0000000000..a78fe5b70d
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Block_Reinforced.java
@@ -0,0 +1,409 @@
+package gregtech.common.blocks;
+
+import static gregtech.api.objects.XSTR.XSTR_INSTANCE;
+
+import java.util.List;
+
+import net.minecraft.block.Block;
+import net.minecraft.client.renderer.texture.IIconRegister;
+import net.minecraft.creativetab.CreativeTabs;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.EnumCreatureType;
+import net.minecraft.entity.boss.EntityWither;
+import net.minecraft.entity.item.EntityTNTPrimed;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraft.init.Items;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.IIcon;
+import net.minecraft.util.StatCollector;
+import net.minecraft.world.Explosion;
+import net.minecraft.world.IBlockAccess;
+import net.minecraft.world.World;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.enums.SoundResource;
+import gregtech.api.enums.Textures;
+import gregtech.api.items.GT_Generic_Block;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_LanguageManager;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.WorldSpawnedEventBuilder;
+
+public class GT_Block_Reinforced extends GT_Generic_Block {
+
+ public GT_Block_Reinforced(String aName) {
+ super(GT_Item_Storage.class, aName, new GT_Material_Reinforced());
+ for (int i = 0; i < 16; i++) {
+ Textures.BlockIcons.casingTexturePages[1][i + 80] = TextureFactory.of(this, i);
+ }
+ setStepSound(soundTypeStone);
+ setCreativeTab(GregTech_API.TAB_GREGTECH);
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".0.name", "Bronzeplate Reinforced Block");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".1.name", "Iridium Reinforced Block");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".2.name", "Plascrete Block");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".3.name", "Tungstensteel Reinforced Block");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".4.name", "Brittle Charcoal");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".5.name", "Powderbarrel");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".6.name", "Solid Super Fuel");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".7.name", "Magic Solid Super Fuel");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".8.name", "Steel Reinforced Block");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".9.name", "Titanium Reinforced Block");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".10.name", "Naquadah Reinforced Block");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".11.name", "Neutronium Reinforced Block");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".12.name", "Raw Deep Dark Portal Block");
+ ItemList.Block_BronzePlate.set(
+ new ItemStack(
+ this.setHardness(60.0f)
+ .setResistance(150.0f),
+ 1,
+ 0));
+ ItemList.Block_IridiumTungstensteel.set(
+ new ItemStack(
+ this.setHardness(400.0f)
+ .setResistance(600.0f),
+ 1,
+ 1));
+ ItemList.Block_Plascrete.set(
+ new ItemStack(
+ this.setHardness(5.0f)
+ .setResistance(6.0f),
+ 1,
+ 2));
+ ItemList.Block_TungstenSteelReinforced.set(
+ new ItemStack(
+ this.setHardness(250.0f)
+ .setResistance(400.0f),
+ 1,
+ 3));
+ ItemList.Block_BrittleCharcoal.set(
+ new ItemStack(
+ this.setHardness(0.5f)
+ .setResistance(8.0f),
+ 1,
+ 4));
+ ItemList.Block_Powderbarrel.set(
+ new ItemStack(
+ this.setHardness(2.5f)
+ .setResistance(2.0f),
+ 1,
+ 5));
+ ItemList.Block_SSFUEL.set(
+ new ItemStack(
+ this.setHardness(2.5f)
+ .setResistance(2.0f),
+ 1,
+ 6));
+ ItemList.Block_MSSFUEL.set(
+ new ItemStack(
+ this.setHardness(2.5f)
+ .setResistance(2.0f),
+ 1,
+ 7));
+ ItemList.Block_SteelPlate.set(
+ new ItemStack(
+ this.setHardness(150.0f)
+ .setResistance(200.0f),
+ 1,
+ 8));
+ ItemList.Block_TitaniumPlate.set(
+ new ItemStack(
+ this.setHardness(200.0f)
+ .setResistance(300.0f),
+ 1,
+ 9));
+ ItemList.Block_NaquadahPlate.set(
+ new ItemStack(
+ this.setHardness(500.0f)
+ .setResistance(1000.0f),
+ 1,
+ 10));
+ ItemList.Block_NeutroniumPlate.set(
+ new ItemStack(
+ this.setHardness(750.0f)
+ .setResistance(2500.0f),
+ 1,
+ 11));
+ ItemList.Block_BedrockiumCompressed.set(
+ new ItemStack(
+ this.setHardness(1500.0f)
+ .setResistance(5000.0f),
+ 1,
+ 12));
+ GT_ModHandler.addShapelessCraftingRecipe(
+ new ItemStack(Items.coal, 1, 1),
+ new Object[] { ItemList.Block_BrittleCharcoal.get(1) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Block_Powderbarrel.get(1L),
+ GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "WSW", "GGG", "WGW", 'W', OrePrefixes.plate.get(Materials.Wood), 'G',
+ new ItemStack(Items.gunpowder, 1), 'S', new ItemStack(Items.string, 1) });
+ }
+
+ @Override
+ public String getHarvestTool(int aMeta) {
+ if (aMeta == 5 || aMeta == 4 || aMeta == 6 || aMeta == 7) return "axe";
+ if (aMeta == 2) return "wrench";
+ return "pickaxe";
+ }
+
+ @Override
+ public int getHarvestLevel(int aMeta) {
+ if (aMeta == 4 || aMeta == 5 || aMeta == 6 || aMeta == 7) return 1;
+ if (aMeta == 2) return 2;
+ if (aMeta == 9 || aMeta == 3 || aMeta == 1) return 5;
+ if (aMeta == 10 || aMeta == 11) return 7;
+ return 4;
+ }
+
+ @Override
+ public IIcon getIcon(int ordinalSide, int aMeta) {
+ if ((aMeta >= 0) && (aMeta < 16)) {
+ switch (aMeta) {
+ case 0 -> {
+ return Textures.BlockIcons.BLOCK_BRONZEPREIN.getIcon();
+ }
+ case 1 -> {
+ return Textures.BlockIcons.BLOCK_IRREIN.getIcon();
+ }
+ case 2 -> {
+ return Textures.BlockIcons.BLOCK_PLASCRETE.getIcon();
+ }
+ case 3 -> {
+ return Textures.BlockIcons.BLOCK_TSREIN.getIcon();
+ }
+ case 4, 6, 7 -> {
+ return Blocks.coal_block.getIcon(0, 0);
+ }
+ case 5 -> {
+ return Textures.BlockIcons.COVER_WOOD_PLATE.getIcon();
+ }
+ case 8 -> {
+ return Textures.BlockIcons.BLOCK_STEELPREIN.getIcon();
+ }
+ case 9 -> {
+ return Textures.BlockIcons.BLOCK_TITANIUMPREIN.getIcon();
+ }
+ case 10 -> {
+ return Textures.BlockIcons.BLOCK_NAQUADAHPREIN.getIcon();
+ }
+ case 11 -> {
+ return Textures.BlockIcons.BLOCK_NEUTRONIUMPREIN.getIcon();
+ }
+ case 12 -> {
+ return Textures.BlockIcons.BLOCK_DEEP_DARK_RAW.getIcon();
+ }
+ }
+ }
+ return Textures.BlockIcons.MACHINE_CASING_SOLID_STEEL.getIcon();
+ }
+
+ @Override
+ public float getBlockHardness(World aWorld, int aX, int aY, int aZ) {
+ if (aWorld == null) {
+ return 0.0F;
+ }
+ if (aWorld.isAirBlock(aX, aY, aZ)) {
+ return 0.0F;
+ }
+ int tMeta = aWorld.getBlockMetadata(aX, aY, aZ);
+ if (tMeta == 0) {
+ return 60.0F;
+ }
+ if (tMeta == 1) {
+ return 400.0F;
+ }
+ if (tMeta == 2) {
+ return 5.0F;
+ }
+ if (tMeta == 3) {
+ return 250.0F;
+ }
+ if (tMeta == 4 || tMeta == 5 || tMeta == 6 || tMeta == 7) {
+ return 0.5F;
+ }
+ if (tMeta == 8) {
+ return 150.0F;
+ }
+ if (tMeta == 9) {
+ return 200.0F;
+ }
+ if (tMeta == 10) {
+ return 500.0F;
+ }
+ if (tMeta == 11) {
+ return 750.0F;
+ }
+ return Blocks.iron_block.getBlockHardness(aWorld, aX, aY, aZ);
+ }
+
+ @Override
+ public float getExplosionResistance(Entity entity, World world, int x, int y, int z, double explosionX,
+ double explosionY, double explosionZ) {
+ if (world == null) {
+ return 0.0F;
+ }
+ int tMeta = world.getBlockMetadata(x, y, z);
+ if (tMeta == 0) {
+ return 150.0F;
+ }
+ if (tMeta == 1) {
+ return 600.0F;
+ }
+ if (tMeta == 2) {
+ return 6.0F;
+ }
+ if (tMeta == 3) {
+ return 400.0F;
+ }
+ if (tMeta == 4 || tMeta == 6 || tMeta == 7) {
+ return 8.0F;
+ }
+ if (tMeta == 5) {
+ return 1.0F;
+ }
+ if (tMeta == 8) {
+ return 200.0F;
+ }
+ if (tMeta == 9) {
+ return 300.0F;
+ }
+ if (tMeta == 10) {
+ return 1000.0F;
+ }
+ if (tMeta == 11) {
+ return 2500.0F;
+ }
+ return super.getExplosionResistance(entity, world, x, y, z, explosionX, explosionY, explosionZ);
+ }
+
+ @Override
+ public String getUnlocalizedName() {
+ return this.mUnlocalizedName;
+ }
+
+ @Override
+ public String getLocalizedName() {
+ return StatCollector.translateToLocal(this.mUnlocalizedName + ".name");
+ }
+
+ @Override
+ public boolean canBeReplacedByLeaves(IBlockAccess aWorld, int aX, int aY, int aZ) {
+ return false;
+ }
+
+ @Override
+ public boolean isNormalCube(IBlockAccess aWorld, int aX, int aY, int aZ) {
+ return true;
+ }
+
+ @Override
+ public boolean canCreatureSpawn(EnumCreatureType type, IBlockAccess world, int x, int y, int z) {
+ return false;
+ }
+
+ @Override
+ public int damageDropped(int metadata) {
+ return metadata;
+ }
+
+ @Override
+ public int getDamageValue(World aWorld, int aX, int aY, int aZ) {
+ return aWorld.getBlockMetadata(aX, aY, aZ);
+ }
+
+ @Override
+ public void dropBlockAsItemWithChance(World aWorld, int aX, int aY, int aZ, int aMetadata, float chance,
+ int aFortune) {
+ if (aMetadata == 4) {
+ this.dropBlockAsItem(aWorld, aX, aY, aZ, new ItemStack(Items.coal, XSTR_INSTANCE.nextInt(2) + 1, 1));
+ } else {
+ super.dropBlockAsItemWithChance(aWorld, aX, aY, aZ, aMetadata, chance, aFortune);
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ @Override
+ public boolean removedByPlayer(World world, EntityPlayer player, int x, int y, int z) {
+ if (!world.isRemote && world.getBlockMetadata(x, y, z) == 5) {
+ EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(world, x + 0.5F, y + 0.5F, z + 0.5F, player);
+ world.spawnEntityInWorld(entitytntprimed);
+ new WorldSpawnedEventBuilder.SoundAtEntityEventBuilder().setPitch(1f)
+ .setVolume(1f)
+ .setIdentifier(SoundResource.GAME_TNT_PRIMED)
+ .setEntity(entitytntprimed)
+ .setWorld(world)
+ .run();
+ world.setBlockToAir(x, y, z);
+ return false;
+ }
+ return super.removedByPlayer(world, player, x, y, z);
+ }
+
+ @Override
+ public void onBlockAdded(World world, int x, int y, int z) {
+ super.onBlockAdded(world, x, y, z);
+ if (world.isBlockIndirectlyGettingPowered(x, y, z) && world.getBlockMetadata(x, y, z) == 5) {
+ removedByPlayer(world, null, x, y, z);
+ }
+ }
+
+ @Override
+ public void onNeighborBlockChange(World world, int x, int y, int z, Block neighbor) {
+ if (world.isBlockIndirectlyGettingPowered(x, y, z) && world.getBlockMetadata(x, y, z) == 5) {
+ removedByPlayer(world, null, x, y, z);
+ }
+ }
+
+ @Override
+ public void onBlockExploded(World world, int x, int y, int z, Explosion explosion) {
+ if (!world.isRemote && world.getBlockMetadata(x, y, z) == 5) {
+ EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(
+ world,
+ x + 0.5F,
+ y + 0.5F,
+ z + 0.5F,
+ explosion.getExplosivePlacedBy());
+ entitytntprimed.fuse = (world.rand.nextInt(entitytntprimed.fuse / 4) + entitytntprimed.fuse / 8);
+ world.spawnEntityInWorld(entitytntprimed);
+ }
+ super.onBlockExploded(world, x, y, z, explosion);
+ }
+
+ @Override
+ public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int ordinalSide,
+ float xOffset, float yOffset, float zOffset) {
+ if ((player.getCurrentEquippedItem() != null) && (player.getCurrentEquippedItem()
+ .getItem() == Items.flint_and_steel) && world.getBlockMetadata(x, y, z) == 5) {
+ removedByPlayer(world, player, x, y, z);
+
+ return true;
+ }
+ return super.onBlockActivated(world, x, y, z, player, ordinalSide, xOffset, yOffset, zOffset);
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void registerBlockIcons(IIconRegister aIconRegister) {}
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void getSubBlocks(Item aItem, CreativeTabs aCreativeTab, List<ItemStack> aList) {
+ for (int i = 0; i < 16; i++) {
+ ItemStack aStack = new ItemStack(aItem, 1, i);
+ if (!aStack.getDisplayName()
+ .contains(".name")) aList.add(aStack);
+ }
+ }
+
+ @Override
+ public boolean canEntityDestroy(IBlockAccess world, int x, int y, int z, Entity entity) {
+ return !(entity instanceof EntityWither);
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Block_Stones.java b/src/main/java/gregtech/common/blocks/GT_Block_Stones.java
new file mode 100644
index 0000000000..4ca52aee56
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Block_Stones.java
@@ -0,0 +1,62 @@
+package gregtech.common.blocks;
+
+import net.minecraft.init.Blocks;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.IIcon;
+import net.minecraft.world.World;
+
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.util.GT_LanguageManager;
+import gregtech.api.util.GT_OreDictUnificator;
+
+public class GT_Block_Stones extends GT_Block_Stones_Abstract {
+
+ public GT_Block_Stones() {
+ super(GT_Item_Granites.class, "gt.blockstones");
+ setResistance(60.0F);
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".0.name", "Marble");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".1.name", "Marble Cobblestone");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".2.name", "Mossy Marble Cobblestone");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".3.name", "Marble Bricks");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".4.name", "Cracked Marble Bricks");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".5.name", "Mossy Marble Bricks");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".6.name", "Chiseled Marble");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".7.name", "Smooth Marble");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".8.name", "Basalt");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".9.name", "Basalt Cobblestone");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".10.name", "Mossy Basalt Cobblestone");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".11.name", "Basalt Bricks");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".12.name", "Cracked Basalt Bricks");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".13.name", "Mossy Basalt Bricks");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".14.name", "Chiseled Basalt");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".15.name", "Smooth Basalt");
+ for (int i = 0; i < 16; i++) {
+ GT_OreDictUnificator
+ .registerOre(OrePrefixes.stone, i < 8 ? Materials.Marble : Materials.Basalt, new ItemStack(this, 1, i));
+ GT_OreDictUnificator
+ .registerOre(OrePrefixes.block, i < 8 ? Materials.Marble : Materials.Basalt, new ItemStack(this, 1, i));
+ GT_OreDictUnificator.registerOre(
+ (i < 8 ? Materials.Marble.mName.toLowerCase() : Materials.Basalt.mName.toLowerCase()),
+ new ItemStack(this, 1, i));
+ }
+ }
+
+ @Override
+ public int getHarvestLevel(int aMeta) {
+ return 2;
+ }
+
+ @Override
+ public float getBlockHardness(World aWorld, int aX, int aY, int aZ) {
+ return this.blockHardness = Blocks.stone.getBlockHardness(aWorld, aX, aY, aZ) * 3.0F;
+ }
+
+ @Override
+ public IIcon getIcon(int ordinalSide, int aMeta) {
+ if ((aMeta >= 0) && (aMeta < 16)) {
+ return gregtech.api.enums.Textures.BlockIcons.STONES[aMeta].getIcon();
+ }
+ return gregtech.api.enums.Textures.BlockIcons.STONES[0].getIcon();
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Block_Stones_Abstract.java b/src/main/java/gregtech/common/blocks/GT_Block_Stones_Abstract.java
new file mode 100644
index 0000000000..4a5bb9456e
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Block_Stones_Abstract.java
@@ -0,0 +1,250 @@
+package gregtech.common.blocks;
+
+import static gregtech.api.recipe.RecipeMaps.assemblerRecipes;
+import static gregtech.api.recipe.RecipeMaps.hammerRecipes;
+import static gregtech.api.recipe.RecipeMaps.laserEngraverRecipes;
+import static gregtech.api.util.GT_RecipeBuilder.SECONDS;
+import static gregtech.api.util.GT_RecipeBuilder.TICKS;
+
+import java.util.List;
+
+import net.minecraft.block.material.Material;
+import net.minecraft.client.renderer.texture.IIconRegister;
+import net.minecraft.creativetab.CreativeTabs;
+import net.minecraft.entity.EnumCreatureType;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemBlock;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.IIcon;
+import net.minecraft.util.StatCollector;
+import net.minecraft.world.IBlockAccess;
+import net.minecraft.world.World;
+
+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.OreDictNames;
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.interfaces.IOreRecipeRegistrator;
+import gregtech.api.items.GT_Generic_Block;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_Utility;
+
+public class GT_Block_Stones_Abstract extends GT_Generic_Block implements IOreRecipeRegistrator {
+
+ public GT_Block_Stones_Abstract(Class<? extends ItemBlock> aItemClass, String aName) {
+ super(aItemClass, aName, Material.rock);
+ OrePrefixes.crafting.add(this);
+ setStepSound(soundTypeStone);
+ setCreativeTab(GregTech_API.TAB_GREGTECH_MATERIALS);
+
+ this.registerSmeltingRecipes();
+ this.registerAssemblerRecipes();
+ this.registerCraftingRecipes();
+ this.registerForgeHammerRecipes();
+
+ }
+
+ private void registerSmeltingRecipes() {
+ GT_ModHandler.addSmeltingRecipe(new ItemStack(this, 1, 0), new ItemStack(this, 1, 7));
+ GT_ModHandler.addSmeltingRecipe(new ItemStack(this, 1, 1), new ItemStack(this, 1, 0));
+ GT_ModHandler.addSmeltingRecipe(new ItemStack(this, 1, 2), new ItemStack(this, 1, 0));
+ GT_ModHandler.addSmeltingRecipe(new ItemStack(this, 1, 3), new ItemStack(this, 1, 0));
+ GT_ModHandler.addSmeltingRecipe(new ItemStack(this, 1, 4), new ItemStack(this, 1, 0));
+ GT_ModHandler.addSmeltingRecipe(new ItemStack(this, 1, 5), new ItemStack(this, 1, 0));
+ GT_ModHandler.addSmeltingRecipe(new ItemStack(this, 1, 6), new ItemStack(this, 1, 0));
+ GT_ModHandler.addSmeltingRecipe(new ItemStack(this, 1, 7), new ItemStack(this, 1, 0));
+ GT_ModHandler.addSmeltingRecipe(new ItemStack(this, 1, 8), new ItemStack(this, 1, 15));
+ GT_ModHandler.addSmeltingRecipe(new ItemStack(this, 1, 9), new ItemStack(this, 1, 8));
+ GT_ModHandler.addSmeltingRecipe(new ItemStack(this, 1, 10), new ItemStack(this, 1, 8));
+ GT_ModHandler.addSmeltingRecipe(new ItemStack(this, 1, 11), new ItemStack(this, 1, 8));
+ GT_ModHandler.addSmeltingRecipe(new ItemStack(this, 1, 12), new ItemStack(this, 1, 8));
+ GT_ModHandler.addSmeltingRecipe(new ItemStack(this, 1, 13), new ItemStack(this, 1, 8));
+ GT_ModHandler.addSmeltingRecipe(new ItemStack(this, 1, 14), new ItemStack(this, 1, 8));
+ GT_ModHandler.addSmeltingRecipe(new ItemStack(this, 1, 15), new ItemStack(this, 1, 8));
+
+ }
+
+ private void registerAssemblerRecipes() {
+ GT_Values.RA.stdBuilder()
+ .itemInputs(new ItemStack(this, 1, 0), GT_Utility.getIntegratedCircuit(4))
+ .itemOutputs(new ItemStack(this, 1, 3))
+ .duration(2 * SECONDS + 10 * TICKS)
+ .eut(4)
+ .addTo(assemblerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(new ItemStack(this, 1, 8), GT_Utility.getIntegratedCircuit(4))
+ .itemOutputs(new ItemStack(this, 1, 11))
+ .duration(2 * SECONDS + 10 * TICKS)
+ .eut(4)
+ .addTo(assemblerRecipes);
+ }
+
+ private void registerCraftingRecipes() {
+ GT_ModHandler.addCraftingRecipe(
+ new ItemStack(this, 1, 6),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { "f", "X", 'X', new ItemStack(this, 1, 7) });
+ GT_ModHandler.addCraftingRecipe(
+ new ItemStack(this, 1, 14),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { "f", "X", 'X', new ItemStack(this, 1, 15) });
+ GT_ModHandler.addCraftingRecipe(
+ new ItemStack(this, 1, 4),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { "h", "X", 'X', new ItemStack(this, 1, 3) });
+ GT_ModHandler.addCraftingRecipe(
+ new ItemStack(this, 1, 12),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { "h", "X", 'X', new ItemStack(this, 1, 11) });
+ GT_ModHandler.addCraftingRecipe(
+ new ItemStack(this, 1, 1),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { "h", "X", 'X', new ItemStack(this, 1, 0) });
+ GT_ModHandler.addCraftingRecipe(
+ new ItemStack(this, 1, 9),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { "h", "X", 'X', new ItemStack(this, 1, 8) });
+ GT_ModHandler.addCraftingRecipe(
+ new ItemStack(this, 4, 3),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { "XX", "XX", 'X', new ItemStack(this, 4, 0) });
+ GT_ModHandler.addCraftingRecipe(
+ new ItemStack(this, 4, 11),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { "XX", "XX", 'X', new ItemStack(this, 4, 8) });
+ GT_ModHandler.addCraftingRecipe(
+ new ItemStack(this, 4, 3),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { "XX", "XX", 'X', new ItemStack(this, 4, 7) });
+ GT_ModHandler.addCraftingRecipe(
+ new ItemStack(this, 4, 11),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { "XX", "XX", 'X', new ItemStack(this, 4, 15) });
+ }
+
+ private void registerForgeHammerRecipes() {
+ GT_Values.RA.stdBuilder()
+ .itemInputs(new ItemStack(this, 1, 3))
+ .itemOutputs(new ItemStack(this, 1, 4))
+ .duration(16 * TICKS)
+ .eut(10)
+ .addTo(hammerRecipes);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(new ItemStack(this, 1, 11))
+ .itemOutputs(new ItemStack(this, 1, 12))
+ .duration(16 * TICKS)
+ .eut(10)
+ .addTo(hammerRecipes);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(new ItemStack(this, 1, 0))
+ .itemOutputs(new ItemStack(this, 1, 1))
+ .duration(16 * TICKS)
+ .eut(10)
+ .addTo(hammerRecipes);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(new ItemStack(this, 1, 8))
+ .itemOutputs(new ItemStack(this, 1, 9))
+ .duration(16 * TICKS)
+ .eut(10)
+ .addTo(hammerRecipes);
+ }
+
+ @Override
+ public void registerOre(OrePrefixes aPrefix, Materials aMaterial, String aOreDictName, String aModName,
+ ItemStack aStack) {
+ if (aOreDictName.equals(OreDictNames.craftingLensWhite.toString())) {
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(new ItemStack(this, 1, 7), GT_Utility.copyAmount(0, aStack))
+ .itemOutputs(new ItemStack(this, 1, 6))
+ .duration(2 * SECONDS + 10 * TICKS)
+ .eut(16)
+ .addTo(laserEngraverRecipes);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(new ItemStack(this, 1, 15), GT_Utility.copyAmount(0, aStack))
+ .itemOutputs(new ItemStack(this, 1, 14))
+ .duration(2 * SECONDS + 10 * TICKS)
+ .eut(16)
+ .addTo(laserEngraverRecipes);
+
+ }
+ }
+
+ @Override
+ public String getHarvestTool(int aMeta) {
+ return "pickaxe";
+ }
+
+ @Override
+ public int getHarvestLevel(int aMeta) {
+ return 1;
+ }
+
+ @Override
+ public float getBlockHardness(World aWorld, int aX, int aY, int aZ) {
+ return this.blockHardness = Blocks.stone.getBlockHardness(aWorld, aX, aY, aZ) * 3.0F;
+ }
+
+ @Override
+ public String getUnlocalizedName() {
+ return this.mUnlocalizedName;
+ }
+
+ @Override
+ public String getLocalizedName() {
+ return StatCollector.translateToLocal(this.mUnlocalizedName + ".name");
+ }
+
+ @Override
+ public boolean canBeReplacedByLeaves(IBlockAccess aWorld, int aX, int aY, int aZ) {
+ return false;
+ }
+
+ @Override
+ public boolean isNormalCube(IBlockAccess aWorld, int aX, int aY, int aZ) {
+ return true;
+ }
+
+ @Override
+ public IIcon getIcon(int ordinalSide, int aMeta) {
+ if ((aMeta >= 0) && (aMeta < 16)) {
+ return gregtech.api.enums.Textures.BlockIcons.GRANITES[aMeta].getIcon();
+ }
+ return null;
+ }
+
+ @Override
+ public boolean canCreatureSpawn(EnumCreatureType type, IBlockAccess world, int x, int y, int z) {
+ return world.getBlockMetadata(x, y, z) % 8 < 3;
+ }
+
+ @Override
+ public int damageDropped(int metadata) {
+ return metadata % 8 == 0 ? metadata + 1 : metadata;
+ }
+
+ @Override
+ public int getDamageValue(World aWorld, int aX, int aY, int aZ) {
+ return aWorld.getBlockMetadata(aX, aY, aZ);
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void registerBlockIcons(IIconRegister aIconRegister) {}
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void getSubBlocks(Item aItem, CreativeTabs aCreativeTab, List<ItemStack> aList) {
+ for (int i = 0; i < 16; i++) {
+ aList.add(new ItemStack(aItem, 1, i));
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Block_Storage.java b/src/main/java/gregtech/common/blocks/GT_Block_Storage.java
new file mode 100644
index 0000000000..ada3f01cde
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Block_Storage.java
@@ -0,0 +1,103 @@
+package gregtech.common.blocks;
+
+import java.util.List;
+
+import net.minecraft.block.material.Material;
+import net.minecraft.client.renderer.texture.IIconRegister;
+import net.minecraft.creativetab.CreativeTabs;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.EnumCreatureType;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemBlock;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.StatCollector;
+import net.minecraft.world.IBlockAccess;
+import net.minecraft.world.World;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.api.GregTech_API;
+import gregtech.api.items.GT_Generic_Block;
+
+public class GT_Block_Storage extends GT_Generic_Block {
+
+ protected GT_Block_Storage(Class<? extends ItemBlock> aItemClass, String aName, Material aMaterial) {
+ super(aItemClass, aName, aMaterial);
+ setStepSound(soundTypeMetal);
+ setCreativeTab(GregTech_API.TAB_GREGTECH_MATERIALS);
+ }
+
+ @Override
+ public String getHarvestTool(int aMeta) {
+ return "pickaxe";
+ }
+
+ @Override
+ public boolean isBeaconBase(IBlockAccess worldObj, int x, int y, int z, int beaconX, int beaconY, int beaconZ) {
+ return true;
+ }
+
+ @Override
+ public int getHarvestLevel(int aMeta) {
+ return 1;
+ }
+
+ @Override
+ public float getBlockHardness(World aWorld, int aX, int aY, int aZ) {
+ return Blocks.iron_block.getBlockHardness(aWorld, aX, aY, aZ);
+ }
+
+ @Override
+ public float getExplosionResistance(Entity aTNT) {
+ return Blocks.iron_block.getExplosionResistance(aTNT);
+ }
+
+ @Override
+ public String getUnlocalizedName() {
+ return this.mUnlocalizedName;
+ }
+
+ @Override
+ public String getLocalizedName() {
+ return StatCollector.translateToLocal(this.mUnlocalizedName + ".name");
+ }
+
+ @Override
+ public boolean canBeReplacedByLeaves(IBlockAccess aWorld, int aX, int aY, int aZ) {
+ return false;
+ }
+
+ @Override
+ public boolean isNormalCube(IBlockAccess aWorld, int aX, int aY, int aZ) {
+ return true;
+ }
+
+ @Override
+ public boolean canCreatureSpawn(EnumCreatureType type, IBlockAccess world, int x, int y, int z) {
+ return true;
+ }
+
+ @Override
+ public int damageDropped(int metadata) {
+ return metadata;
+ }
+
+ @Override
+ public int getDamageValue(World aWorld, int aX, int aY, int aZ) {
+ return aWorld.getBlockMetadata(aX, aY, aZ);
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void registerBlockIcons(IIconRegister aIconRegister) {}
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void getSubBlocks(Item aItem, CreativeTabs aCreativeTab, List<ItemStack> aList) {
+ for (int i = 0; i < 16; i++) {
+ if (!(new ItemStack(aItem, 1, i).getDisplayName()
+ .contains(".name"))) aList.add(new ItemStack(aItem, 1, i));
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Cyclotron_Coils.java b/src/main/java/gregtech/common/blocks/GT_Cyclotron_Coils.java
new file mode 100644
index 0000000000..1a544f027f
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Cyclotron_Coils.java
@@ -0,0 +1,127 @@
+package gregtech.common.blocks;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.IIcon;
+import net.minecraft.world.IBlockAccess;
+
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Textures;
+import gregtech.api.util.GT_LanguageManager;
+
+public class GT_Cyclotron_Coils extends GT_Block_Casings_Abstract {
+
+ public GT_Cyclotron_Coils() {
+ super(GT_Cyclotron_Item_Casings.class, "gt.blockcasings.cyclotron_coils", GT_Material_Casings.INSTANCE, 16);
+
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".0.name", "MV Solenoid Superconductor Coil");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".1.name", "HV Solenoid Superconductor Coil");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".2.name", "EV Solenoid Superconductor Coil");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".3.name", "IV Solenoid Superconductor Coil");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".4.name", "LuV Solenoid Superconductor Coil");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".5.name", "ZPM Solenoid Superconductor Coil");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".6.name", "UV Solenoid Superconductor Coil");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".7.name", "UHV Solenoid Superconductor Coil");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".8.name", "UEV Solenoid Superconductor Coil");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".9.name", "UIV Solenoid Superconductor Coil");
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".10.name", "UMV Solenoid Superconductor Coil");
+
+ ItemList.Superconducting_Magnet_Solenoid_MV.set(new ItemStack(this, 1, 0));
+ ItemList.Superconducting_Magnet_Solenoid_HV.set(new ItemStack(this, 1, 1));
+ ItemList.Superconducting_Magnet_Solenoid_EV.set(new ItemStack(this, 1, 2));
+ ItemList.Superconducting_Magnet_Solenoid_IV.set(new ItemStack(this, 1, 3));
+ ItemList.Superconducting_Magnet_Solenoid_LuV.set(new ItemStack(this, 1, 4));
+ ItemList.Superconducting_Magnet_Solenoid_ZPM.set(new ItemStack(this, 1, 5));
+ ItemList.Superconducting_Magnet_Solenoid_UV.set(new ItemStack(this, 1, 6));
+ ItemList.Superconducting_Magnet_Solenoid_UHV.set(new ItemStack(this, 1, 7));
+ ItemList.Superconducting_Magnet_Solenoid_UEV.set(new ItemStack(this, 1, 8));
+ ItemList.Superconducting_Magnet_Solenoid_UIV.set(new ItemStack(this, 1, 9));
+ ItemList.Superconducting_Magnet_Solenoid_UMV.set(new ItemStack(this, 1, 10));
+ }
+
+ @Override // Magic numbers...
+ public int getTextureIndex(int aMeta) {
+ return 192 + aMeta;
+ }
+
+ @Override
+ public IIcon getIcon(int ordinalSide, int aMeta) {
+ if ((aMeta >= 0) && (aMeta < 16)) {
+ switch (aMeta) {
+ case 0 -> {
+ if (ordinalSide == 0 || ordinalSide == 1) {
+ return Textures.BlockIcons.MV_TOP_CYCLOTRON_SOLENOID.getIcon();
+ }
+ return Textures.BlockIcons.MV_SIDE_CYCLOTRON_SOLENOID.getIcon();
+ }
+ case 1 -> {
+ if (ordinalSide == 0 || ordinalSide == 1) {
+ return Textures.BlockIcons.HV_TOP_CYCLOTRON_SOLENOID.getIcon();
+ }
+ return Textures.BlockIcons.HV_SIDE_CYCLOTRON_SOLENOID.getIcon();
+ }
+ case 2 -> {
+ if (ordinalSide == 0 || ordinalSide == 1) {
+ return Textures.BlockIcons.EV_TOP_CYCLOTRON_SOLENOID.getIcon();
+ }
+ return Textures.BlockIcons.EV_SIDE_CYCLOTRON_SOLENOID.getIcon();
+ }
+ case 3 -> {
+ if (ordinalSide == 0 || ordinalSide == 1) {
+ return Textures.BlockIcons.IV_TOP_CYCLOTRON_SOLENOID.getIcon();
+ }
+ return Textures.BlockIcons.IV_SIDE_CYCLOTRON_SOLENOID.getIcon();
+ }
+ case 4 -> {
+ if (ordinalSide == 0 || ordinalSide == 1) {
+ return Textures.BlockIcons.LuV_TOP_CYCLOTRON_SOLENOID.getIcon();
+ }
+ return Textures.BlockIcons.LuV_SIDE_CYCLOTRON_SOLENOID.getIcon();
+ }
+ case 5 -> {
+ if (ordinalSide == 0 || ordinalSide == 1) {
+ return Textures.BlockIcons.ZPM_TOP_CYCLOTRON_SOLENOID.getIcon();
+ }
+ return Textures.BlockIcons.ZPM_SIDE_CYCLOTRON_SOLENOID.getIcon();
+ }
+ case 6 -> {
+ if (ordinalSide == 0 || ordinalSide == 1) {
+ return Textures.BlockIcons.UV_TOP_CYCLOTRON_SOLENOID.getIcon();
+ }
+ return Textures.BlockIcons.UV_SIDE_CYCLOTRON_SOLENOID.getIcon();
+ }
+ case 7 -> {
+ if (ordinalSide == 0 || ordinalSide == 1) {
+ return Textures.BlockIcons.UHV_TOP_CYCLOTRON_SOLENOID.getIcon();
+ }
+ return Textures.BlockIcons.UHV_SIDE_CYCLOTRON_SOLENOID.getIcon();
+ }
+ case 8 -> {
+ if (ordinalSide == 0 || ordinalSide == 1) {
+ return Textures.BlockIcons.UEV_TOP_CYCLOTRON_SOLENOID.getIcon();
+ }
+ return Textures.BlockIcons.UEV_SIDE_CYCLOTRON_SOLENOID.getIcon();
+ }
+ case 9 -> {
+ if (ordinalSide == 0 || ordinalSide == 1) {
+ return Textures.BlockIcons.UIV_TOP_CYCLOTRON_SOLENOID.getIcon();
+ }
+ return Textures.BlockIcons.UIV_SIDE_CYCLOTRON_SOLENOID.getIcon();
+ }
+ case 10 -> {
+ if (ordinalSide == 0 || ordinalSide == 1) {
+ return Textures.BlockIcons.UMV_TOP_CYCLOTRON_SOLENOID.getIcon();
+ }
+ return Textures.BlockIcons.UMV_SIDE_CYCLOTRON_SOLENOID.getIcon();
+ }
+ }
+ }
+ return Textures.BlockIcons.MACHINE_CASING_SOLID_STEEL.getIcon();
+ }
+
+ @Override
+ public int colorMultiplier(IBlockAccess aWorld, int aX, int aY, int aZ) {
+ return aWorld.getBlockMetadata(aX, aY, aZ) > 9 ? super.colorMultiplier(aWorld, aX, aY, aZ)
+ : gregtech.api.enums.Dyes.MACHINE_METAL.mRGBa[0] << 16 | gregtech.api.enums.Dyes.MACHINE_METAL.mRGBa[1] << 8
+ | gregtech.api.enums.Dyes.MACHINE_METAL.mRGBa[2];
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Cyclotron_Item_Casings.java b/src/main/java/gregtech/common/blocks/GT_Cyclotron_Item_Casings.java
new file mode 100644
index 0000000000..f1ca45a805
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Cyclotron_Item_Casings.java
@@ -0,0 +1,10 @@
+package gregtech.common.blocks;
+
+import net.minecraft.block.Block;
+
+public class GT_Cyclotron_Item_Casings extends GT_Item_Casings_Abstract {
+
+ public GT_Cyclotron_Item_Casings(Block block) {
+ super(block);
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Item_Casings1.java b/src/main/java/gregtech/common/blocks/GT_Item_Casings1.java
new file mode 100644
index 0000000000..1a86a2e534
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Item_Casings1.java
@@ -0,0 +1,14 @@
+package gregtech.common.blocks;
+
+import net.minecraft.block.Block;
+
+/**
+ * The casings are split into separate files because they are registered as regular blocks, and a regular block can have
+ * 16 subtypes at most.
+ */
+public class GT_Item_Casings1 extends GT_Item_Casings_Abstract {
+
+ public GT_Item_Casings1(Block block) {
+ super(block);
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Item_Casings2.java b/src/main/java/gregtech/common/blocks/GT_Item_Casings2.java
new file mode 100644
index 0000000000..f98c169c7f
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Item_Casings2.java
@@ -0,0 +1,26 @@
+package gregtech.common.blocks;
+
+import java.util.List;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+
+/**
+ * The casings are split into separate files because they are registered as regular blocks, and a regular block can have
+ * 16 subtypes at most.
+ */
+public class GT_Item_Casings2 extends GT_Item_Casings_Abstract {
+
+ public GT_Item_Casings2(Block block) {
+ super(block);
+ }
+
+ @Override
+ public void addInformation(ItemStack aStack, EntityPlayer aPlayer, List<String> aList, boolean aF3_H) {
+ super.addInformation(aStack, aPlayer, aList, aF3_H);
+ if (getDamage(aStack) == 8) {
+ aList.add(this.mBlastProofTooltip);
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Item_Casings3.java b/src/main/java/gregtech/common/blocks/GT_Item_Casings3.java
new file mode 100644
index 0000000000..861774d96f
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Item_Casings3.java
@@ -0,0 +1,14 @@
+package gregtech.common.blocks;
+
+import net.minecraft.block.Block;
+
+/**
+ * The casings are split into separate files because they are registered as regular blocks, and a regular block can have
+ * 16 subtypes at most.
+ */
+public class GT_Item_Casings3 extends GT_Item_Casings_Abstract {
+
+ public GT_Item_Casings3(Block block) {
+ super(block);
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Item_Casings4.java b/src/main/java/gregtech/common/blocks/GT_Item_Casings4.java
new file mode 100644
index 0000000000..e2badca2cb
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Item_Casings4.java
@@ -0,0 +1,14 @@
+package gregtech.common.blocks;
+
+import net.minecraft.block.Block;
+
+/**
+ * The casings are split into separate files because they are registered as regular blocks, and a regular block can have
+ * 16 subtypes at most.
+ */
+public class GT_Item_Casings4 extends GT_Item_Casings_Abstract {
+
+ public GT_Item_Casings4(Block block) {
+ super(block);
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Item_Casings5.java b/src/main/java/gregtech/common/blocks/GT_Item_Casings5.java
new file mode 100644
index 0000000000..3b3ab68cb1
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Item_Casings5.java
@@ -0,0 +1,36 @@
+package gregtech.common.blocks;
+
+import java.util.List;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.api.enums.HeatingCoilLevel;
+import gregtech.api.util.GT_LanguageManager;
+
+/**
+ * The casings are split into separate files because they are registered as regular blocks, and a regular block can have
+ * 16 subtypes at most.
+ */
+public class GT_Item_Casings5 extends GT_Item_Casings_Abstract {
+
+ public GT_Item_Casings5(Block block) {
+ super(block);
+ }
+
+ protected static final String mCoilHeatTooltip = GT_LanguageManager
+ .addStringLocalization("gt.coilheattooltip", "Base Heating Capacity = ");
+ protected static final String mCoilUnitTooltip = GT_LanguageManager
+ .addStringLocalization("gt.coilunittooltip", " Kelvin");
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void addInformation(ItemStack aStack, EntityPlayer aPlayer, List<String> aList, boolean aF3_H) {
+ super.addInformation(aStack, aPlayer, aList, aF3_H);
+ HeatingCoilLevel coilLevel = GT_Block_Casings5.getCoilHeatFromDamage(aStack.getItemDamage());
+ aList.add(mCoilHeatTooltip + coilLevel.getHeat() + mCoilUnitTooltip);
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Item_Casings6.java b/src/main/java/gregtech/common/blocks/GT_Item_Casings6.java
new file mode 100644
index 0000000000..af533acfa8
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Item_Casings6.java
@@ -0,0 +1,14 @@
+package gregtech.common.blocks;
+
+import net.minecraft.block.Block;
+
+/**
+ * The casings are split into separate files because they are registered as regular blocks, and a regular block can have
+ * 16 subtypes at most.
+ */
+public class GT_Item_Casings6 extends GT_Item_Casings_Abstract {
+
+ public GT_Item_Casings6(Block block) {
+ super(block);
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Item_Casings8.java b/src/main/java/gregtech/common/blocks/GT_Item_Casings8.java
new file mode 100644
index 0000000000..e3f3bbdf97
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Item_Casings8.java
@@ -0,0 +1,14 @@
+package gregtech.common.blocks;
+
+import net.minecraft.block.Block;
+
+/**
+ * The casings are split into separate files because they are registered as regular blocks, and a regular block can have
+ * 16 subtypes at most.
+ */
+public class GT_Item_Casings8 extends GT_Item_Casings_Abstract {
+
+ public GT_Item_Casings8(Block block) {
+ super(block);
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Item_Casings9.java b/src/main/java/gregtech/common/blocks/GT_Item_Casings9.java
new file mode 100644
index 0000000000..678a2424be
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Item_Casings9.java
@@ -0,0 +1,14 @@
+package gregtech.common.blocks;
+
+import net.minecraft.block.Block;
+
+/**
+ * The casings are split into separate files because they are registered as regular blocks, and a regular block can have
+ * 16 subtypes at most.
+ */
+public class GT_Item_Casings9 extends GT_Item_Casings_Abstract {
+
+ public GT_Item_Casings9(Block block) {
+ super(block);
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Item_Casings_Abstract.java b/src/main/java/gregtech/common/blocks/GT_Item_Casings_Abstract.java
new file mode 100644
index 0000000000..46b0aba237
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Item_Casings_Abstract.java
@@ -0,0 +1,63 @@
+package gregtech.common.blocks;
+
+import java.util.List;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemBlock;
+import net.minecraft.item.ItemStack;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.util.GT_LanguageManager;
+
+public abstract class GT_Item_Casings_Abstract extends ItemBlock {
+
+ protected final String mNoMobsToolTip = GT_LanguageManager
+ .addStringLocalization("gt.nomobspawnsonthisblock", "Mobs cannot Spawn on this Block");
+ protected final String mNoTileEntityToolTip = GT_LanguageManager
+ .addStringLocalization("gt.notileentityinthisblock", "This is NOT a TileEntity!");
+ protected final String mCoil01Tooltip = GT_LanguageManager
+ .addStringLocalization("gt.coil01tooltip", "Base Heating Capacity = 1800 Kelvin");
+ protected final String mCoil02Tooltip = GT_LanguageManager
+ .addStringLocalization("gt.coil02tooltip", "Base Heating Capacity = 2700 Kelvin");
+ protected final String mCoil03Tooltip = GT_LanguageManager
+ .addStringLocalization("gt.coil03tooltip", "Base Heating Capacity = 3600 Kelvin");
+ protected final String mCoil04Tooltip = GT_LanguageManager
+ .addStringLocalization("gt.coil04tooltip", "Base Heating Capacity = 4500 Kelvin");
+ protected final String mCoil05Tooltip = GT_LanguageManager
+ .addStringLocalization("gt.coil05tooltip", "Base Heating Capacity = 5400 Kelvin");
+ protected final String mCoil06Tooltip = GT_LanguageManager
+ .addStringLocalization("gt.coil06tooltip", "Base Heating Capacity = 7200 Kelvin");
+ protected final String mCoil07Tooltip = GT_LanguageManager
+ .addStringLocalization("gt.coil07tooltip", "Base Heating Capacity = 9001 Kelvin");
+ protected final String mCoil08Tooltip = GT_LanguageManager
+ .addStringLocalization("gt.coil08tooltip", "Base Heating Capacity = 9900 Kelvin");
+ protected final String mCoil09Tooltip = GT_LanguageManager
+ .addStringLocalization("gt.coil09tooltip", "Base Heating Capacity = 10800 Kelvin");
+ protected final String mBlastProofTooltip = GT_LanguageManager
+ .addStringLocalization("gt.blastprooftooltip", "This Block is Blast Proof");
+
+ public GT_Item_Casings_Abstract(Block block) {
+ super(block);
+ setMaxDamage(0);
+ setHasSubtypes(true);
+ setCreativeTab(GregTech_API.TAB_GREGTECH_MATERIALS);
+ }
+
+ @Override
+ public int getMetadata(int aMeta) {
+ return aMeta;
+ }
+
+ @Override
+ public String getUnlocalizedName(ItemStack aStack) {
+ return this.field_150939_a.getUnlocalizedName() + "." + getDamage(aStack);
+ }
+
+ @Override
+ public void addInformation(ItemStack aStack, EntityPlayer aPlayer, List<String> aList, boolean aF3_H) {
+ super.addInformation(aStack, aPlayer, aList, aF3_H);
+ aList.add(this.mNoMobsToolTip);
+ aList.add(this.mNoTileEntityToolTip);
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Item_Concretes.java b/src/main/java/gregtech/common/blocks/GT_Item_Concretes.java
new file mode 100644
index 0000000000..44c094aa41
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Item_Concretes.java
@@ -0,0 +1,25 @@
+package gregtech.common.blocks;
+
+import java.util.List;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+
+import gregtech.api.util.GT_LanguageManager;
+
+public class GT_Item_Concretes extends GT_Item_Stones_Abstract {
+
+ private final String mRunFasterToolTip = GT_LanguageManager
+ .addStringLocalization("gt.runfastertooltip", "You can walk faster on this Block");
+
+ public GT_Item_Concretes(Block block) {
+ super(block);
+ }
+
+ @Override
+ public void addInformation(ItemStack aStack, EntityPlayer aPlayer, List<String> aList, boolean aF3_H) {
+ super.addInformation(aStack, aPlayer, aList, aF3_H);
+ aList.add(this.mRunFasterToolTip);
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Item_Granites.java b/src/main/java/gregtech/common/blocks/GT_Item_Granites.java
new file mode 100644
index 0000000000..6e3eb8f12c
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Item_Granites.java
@@ -0,0 +1,10 @@
+package gregtech.common.blocks;
+
+import net.minecraft.block.Block;
+
+public class GT_Item_Granites extends GT_Item_Stones_Abstract {
+
+ public GT_Item_Granites(Block block) {
+ super(block);
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Item_LongDistancePipe.java b/src/main/java/gregtech/common/blocks/GT_Item_LongDistancePipe.java
new file mode 100644
index 0000000000..52d0db5165
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Item_LongDistancePipe.java
@@ -0,0 +1,43 @@
+package gregtech.common.blocks;
+
+import java.util.List;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemBlock;
+import net.minecraft.item.ItemStack;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.util.GT_LanguageManager;
+
+public class GT_Item_LongDistancePipe extends ItemBlock {
+
+ protected final String mNoMobsToolTip = GT_LanguageManager
+ .addStringLocalization("gt.nomobspawnsonthisblock", "Mobs cannot Spawn on this Block");
+ protected final String mNoTileEntityToolTip = GT_LanguageManager
+ .addStringLocalization("gt.notileentityinthisblock", "This is NOT a TileEntity!");
+
+ public GT_Item_LongDistancePipe(Block block) {
+ super(block);
+ setMaxDamage(0);
+ setHasSubtypes(true);
+ setCreativeTab(GregTech_API.TAB_GREGTECH_MATERIALS);
+ }
+
+ @Override
+ public int getMetadata(int aMeta) {
+ return aMeta;
+ }
+
+ @Override
+ public String getUnlocalizedName(ItemStack aStack) {
+ return this.field_150939_a.getUnlocalizedName() + "." + getDamage(aStack);
+ }
+
+ @Override
+ public void addInformation(ItemStack aStack, EntityPlayer aPlayer, List<String> aList, boolean aF3_H) {
+ super.addInformation(aStack, aPlayer, aList, aF3_H);
+ aList.add(this.mNoMobsToolTip);
+ aList.add(this.mNoTileEntityToolTip);
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Item_Machines.java b/src/main/java/gregtech/common/blocks/GT_Item_Machines.java
new file mode 100644
index 0000000000..059a3fda94
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Item_Machines.java
@@ -0,0 +1,430 @@
+package gregtech.common.blocks;
+
+import static gregtech.GT_Mod.GT_FML_LOGGER;
+
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemBlock;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.potion.Potion;
+import net.minecraft.potion.PotionEffect;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidRegistry;
+import net.minecraftforge.fluids.FluidStack;
+import net.minecraftforge.fluids.IFluidContainerItem;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.Dyes;
+import gregtech.api.enums.Materials;
+import gregtech.api.interfaces.ISecondaryDescribable;
+import gregtech.api.interfaces.metatileentity.IConnectable;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.CoverableTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaPipeEntity_Cable;
+import gregtech.api.metatileentity.implementations.GT_MetaPipeEntity_Fluid;
+import gregtech.api.metatileentity.implementations.GT_MetaPipeEntity_Frame;
+import gregtech.api.metatileentity.implementations.GT_MetaPipeEntity_Item;
+import gregtech.api.util.GT_ItsNotMyFaultException;
+import gregtech.api.util.GT_LanguageManager;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.tileentities.storage.GT_MetaTileEntity_DigitalTankBase;
+import gregtech.common.tileentities.storage.GT_MetaTileEntity_SuperChest;
+import gregtech.common.tileentities.storage.GT_MetaTileEntity_SuperTank;
+
+public class GT_Item_Machines extends ItemBlock implements IFluidContainerItem {
+
+ public GT_Item_Machines(Block block) {
+ super(block);
+ setMaxDamage(0);
+ setHasSubtypes(true);
+ setCreativeTab(GregTech_API.TAB_GREGTECH);
+ }
+
+ public static IMetaTileEntity getMetaTileEntity(ItemStack aStack) {
+ if (GT_Utility.isStackInvalid(aStack)) return null;
+ if (!(aStack.getItem() instanceof GT_Item_Machines)) return null;
+ if (aStack.getItemDamage() < 0 || aStack.getItemDamage() > GregTech_API.METATILEENTITIES.length) return null;
+ return GregTech_API.METATILEENTITIES[aStack.getItemDamage()];
+ }
+
+ @Override
+ public void addInformation(ItemStack aStack, EntityPlayer aPlayer, List<String> aList, boolean aF3_H) {
+ try {
+ final int tDamage = getDamage(aStack);
+ if ((tDamage <= 0) || (tDamage >= GregTech_API.METATILEENTITIES.length)) {
+ return;
+ }
+
+ if (GregTech_API.METATILEENTITIES[tDamage] != null) {
+ final IGregTechTileEntity tTileEntity = GregTech_API.METATILEENTITIES[tDamage].getBaseMetaTileEntity();
+ if (!GregTech_API.sPostloadFinished
+ && tTileEntity.getMetaTileEntity() instanceof ISecondaryDescribable) {
+ final String[] tSecondaryDescription = ((ISecondaryDescribable) tTileEntity.getMetaTileEntity())
+ .getSecondaryDescription();
+ addDescription(null, tSecondaryDescription, tDamage, "_Secondary");
+ }
+ {
+ final IMetaTileEntity tMetaTileEntity = tTileEntity.getMetaTileEntity();
+ final String tSuffix = (tMetaTileEntity instanceof ISecondaryDescribable
+ && ((ISecondaryDescribable) tMetaTileEntity).isDisplaySecondaryDescription()) ? "_Secondary"
+ : "";
+ addDescription(aList, tTileEntity.getDescription(), tDamage, tSuffix);
+ tMetaTileEntity.addAdditionalTooltipInformation(aStack, aList);
+ }
+ if (tTileEntity.getEUCapacity() > 0L) {
+ if (tTileEntity.getInputVoltage() > 0L) {
+ final byte inputTier = GT_Utility.getTier(tTileEntity.getInputVoltage());
+ aList.add(
+ GT_LanguageManager.addStringLocalization("TileEntity_EUp_IN", "Voltage IN: ")
+ + EnumChatFormatting.GREEN
+ + GT_Utility.formatNumbers(tTileEntity.getInputVoltage())
+ + " ("
+ + GT_Utility.getColoredTierNameFromTier(inputTier)
+ + EnumChatFormatting.GREEN
+ + ")"
+ + EnumChatFormatting.GRAY);
+ }
+ if (tTileEntity.getOutputVoltage() > 0L) {
+ final byte outputTier = GT_Utility.getTier(tTileEntity.getOutputVoltage());
+ aList.add(
+ GT_LanguageManager.addStringLocalization("TileEntity_EUp_OUT", "Voltage OUT: ")
+ + EnumChatFormatting.GREEN
+ + GT_Utility.formatNumbers(tTileEntity.getOutputVoltage())
+ + " ("
+ + GT_Utility.getColoredTierNameFromTier(outputTier)
+ + EnumChatFormatting.GREEN
+ + ")"
+ + EnumChatFormatting.GRAY);
+ }
+ if (tTileEntity.getOutputAmperage() > 1L) {
+ aList.add(
+ GT_LanguageManager.addStringLocalization("TileEntity_EUp_AMOUNT", "Amperage: ")
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(tTileEntity.getOutputAmperage())
+ + EnumChatFormatting.GRAY);
+ }
+ aList.add(
+ GT_LanguageManager.addStringLocalization("TileEntity_EUp_STORE", "Capacity: ")
+ + EnumChatFormatting.BLUE
+ + GT_Utility.formatNumbers(tTileEntity.getEUCapacity())
+ + EnumChatFormatting.GRAY
+ + " EU");
+ }
+ }
+ final NBTTagCompound aNBT = aStack.getTagCompound();
+ if (aNBT != null) {
+ if (aNBT.getBoolean("mMuffler")) {
+ aList.add(GT_LanguageManager.addStringLocalization("GT_TileEntity_MUFFLER", "has Muffler Upgrade"));
+ }
+ if (aNBT.getBoolean("mSteamConverter")) {
+ aList.add(
+ GT_LanguageManager.addStringLocalization("GT_TileEntity_STEAMCONVERTER", "has Steam Upgrade"));
+ }
+ int tAmount = 0;
+ if ((tAmount = aNBT.getByte("mSteamTanks")) > 0) {
+ aList.add(
+ tAmount + " "
+ + GT_LanguageManager
+ .addStringLocalization("GT_TileEntity_STEAMTANKS", "Steam Tank Upgrades"));
+ }
+
+ CoverableTileEntity.addInstalledCoversInformation(aNBT, aList);
+ if (aNBT.hasKey("mColor") && aNBT.getByte("mColor") != -1) {
+ aList.add(
+ GT_LanguageManager.addStringLocalization("GT_TileEntity_COLORED", "Colored") + " ("
+ + Dyes.get(aNBT.getByte("mColor") - 1).formatting
+ + Dyes.get(aNBT.getByte("mColor") - 1).mName
+ + EnumChatFormatting.GRAY
+ + ")");
+ }
+ }
+ } catch (Throwable e) {
+ GT_FML_LOGGER.error("addInformation", e);
+ }
+ }
+
+ private void addDescription(@Nullable List<String> aList, @Nullable String[] aDescription, int aDamage,
+ String aSuffix) {
+ if (aDescription == null) return;
+ for (int i = 0, tLength = aDescription.length; i < tLength; i++) {
+ String tDescLine = aDescription[i];
+ if (!GT_Utility.isStringValid(tDescLine)) continue;
+
+ String tKey = String.format("TileEntity_DESCRIPTION_%05d%s_Index_%02d", aDamage, aSuffix, i);
+ if (tDescLine.contains("%%%")) {
+ final String[] tSplitStrings = tDescLine.split("%%%");
+ final StringBuilder tBuffer = new StringBuilder();
+ final String[] tRep = new String[tSplitStrings.length / 2];
+ for (int j = 0; j < tSplitStrings.length; j++) if (j % 2 == 0) tBuffer.append(tSplitStrings[j]);
+ else {
+ tBuffer.append("%s");
+ tRep[j / 2] = tSplitStrings[j];
+ }
+ final String tTranslated = String
+ .format(GT_LanguageManager.addStringLocalization(tKey, tBuffer.toString()), (Object[]) tRep);
+ if (aList != null) aList.add(tTranslated);
+ } else {
+ String tTranslated = GT_LanguageManager.addStringLocalization(tKey, tDescLine);
+ if (aList != null) aList.add(tTranslated.equals("") ? tDescLine : tTranslated);
+ }
+ }
+ }
+
+ @SideOnly(Side.CLIENT)
+ public void registerDescription(int aDamage) {
+ if (aDamage >= GregTech_API.METATILEENTITIES.length) return;
+ if (GregTech_API.METATILEENTITIES[aDamage] != null) {
+ final IMetaTileEntity tMetaTileEntity = GregTech_API.METATILEENTITIES[aDamage].getBaseMetaTileEntity()
+ .getMetaTileEntity();
+ if (tMetaTileEntity instanceof ISecondaryDescribable) {
+ final String[] tSecondaryDescription = ((ISecondaryDescribable) tMetaTileEntity)
+ .getSecondaryDescription();
+ addDescription(null, tSecondaryDescription, aDamage, "_Secondary");
+ }
+ addDescription(null, tMetaTileEntity.getDescription(), aDamage, "");
+ }
+ }
+
+ @Override
+ public boolean onItemUseFirst(ItemStack stack, EntityPlayer player, World world, int x, int y, int z,
+ int ordinalSide, float hitX, float hitY, float hitZ) {
+ return false;
+ }
+
+ @Override
+ public String getUnlocalizedName(ItemStack aStack) {
+ final short tDamage = (short) getDamage(aStack);
+ if ((tDamage < 0) || (tDamage >= GregTech_API.METATILEENTITIES.length)) {
+ return "";
+ }
+ if (GregTech_API.METATILEENTITIES[tDamage] != null) {
+ return getUnlocalizedName() + "." + GregTech_API.METATILEENTITIES[tDamage].getMetaName();
+ }
+ return "";
+ }
+
+ @Override
+ public String getItemStackDisplayName(ItemStack aStack) {
+ String aName = super.getItemStackDisplayName(aStack);
+ final short aDamage = (short) getDamage(aStack);
+ if (aDamage >= 0 && aDamage < GregTech_API.METATILEENTITIES.length
+ && GregTech_API.METATILEENTITIES[aDamage] != null) {
+ Materials aMaterial = null;
+ if (GregTech_API.METATILEENTITIES[aDamage] instanceof GT_MetaPipeEntity_Item) {
+ aMaterial = ((GT_MetaPipeEntity_Item) GregTech_API.METATILEENTITIES[aDamage]).mMaterial;
+ } else if (GregTech_API.METATILEENTITIES[aDamage] instanceof GT_MetaPipeEntity_Fluid) {
+ aMaterial = ((GT_MetaPipeEntity_Fluid) GregTech_API.METATILEENTITIES[aDamage]).mMaterial;
+ } else if (GregTech_API.METATILEENTITIES[aDamage] instanceof GT_MetaPipeEntity_Cable) {
+ aMaterial = ((GT_MetaPipeEntity_Cable) GregTech_API.METATILEENTITIES[aDamage]).mMaterial;
+ } else if (GregTech_API.METATILEENTITIES[aDamage] instanceof GT_MetaPipeEntity_Frame) {
+ aMaterial = ((GT_MetaPipeEntity_Frame) GregTech_API.METATILEENTITIES[aDamage]).mMaterial;
+ }
+ if (aMaterial != null) {
+ aName = aMaterial.getLocalizedNameForItem(aName);
+ }
+ }
+ return aName;
+ }
+
+ @Override
+ public void onCreated(ItemStack aStack, World aWorld, EntityPlayer aPlayer) {
+ super.onCreated(aStack, aWorld, aPlayer);
+ final short tDamage = (short) getDamage(aStack);
+ if ((tDamage < 0) || ((tDamage >= GregTech_API.METATILEENTITIES.length)
+ && (GregTech_API.METATILEENTITIES[tDamage] != null))) {
+ GregTech_API.METATILEENTITIES[tDamage].onCreated(aStack, aWorld, aPlayer);
+ }
+ }
+
+ @Override
+ public boolean placeBlockAt(ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX, int aY, int aZ,
+ int ordinalSide, float hitX, float hitY, float hitZ, int aMeta) {
+ final ForgeDirection side = ForgeDirection.getOrientation(ordinalSide);
+ final short tDamage = (short) getDamage(aStack);
+ if (tDamage > 0) {
+ if (GregTech_API.METATILEENTITIES[tDamage] == null) {
+ return false;
+ }
+ final int tMetaData = GregTech_API.METATILEENTITIES[tDamage].getTileEntityBaseType();
+ if (!aWorld.setBlock(aX, aY, aZ, this.field_150939_a, tMetaData, 3)) {
+ return false;
+ }
+ if (aWorld.getBlock(aX, aY, aZ) != this.field_150939_a) {
+ throw new GT_ItsNotMyFaultException(
+ "Failed to place Block even though World.setBlock returned true. It COULD be MCPC/Bukkit causing that. In case you really have that installed, don't report this Bug to me, I don't know how to fix it.");
+ }
+ if (aWorld.getBlockMetadata(aX, aY, aZ) != tMetaData) {
+ throw new GT_ItsNotMyFaultException(
+ "Failed to set the MetaValue of the Block even though World.setBlock returned true. It COULD be MCPC/Bukkit causing that. In case you really have that installed, don't report this Bug to me, I don't know how to fix it.");
+ }
+ final IGregTechTileEntity tTileEntity = (IGregTechTileEntity) aWorld.getTileEntity(aX, aY, aZ);
+ if (tTileEntity != null) {
+ tTileEntity.setInitialValuesAsNBT(tTileEntity.isServerSide() ? aStack.getTagCompound() : null, tDamage);
+ if (aPlayer != null) {
+ tTileEntity.setOwnerName(aPlayer.getDisplayName());
+ tTileEntity.setOwnerUuid(aPlayer.getUniqueID());
+ }
+ tTileEntity.getMetaTileEntity()
+ .initDefaultModes(aStack.getTagCompound());
+ final ForgeDirection oppositeSide = side.getOpposite();
+ if (tTileEntity.getMetaTileEntity() instanceof IConnectable connectable) {
+ // If we're connectable, try connecting to whatever we're up against
+ connectable.connect(oppositeSide);
+ } else if (aPlayer != null && aPlayer.isSneaking()) {
+ // If we're being placed against something that is connectable, try telling it to connect to us
+ final IGregTechTileEntity aTileEntity = tTileEntity.getIGregTechTileEntityAtSide(oppositeSide);
+ if (aTileEntity != null && aTileEntity.getMetaTileEntity() instanceof IConnectable connectable) {
+ connectable.connect(side);
+ }
+ }
+ }
+ } else if (!aWorld.setBlock(aX, aY, aZ, this.field_150939_a, tDamage, 3)) {
+ return false;
+ }
+ if (aWorld.getBlock(aX, aY, aZ) == this.field_150939_a) {
+ this.field_150939_a.onBlockPlacedBy(aWorld, aX, aY, aZ, aPlayer, aStack);
+ this.field_150939_a.onPostBlockPlaced(aWorld, aX, aY, aZ, tDamage);
+ }
+ return true;
+ }
+
+ @Override
+ public void onUpdate(ItemStack aStack, World aWorld, Entity aPlayer, int aTimer, boolean aIsInHand) {
+ super.onUpdate(aStack, aWorld, aPlayer, aTimer, aIsInHand);
+ final short tDamage = (short) getDamage(aStack);
+ final EntityLivingBase tPlayer = (EntityPlayer) aPlayer;
+ if (GregTech_API.METATILEENTITIES[tDamage] instanceof GT_MetaTileEntity_SuperChest
+ || GregTech_API.METATILEENTITIES[tDamage] instanceof GT_MetaTileEntity_SuperTank) {
+ final NBTTagCompound tNBT = aStack.stackTagCompound;
+ if (tNBT == null) return;
+ if (tNBT.hasNoTags()) {
+ aStack.setTagCompound(null);
+ return;
+ }
+ if ((tNBT.hasKey("mItemCount") && tNBT.getInteger("mItemCount") > 0) || (tNBT.hasKey("mFluid")
+ && FluidStack.loadFluidStackFromNBT(tNBT.getCompoundTag("mFluid")).amount > 64000)) {
+ final FluidStack tFluid = FluidStack.loadFluidStackFromNBT(tNBT.getCompoundTag("mFluid"));
+ int tEffectDuration = 1200;
+ if (tFluid != null) {
+ final double tFluidAmount = tFluid.amount;
+ final double tMiddlePoint = 4096000;
+ final double tSmoothingCoefficient = 2000000;
+ final int tMaxDuration = 12000;
+ final double tmp = (tFluidAmount - tMiddlePoint) / tSmoothingCoefficient;
+ tEffectDuration = (int) (Math.exp(tmp) / (Math.exp(tmp) + Math.exp(-tmp)) * tMaxDuration);
+ }
+ tPlayer.addPotionEffect(new PotionEffect(Potion.hunger.id, tEffectDuration, 1));
+ tPlayer.addPotionEffect(new PotionEffect(Potion.moveSlowdown.id, tEffectDuration, 1));
+ tPlayer.addPotionEffect(new PotionEffect(Potion.digSlowdown.id, tEffectDuration, 1));
+ tPlayer.addPotionEffect(new PotionEffect(Potion.weakness.id, tEffectDuration, 1));
+ }
+ }
+ }
+
+ @Override
+ public FluidStack getFluid(ItemStack container) {
+ if (container != null) {
+ final NBTTagCompound tNBT = container.stackTagCompound;
+ if (tNBT != null && tNBT.hasKey("mFluid", 10)) {
+ return FluidStack.loadFluidStackFromNBT(tNBT.getCompoundTag("mFluid"));
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public int getCapacity(ItemStack container) {
+ if (container != null) {
+ final int tDamage = container.getItemDamage();
+ final IMetaTileEntity tMetaTile = GregTech_API.METATILEENTITIES[tDamage];
+ if (tMetaTile != null) return tMetaTile.getCapacity();
+ }
+ return 0;
+ }
+
+ @Nullable
+ private Fluid getLockedFluid(@Nonnull ItemStack container) {
+ final NBTTagCompound tag = container.stackTagCompound;
+ if (tag == null) return null;
+ String lockedName = tag.getString("lockedFluidName");
+ if (GT_Utility.isStringInvalid(lockedName)) return null;
+ return FluidRegistry.getFluid(lockedName);
+ }
+
+ @Override
+ public int fill(ItemStack container, FluidStack resource, boolean doFill) {
+ if (container != null && resource != null) {
+ final int tDamage = container.getItemDamage();
+ final IMetaTileEntity tMetaTile = GregTech_API.METATILEENTITIES[tDamage];
+ if (!(tMetaTile instanceof GT_MetaTileEntity_DigitalTankBase)) {
+ return 0;
+ }
+ if (container.stackTagCompound == null) container.stackTagCompound = new NBTTagCompound();
+ final FluidStack tStoredFluid = getFluid(container);
+ final int tCapacity = getCapacity(container);
+ if (tCapacity <= 0) return 0;
+ final Fluid lockedFluid = getLockedFluid(container);
+ if (lockedFluid != null && resource.getFluid() != lockedFluid) {
+ return 0;
+ }
+ if (tStoredFluid != null && tStoredFluid.isFluidEqual(resource)) {
+ final int tAmount = Math.min(tCapacity - tStoredFluid.amount, resource.amount);
+ if (doFill) {
+ final FluidStack tNewFluid = new FluidStack(tStoredFluid, tAmount + tStoredFluid.amount);
+ container.stackTagCompound.setTag("mFluid", tNewFluid.writeToNBT(new NBTTagCompound()));
+ }
+ return tAmount;
+ }
+ if (tStoredFluid == null) {
+ final int tAmount = Math.min(tCapacity, resource.amount);
+ if (doFill) {
+ final FluidStack tNewFluid = new FluidStack(resource, tAmount);
+ container.stackTagCompound.setTag("mFluid", tNewFluid.writeToNBT(new NBTTagCompound()));
+ }
+ return tAmount;
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public FluidStack drain(ItemStack container, int maxDrain, boolean doDrain) {
+ if (container != null && container.hasTagCompound()) {
+ final int tDamage = container.getItemDamage();
+ final IMetaTileEntity tMetaTile = GregTech_API.METATILEENTITIES[tDamage];
+ if (!(tMetaTile instanceof GT_MetaTileEntity_DigitalTankBase)) {
+ return null;
+ }
+ final FluidStack tStoredFluid = getFluid(container);
+ if (tStoredFluid != null) {
+ final int tAmount = Math.min(maxDrain, tStoredFluid.amount);
+ final FluidStack tNewFluid = new FluidStack(tStoredFluid, tStoredFluid.amount - tAmount);
+ final FluidStack tOutputFluid = new FluidStack(tStoredFluid, tAmount);
+ if (doDrain) {
+ if (tNewFluid.amount <= 0) {
+ container.stackTagCompound.removeTag("mFluid");
+ if (container.stackTagCompound.hasNoTags()) container.setTagCompound(null);
+ } else {
+ container.stackTagCompound.setTag("mFluid", tNewFluid.writeToNBT(new NBTTagCompound()));
+ }
+ }
+ return tOutputFluid;
+ }
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Item_Ores.java b/src/main/java/gregtech/common/blocks/GT_Item_Ores.java
new file mode 100644
index 0000000000..2ba78572b3
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Item_Ores.java
@@ -0,0 +1,81 @@
+package gregtech.common.blocks;
+
+import java.util.List;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemBlock;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.StatCollector;
+import net.minecraft.world.World;
+
+import org.apache.commons.lang3.StringUtils;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.Materials;
+
+public class GT_Item_Ores extends ItemBlock {
+
+ public GT_Item_Ores(Block block) {
+ super(block);
+ setMaxDamage(0);
+ setHasSubtypes(true);
+ setCreativeTab(GregTech_API.TAB_GREGTECH_MATERIALS);
+ }
+
+ @Override
+ public boolean onItemUseFirst(ItemStack stack, EntityPlayer player, World world, int x, int y, int z,
+ int ordinalSide, float hitX, float hitY, float hitZ) {
+ return false;
+ }
+
+ @Override
+ public String getUnlocalizedName(ItemStack aStack) {
+ return this.field_150939_a.getUnlocalizedName() + "." + getDamage(aStack);
+ }
+
+ @Override
+ public String getItemStackDisplayName(ItemStack aStack) {
+ String aName = super.getItemStackDisplayName(aStack);
+ if (this.field_150939_a instanceof GT_Block_Ores_Abstract) {
+ aName = Materials.getLocalizedNameForItem(aName, aStack.getItemDamage() % 1000);
+ }
+ return aName;
+ }
+
+ @Override
+ public boolean placeBlockAt(ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX, int aY, int aZ,
+ int ordinalSide, float hitX, float hitY, float hitZ, int aMeta) {
+ short tDamage = (short) getDamage(aStack);
+ if (tDamage > 0) {
+ if (!aWorld.setBlock(
+ aX,
+ aY,
+ aZ,
+ this.field_150939_a,
+ GT_TileEntity_Ores.getHarvestData(
+ tDamage,
+ ((GT_Block_Ores_Abstract) field_150939_a).getBaseBlockHarvestLevel(aMeta % 16000 / 1000)),
+ 3)) {
+ return false;
+ }
+ GT_TileEntity_Ores tTileEntity = (GT_TileEntity_Ores) aWorld.getTileEntity(aX, aY, aZ);
+ tTileEntity.mMetaData = tDamage;
+ tTileEntity.mNatural = false;
+ } else if (!aWorld.setBlock(aX, aY, aZ, this.field_150939_a, 0, 3)) {
+ return false;
+ }
+ if (aWorld.getBlock(aX, aY, aZ) == this.field_150939_a) {
+ this.field_150939_a.onBlockPlacedBy(aWorld, aX, aY, aZ, aPlayer, aStack);
+ this.field_150939_a.onPostBlockPlaced(aWorld, aX, aY, aZ, tDamage);
+ }
+ return true;
+ }
+
+ @Override
+ public void addInformation(ItemStack aStack, EntityPlayer aPlayer, List<String> aList, boolean aF3_H) {
+ String formula = StatCollector
+ .translateToLocal(field_150939_a.getUnlocalizedName() + '.' + getDamage(aStack) + ".tooltip");
+ if (!StringUtils.isBlank(formula)) aList.add(formula);
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Item_Stones_Abstract.java b/src/main/java/gregtech/common/blocks/GT_Item_Stones_Abstract.java
new file mode 100644
index 0000000000..5b73108301
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Item_Stones_Abstract.java
@@ -0,0 +1,42 @@
+package gregtech.common.blocks;
+
+import java.util.List;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemBlock;
+import net.minecraft.item.ItemStack;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.util.GT_LanguageManager;
+
+public class GT_Item_Stones_Abstract extends ItemBlock {
+
+ private final String mNoMobsToolTip = GT_LanguageManager
+ .addStringLocalization("gt.nomobspawnsonthisblock", "Mobs cannot Spawn on this Block");
+
+ public GT_Item_Stones_Abstract(Block block) {
+ super(block);
+ setMaxDamage(0);
+ setHasSubtypes(true);
+ setCreativeTab(GregTech_API.TAB_GREGTECH_MATERIALS);
+ }
+
+ @Override
+ public String getUnlocalizedName(ItemStack aStack) {
+ return this.field_150939_a.getUnlocalizedName() + "." + getDamage(aStack);
+ }
+
+ @Override
+ public int getMetadata(int aMeta) {
+ return aMeta;
+ }
+
+ @Override
+ public void addInformation(ItemStack aStack, EntityPlayer aPlayer, List<String> aList, boolean aF3_H) {
+ super.addInformation(aStack, aPlayer, aList, aF3_H);
+ if (aStack.getItemDamage() % 8 >= 3) {
+ aList.add(this.mNoMobsToolTip);
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Item_Storage.java b/src/main/java/gregtech/common/blocks/GT_Item_Storage.java
new file mode 100644
index 0000000000..4ac1b9cdfd
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Item_Storage.java
@@ -0,0 +1,47 @@
+package gregtech.common.blocks;
+
+import java.util.List;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemBlock;
+import net.minecraft.item.ItemStack;
+
+import gregtech.api.GregTech_API;
+
+public class GT_Item_Storage extends ItemBlock {
+
+ public GT_Item_Storage(Block block) {
+ super(block);
+ setMaxDamage(0);
+ setHasSubtypes(true);
+ setCreativeTab(GregTech_API.TAB_GREGTECH_MATERIALS);
+ }
+
+ @Override
+ public String getUnlocalizedName(ItemStack aStack) {
+ return this.field_150939_a.getUnlocalizedName() + "." + getDamage(aStack);
+ }
+
+ @Override
+ public String getItemStackDisplayName(ItemStack aStack) {
+ String aName = super.getItemStackDisplayName(aStack);
+ if (this.field_150939_a instanceof GT_Block_Metal) {
+ int aDamage = aStack.getItemDamage();
+ if (aDamage >= 0 && aDamage < ((GT_Block_Metal) this.field_150939_a).mMats.length) {
+ aName = ((GT_Block_Metal) this.field_150939_a).mMats[aDamage].getLocalizedNameForItem(aName);
+ }
+ }
+ return aName;
+ }
+
+ @Override
+ public int getMetadata(int aMeta) {
+ return aMeta;
+ }
+
+ @Override
+ public void addInformation(ItemStack aStack, EntityPlayer aPlayer, List<String> aList, boolean aF3_H) {
+ super.addInformation(aStack, aPlayer, aList, aF3_H);
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Material_Casings.java b/src/main/java/gregtech/common/blocks/GT_Material_Casings.java
new file mode 100644
index 0000000000..2fc839768f
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Material_Casings.java
@@ -0,0 +1,19 @@
+package gregtech.common.blocks;
+
+import net.minecraft.block.material.MapColor;
+import net.minecraft.block.material.Material;
+
+public class GT_Material_Casings extends Material {
+
+ public static final Material INSTANCE = new GT_Material_Casings();
+
+ private GT_Material_Casings() {
+ super(MapColor.ironColor);
+ setRequiresTool();
+ }
+
+ @Override
+ public boolean isOpaque() {
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Material_Machines.java b/src/main/java/gregtech/common/blocks/GT_Material_Machines.java
new file mode 100644
index 0000000000..df8b57226c
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Material_Machines.java
@@ -0,0 +1,19 @@
+package gregtech.common.blocks;
+
+import net.minecraft.block.material.MapColor;
+import net.minecraft.block.material.Material;
+
+public class GT_Material_Machines extends Material {
+
+ public GT_Material_Machines() {
+ super(MapColor.ironColor);
+ setRequiresTool();
+ setImmovableMobility();
+ setAdventureModeExempt();
+ }
+
+ @Override
+ public boolean isOpaque() {
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Material_Reinforced.java b/src/main/java/gregtech/common/blocks/GT_Material_Reinforced.java
new file mode 100644
index 0000000000..2e3301bb60
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Material_Reinforced.java
@@ -0,0 +1,18 @@
+package gregtech.common.blocks;
+
+import net.minecraft.block.material.MapColor;
+import net.minecraft.block.material.Material;
+
+public class GT_Material_Reinforced extends Material {
+
+ public GT_Material_Reinforced() {
+ super(MapColor.stoneColor);
+ setRequiresTool();
+ setAdventureModeExempt();
+ }
+
+ @Override
+ public boolean isOpaque() {
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_Packet_Ores.java b/src/main/java/gregtech/common/blocks/GT_Packet_Ores.java
new file mode 100644
index 0000000000..d7ab28a19e
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_Packet_Ores.java
@@ -0,0 +1,61 @@
+package gregtech.common.blocks;
+
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.world.IBlockAccess;
+import net.minecraft.world.World;
+
+import com.google.common.io.ByteArrayDataInput;
+
+import gregtech.api.net.GT_Packet_New;
+import io.netty.buffer.ByteBuf;
+
+public class GT_Packet_Ores extends GT_Packet_New {
+
+ private int mX;
+ private int mZ;
+ private short mY;
+ private short mMetaData;
+
+ public GT_Packet_Ores() {
+ super(true);
+ }
+
+ public GT_Packet_Ores(int aX, short aY, int aZ, short aMetaData) {
+ super(false);
+ this.mX = aX;
+ this.mY = aY;
+ this.mZ = aZ;
+ this.mMetaData = aMetaData;
+ }
+
+ @Override
+ public void encode(ByteBuf aOut) {
+ aOut.writeInt(this.mX);
+ aOut.writeShort(this.mY);
+ aOut.writeInt(this.mZ);
+ aOut.writeShort(this.mMetaData);
+ }
+
+ @Override
+ public GT_Packet_New decode(ByteArrayDataInput aData) {
+ return new GT_Packet_Ores(aData.readInt(), aData.readShort(), aData.readInt(), aData.readShort());
+ }
+
+ @Override
+ public void process(IBlockAccess aWorld) {
+ if (aWorld != null) {
+ TileEntity tTileEntity = aWorld.getTileEntity(this.mX, this.mY, this.mZ);
+ if ((tTileEntity instanceof GT_TileEntity_Ores)) {
+ ((GT_TileEntity_Ores) tTileEntity).mMetaData = this.mMetaData;
+ }
+ if (((aWorld instanceof World)) && (((World) aWorld).isRemote)) {
+ ((World) aWorld).markBlockForUpdate(this.mX, this.mY, this.mZ);
+ }
+ }
+ }
+
+ @Override
+ public byte getPacketID() {
+ return 3;
+ }
+}
diff --git a/src/main/java/gregtech/common/blocks/GT_TileEntity_Ores.java b/src/main/java/gregtech/common/blocks/GT_TileEntity_Ores.java
new file mode 100644
index 0000000000..f3d247a265
--- /dev/null
+++ b/src/main/java/gregtech/common/blocks/GT_TileEntity_Ores.java
@@ -0,0 +1,485 @@
+package gregtech.common.blocks;
+
+import static gregtech.api.enums.TextureSet.SET_NONE;
+
+import java.util.ArrayList;
+import java.util.Random;
+
+import net.minecraft.block.Block;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.network.Packet;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.world.World;
+
+import org.jetbrains.annotations.NotNull;
+
+import gregtech.GT_Mod;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IAllSidedTexturedTileEntity;
+import gregtech.api.objects.XSTR;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_OreDictUnificator;
+import gregtech.api.util.GT_Utility;
+
+public class GT_TileEntity_Ores extends TileEntity implements IAllSidedTexturedTileEntity {
+
+ public short mMetaData = 0;
+ protected static boolean shouldFortune = false;
+ protected static boolean shouldSilkTouch = false;
+ public boolean mNatural = false;
+ public boolean mBlocked = true;
+ public boolean mBlockedChecked = false;
+ private short mMetadataForCachedTexture = -1;
+ private ITexture[] mCachedTexture;
+
+ public static byte getHarvestData(short aMetaData, int aBaseBlockHarvestLevel) {
+ Materials aMaterial = GregTech_API.sGeneratedMaterials[(aMetaData % 1000)];
+ byte tByte = aMaterial == null ? 0
+ : (byte) Math
+ .max(aBaseBlockHarvestLevel, Math.min(7, aMaterial.mToolQuality - (aMetaData < 16000 ? 0 : 1)));
+ if (GT_Mod.gregtechproxy.mChangeHarvestLevels) {
+ tByte = aMaterial == null ? 0
+ : (byte) Math.max(
+ aBaseBlockHarvestLevel,
+ Math.min(
+ GT_Mod.gregtechproxy.mMaxHarvestLevel,
+ GT_Mod.gregtechproxy.mHarvestLevel[aMaterial.mMetaItemSubID] - (aMetaData < 16000 ? 0 : 1)));
+ }
+ return tByte;
+ }
+
+ public static boolean setOreBlock(World aWorld, int aX, int aY, int aZ, int aMetaData, boolean isSmallOre) {
+ return setOreBlock(aWorld, aX, aY, aZ, aMetaData, isSmallOre, true);
+ }
+
+ public static boolean setOreBlock(World aWorld, int aX, int aY, int aZ, int aMetaData, boolean isSmallOre,
+ boolean air) {
+ if (!air) {
+ aY = Math.min(aWorld.getActualHeight(), Math.max(aY, 1));
+ }
+ Block tBlock = aWorld.getBlock(aX, aY, aZ);
+ Block tOreBlock = GregTech_API.sBlockOres1;
+ int BlockMeta = aWorld.getBlockMetadata(aX, aY, aZ);
+ String BlockName = tBlock.getUnlocalizedName();
+ aMetaData += isSmallOre ? 16000 : 0;
+ if ((aMetaData > 0) && ((tBlock != Blocks.air) || air)) {
+ if (tBlock.isReplaceableOreGen(aWorld, aX, aY, aZ, Blocks.stone)) {
+ // Do nothing, stone background is default background.
+ // Do this comparison first since stone is most common
+ } else if (tBlock.isReplaceableOreGen(aWorld, aX, aY, aZ, Blocks.netherrack)) {
+ aMetaData += 1000;
+ } else if (tBlock.isReplaceableOreGen(aWorld, aX, aY, aZ, Blocks.end_stone)) {
+ aMetaData += 2000;
+ } else if (tBlock.isReplaceableOreGen(aWorld, aX, aY, aZ, GregTech_API.sBlockGranites)) {
+ if (tBlock == GregTech_API.sBlockGranites) {
+ if (aWorld.getBlockMetadata(aX, aY, aZ) < 8) {
+ aMetaData += 3000;
+ } else {
+ aMetaData += 4000;
+ }
+ } else {
+ aMetaData += 3000;
+ }
+ } else if (tBlock.isReplaceableOreGen(aWorld, aX, aY, aZ, GregTech_API.sBlockStones)) {
+ if (tBlock == GregTech_API.sBlockStones) {
+ if (aWorld.getBlockMetadata(aX, aY, aZ) < 8) {
+ aMetaData += 5000;
+ } else {
+ aMetaData += 6000;
+ }
+ } else {
+ aMetaData += 5000;
+ }
+ } else if (BlockName.equals("tile.igneousStone")) {
+ if (GregTech_API.sBlockOresUb1 != null) {
+ tOreBlock = GregTech_API.sBlockOresUb1;
+ aMetaData += (BlockMeta * 1000);
+ // GT_FML_LOGGER.info("Block changed to UB1");
+ }
+ } else if (BlockName.equals("tile.metamorphicStone")) {
+ if (GregTech_API.sBlockOresUb2 != null) {
+ tOreBlock = GregTech_API.sBlockOresUb2;
+ aMetaData += (BlockMeta * 1000);
+ // GT_FML_LOGGER.info("Block changed to UB2");
+ }
+ } else if (BlockName.equals("tile.sedimentaryStone")) {
+ if (GregTech_API.sBlockOresUb3 != null) {
+ tOreBlock = GregTech_API.sBlockOresUb3;
+ aMetaData += (BlockMeta * 1000);
+ // GT_FML_LOGGER.info("Block changed to UB3");
+ }
+ } else {
+ return false;
+ }
+ // GT_FML_LOGGER.info(tOreBlock);
+ aWorld.setBlock(
+ aX,
+ aY,
+ aZ,
+ tOreBlock,
+ getHarvestData(
+ (short) aMetaData,
+ ((GT_Block_Ores_Abstract) tOreBlock).getBaseBlockHarvestLevel(aMetaData % 16000 / 1000)),
+ 0);
+ TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if ((tTileEntity instanceof GT_TileEntity_Ores)) {
+ ((GT_TileEntity_Ores) tTileEntity).mMetaData = ((short) aMetaData);
+ ((GT_TileEntity_Ores) tTileEntity).mNatural = true;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void readFromNBT(NBTTagCompound aNBT) {
+ super.readFromNBT(aNBT);
+ this.mMetaData = aNBT.getShort("m");
+ this.mNatural = aNBT.getBoolean("n");
+ }
+
+ @Override
+ public void writeToNBT(NBTTagCompound aNBT) {
+ super.writeToNBT(aNBT);
+ aNBT.setShort("m", this.mMetaData);
+ aNBT.setBoolean("n", this.mNatural);
+ }
+
+ public void onUpdated() {
+ if ((!this.worldObj.isRemote) && (this.mBlocked)) {
+ this.mBlocked = false;
+ GT_Values.NW.sendPacketToAllPlayersInRange(
+ this.worldObj,
+ new GT_Packet_Ores(this.xCoord, (short) this.yCoord, this.zCoord, this.mMetaData),
+ this.xCoord,
+ this.zCoord);
+ }
+ }
+
+ @Override
+ public Packet getDescriptionPacket() {
+ if (!this.worldObj.isRemote) {
+ boolean sendUpdate = mBlockedChecked ? !mBlocked : checkBlocked();
+ if (sendUpdate) {
+ GT_Values.NW.sendPacketToAllPlayersInRange(
+ this.worldObj,
+ new GT_Packet_Ores(this.xCoord, (short) this.yCoord, this.zCoord, this.mMetaData),
+ this.xCoord,
+ this.zCoord);
+ }
+ }
+ return null;
+ }
+
+ private boolean checkBlocked() {
+ // this is called very frequently and is performance critical. unroll the loop.
+ mBlockedChecked = true;
+ if (!worldObj.blockExists(xCoord + 1, yCoord, zCoord)) {
+ mBlockedChecked = false;
+ } else if (!GT_Utility.isOpaqueBlock(worldObj, xCoord + 1, yCoord, zCoord)) {
+ mBlocked = false;
+ return true;
+ }
+ if (!worldObj.blockExists(xCoord - 1, yCoord, zCoord)) {
+ mBlockedChecked = false;
+ } else if (!GT_Utility.isOpaqueBlock(worldObj, xCoord - 1, yCoord, zCoord)) {
+ mBlocked = false;
+ return true;
+ }
+ if (!worldObj.blockExists(xCoord, yCoord + 1, zCoord)) {
+ mBlockedChecked = false;
+ } else if (!GT_Utility.isOpaqueBlock(worldObj, xCoord, yCoord + 1, zCoord)) {
+ mBlocked = false;
+ return true;
+ }
+ if (!worldObj.blockExists(xCoord, yCoord - 1, zCoord)) {
+ mBlockedChecked = false;
+ } else if (!GT_Utility.isOpaqueBlock(worldObj, xCoord, yCoord - 1, zCoord)) {
+ mBlocked = false;
+ return true;
+ }
+ if (!worldObj.blockExists(xCoord, yCoord, zCoord + 1)) {
+ mBlockedChecked = false;
+ } else if (!GT_Utility.isOpaqueBlock(worldObj, xCoord, yCoord, zCoord + 1)) {
+ mBlocked = false;
+ return true;
+ }
+ if (!worldObj.blockExists(xCoord, yCoord, zCoord - 1)) {
+ mBlockedChecked = false;
+ } else if (!GT_Utility.isOpaqueBlock(worldObj, xCoord, yCoord, zCoord - 1)) {
+ mBlocked = false;
+ return true;
+ }
+ mBlocked = true;
+ return false;
+ }
+
+ public void overrideOreBlockMaterial(Block aOverridingStoneBlock, byte aOverridingStoneMeta) {
+ if (this.worldObj == null || blockType == null) return;
+ this.mMetaData = ((short) (int) (this.mMetaData % 1000L + this.mMetaData / 16000L * 16000L));
+ if (aOverridingStoneBlock
+ .isReplaceableOreGen(this.worldObj, this.xCoord, this.yCoord, this.zCoord, Blocks.netherrack)) {
+ this.mMetaData = ((short) (this.mMetaData + 1000));
+ } else if (aOverridingStoneBlock
+ .isReplaceableOreGen(this.worldObj, this.xCoord, this.yCoord, this.zCoord, Blocks.end_stone)) {
+ this.mMetaData = ((short) (this.mMetaData + 2000));
+ } else if (aOverridingStoneBlock.isReplaceableOreGen(
+ this.worldObj,
+ this.xCoord,
+ this.yCoord,
+ this.zCoord,
+ GregTech_API.sBlockGranites)) {
+ if (aOverridingStoneBlock == GregTech_API.sBlockGranites) {
+ if (aOverridingStoneMeta < 8) {
+ this.mMetaData = ((short) (this.mMetaData + 3000));
+ } else {
+ this.mMetaData = ((short) (this.mMetaData + 4000));
+ }
+ } else {
+ this.mMetaData = ((short) (this.mMetaData + 3000));
+ }
+ } else if (aOverridingStoneBlock.isReplaceableOreGen(
+ this.worldObj,
+ this.xCoord,
+ this.yCoord,
+ this.zCoord,
+ GregTech_API.sBlockStones)) {
+ if (aOverridingStoneBlock == GregTech_API.sBlockStones) {
+ if (aOverridingStoneMeta < 8) {
+ this.mMetaData = ((short) (this.mMetaData + 5000));
+ } else {
+ this.mMetaData = ((short) (this.mMetaData + 6000));
+ }
+ } else {
+ this.mMetaData = ((short) (this.mMetaData + 5000));
+ }
+ }
+ this.worldObj.setBlockMetadataWithNotify(
+ this.xCoord,
+ this.yCoord,
+ this.zCoord,
+ getHarvestData(
+ this.mMetaData,
+ ((GT_Block_Ores_Abstract) blockType).getBaseBlockHarvestLevel(mMetaData % 16000 / 1000)),
+ 0);
+ }
+
+ public void convertOreBlock(World aWorld, int aX, int aY, int aZ) {
+ short aMeta = ((short) (this.mMetaData % 1000 + (this.mMetaData / 16000 * 16000)));
+ aWorld.setBlock(aX, aY, aZ, GregTech_API.sBlockOres1);
+ TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if (tTileEntity instanceof GT_TileEntity_Ores) {
+ ((GT_TileEntity_Ores) tTileEntity).mMetaData = aMeta;
+ this.worldObj.setBlockMetadataWithNotify(
+ this.xCoord,
+ this.yCoord,
+ this.zCoord,
+ getHarvestData(
+ aMeta,
+ ((GT_Block_Ores_Abstract) tTileEntity.blockType).getBaseBlockHarvestLevel(aMeta % 16000 / 1000)),
+ 0);
+ }
+ }
+
+ public short getMetaData() {
+ return this.mMetaData;
+ }
+
+ @Override
+ public boolean canUpdate() {
+ return false;
+ }
+
+ public ArrayList<ItemStack> getDrops(Block aDroppedOre, int aFortune) {
+ ArrayList<ItemStack> rList = new ArrayList<>();
+ if (this.mMetaData <= 0) {
+ rList.add(new ItemStack(Blocks.cobblestone, 1, 0));
+ return rList;
+ }
+ Materials aOreMaterial = GregTech_API.sGeneratedMaterials[(this.mMetaData % 1000)];
+ if (this.mMetaData < 16000) {
+ boolean tIsRich = false;
+
+ // For Sake of god of balance!
+
+ // Dense ore
+
+ // NetherOre
+ if (GT_Mod.gregtechproxy.mNetherOreYieldMultiplier && !tIsRich) {
+ tIsRich = (this.mMetaData >= 1000 && this.mMetaData < 2000);
+ }
+ // EndOre
+ if (GT_Mod.gregtechproxy.mEndOreYieldMultiplier && !tIsRich) {
+ tIsRich = (this.mMetaData >= 2000 && this.mMetaData < 3000);
+ }
+
+ // Silk Touch
+ if (shouldSilkTouch) {
+ rList.add(new ItemStack(aDroppedOre, 1, this.mMetaData));
+
+ } else {
+ switch (GT_Mod.gregtechproxy.oreDropSystem) {
+ case Item -> {
+ rList.add(GT_OreDictUnificator.get(OrePrefixes.rawOre, aOreMaterial, (tIsRich ? 2 : 1)));
+ }
+ // TODO: Test
+ case FortuneItem -> {
+ // if shouldFortune and isNatural then get fortune drops
+ // if not shouldFortune or not isNatural then get normal drops
+ // if not shouldFortune and isNatural then get normal drops
+ // if shouldFortune and not isNatural then get normal drops
+ if (shouldFortune && this.mNatural && aFortune > 0) {
+ int aMinAmount = 1;
+ // Max applicable fortune
+ if (aFortune > 3) aFortune = 3;
+ long amount = (long) new Random().nextInt(aFortune * (tIsRich ? 2 : 1)) + aMinAmount;
+ for (int i = 0; i < amount; i++) {
+ rList.add(GT_OreDictUnificator.get(OrePrefixes.rawOre, aOreMaterial, 1));
+ }
+ } else {
+ for (int i = 0; i < (tIsRich ? 2 : 1); i++) {
+ rList.add(GT_OreDictUnificator.get(OrePrefixes.rawOre, aOreMaterial, 1));
+ }
+ }
+ }
+ case UnifiedBlock -> {
+ // Unified ore
+ for (int i = 0; i < (tIsRich ? 2 : 1); i++) {
+ rList.add(new ItemStack(aDroppedOre, 1, this.mMetaData % 1000));
+ }
+ }
+ case PerDimBlock -> {
+ // Per Dimension ore
+ if (tIsRich) {
+ rList.add(new ItemStack(aDroppedOre, 1, this.mMetaData));
+ } else {
+ rList.add(new ItemStack(aDroppedOre, 1, this.mMetaData % 1000));
+ }
+ }
+ case Block -> {
+ // Regular ore
+ rList.add(new ItemStack(aDroppedOre, 1, this.mMetaData));
+ }
+ }
+ }
+ return rList;
+ }
+
+ // Everyone gets a free small fortune boost
+ aFortune += 1;
+ if (!this.mNatural) {
+ aFortune = 0;
+ }
+ if (aOreMaterial != null) {
+ Random tRandom = new XSTR(this.xCoord ^ this.yCoord ^ this.zCoord);
+ ArrayList<ItemStack> tSelector = new ArrayList<>();
+
+ Materials aMaterial = aOreMaterial.mOreReplacement;
+
+ ItemStack tStack = GT_OreDictUnificator
+ .get(OrePrefixes.gemExquisite, aMaterial, GT_OreDictUnificator.get(OrePrefixes.gem, aMaterial, 1L), 1L);
+ if (tStack != null) {
+ for (int i = 0; i < 1; i++) {
+ tSelector.add(tStack);
+ }
+ }
+ tStack = GT_OreDictUnificator
+ .get(OrePrefixes.gemFlawless, aMaterial, GT_OreDictUnificator.get(OrePrefixes.gem, aMaterial, 1L), 1L);
+ if (tStack != null) {
+ for (int i = 0; i < 2; i++) {
+ tSelector.add(tStack);
+ }
+ }
+ tStack = GT_OreDictUnificator.get(OrePrefixes.gem, aMaterial, 1L);
+ if (tStack != null) {
+ for (int i = 0; i < 12; i++) {
+ tSelector.add(tStack);
+ }
+ }
+ tStack = GT_OreDictUnificator.get(
+ OrePrefixes.gemFlawed,
+ aMaterial,
+ GT_OreDictUnificator.get(OrePrefixes.crushed, aMaterial, 1L),
+ 1L);
+ if (tStack != null) {
+ for (int i = 0; i < 5; i++) {
+ tSelector.add(tStack);
+ }
+ }
+ tStack = GT_OreDictUnificator.get(OrePrefixes.crushed, aMaterial, 1L);
+ if (tStack != null) {
+ for (int i = 0; i < 10; i++) {
+ tSelector.add(tStack);
+ }
+ }
+ tStack = GT_OreDictUnificator.get(
+ OrePrefixes.gemChipped,
+ aMaterial,
+ GT_OreDictUnificator.get(OrePrefixes.dustImpure, aMaterial, 1L),
+ 1L);
+ if (tStack != null) {
+ for (int i = 0; i < 5; i++) {
+ tSelector.add(tStack);
+ }
+ }
+ tStack = GT_OreDictUnificator.get(OrePrefixes.dustImpure, aMaterial, 1L);
+ if (tStack != null) {
+ for (int i = 0; i < 10; i++) {
+ tSelector.add(tStack);
+ }
+ }
+ if (!tSelector.isEmpty()) {
+ int i = 0;
+ for (int j = Math.max(
+ 1,
+ aMaterial.mOreMultiplier
+ + (aFortune > 0 ? tRandom.nextInt(1 + aFortune * aMaterial.mOreMultiplier) : 0) / 2); i
+ < j; i++) {
+ rList.add(GT_Utility.copyAmount(1, tSelector.get(tRandom.nextInt(tSelector.size()))));
+ }
+ }
+ if (tRandom.nextInt(3 + aFortune) > 1) {
+ Materials dustMat = ((GT_Block_Ores_Abstract) aDroppedOre).getDroppedDusts()[this.mMetaData / 1000
+ % 16];
+ if (dustMat != null) rList.add(
+ GT_OreDictUnificator
+ .get(tRandom.nextInt(3) > 0 ? OrePrefixes.dustImpure : OrePrefixes.dust, dustMat, 1L));
+ }
+ }
+ return rList;
+ }
+
+ @Override
+ public ITexture[] getTexture(Block aBlock) {
+ if (mMetadataForCachedTexture == mMetaData && mCachedTexture != null) return mCachedTexture;
+
+ mMetadataForCachedTexture = mMetaData;
+ mCachedTexture = getTextureInternal(aBlock);
+ return mCachedTexture;
+ }
+
+ private ITexture @NotNull [] getTextureInternal(Block aBlock) {
+ Materials aMaterial = GregTech_API.sGeneratedMaterials[(this.mMetaData % 1000)];
+ if ((aMaterial != null) && (this.mMetaData < 32000) && (aBlock instanceof GT_Block_Ores_Abstract)) {
+ ITexture iTexture = TextureFactory.builder()
+ .addIcon(
+ aMaterial.mIconSet.mTextures[this.mMetaData / 16000 == 0 ? OrePrefixes.ore.mTextureIndex
+ : OrePrefixes.oreSmall.mTextureIndex])
+ .setRGBA(aMaterial.mRGBa)
+ .stdOrient()
+ .build();
+ return new ITexture[] { ((GT_Block_Ores_Abstract) aBlock).getTextureSet()[((this.mMetaData / 1000) % 16)],
+ iTexture };
+ }
+ return new ITexture[] { TextureFactory.of(Blocks.stone, 0), TextureFactory.builder()
+ .addIcon(SET_NONE.mTextures[OrePrefixes.ore.mTextureIndex])
+ .stdOrient()
+ .build() };
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/CoverInfo.java b/src/main/java/gregtech/common/covers/CoverInfo.java
new file mode 100644
index 0000000000..3deafba899
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/CoverInfo.java
@@ -0,0 +1,335 @@
+package gregtech.common.covers;
+
+import java.lang.ref.WeakReference;
+import java.util.List;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.StatCollector;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.gui.modularui.GT_CoverUIBuildContext;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.util.GT_CoverBehaviorBase;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.ISerializableObject;
+
+public final class CoverInfo {
+
+ private static final String NBT_SIDE = "s", NBT_ID = "id", NBT_DATA = "d", NBT_TICK_RATE_ADDITION = "tra";
+
+ // One minute
+ public static final int MAX_TICK_RATE_ADDITION = 1200;
+
+ public static final CoverInfo EMPTY_INFO = new CoverInfo(ForgeDirection.UNKNOWN, null);
+ private final ForgeDirection coverSide;
+ private int coverID = 0;
+ private GT_CoverBehaviorBase<?> coverBehavior;
+ private ISerializableObject coverData;
+ private final WeakReference<ICoverable> coveredTile;
+ private boolean needsUpdate = false;
+
+ private int tickRateAddition = 0;
+
+ public CoverInfo(ForgeDirection side, ICoverable aTile) {
+ coverSide = side;
+ coveredTile = new WeakReference<>(aTile);
+ coverBehavior = GregTech_API.sNoBehavior;
+ }
+
+ public CoverInfo(ForgeDirection side, int aID, ICoverable aTile, ISerializableObject aCoverData) {
+ coverSide = side;
+ coverID = aID;
+ coverBehavior = GregTech_API.getCoverBehaviorNew(aID);
+ coverData = aCoverData == null ? coverBehavior.createDataObject() : aCoverData;
+ coveredTile = new WeakReference<>(aTile);
+ }
+
+ public CoverInfo(ICoverable aTile, NBTTagCompound aNBT) {
+ coverSide = ForgeDirection.getOrientation(aNBT.getByte(NBT_SIDE));
+ coverID = aNBT.getInteger(NBT_ID);
+ coverBehavior = GregTech_API.getCoverBehaviorNew(coverID);
+ coverData = aNBT.hasKey(NBT_DATA) ? coverBehavior.createDataObject(aNBT.getTag(NBT_DATA))
+ : coverBehavior.createDataObject();
+ coveredTile = new WeakReference<>(aTile);
+ tickRateAddition = aNBT.hasKey(NBT_TICK_RATE_ADDITION) ? aNBT.getInteger(NBT_TICK_RATE_ADDITION) : 0;
+ }
+
+ public boolean isValid() {
+ return coverID != 0 && coverSide != ForgeDirection.UNKNOWN;
+ }
+
+ public NBTTagCompound writeToNBT(NBTTagCompound aNBT) {
+ aNBT.setByte(NBT_SIDE, (byte) coverSide.ordinal());
+ aNBT.setInteger(NBT_ID, coverID);
+ aNBT.setInteger(NBT_TICK_RATE_ADDITION, tickRateAddition);
+ if (coverData != null) aNBT.setTag(NBT_DATA, coverData.saveDataToNBT());
+
+ return aNBT;
+ }
+
+ public int getCoverID() {
+ return coverID;
+ }
+
+ public boolean needsUpdate() {
+ return needsUpdate;
+ }
+
+ public void setNeedsUpdate(boolean aUpdate) {
+ needsUpdate = aUpdate;
+ }
+
+ public GT_CoverBehaviorBase<?> getCoverBehavior() {
+ return coverBehavior;
+ }
+
+ public ISerializableObject getCoverData() {
+ if (coverData != null) return coverData;
+ return GregTech_API.sNoBehavior.createDataObject();
+ }
+
+ public boolean onCoverRemoval(boolean aForced) {
+ return getCoverBehavior().onCoverRemoval(coverSide, coverID, coverData, coveredTile.get(), aForced);
+ }
+
+ public ItemStack getDrop() {
+ return getCoverBehavior().getDrop(coverSide, coverID, coverData, coveredTile.get());
+ }
+
+ public ItemStack getDisplayStack() {
+ return getCoverBehavior().getDisplayStack(coverID, coverData);
+ }
+
+ public boolean isDataNeededOnClient() {
+ return getCoverBehavior().isDataNeededOnClient(coverSide, coverID, coverData, coveredTile.get());
+ }
+
+ public void onDropped() {
+ getCoverBehavior().onDropped(coverSide, coverID, coverData, coveredTile.get());
+ }
+
+ public void setCoverData(ISerializableObject aData) {
+ coverData = aData;
+ }
+
+ public ITexture getSpecialCoverFGTexture() {
+ return getCoverBehavior().getSpecialCoverFGTexture(coverSide, coverID, coverData, coveredTile.get());
+ }
+
+ public ITexture getSpecialCoverTexture() {
+ return getCoverBehavior().getSpecialCoverTexture(coverSide, coverID, coverData, coveredTile.get());
+ }
+
+ public int getTickRate() {
+ return getMinimumTickRate() + tickRateAddition;
+ }
+
+ public ForgeDirection getSide() {
+ return coverSide;
+ }
+
+ public ICoverable getTile() {
+ return coveredTile.get();
+ }
+
+ public boolean isRedstoneSensitive(long aTickTimer) {
+ return getCoverBehavior().isRedstoneSensitive(coverSide, coverID, coverData, coveredTile.get(), aTickTimer);
+ }
+
+ public ISerializableObject doCoverThings(long aTickTimer, byte aRedstone) {
+ return getCoverBehavior()
+ .doCoverThings(coverSide, aRedstone, coverID, coverData, coveredTile.get(), aTickTimer);
+ }
+
+ public void onBaseTEDestroyed() {
+ getCoverBehavior().onBaseTEDestroyed(coverSide, coverID, coverData, coveredTile.get());
+ }
+
+ public void updateCoverBehavior() {
+ coverBehavior = GregTech_API.getCoverBehaviorNew(coverID);
+ }
+
+ public void preDataChanged(int aCoverID, ISerializableObject aCoverData) {
+ getCoverBehavior().preDataChanged(coverSide, coverID, aCoverID, coverData, aCoverData, coveredTile.get());
+ }
+
+ public void onDataChanged() {
+ getCoverBehavior().onDataChanged(coverSide, coverID, coverData, coveredTile.get());
+ }
+
+ public String getBehaviorDescription() {
+ return getCoverBehavior().getDescription(coverSide, coverID, coverData, null);
+ }
+
+ public ModularWindow createWindow(EntityPlayer player) {
+ final GT_CoverUIBuildContext buildContext = new GT_CoverUIBuildContext(
+ player,
+ coverID,
+ coverSide,
+ coveredTile.get(),
+ true);
+ return getCoverBehavior().createWindow(buildContext);
+ }
+
+ public boolean isGUIClickable() {
+ return getCoverBehavior().isGUIClickable(coverSide, coverID, coverData, coveredTile.get());
+ }
+
+ public boolean hasCoverGUI() {
+ return getCoverBehavior().hasCoverGUI();
+ }
+
+ public boolean useModularUI() {
+ return getCoverBehavior().useModularUI();
+ }
+
+ public boolean letsItemsIn(int aSlot) {
+ return getCoverBehavior().letsItemsIn(coverSide, coverID, coverData, aSlot, coveredTile.get());
+ }
+
+ public boolean letsItemsOut(int aSlot) {
+ return getCoverBehavior().letsItemsOut(coverSide, coverID, coverData, aSlot, coveredTile.get());
+ }
+
+ public boolean letsFluidIn(Fluid aFluid) {
+ return letsFluidIn(aFluid, coveredTile.get());
+ }
+
+ public boolean letsFluidOut(Fluid aFluid) {
+ return letsFluidOut(aFluid, coveredTile.get());
+ }
+
+ public boolean letsFluidIn(Fluid aFluid, ICoverable tile) {
+ return getCoverBehavior().letsFluidIn(coverSide, coverID, coverData, aFluid, tile);
+ }
+
+ public boolean letsFluidOut(Fluid aFluid, ICoverable tile) {
+ return getCoverBehavior().letsFluidOut(coverSide, coverID, coverData, aFluid, tile);
+ }
+
+ public boolean letsEnergyIn() {
+ return getCoverBehavior().letsEnergyIn(coverSide, coverID, coverData, coveredTile.get());
+ }
+
+ public boolean letsEnergyOut() {
+ return getCoverBehavior().letsEnergyOut(coverSide, coverID, coverData, coveredTile.get());
+ }
+
+ public boolean alwaysLookConnected() {
+ return getCoverBehavior().alwaysLookConnected(coverSide, coverID, coverData, coveredTile.get());
+ }
+
+ public boolean onCoverRightClick(EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ return getCoverBehavior()
+ .onCoverRightClick(coverSide, coverID, coverData, coveredTile.get(), aPlayer, aX, aY, aZ);
+ }
+
+ public boolean onCoverShiftRightClick(EntityPlayer aPlayer) {
+ return getCoverBehavior().onCoverShiftRightClick(coverSide, coverID, coverData, coveredTile.get(), aPlayer);
+ }
+
+ public ISerializableObject onCoverScrewdriverClick(EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ return getCoverBehavior()
+ .onCoverScrewdriverClick(coverSide, coverID, coverData, coveredTile.get(), aPlayer, aX, aY, aZ);
+ }
+
+ public void onCoverJackhammer(EntityPlayer aPlayer) {
+ adjustTickRateMultiplier(aPlayer.isSneaking());
+
+ GT_Utility.sendChatToPlayer(
+ aPlayer,
+ StatCollector.translateToLocalFormatted("gt.cover.info.chat.tick_rate", getCurrentTickRateFormatted()));
+ }
+
+ /**
+ * Adjusts the tick rate by one step.
+ *
+ * @param isDecreasing If true, lower one step.
+ */
+ public void adjustTickRateMultiplier(final boolean isDecreasing) {
+ final int currentTickRate = getTickRate();
+ final int stepAmount = currentTickRate == 20 ? (isDecreasing ? 5 : 20) : (currentTickRate < 20 ? 5 : 20);
+
+ tickRateAddition = clamp(tickRateAddition + (isDecreasing ? -1 : 1) * stepAmount);
+ tickRateAddition = clamp(tickRateAddition - (getTickRate() % stepAmount));
+ }
+
+ /**
+ * Returns information about the cover's tick rate.
+ *
+ * @return An instance of tick rate components
+ */
+ @NotNull
+ public CoverInfo.ClientTickRateFormatter getCurrentTickRateFormatted() {
+ return new ClientTickRateFormatter(getTickRate());
+ }
+
+ public int getMinimumTickRate() {
+ return getCoverBehavior().getTickRate(coverSide, coverID, coverData, coveredTile.get());
+ }
+
+ public int getTickRateAddition() {
+ return tickRateAddition;
+ }
+
+ public void setTickRateAddition(final int tickRateAddition) {
+ this.tickRateAddition = clamp(tickRateAddition);
+ }
+
+ public Block getFacadeBlock() {
+ return getCoverBehavior().getFacadeBlock(coverSide, coverID, coverData, coveredTile.get());
+ }
+
+ public int getFacadeMeta() {
+ return getCoverBehavior().getFacadeMeta(coverSide, coverID, coverData, coveredTile.get());
+ }
+
+ @NotNull
+ public List<String> getAdditionalTooltip(ISerializableObject data) {
+ return getCoverBehavior().getAdditionalTooltip(data);
+ }
+
+ private static int clamp(int input) {
+ return Math.min(MAX_TICK_RATE_ADDITION, Math.max(0, input));
+ }
+
+ public static final class ClientTickRateFormatter {
+
+ /** A translation key for the type of time units being used (e.g.: "tick", "seconds".) */
+ private final String unitI18NKey;
+ /** A number representing a quantity of time. */
+ private final int tickRate;
+
+ /**
+ * Converts a given tick rate into a human-friendly format.
+ *
+ * @param tickRate The rate at which something ticks, in ticks per operation.
+ */
+ public ClientTickRateFormatter(final int tickRate) {
+ if (tickRate < 20) {
+ this.unitI18NKey = tickRate == 1 ? "gt.time.tick.singular" : "gt.time.tick.plural";
+ this.tickRate = tickRate;
+ } else {
+ this.unitI18NKey = tickRate == 20 ? "gt.time.second.singular" : "gt.time.second.plural";
+ this.tickRate = tickRate / 20;
+ }
+ }
+
+ public String toString() {
+ return StatCollector.translateToLocalFormatted(
+ "gt.cover.info.format.tick_rate",
+ tickRate,
+ StatCollector.translateToLocal(unitI18NKey));
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/GT_Cover_Arm.java b/src/main/java/gregtech/common/covers/GT_Cover_Arm.java
new file mode 100644
index 0000000000..f2440ebc44
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/GT_Cover_Arm.java
@@ -0,0 +1,436 @@
+package gregtech.common.covers;
+
+import java.text.FieldPosition;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.inventory.IInventory;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+
+import com.gtnewhorizons.modularui.api.NumberFormatMUI;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.api.gui.modularui.GT_CoverUIBuildContext;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.interfaces.tileentity.IMachineProgress;
+import gregtech.api.util.GT_CoverBehavior;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.ISerializableObject;
+import gregtech.common.gui.modularui.widget.CoverDataControllerWidget;
+import gregtech.common.gui.modularui.widget.CoverDataFollower_NumericWidget;
+import gregtech.common.gui.modularui.widget.CoverDataFollower_ToggleButtonWidget;
+
+public class GT_Cover_Arm extends GT_CoverBehavior {
+
+ public final int mTickRate;
+ // msb converted, 2nd : direction (1=export)
+ // right 14 bits: internalSlot, next 14 bits adjSlot, 0 = all, slot = -1
+ protected static final int EXPORT_MASK = 0x40000000;
+ protected static final int SLOT_ID_MASK = 0x3FFF;
+ protected static final int SLOT_ID_MIN = 0;
+ protected static final int CONVERTED_BIT = 0x80000000;
+
+ public GT_Cover_Arm(int aTickRate, ITexture coverTexture) {
+ super(coverTexture);
+ this.mTickRate = aTickRate;
+ }
+
+ @Override
+ public boolean isRedstoneSensitive(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ long aTimer) {
+ return false;
+ }
+
+ @Override
+ public int doCoverThings(ForgeDirection side, byte aInputRedstone, int aCoverID, int aCoverVariable,
+ ICoverable aTileEntity, long aTimer) {
+ if ((((aTileEntity instanceof IMachineProgress)) && (!((IMachineProgress) aTileEntity).isAllowedToWork()))) {
+ return aCoverVariable;
+ }
+
+ // Convert from ver. 5.09.33.50, check if 3 last bits are equal
+ if ((aCoverVariable >>> 29) == 0) {
+ aCoverVariable = CONVERTED_BIT | (((aCoverVariable + 1) & SLOT_ID_MASK) << 14) | EXPORT_MASK;
+ } else if ((aCoverVariable >>> 29) == 7) {
+ aCoverVariable = CONVERTED_BIT | Math.min(Math.abs(aCoverVariable - 1), SLOT_ID_MASK);
+ }
+
+ final TileEntity toTile;
+ final TileEntity fromTile;
+ final int toSlot;
+ final int fromSlot;
+
+ if ((aCoverVariable & EXPORT_MASK) > 0) {
+ fromTile = (TileEntity) aTileEntity;
+ toTile = aTileEntity.getTileEntityAtSide(side);
+ fromSlot = aCoverVariable & SLOT_ID_MASK;
+ toSlot = (aCoverVariable >> 14) & SLOT_ID_MASK;
+ } else {
+ fromTile = aTileEntity.getTileEntityAtSide(side);
+ toTile = (TileEntity) aTileEntity;
+ fromSlot = (aCoverVariable >> 14) & SLOT_ID_MASK;
+ toSlot = aCoverVariable & SLOT_ID_MASK;
+ }
+
+ if (fromSlot > 0 && toSlot > 0) {
+ if (fromTile instanceof IInventory fromInventory && toTile instanceof IInventory toInventory)
+ GT_Utility.moveFromSlotToSlot(
+ fromInventory,
+ toInventory,
+ fromSlot - 1,
+ toSlot - 1,
+ null,
+ false,
+ (byte) 64,
+ (byte) 1,
+ (byte) 64,
+ (byte) 1);
+ } else if (toSlot > 0) {
+ final ForgeDirection toSide;
+ if ((aCoverVariable & EXPORT_MASK) > 0) toSide = side;
+ else toSide = side.getOpposite();
+ GT_Utility.moveOneItemStackIntoSlot(
+ fromTile,
+ toTile,
+ toSide,
+ toSlot - 1,
+ null,
+ false,
+ (byte) 64,
+ (byte) 1,
+ (byte) 64,
+ (byte) 1);
+ } else if (fromSlot > 0) {
+ final ForgeDirection toSide;
+ if ((aCoverVariable & EXPORT_MASK) > 0) toSide = side;
+ else toSide = side.getOpposite();
+ if (fromTile instanceof IInventory) GT_Utility.moveFromSlotToSide(
+ (IInventory) fromTile,
+ toTile,
+ fromSlot - 1,
+ toSide,
+ null,
+ false,
+ (byte) 64,
+ (byte) 1,
+ (byte) 64,
+ (byte) 1);
+ } else {
+ final ForgeDirection fromSide;
+ final ForgeDirection toSide;
+ if ((aCoverVariable & EXPORT_MASK) > 0) {
+ fromSide = side;
+ toSide = side.getOpposite();
+ } else {
+ fromSide = side.getOpposite();
+ toSide = side;
+ }
+ GT_Utility.moveOneItemStack(
+ fromTile,
+ toTile,
+ fromSide,
+ toSide,
+ null,
+ false,
+ (byte) 64,
+ (byte) 1,
+ (byte) 64,
+ (byte) 1);
+ }
+
+ return aCoverVariable;
+ }
+
+ @Override
+ public int onCoverScrewdriverclick(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ int step = 0;
+ if (GT_Utility.getClickedFacingCoords(side, aX, aY, aZ)[0] >= 0.5F) {
+ step += aPlayer.isSneaking() ? 256 : 16;
+ } else {
+ step -= aPlayer.isSneaking() ? 256 : 16;
+ }
+ aCoverVariable = getNewVar(aCoverVariable, step);
+ sendMessageToPlayer(aPlayer, aCoverVariable);
+ return aCoverVariable;
+ }
+
+ @Override
+ protected boolean onCoverRightClickImpl(ForgeDirection side, int aCoverID,
+ ISerializableObject.LegacyCoverData aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, float aX,
+ float aY, float aZ) {
+ int step = (GT_Utility.getClickedFacingCoords(side, aX, aY, aZ)[0] >= 0.5F) ? 1 : -1;
+ int tCoverVariable = getNewVar(aCoverVariable.get(), step);
+ sendMessageToPlayer(aPlayer, tCoverVariable);
+ aCoverVariable.set(tCoverVariable);
+ return true;
+ }
+
+ @Override
+ @SuppressWarnings("deprecation")
+ public boolean onCoverRightclick(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ final int step = (GT_Utility.getClickedFacingCoords(side, aX, aY, aZ)[0] >= 0.5F) ? 1 : -1;
+ aCoverVariable = getNewVar(aCoverVariable, step);
+ sendMessageToPlayer(aPlayer, aCoverVariable);
+ aTileEntity.setCoverDataAtSide(side, aCoverVariable);
+ return true;
+ }
+
+ @Override
+ protected boolean isGUIClickableImpl(ForgeDirection side, int aCoverID,
+ ISerializableObject.LegacyCoverData aCoverVariable, ICoverable aTileEntity) {
+ return false;
+ }
+
+ private void sendMessageToPlayer(EntityPlayer aPlayer, int var) {
+ if ((var & EXPORT_MASK) != 0) GT_Utility.sendChatToPlayer(
+ aPlayer,
+ GT_Utility.trans("001", "Puts out into adjacent Slot #") + (((var >> 14) & SLOT_ID_MASK) - 1));
+ else GT_Utility
+ .sendChatToPlayer(aPlayer, GT_Utility.trans("002", "Grabs in for own Slot #") + ((var & SLOT_ID_MASK) - 1));
+ }
+
+ private int getNewVar(int var, int step) {
+ int intSlot = (var & SLOT_ID_MASK);
+ int adjSlot = (var >> 14) & SLOT_ID_MASK;
+ if ((var & EXPORT_MASK) == 0) {
+ int x = (intSlot + step);
+ if (x > SLOT_ID_MASK) return createVar(0, SLOT_ID_MASK, 0);
+ else if (x < 1) return createVar(-step - intSlot + 1, 0, EXPORT_MASK);
+ else return createVar(0, x, 0);
+ } else {
+ int x = (adjSlot - step);
+ if (x > SLOT_ID_MASK) return createVar(SLOT_ID_MASK, 0, EXPORT_MASK);
+ else if (x < 1) return createVar(0, step - adjSlot + 1, 0);
+ else return createVar(x, 0, EXPORT_MASK);
+ }
+ }
+
+ private int createVar(int adjSlot, int intSlot, int export) {
+ return CONVERTED_BIT | export | ((adjSlot & SLOT_ID_MASK) << 14) | (intSlot & SLOT_ID_MASK);
+ }
+
+ @Override
+ public boolean letsRedstoneGoIn(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsRedstoneGoOut(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsEnergyIn(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsEnergyOut(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsFluidIn(ForgeDirection side, int aCoverID, int aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsFluidOut(ForgeDirection side, int aCoverID, int aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsItemsIn(ForgeDirection side, int aCoverID, int aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsItemsOut(ForgeDirection side, int aCoverID, int aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean alwaysLookConnected(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public int getTickRate(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return this.mTickRate;
+ }
+
+ // GUI stuff
+
+ @Override
+ public boolean hasCoverGUI() {
+ return true;
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ @Override
+ public ModularWindow createWindow(GT_CoverUIBuildContext buildContext) {
+ return new ArmUIFactory(buildContext).createWindow();
+ }
+
+ private class ArmUIFactory extends UIFactory {
+
+ private static final int startX = 10;
+ private static final int startY = 25;
+ private static final int spaceX = 18;
+ private static final int spaceY = 18;
+
+ private int maxSlot;
+
+ /**
+ * Display the text "Any" instead of a number when the slot is set to -1.
+ */
+ protected static final NumberFormatMUI numberFormatAny = new NumberFormatMUI() {
+
+ @Override
+ public StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos) {
+ if (number < 0) {
+ return toAppendTo.append(GT_Utility.trans("ANY", "Any"));
+ } else {
+ return super.format(number, toAppendTo, pos);
+ }
+ }
+ };
+
+ protected ArmUIFactory(GT_CoverUIBuildContext buildContext) {
+ super(buildContext);
+ }
+
+ @SuppressWarnings("PointlessArithmeticExpression")
+ @Override
+ protected void addUIWidgets(ModularWindow.Builder builder) {
+ maxSlot = getMaxSlot();
+ builder.widget(
+ new CoverDataControllerWidget<>(this::getCoverData, this::setCoverData, GT_Cover_Arm.this).addFollower(
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ coverData -> getFlagExport(convert(coverData)) > 0,
+ (coverData, state) -> {
+ if (state) {
+ return new ISerializableObject.LegacyCoverData(
+ convert(coverData) | EXPORT_MASK | CONVERTED_BIT);
+ } else {
+ return new ISerializableObject.LegacyCoverData(
+ convert(coverData) & ~EXPORT_MASK | CONVERTED_BIT);
+ }
+ },
+ widget -> widget.setStaticTexture(GT_UITextures.OVERLAY_BUTTON_EXPORT)
+ .addTooltip(GT_Utility.trans("006", "Export"))
+ .setPos(spaceX * 0, spaceY * 0))
+ .addFollower(
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ coverData -> getFlagExport(convert(coverData)) == 0,
+ (coverData, state) -> {
+ if (state) {
+ return new ISerializableObject.LegacyCoverData(
+ convert(coverData) & ~EXPORT_MASK | CONVERTED_BIT);
+ } else {
+ return new ISerializableObject.LegacyCoverData(
+ convert(coverData) | EXPORT_MASK | CONVERTED_BIT);
+ }
+ },
+ widget -> widget.setStaticTexture(GT_UITextures.OVERLAY_BUTTON_IMPORT)
+ .addTooltip(GT_Utility.trans("007", "Import"))
+ .setPos(spaceX * 1, spaceY * 0))
+ .addFollower(
+ new CoverDataFollower_NumericWidget<>(),
+ coverData -> (double) (getFlagInternalSlot(convert(coverData)) - 1),
+ (coverData, state) -> {
+ final int coverVariable = convert(coverData);
+ return new ISerializableObject.LegacyCoverData(
+ getFlagExport(coverVariable) | ((state.intValue() + 1) & SLOT_ID_MASK)
+ | (getFlagAdjacentSlot(coverVariable) << 14)
+ | CONVERTED_BIT);
+ },
+ widget -> widget.setBounds(-1, maxSlot)
+ .setDefaultValue(-1)
+ .setScrollValues(1, 100, 10)
+ .setNumberFormat(numberFormatAny)
+ .setPos(spaceX * 0, spaceY * 1 + 2)
+ .setSize(spaceX * 2 + 5, 12))
+ .addFollower(
+ new CoverDataFollower_NumericWidget<>(),
+ coverData -> (double) (getFlagAdjacentSlot(convert(coverData)) - 1),
+ (coverData, state) -> {
+ final int coverVariable = convert(coverData);
+ return new ISerializableObject.LegacyCoverData(
+ getFlagExport(coverVariable) | getFlagInternalSlot(coverVariable)
+ | (((state.intValue() + 1) & SLOT_ID_MASK) << 14)
+ | CONVERTED_BIT);
+ },
+ widget -> widget.setValidator(val -> {
+ // We need to check the adjacent inventory here, and can't simply set a maximum value,
+ // because it can change while this cover is alive.
+ final int adjacentMaxSlot;
+ final ICoverable tile = getUIBuildContext().getTile();
+ if (tile instanceof TileEntity && !tile.isDead()) {
+ TileEntity adj = tile.getTileEntityAtSide(getUIBuildContext().getCoverSide());
+ if (adj instanceof IInventory)
+ adjacentMaxSlot = ((IInventory) adj).getSizeInventory() - 1;
+ else adjacentMaxSlot = -1;
+ } else {
+ adjacentMaxSlot = -1;
+ }
+ return Math.min(val, adjacentMaxSlot);
+ })
+ .setMinValue(-1)
+ .setDefaultValue(-1)
+ .setScrollValues(1, 100, 10)
+ .setNumberFormat(numberFormatAny)
+ .setPos(spaceX * 0, spaceY * 2 + 2)
+ .setSize(spaceX * 2 + 5, 12))
+ .setPos(startX, startY))
+ .widget(
+ new TextWidget()
+ .setStringSupplier(
+ () -> (convert(getCoverData()) & EXPORT_MASK) > 0 ? GT_Utility.trans("006", "Export")
+ : GT_Utility.trans("007", "Import"))
+ .setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * 3, 4 + startY + spaceY * 0))
+ .widget(
+ new TextWidget(GT_Utility.trans("254.1", "Internal slot#")).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * 3, 4 + startY + spaceY * 1))
+ .widget(
+ new TextWidget(GT_Utility.trans("255", "Adjacent slot#")).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * 3, 4 + startY + spaceY * 2));
+ }
+
+ private int getMaxSlot() {
+ final ICoverable tile = getUIBuildContext().getTile();
+ if (tile instanceof TileEntity && !tile.isDead()) {
+ return tile.getSizeInventory() - 1;
+ } else {
+ return -1;
+ }
+ }
+
+ private int getFlagExport(int coverVariable) {
+ return coverVariable & EXPORT_MASK;
+ }
+
+ private int getFlagInternalSlot(int coverVariable) {
+ return coverVariable & SLOT_ID_MASK;
+ }
+
+ private int getFlagAdjacentSlot(int coverVariable) {
+ return (coverVariable >> 14) & SLOT_ID_MASK;
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/GT_Cover_ControlsWork.java b/src/main/java/gregtech/common/covers/GT_Cover_ControlsWork.java
new file mode 100644
index 0000000000..320876568f
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/GT_Cover_ControlsWork.java
@@ -0,0 +1,275 @@
+package gregtech.common.covers;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.api.gui.modularui.GT_CoverUIBuildContext;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.covers.IControlsWorkCover;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.interfaces.tileentity.IMachineProgress;
+import gregtech.api.util.GT_CoverBehavior;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.ISerializableObject;
+import gregtech.common.gui.modularui.widget.CoverDataControllerWidget;
+import gregtech.common.gui.modularui.widget.CoverDataFollower_ToggleButtonWidget;
+
+public class GT_Cover_ControlsWork extends GT_CoverBehavior implements IControlsWorkCover {
+
+ public GT_Cover_ControlsWork(ITexture coverTexture) {
+ super(coverTexture);
+ }
+
+ @Override
+ public int doCoverThings(ForgeDirection side, byte aInputRedstone, int aCoverID, int aCoverVariable,
+ ICoverable aTileEntity, long aTimer) {
+ if (!makeSureOnlyOne(side, aTileEntity)) return 0;
+ if (aTileEntity instanceof IMachineProgress machine) {
+ if (aCoverVariable < 2) {
+ if ((aInputRedstone > 0) == (aCoverVariable == 0)) {
+ if (!machine.isAllowedToWork()) machine.enableWorking();
+ } else if (machine.isAllowedToWork()) machine.disableWorking();
+ machine.setWorkDataValue(aInputRedstone);
+ } else if (aCoverVariable == 2) {
+ machine.disableWorking();
+ } else {
+ if (machine.wasShutdown() && machine.getLastShutDownReason()
+ .wasCritical()) {
+ machine.disableWorking();
+ if (!mPlayerNotified) {
+ EntityPlayer player = lastPlayer == null ? null : lastPlayer.get();
+ if (player != null) {
+ lastPlayer = null;
+ mPlayerNotified = true;
+ GT_Utility.sendChatToPlayer(
+ player,
+ aTileEntity.getInventoryName() + "at "
+ + String.format(
+ "(%d,%d,%d)",
+ aTileEntity.getXCoord(),
+ aTileEntity.getYCoord(),
+ aTileEntity.getZCoord())
+ + " shut down.");
+ }
+ }
+ return 2;
+ } else {
+ return 3 + doCoverThings(side, aInputRedstone, aCoverID, aCoverVariable - 3, aTileEntity, aTimer);
+ }
+ }
+ }
+ return aCoverVariable;
+ }
+
+ @Override
+ protected boolean isRedstoneSensitiveImpl(ForgeDirection side, int aCoverID,
+ ISerializableObject.LegacyCoverData aCoverVariable, ICoverable aTileEntity, long aTimer) {
+ return aCoverVariable.get() != 2; // always off, so no redstone needed either
+ }
+
+ /**
+ * Make sure there is only one GT_Cover_ControlsWork on the aTileEntity TODO this is a migration thing. Remove this
+ * after 2.3.0 is released.
+ *
+ * @return true if the cover is the first (side) one
+ **/
+ private boolean makeSureOnlyOne(ForgeDirection side, ICoverable aTileEntity) {
+ return IControlsWorkCover.makeSureOnlyOne(side, aTileEntity);
+ }
+
+ @Override
+ public boolean letsEnergyIn(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsEnergyOut(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsFluidIn(ForgeDirection side, int aCoverID, int aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsFluidOut(ForgeDirection side, int aCoverID, int aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsItemsIn(ForgeDirection side, int aCoverID, int aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsItemsOut(ForgeDirection side, int aCoverID, int aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean onCoverRemoval(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ boolean aForced) {
+ if ((aTileEntity instanceof IMachineProgress)) {
+ ((IMachineProgress) aTileEntity).enableWorking();
+ ((IMachineProgress) aTileEntity).setWorkDataValue((byte) 0);
+ }
+ return true;
+ }
+
+ @Override
+ public int onCoverScrewdriverclick(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ aCoverVariable = (aCoverVariable + (aPlayer.isSneaking() ? -1 : 1)) % 5;
+ if (aCoverVariable < 0) {
+ aCoverVariable = 2;
+ }
+ if (aCoverVariable == 0) {
+ GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("003", "Enable with Signal"));
+ }
+ if (aCoverVariable == 1) {
+ GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("004", "Disable with Signal"));
+ }
+ if (aCoverVariable == 2) {
+ GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("005", "Disabled"));
+ }
+ if (aCoverVariable == 3) {
+ GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("505", "Enable with Signal (Safe)"));
+ }
+ if (aCoverVariable == 4) {
+ GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("506", "Disable with Signal (Safe)"));
+ }
+ // TODO: Set lastPlayer
+ return aCoverVariable;
+ }
+
+ @Override
+ public int getTickRate(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return 1;
+ }
+
+ @Override
+ public boolean isCoverPlaceable(ForgeDirection side, ItemStack aStack, ICoverable aTileEntity) {
+ if (!super.isCoverPlaceable(side, aStack, aTileEntity)) return false;
+ for (final ForgeDirection tSide : ForgeDirection.VALID_DIRECTIONS) {
+ if (aTileEntity.getCoverBehaviorAtSideNew(tSide) instanceof IControlsWorkCover) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // GUI stuff
+
+ @Override
+ public boolean hasCoverGUI() {
+ return true;
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ @Override
+ public ModularWindow createWindow(GT_CoverUIBuildContext buildContext) {
+ return new ControlsWorkUIFactory(buildContext).createWindow();
+ }
+
+ private class ControlsWorkUIFactory extends UIFactory {
+
+ private static final int startX = 10;
+ private static final int startY = 25;
+ private static final int spaceX = 18;
+ private static final int spaceY = 18;
+
+ public ControlsWorkUIFactory(GT_CoverUIBuildContext buildContext) {
+ super(buildContext);
+ }
+
+ @SuppressWarnings("PointlessArithmeticExpression")
+ @Override
+ protected void addUIWidgets(ModularWindow.Builder builder) {
+ builder
+ .widget(
+ new CoverDataControllerWidget.CoverDataIndexedControllerWidget_ToggleButtons<>(
+ this::getCoverData,
+ this::setCoverData,
+ GT_Cover_ControlsWork.this,
+ (id, coverData) -> !getClickable(id, convert(coverData)),
+ (id, coverData) -> new ISerializableObject.LegacyCoverData(
+ getNewCoverVariable(id, convert(coverData))))
+ .addToggleButton(
+ 0,
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ widget -> widget.setStaticTexture(GT_UITextures.OVERLAY_BUTTON_REDSTONE_ON)
+ .setPos(spaceX * 0, spaceY * 0))
+ .addToggleButton(
+ 1,
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ widget -> widget.setStaticTexture(GT_UITextures.OVERLAY_BUTTON_REDSTONE_OFF)
+ .setPos(spaceX * 0, spaceY * 1))
+ .addToggleButton(
+ 2,
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ widget -> widget.setStaticTexture(GT_UITextures.OVERLAY_BUTTON_CROSS)
+ .setPos(spaceX * 0, spaceY * 2))
+ .setPos(startX, startY))
+ .widget(
+ new CoverDataControllerWidget<>(this::getCoverData, this::setCoverData, GT_Cover_ControlsWork.this)
+ .addFollower(
+ CoverDataFollower_ToggleButtonWidget.ofCheckAndCross(),
+ coverData -> convert(coverData) > 2,
+ (coverData, state) -> new ISerializableObject.LegacyCoverData(
+ adjustCoverVariable(state, convert(coverData))),
+ widget -> widget.setPos(spaceX * 0, spaceY * 3))
+ .setPos(startX, startY))
+ .widget(
+ new TextWidget(GT_Utility.trans("243", "Enable with Redstone"))
+ .setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(3 + startX + spaceX * 1, 4 + startY + spaceY * 0))
+ .widget(
+ new TextWidget(GT_Utility.trans("244", "Disable with Redstone"))
+ .setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(3 + startX + spaceX * 1, 4 + startY + spaceY * 1))
+ .widget(
+ new TextWidget(GT_Utility.trans("245", "Disable machine")).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(3 + startX + spaceX * 1, 4 + startY + spaceY * 2))
+ .widget(
+ new TextWidget(GT_Utility.trans("507", "Safe Mode")).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(3 + startX + spaceX * 1, 4 + startY + spaceY * 3));
+ }
+
+ private int getNewCoverVariable(int id, int coverVariable) {
+ if (coverVariable > 2) {
+ return id + 3;
+ } else {
+ return id;
+ }
+ }
+
+ private boolean getClickable(int id, int coverVariable) {
+ return ((id != coverVariable && id != coverVariable - 3) || id == 3);
+ }
+
+ private int adjustCoverVariable(boolean safeMode, int coverVariable) {
+ if (safeMode && coverVariable <= 2) {
+ coverVariable += 3;
+ }
+ if (!safeMode && coverVariable > 2) {
+ coverVariable -= 3;
+ }
+ return coverVariable;
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/GT_Cover_Conveyor.java b/src/main/java/gregtech/common/covers/GT_Cover_Conveyor.java
new file mode 100644
index 0000000000..fcedfbe768
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/GT_Cover_Conveyor.java
@@ -0,0 +1,333 @@
+package gregtech.common.covers;
+
+import static gregtech.api.util.GT_Utility.moveMultipleItemStacks;
+
+import java.util.Arrays;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.api.gui.modularui.GT_CoverUIBuildContext;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.interfaces.tileentity.IMachineProgress;
+import gregtech.api.util.GT_CoverBehavior;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.ISerializableObject;
+import gregtech.common.gui.modularui.widget.CoverDataControllerWidget;
+import gregtech.common.gui.modularui.widget.CoverDataFollower_ToggleButtonWidget;
+
+public class GT_Cover_Conveyor extends GT_CoverBehavior {
+
+ public final int mTickRate;
+ private final int mMaxStacks;
+
+ public GT_Cover_Conveyor(int aTickRate, int maxStacks, ITexture coverTexture) {
+ super(coverTexture);
+ this.mTickRate = aTickRate;
+ this.mMaxStacks = maxStacks;
+ }
+
+ @Override
+ public boolean isRedstoneSensitive(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ long aTimer) {
+ return false;
+ }
+
+ @Override
+ public int doCoverThings(ForgeDirection side, byte aInputRedstone, int aCoverID, int aCoverVariable,
+ ICoverable aTileEntity, long aTimer) {
+ if ((aCoverVariable % 6 > 1) && ((aTileEntity instanceof IMachineProgress))) {
+ if (((IMachineProgress) aTileEntity).isAllowedToWork() != aCoverVariable % 6 < 4) {
+ return aCoverVariable;
+ }
+ }
+ final TileEntity tTileEntity = aTileEntity.getTileEntityAtSide(side);
+ final Object fromEntity = aCoverVariable % 2 == 0 ? aTileEntity : tTileEntity;
+ final Object toEntity = aCoverVariable % 2 != 0 ? aTileEntity : tTileEntity;
+ final ForgeDirection fromSide = aCoverVariable % 2 != 0 ? side.getOpposite() : side;
+ final ForgeDirection toSide = aCoverVariable % 2 == 0 ? side.getOpposite() : side;
+
+ moveMultipleItemStacks(
+ fromEntity,
+ toEntity,
+ fromSide,
+ toSide,
+ null,
+ false,
+ (byte) 64,
+ (byte) 1,
+ (byte) 64,
+ (byte) 1,
+ this.mMaxStacks);
+
+ return aCoverVariable;
+ }
+
+ @Override
+ public int onCoverScrewdriverclick(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ aCoverVariable = (aCoverVariable + (aPlayer.isSneaking() ? -1 : 1)) % 12;
+ if (aCoverVariable < 0) {
+ aCoverVariable = 11;
+ }
+ switch (aCoverVariable) {
+ case 0 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("006", "Export"));
+ case 1 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("007", "Import"));
+ case 2 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("008", "Export (conditional)"));
+ case 3 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("009", "Import (conditional)"));
+ case 4 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("010", "Export (invert cond)"));
+ case 5 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("011", "Import (invert cond)"));
+ case 6 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("012", "Export allow Input"));
+ case 7 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("013", "Import allow Output"));
+ case 8 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("014", "Export allow Input (conditional)"));
+ case 9 -> GT_Utility
+ .sendChatToPlayer(aPlayer, GT_Utility.trans("015", "Import allow Output (conditional)"));
+ case 10 -> GT_Utility
+ .sendChatToPlayer(aPlayer, GT_Utility.trans("016", "Export allow Input (invert cond)"));
+ case 11 -> GT_Utility
+ .sendChatToPlayer(aPlayer, GT_Utility.trans("017", "Import allow Output (invert cond)"));
+ }
+ return aCoverVariable;
+ }
+
+ @Override
+ public boolean letsRedstoneGoIn(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsRedstoneGoOut(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsEnergyIn(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsEnergyOut(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsFluidIn(ForgeDirection side, int aCoverID, int aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsFluidOut(ForgeDirection side, int aCoverID, int aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsItemsIn(ForgeDirection side, int aCoverID, int aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return (aCoverVariable >= 6) || (aCoverVariable % 2 != 0);
+ }
+
+ @Override
+ public boolean letsItemsOut(ForgeDirection side, int aCoverID, int aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return (aCoverVariable >= 6) || (aCoverVariable % 2 == 0);
+ }
+
+ @Override
+ public boolean alwaysLookConnected(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public int getTickRate(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return this.mTickRate;
+ }
+
+ // GUI stuff
+
+ @Override
+ public boolean hasCoverGUI() {
+ return true;
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ @Override
+ public ModularWindow createWindow(GT_CoverUIBuildContext buildContext) {
+ return new ConveyorUIFactory(buildContext).createWindow();
+ }
+
+ private class ConveyorUIFactory extends UIFactory {
+
+ private static final int startX = 10;
+ private static final int startY = 25;
+ private static final int spaceX = 18;
+ private static final int spaceY = 18;
+
+ private CoverDataFollower_ToggleButtonWidget<ISerializableObject.LegacyCoverData> mBlockWidget = null;
+ private CoverDataFollower_ToggleButtonWidget<ISerializableObject.LegacyCoverData> mAllowWidget = null;
+
+ public ConveyorUIFactory(GT_CoverUIBuildContext buildContext) {
+ super(buildContext);
+ }
+
+ @SuppressWarnings("PointlessArithmeticExpression")
+ @Override
+ protected void addUIWidgets(ModularWindow.Builder builder) {
+ builder.widget(
+ new CoverDataControllerWidget.CoverDataIndexedControllerWidget_ToggleButtons<>(
+ this::getCoverData,
+ this::setCoverData,
+ GT_Cover_Conveyor.this,
+ (id, coverData) -> !getClickable(id, convert(coverData)),
+ (id, coverData) -> new ISerializableObject.LegacyCoverData(
+ getNewCoverVariable(id, convert(coverData))))
+ .addToggleButton(
+ 0,
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ widget -> widget.setStaticTexture(GT_UITextures.OVERLAY_BUTTON_EXPORT)
+ .addTooltip(GT_Utility.trans("006", "Export"))
+ .setPos(spaceX * 0, spaceY * 0))
+ .addToggleButton(
+ 1,
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ widget -> widget.setStaticTexture(GT_UITextures.OVERLAY_BUTTON_IMPORT)
+ .addTooltip(GT_Utility.trans("007", "Import"))
+ .setPos(spaceX * 1, spaceY * 0))
+ .addToggleButton(
+ 2,
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ widget -> widget.setStaticTexture(GT_UITextures.OVERLAY_BUTTON_CHECKMARK)
+ .addTooltip(GT_Utility.trans("224", "Always On"))
+ .setPos(spaceX * 0, spaceY * 1))
+ .addToggleButton(
+ 3,
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ widget -> widget.setStaticTexture(GT_UITextures.OVERLAY_BUTTON_USE_PROCESSING_STATE)
+ .addTooltip(GT_Utility.trans("343", "Use Machine Processing State"))
+ .setPos(spaceX * 1, spaceY * 1))
+ .addToggleButton(
+ 4,
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ widget -> widget
+ .setStaticTexture(GT_UITextures.OVERLAY_BUTTON_USE_INVERTED_PROCESSING_STATE)
+ .addTooltip(GT_Utility.trans("343.1", "Use Inverted Machine Processing State"))
+ .setPos(spaceX * 2, spaceY * 1))
+ .addToggleButton(5, CoverDataFollower_ToggleButtonWidget.ofDisableable(), widget -> {
+ mAllowWidget = widget;
+ widget.setTextureGetter(i -> {
+ ISerializableObject.LegacyCoverData coverData = getCoverData();
+ return coverData == null || coverData.get() % 2 == 0
+ ? GT_UITextures.OVERLAY_BUTTON_ALLOW_INPUT
+ : GT_UITextures.OVERLAY_BUTTON_ALLOW_OUTPUT;
+ })
+ .dynamicTooltip(() -> {
+ ISerializableObject.LegacyCoverData coverData = getCoverData();
+ return Arrays.asList(
+ coverData == null || coverData.get() % 2 == 0
+ ? GT_Utility.trans("314", "Allow Input")
+ : GT_Utility.trans("312", "Allow Output"));
+ })
+ .setPos(spaceX * 0, spaceY * 2);
+ })
+ .addToggleButton(6, CoverDataFollower_ToggleButtonWidget.ofDisableable(), widget -> {
+ mBlockWidget = widget;
+ widget.setTextureGetter(i -> {
+ ISerializableObject.LegacyCoverData coverData = getCoverData();
+ return coverData == null || coverData.get() % 2 == 0
+ ? GT_UITextures.OVERLAY_BUTTON_BLOCK_INPUT
+ : GT_UITextures.OVERLAY_BUTTON_BLOCK_OUTPUT;
+ })
+ .dynamicTooltip(() -> {
+ ISerializableObject.LegacyCoverData coverData = getCoverData();
+ return Arrays.asList(
+ coverData == null || coverData.get() % 2 == 0
+ ? GT_Utility.trans("313", "Block Input")
+ : GT_Utility.trans("311", "Block Output"));
+ })
+ .setPos(spaceX * 1, spaceY * 2);
+ })
+ .setPos(startX, startY))
+ .widget(
+ new TextWidget(GT_Utility.trans("229", "Export/Import")).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(3 + startX + spaceX * 3, 4 + startY + spaceY * 0))
+ .widget(
+ new TextWidget(GT_Utility.trans("230", "Conditional")).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(3 + startX + spaceX * 3, 4 + startY + spaceY * 1))
+ .widget(TextWidget.dynamicString(() -> {
+ ISerializableObject.LegacyCoverData coverData = getCoverData();
+ return coverData == null || coverData.get() % 2 == 0 ? GT_Utility.trans("344", "Input Blocking")
+ : GT_Utility.trans("344.1", "Output Blocking");
+ })
+ .setSynced(false)
+ .setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(3 + startX + spaceX * 3, 4 + startY + spaceY * 2));
+ }
+
+ private int getNewCoverVariable(int id, int coverVariable) {
+ switch (id) {
+ case 0 -> {
+ if (mBlockWidget != null) {
+ mBlockWidget.notifyTooltipChange();
+ }
+ if (mAllowWidget != null) {
+ mAllowWidget.notifyTooltipChange();
+ }
+ return coverVariable & ~0x1;
+ }
+ case 1 -> {
+ if (mBlockWidget != null) {
+ mBlockWidget.notifyTooltipChange();
+ }
+ if (mAllowWidget != null) {
+ mAllowWidget.notifyTooltipChange();
+ }
+ return coverVariable | 0x1;
+ }
+ case 2 -> {
+ if (coverVariable > 5) return 0x6 | (coverVariable & ~0xE);
+ return (coverVariable & ~0xE);
+ }
+ case 3 -> {
+ if (coverVariable > 5) return 0x8 | (coverVariable & ~0xE);
+ return 0x2 | (coverVariable & ~0xE);
+ }
+ case 4 -> {
+ if (coverVariable > 5) return 0xA | (coverVariable & ~0xE);
+ return (0x4 | (coverVariable & ~0xE));
+ }
+ case 5 -> {
+ if (coverVariable <= 5) return coverVariable + 6;
+ }
+ case 6 -> {
+ if (coverVariable > 5) return coverVariable - 6;
+ }
+ }
+ return coverVariable;
+ }
+
+ private boolean getClickable(int id, int coverVariable) {
+ if (coverVariable < 0 || 11 < coverVariable) return false;
+ return switch (id) {
+ case 0, 1 -> (0x1 & coverVariable) != id;
+ case 2 -> (coverVariable % 6) >= 2;
+ case 3 -> (coverVariable % 6) < 2 || 4 <= (coverVariable % 6);
+ case 4 -> (coverVariable % 6) < 4;
+ case 5 -> coverVariable < 6;
+ case 6 -> coverVariable >= 6;
+ default -> false;
+ };
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/GT_Cover_Crafting.java b/src/main/java/gregtech/common/covers/GT_Cover_Crafting.java
new file mode 100644
index 0000000000..f492542fa9
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/GT_Cover_Crafting.java
@@ -0,0 +1,56 @@
+package gregtech.common.covers;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.inventory.ContainerWorkbench;
+import net.minecraft.network.play.server.S2DPacketOpenWindow;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.util.GT_CoverBehavior;
+import gregtech.api.util.ISerializableObject;
+
+public class GT_Cover_Crafting extends GT_CoverBehavior {
+
+ public GT_Cover_Crafting(ITexture coverTexture) {
+ super(coverTexture);
+ }
+
+ @Override
+ public boolean isRedstoneSensitive(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ long aTimer) {
+ return false;
+ }
+
+ @Override
+ public boolean onCoverRightclick(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ if ((aPlayer instanceof EntityPlayerMP)) {
+ ((EntityPlayerMP) aPlayer).getNextWindowId();
+ ((EntityPlayerMP) aPlayer).playerNetServerHandler.sendPacket(
+ new S2DPacketOpenWindow(((EntityPlayerMP) aPlayer).currentWindowId, 1, "Crafting", 9, true));
+ aPlayer.openContainer = new ContainerWorkbench(
+ aPlayer.inventory,
+ aPlayer.worldObj,
+ aTileEntity.getXCoord(),
+ aTileEntity.getYCoord(),
+ aTileEntity.getZCoord()) {
+
+ @Override
+ public boolean canInteractWith(EntityPlayer player) {
+ return true;
+ }
+ };
+ aPlayer.openContainer.windowId = ((EntityPlayerMP) aPlayer).currentWindowId;
+ aPlayer.openContainer.addCraftingToCrafters((EntityPlayerMP) aPlayer);
+ }
+ return true;
+ }
+
+ @Override
+ protected boolean isGUIClickableImpl(ForgeDirection side, int aCoverID,
+ ISerializableObject.LegacyCoverData aCoverVariable, ICoverable aTileEntity) {
+ return false;
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/GT_Cover_DoesWork.java b/src/main/java/gregtech/common/covers/GT_Cover_DoesWork.java
new file mode 100644
index 0000000000..4e32a69330
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/GT_Cover_DoesWork.java
@@ -0,0 +1,257 @@
+package gregtech.common.covers;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.api.gui.modularui.GT_CoverUIBuildContext;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.interfaces.tileentity.IMachineProgress;
+import gregtech.api.util.GT_CoverBehavior;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.ISerializableObject;
+import gregtech.common.gui.modularui.widget.CoverDataControllerWidget;
+import gregtech.common.gui.modularui.widget.CoverDataFollower_ToggleButtonWidget;
+
+public class GT_Cover_DoesWork extends GT_CoverBehavior {
+
+ private static int FLAG_INVERTED = 0x1;
+ private static int FLAG_PROGRESS = 0x2;
+ private static int FLAG_ENABLED = 0x4;
+
+ public GT_Cover_DoesWork(ITexture coverTexture) {
+ super(coverTexture);
+ }
+
+ @Override
+ public boolean isRedstoneSensitive(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ long aTimer) {
+ return false;
+ }
+
+ @Override
+ public int doCoverThings(ForgeDirection side, byte aInputRedstone, int aCoverID, int aCoverVariable,
+ ICoverable aTileEntity, long aTimer) {
+ if ((aTileEntity instanceof IMachineProgress)) {
+ IMachineProgress mProgress = (IMachineProgress) aTileEntity;
+ boolean inverted = isFlagSet(aCoverVariable, FLAG_INVERTED);
+ int signal = 0;
+
+ if (isFlagSet(aCoverVariable, FLAG_ENABLED)) {
+ signal = inverted == mProgress.isAllowedToWork() ? 0 : 15;
+ } else if (isFlagSet(aCoverVariable, FLAG_PROGRESS)) {
+ signal = inverted == (mProgress.getMaxProgress() == 0) ? 0 : 15;
+ } else {
+ int tScale = mProgress.getMaxProgress() / 15;
+
+ if (tScale > 0 && mProgress.hasThingsToDo()) {
+ signal = inverted ? (15 - mProgress.getProgress() / tScale) : (mProgress.getProgress() / tScale);
+ } else {
+ signal = inverted ? 15 : 0;
+ }
+ }
+
+ aTileEntity.setOutputRedstoneSignal(side, (byte) signal);
+ } else {
+ aTileEntity.setOutputRedstoneSignal(side, (byte) 0);
+ }
+ return aCoverVariable;
+ }
+
+ @Override
+ public int onCoverScrewdriverclick(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ aCoverVariable = (aCoverVariable + (aPlayer.isSneaking() ? -1 : 1)) % 6;
+ if (aCoverVariable < 0) {
+ aCoverVariable = 5;
+ }
+ switch (aCoverVariable) {
+ case 0 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("018", "Normal"));
+ // Progress scaled
+ case 1 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("019", "Inverted"));
+ // ^ inverted
+ case 2 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("020", "Ready to work"));
+ // Not Running
+ case 3 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("021", "Not ready to work"));
+ // Running
+ case 4 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("028", "Machine Enabled"));
+ // Enabled
+ case 5 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("029", "Machine Disabled"));
+ // Disabled
+ }
+ return aCoverVariable;
+ }
+
+ @Override
+ public boolean letsEnergyIn(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsEnergyOut(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsFluidIn(ForgeDirection side, int aCoverID, int aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsFluidOut(ForgeDirection side, int aCoverID, int aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsItemsIn(ForgeDirection side, int aCoverID, int aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsItemsOut(ForgeDirection side, int aCoverID, int aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean manipulatesSidedRedstoneOutput(ForgeDirection side, int aCoverID, int aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public int getTickRate(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return 5;
+ }
+
+ // GUI stuff
+
+ @Override
+ public boolean hasCoverGUI() {
+ return true;
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ @Override
+ public ModularWindow createWindow(GT_CoverUIBuildContext buildContext) {
+ return new DoesWorkUIFactory(buildContext).createWindow();
+ }
+
+ private static boolean isFlagSet(int coverVariable, int flag) {
+ return (coverVariable & flag) == flag;
+ }
+
+ private class DoesWorkUIFactory extends UIFactory {
+
+ private static final int startX = 10;
+ private static final int startY = 25;
+ private static final int spaceX = 18;
+ private static final int spaceY = 18;
+
+ public DoesWorkUIFactory(GT_CoverUIBuildContext buildContext) {
+ super(buildContext);
+ }
+
+ @SuppressWarnings("PointlessArithmeticExpression")
+ @Override
+ protected void addUIWidgets(ModularWindow.Builder builder) {
+ builder
+ .widget(
+ new CoverDataControllerWidget.CoverDataIndexedControllerWidget_ToggleButtons<>(
+ this::getCoverData,
+ this::setCoverData,
+ GT_Cover_DoesWork.this,
+ (id, coverData) -> isEnabled(id, convert(coverData)),
+ (id, coverData) -> new ISerializableObject.LegacyCoverData(
+ getNewCoverVariable(id, convert(coverData))))
+ .addToggleButton(
+ 0,
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ widget -> widget.setStaticTexture(GT_UITextures.OVERLAY_BUTTON_PROGRESS)
+ .setPos(spaceX * 0, spaceY * 0))
+ .addToggleButton(
+ 1,
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ widget -> widget.setStaticTexture(GT_UITextures.OVERLAY_BUTTON_CHECKMARK)
+ .setPos(spaceX * 1, spaceY * 0))
+ .addToggleButton(
+ 2,
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ widget -> widget.setStaticTexture(GT_UITextures.OVERLAY_BUTTON_POWER_SWITCH_ON)
+ .setPos(spaceX * 2, spaceY * 0))
+ .addToggleButton(
+ 3,
+ CoverDataFollower_ToggleButtonWidget.ofRedstone(),
+ widget -> widget.setPos(spaceX * 0, spaceY * 1))
+ .setPos(startX, startY))
+ .widget(TextWidget.dynamicString(() -> {
+ int coverVariable = convert(getCoverData());
+
+ if (isFlagSet(coverVariable, FLAG_ENABLED)) {
+ return GT_Utility.trans("271", "Machine enabled");
+ } else if (isFlagSet(coverVariable, FLAG_PROGRESS)) {
+ return GT_Utility.trans("242", "Machine idle");
+ } else {
+ return GT_Utility.trans("241", "Recipe progress");
+ }
+
+ })
+ .setSynced(false)
+ .setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * 3, 4 + startY + spaceY * 0))
+ .widget(
+ TextWidget
+ .dynamicString(
+ () -> isFlagSet(convert(getCoverData()), FLAG_INVERTED)
+ ? GT_Utility.trans("INVERTED", "Inverted")
+ : GT_Utility.trans("NORMAL", "Normal"))
+ .setSynced(false)
+ .setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * 3, 4 + startY + spaceY * 1));
+ }
+
+ private int getNewCoverVariable(int id, int coverVariable) {
+ switch (id) {
+ case 0 -> {
+ return (coverVariable & ~FLAG_ENABLED) & ~FLAG_PROGRESS;
+ }
+ case 1 -> {
+ return (coverVariable & ~FLAG_ENABLED) | FLAG_PROGRESS;
+ }
+ case 2 -> {
+ return (coverVariable & ~FLAG_PROGRESS) | FLAG_ENABLED;
+ }
+ case 3 -> {
+ if (isFlagSet(coverVariable, FLAG_INVERTED)) {
+ return coverVariable & ~FLAG_INVERTED;
+ } else {
+ return coverVariable | FLAG_INVERTED;
+ }
+ }
+ }
+ return coverVariable;
+ }
+
+ private boolean isEnabled(int id, int coverVariable) {
+ return switch (id) {
+ case 0 -> !isFlagSet(coverVariable, FLAG_PROGRESS) && !isFlagSet(coverVariable, FLAG_ENABLED);
+ case 1 -> isFlagSet(coverVariable, FLAG_PROGRESS);
+ case 2 -> isFlagSet(coverVariable, FLAG_ENABLED);
+ case 3 -> isFlagSet(coverVariable, FLAG_INVERTED);
+ default -> true;
+ };
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/GT_Cover_Drain.java b/src/main/java/gregtech/common/covers/GT_Cover_Drain.java
new file mode 100644
index 0000000000..2590f8e7ae
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/GT_Cover_Drain.java
@@ -0,0 +1,140 @@
+package gregtech.common.covers;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidStack;
+import net.minecraftforge.fluids.IFluidBlock;
+import net.minecraftforge.fluids.IFluidHandler;
+
+import gregtech.api.enums.Materials;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.interfaces.tileentity.IMachineProgress;
+import gregtech.api.util.GT_CoverBehavior;
+import gregtech.api.util.GT_Utility;
+
+public class GT_Cover_Drain extends GT_CoverBehavior {
+
+ public GT_Cover_Drain(ITexture coverTexture) {
+ super(coverTexture);
+ }
+
+ @Override
+ public boolean isRedstoneSensitive(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ long aTimer) {
+ return false;
+ }
+
+ @Override
+ public int doCoverThings(ForgeDirection side, byte aInputRedstone, int aCoverID, int aCoverVariable,
+ ICoverable aTileEntity, long aTimer) {
+ if ((aCoverVariable % 3 > 1) && ((aTileEntity instanceof IMachineProgress))) {
+ if (((IMachineProgress) aTileEntity).isAllowedToWork()) {
+ return aCoverVariable;
+ }
+ }
+ if (side != ForgeDirection.UNKNOWN) {
+ final Block tBlock = aTileEntity.getBlockAtSide(side);
+ if ((aCoverVariable < 3) && ((aTileEntity instanceof IFluidHandler))) {
+ if ((side == ForgeDirection.UP) && (aTileEntity.getWorld()
+ .isRaining())
+ && (aTileEntity.getWorld()
+ .getPrecipitationHeight(aTileEntity.getXCoord(), aTileEntity.getZCoord()) - 2
+ < aTileEntity.getYCoord())) {
+ int tAmount = (int) (aTileEntity.getBiome().rainfall * 10.0F);
+ if (tAmount > 0) {
+ ((IFluidHandler) aTileEntity).fill(
+ side,
+ Materials.Water.getFluid(
+ aTileEntity.getWorld()
+ .isThundering() ? tAmount * 2L : tAmount),
+ true);
+ }
+ }
+ FluidStack tLiquid = null;
+ if (tBlock != null) {
+ if (((tBlock == Blocks.water) || (tBlock == Blocks.flowing_water))
+ && (aTileEntity.getMetaIDAtSide(side) == 0)) {
+ tLiquid = Materials.Water.getFluid(1000L);
+ } else if (((tBlock == Blocks.lava) || (tBlock == Blocks.flowing_lava))
+ && (aTileEntity.getMetaIDAtSide(side) == 0)) {
+ tLiquid = Materials.Lava.getFluid(1000L);
+ } else if ((tBlock instanceof IFluidBlock)) {
+ tLiquid = ((IFluidBlock) tBlock).drain(
+ aTileEntity.getWorld(),
+ aTileEntity.getOffsetX(side, 1),
+ aTileEntity.getOffsetY(side, 1),
+ aTileEntity.getOffsetZ(side, 1),
+ false);
+ }
+ if ((tLiquid != null) && (tLiquid.getFluid() != null)
+ && ((side.flag & (ForgeDirection.UP.flag | ForgeDirection.DOWN.flag)) == 0 // Horizontal
+ || ((side == ForgeDirection.DOWN) && (tLiquid.getFluid()
+ .getDensity() <= 0))
+ || ((side == ForgeDirection.UP) && (tLiquid.getFluid()
+ .getDensity() >= 0)))
+ && (((IFluidHandler) aTileEntity).fill(side, tLiquid, false) == tLiquid.amount)) {
+ ((IFluidHandler) aTileEntity).fill(side, tLiquid, true);
+ aTileEntity.getWorld()
+ .setBlockToAir(
+ aTileEntity.getXCoord() + side.offsetX,
+ aTileEntity.getYCoord() + side.offsetY,
+ aTileEntity.getZCoord() + side.offsetZ);
+ }
+ }
+ }
+ if ((aCoverVariable >= 3) && (tBlock != null)
+ && ((tBlock == Blocks.lava) || (tBlock == Blocks.flowing_lava)
+ || (tBlock == Blocks.water)
+ || (tBlock == Blocks.flowing_water)
+ || ((tBlock instanceof IFluidBlock)))) {
+ aTileEntity.getWorld()
+ .setBlock(
+ aTileEntity.getOffsetX(side, 1),
+ aTileEntity.getOffsetY(side, 1),
+ aTileEntity.getOffsetZ(side, 1),
+ Blocks.air,
+ 0,
+ 0);
+ }
+ }
+ return aCoverVariable;
+ }
+
+ @Override
+ public int onCoverScrewdriverclick(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ aCoverVariable = (aCoverVariable + (aPlayer.isSneaking() ? -1 : 1)) % 6;
+ if (aCoverVariable < 0) {
+ aCoverVariable = 5;
+ }
+ switch (aCoverVariable) {
+ case 0 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("022", "Import"));
+ case 1 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("023", "Import (conditional)"));
+ case 2 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("024", "Import (invert cond)"));
+ case 3 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("025", "Keep Liquids Away"));
+ case 4 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("026", "Keep Liquids Away (conditional)"));
+ case 5 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("027", "Keep Liquids Away (invert cond)"));
+ }
+ return aCoverVariable;
+ }
+
+ @Override
+ public boolean letsFluidIn(ForgeDirection side, int aCoverID, int aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return ((IMachineProgress) aTileEntity).isAllowedToWork() == aCoverVariable < 2;
+ }
+
+ @Override
+ public boolean alwaysLookConnected(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public int getTickRate(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return aCoverVariable < 3 ? 50 : 1;
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/GT_Cover_EUMeter.java b/src/main/java/gregtech/common/covers/GT_Cover_EUMeter.java
new file mode 100644
index 0000000000..0010f7745b
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/GT_Cover_EUMeter.java
@@ -0,0 +1,415 @@
+package gregtech.common.covers;
+
+import java.util.function.Function;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.nbt.NBTBase;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+
+import com.google.common.io.ByteArrayDataInput;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.api.gui.modularui.GT_CoverUIBuildContext;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicBatteryBuffer;
+import gregtech.api.util.GT_CoverBehaviorBase;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.ISerializableObject;
+import gregtech.common.gui.modularui.widget.CoverDataControllerWidget;
+import gregtech.common.gui.modularui.widget.CoverDataFollower_CycleButtonWidget;
+import gregtech.common.gui.modularui.widget.CoverDataFollower_NumericWidget;
+import gregtech.common.gui.modularui.widget.CoverDataFollower_ToggleButtonWidget;
+import io.netty.buffer.ByteBuf;
+
+public class GT_Cover_EUMeter extends GT_CoverBehaviorBase<GT_Cover_EUMeter.EUMeterData> {
+
+ public GT_Cover_EUMeter(ITexture coverTexture) {
+ super(EUMeterData.class, coverTexture);
+ }
+
+ @Override
+ public EUMeterData createDataObject(int aLegacyData) {
+ return new EUMeterData(aLegacyData, 0);
+ }
+
+ @Override
+ public EUMeterData createDataObject() {
+ return new EUMeterData();
+ }
+
+ @Override
+ protected EUMeterData doCoverThingsImpl(ForgeDirection side, byte aInputRedstone, int aCoverID,
+ EUMeterData aCoverVariable, ICoverable aTileEntity, long aTimer) {
+ final long stored = aCoverVariable.type.getTileEntityStoredEnergy(aTileEntity);
+ final long capacity = aCoverVariable.type.getTileEntityEnergyCapacity(aTileEntity);
+
+ byte redstoneSignal;
+
+ if (stored == 0L) {
+ // nothing
+ redstoneSignal = 0;
+ } else if (stored >= capacity) {
+ // full
+ redstoneSignal = 15;
+ } else {
+ // 1-14 range
+ redstoneSignal = (byte) (1 + (14 * stored) / capacity);
+ }
+
+ if (aCoverVariable.inverted) {
+ redstoneSignal = (byte) (15 - redstoneSignal);
+ }
+
+ if (aCoverVariable.threshold > 0) {
+ if (aCoverVariable.inverted && stored >= aCoverVariable.threshold) {
+ redstoneSignal = 0;
+ } else if (!aCoverVariable.inverted && stored < aCoverVariable.threshold) {
+ redstoneSignal = 0;
+ }
+ }
+
+ aTileEntity.setOutputRedstoneSignal(side, redstoneSignal);
+ return aCoverVariable;
+ }
+
+ @Override
+ protected EUMeterData onCoverScrewdriverClickImpl(ForgeDirection side, int aCoverID, EUMeterData aCoverVariable,
+ ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ int num = (aCoverVariable.getNum() + (aPlayer.isSneaking() ? -1 : 1) + EnergyType.values().length * 2)
+ % (EnergyType.values().length * 2);
+ switch (num) {
+ case 0 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("031", "Normal Universal Storage"));
+ case 1 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("032", "Inverted Universal Storage"));
+ case 2 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("033", "Normal Electricity Storage"));
+ case 3 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("034", "Inverted Electricity Storage"));
+ case 4 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("035", "Normal Steam Storage"));
+ case 5 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("036", "Inverted Steam Storage"));
+ case 6 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("037", "Normal Average Electric Input"));
+ case 7 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("038", "Inverted Average Electric Input"));
+ case 8 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("039", "Normal Average Electric Output"));
+ case 9 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("040", "Inverted Average Electric Output"));
+ case 10 -> GT_Utility
+ .sendChatToPlayer(aPlayer, GT_Utility.trans("041", "Normal Electricity Storage(Including Batteries)"));
+ case 11 -> GT_Utility.sendChatToPlayer(
+ aPlayer,
+ GT_Utility.trans("042", "Inverted Electricity Storage(Including Batteries)"));
+ }
+ aCoverVariable.setNum(num);
+ return aCoverVariable;
+ }
+
+ // region Static Result Methods
+ @Override
+ protected boolean isRedstoneSensitiveImpl(ForgeDirection side, int aCoverID, EUMeterData aCoverVariable,
+ ICoverable aTileEntity, long aTimer) {
+ return false;
+ }
+
+ @Override
+ protected boolean letsEnergyInImpl(ForgeDirection side, int aCoverID, EUMeterData aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected boolean letsEnergyOutImpl(ForgeDirection side, int aCoverID, EUMeterData aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected boolean letsFluidInImpl(ForgeDirection side, int aCoverID, EUMeterData aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected boolean letsFluidOutImpl(ForgeDirection side, int aCoverID, EUMeterData aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected boolean letsItemsInImpl(ForgeDirection side, int aCoverID, EUMeterData aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected boolean letsItemsOutImpl(ForgeDirection side, int aCoverID, EUMeterData aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected boolean manipulatesSidedRedstoneOutputImpl(ForgeDirection side, int aCoverID, EUMeterData aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected int getTickRateImpl(ForgeDirection side, int aCoverID, EUMeterData aCoverVariable,
+ ICoverable aTileEntity) {
+ return 20;
+ }
+ // endregion
+
+ // region GUI Stuff
+ @Override
+ public boolean hasCoverGUI() {
+ return true;
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ @Override
+ public ModularWindow createWindow(GT_CoverUIBuildContext buildContext) {
+ return new EUMeterUIFactory(buildContext).createWindow();
+ }
+
+ private class EUMeterUIFactory extends UIFactory {
+
+ private static final int startX = 10;
+ private static final int startY = 25;
+ private static final int spaceX = 18;
+ private static final int spaceY = 18;
+
+ public EUMeterUIFactory(GT_CoverUIBuildContext buildContext) {
+ super(buildContext);
+ }
+
+ @SuppressWarnings("PointlessArithmeticExpression")
+ @Override
+ protected void addUIWidgets(ModularWindow.Builder builder) {
+ final String INVERTED = GT_Utility.trans("INVERTED", "Inverted");
+ final String NORMAL = GT_Utility.trans("NORMAL", "Normal");
+
+ final CoverDataFollower_NumericWidget<EUMeterData> numericWidget = new CoverDataFollower_NumericWidget<>();
+
+ builder.widget(
+ new CoverDataControllerWidget<>(this::getCoverData, this::setCoverData, GT_Cover_EUMeter.this)
+ .addFollower(
+ new CoverDataFollower_CycleButtonWidget<>(),
+ coverData -> coverData.type.ordinal(),
+ (coverData, state) -> {
+ coverData.type = EnergyType.getEnergyType(state);
+ return coverData;
+ },
+ widget -> widget.setLength(EnergyType.values().length)
+ .addTooltip(
+ state -> EnergyType.getEnergyType(state)
+ .getTooltip())
+ .setStaticTexture(GT_UITextures.OVERLAY_BUTTON_CYCLIC)
+ .setPos(spaceX * 0, spaceY * 0))
+ .addFollower(
+ CoverDataFollower_ToggleButtonWidget.ofRedstone(),
+ coverData -> coverData.inverted,
+ (coverData, state) -> {
+ coverData.inverted = state;
+ return coverData;
+ },
+ widget -> widget.addTooltip(0, NORMAL)
+ .addTooltip(1, INVERTED)
+ .setPos(spaceX * 0, spaceY * 1))
+ .addFollower(numericWidget, coverData -> (double) coverData.threshold, (coverData, state) -> {
+ coverData.threshold = state.longValue();
+ return coverData;
+ },
+ widget -> widget.setScrollValues(1000, 100, 100000)
+ .setFocusOnGuiOpen(true)
+ .setPos(spaceX * 0, spaceY * 2 + 2)
+ .setSize(spaceX * 8, 12))
+ .setPos(startX, startY))
+ .widget(
+ new TextWidget()
+ .setStringSupplier(() -> getCoverData() != null ? getCoverData().type.getTitle() : "")
+ .setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX, 4 + startY))
+ .widget(
+ new TextWidget()
+ .setStringSupplier(
+ () -> getCoverData() != null ? getCoverData().inverted ? INVERTED : NORMAL : "")
+ .setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX, 4 + startY + spaceY))
+ .widget(
+ new TextWidget(GT_Utility.trans("222.1", "Energy threshold")).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX, startY + spaceY * 3 + 4))
+
+ .widget(
+ new FakeSyncWidget.LongSyncer(
+ () -> getCoverData() != null
+ ? getCoverData().type.getTileEntityEnergyCapacity(getUIBuildContext().getTile())
+ : Long.MAX_VALUE,
+ value -> numericWidget.setMaxValue(value)));
+ }
+ }
+
+ // endregion
+
+ public static class EUMeterData implements ISerializableObject {
+
+ private EnergyType type;
+ private boolean inverted;
+ /**
+ * The special value {@code 0} means threshold check is disabled.
+ */
+ private long threshold;
+
+ public EUMeterData() {
+ type = EnergyType.UNIVERSAL_STORAGE;
+ inverted = false;
+ threshold = 0;
+ }
+
+ public EUMeterData(EnergyType type, boolean inverted, long threshold) {
+ this.type = type;
+ this.inverted = inverted;
+ this.threshold = threshold;
+ }
+
+ public EUMeterData(int num, long threshold) {
+ this();
+ this.setNum(num);
+ this.threshold = threshold;
+ }
+
+ public int getNum() {
+ return type.ordinal() * 2 + (inverted ? 1 : 0);
+ }
+
+ public void setNum(int num) {
+ type = EnergyType.getEnergyType(num / 2);
+ inverted = num % 2 == 1;
+ }
+
+ @Nonnull
+ @Override
+ public ISerializableObject copy() {
+ return new EUMeterData(type, inverted, threshold);
+ }
+
+ @Nonnull
+ @Override
+ public NBTBase saveDataToNBT() {
+ NBTTagCompound tag = new NBTTagCompound();
+ tag.setInteger("typeOrdinal", type.ordinal());
+ tag.setBoolean("inverted", inverted);
+ tag.setLong("threshold", threshold);
+ return tag;
+ }
+
+ @Override
+ public void writeToByteBuf(ByteBuf aBuf) {
+ aBuf.writeInt(type.ordinal());
+ aBuf.writeBoolean(inverted);
+ aBuf.writeLong(threshold);
+ }
+
+ @Override
+ public void loadDataFromNBT(NBTBase aNBT) {
+ NBTTagCompound tag = (NBTTagCompound) aNBT;
+ int typeOrdinal = tag.getInteger("typeOrdinal");
+ type = EnergyType.getEnergyType(typeOrdinal);
+ inverted = tag.getBoolean("inverted");
+ threshold = tag.getLong("threshold");
+ }
+
+ @Nonnull
+ @Override
+ public ISerializableObject readFromPacket(ByteArrayDataInput aBuf, @Nullable EntityPlayerMP aPlayer) {
+ int typeOrdinal = aBuf.readInt();
+ type = EnergyType.getEnergyType(typeOrdinal);
+ inverted = aBuf.readBoolean();
+ threshold = aBuf.readLong();
+ return this;
+ }
+ }
+
+ private enum EnergyType {
+
+ UNIVERSAL_STORAGE(GT_Utility.trans("301", "Universal"), GT_Utility.trans("256", "Universal Storage"),
+ ICoverable::getUniversalEnergyStored, ICoverable::getUniversalEnergyCapacity),
+ ELECTRICITY_STORAGE(GT_Utility.trans("302", "Int. EU"), GT_Utility.trans("257", "Electricity Storage"),
+ ICoverable::getStoredEU, ICoverable::getEUCapacity),
+ STEAM_STORAGE(GT_Utility.trans("303", "Steam"), GT_Utility.trans("258", "Steam Storage"),
+ ICoverable::getStoredSteam, ICoverable::getSteamCapacity),
+ AVERAGE_ELECTRIC_INPUT(GT_Utility.trans("304", "Avg. Input"), GT_Utility.trans("259", "Average Electric Input"),
+ ICoverable::getAverageElectricInput, (te) -> te.getInputVoltage() * te.getInputAmperage()),
+ AVERAGE_ELECTRIC_OUTPUT(GT_Utility.trans("305", "Avg. Output"),
+ GT_Utility.trans("260", "Average Electric Output"), ICoverable::getAverageElectricOutput,
+ (te) -> te.getOutputVoltage() * te.getOutputAmperage()),
+ ELECTRICITY_STORAGE_INCLUDING_BATTERIES(GT_Utility.trans("306", "EU stored"),
+ GT_Utility.trans("261", "Electricity Storage(Including Batteries)"), (te) -> {
+ if (te instanceof IGregTechTileEntity) {
+ IMetaTileEntity mte = ((IGregTechTileEntity) te).getMetaTileEntity();
+ if (mte instanceof GT_MetaTileEntity_BasicBatteryBuffer buffer) {
+ return buffer.getStoredEnergy()[0];
+ }
+ }
+ return te.getStoredEU();
+ }, (te) -> {
+ if (te instanceof IGregTechTileEntity) {
+ IMetaTileEntity mte = ((IGregTechTileEntity) te).getMetaTileEntity();
+ if (mte instanceof GT_MetaTileEntity_BasicBatteryBuffer buffer) {
+ return buffer.getStoredEnergy()[1];
+ }
+ }
+ return te.getEUCapacity();
+ });
+
+ private final String title;
+ private final String tooltip;
+ private final Function<ICoverable, Long> getTileEntityStoredEnergyFunc;
+ private final Function<ICoverable, Long> getTileEntityEnergyCapacityFunc;
+
+ EnergyType(String title, String tooltip, Function<ICoverable, Long> getTileEntityStoredEnergyFunc,
+ Function<ICoverable, Long> getTileEntityEnergyCapacityFunc) {
+ this.title = title;
+ this.tooltip = tooltip;
+ this.getTileEntityStoredEnergyFunc = getTileEntityStoredEnergyFunc;
+ this.getTileEntityEnergyCapacityFunc = getTileEntityEnergyCapacityFunc;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public String getTooltip() {
+ return tooltip;
+ }
+
+ public long getTileEntityStoredEnergy(ICoverable aTileEntity) {
+ return getTileEntityStoredEnergyFunc.apply(aTileEntity);
+ }
+
+ public long getTileEntityEnergyCapacity(ICoverable aTileEntity) {
+ return getTileEntityEnergyCapacityFunc.apply(aTileEntity);
+ }
+
+ public EnergyType getNext() {
+ return values()[(ordinal() + 1) % values().length];
+ }
+
+ public static EnergyType getEnergyType(int ordinal) {
+ if (ordinal < 0 || values().length <= ordinal) {
+ ordinal = 0;
+ }
+ return values()[ordinal];
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/GT_Cover_FacadeAE.java b/src/main/java/gregtech/common/covers/GT_Cover_FacadeAE.java
new file mode 100644
index 0000000000..da6c2c9cfa
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/GT_Cover_FacadeAE.java
@@ -0,0 +1,31 @@
+package gregtech.common.covers;
+
+import net.minecraft.block.Block;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+
+import appeng.facade.IFacadeItem;
+
+public class GT_Cover_FacadeAE extends GT_Cover_FacadeBase {
+
+ @Override
+ protected Block getTargetBlock(ItemStack aFacadeStack) {
+ if (aFacadeStack == null) return null;
+ final Item item = aFacadeStack.getItem();
+ if (!(item instanceof IFacadeItem)) return null;
+ return ((IFacadeItem) item).getBlock(aFacadeStack);
+ }
+
+ @Override
+ protected int getTargetMeta(ItemStack aFacadeStack) {
+ if (aFacadeStack == null) return 0;
+ final Item item = aFacadeStack.getItem();
+ if (!(item instanceof IFacadeItem)) return 0;
+ return ((IFacadeItem) item).getMeta(aFacadeStack);
+ }
+
+ @Override
+ protected ItemStack getDisplayStackImpl(int aCoverID, FacadeData aCoverVariable) {
+ return aCoverVariable.mStack;
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/GT_Cover_FacadeBase.java b/src/main/java/gregtech/common/covers/GT_Cover_FacadeBase.java
new file mode 100644
index 0000000000..a8d853dc1b
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/GT_Cover_FacadeBase.java
@@ -0,0 +1,401 @@
+package gregtech.common.covers;
+
+import javax.annotation.Nonnull;
+
+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.NBTBase;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+
+import com.google.common.io.ByteArrayDataInput;
+import com.gtnewhorizons.modularui.api.drawable.ItemDrawable;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import cpw.mods.fml.common.network.ByteBufUtils;
+import gregtech.api.enums.Textures;
+import gregtech.api.gui.modularui.GT_CoverUIBuildContext;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_CoverBehaviorBase;
+import gregtech.api.util.GT_RenderingWorld;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.ISerializableObject;
+import gregtech.common.gui.modularui.widget.CoverDataControllerWidget;
+import gregtech.common.gui.modularui.widget.CoverDataFollower_ToggleButtonWidget;
+import io.netty.buffer.ByteBuf;
+
+public abstract class GT_Cover_FacadeBase extends GT_CoverBehaviorBase<GT_Cover_FacadeBase.FacadeData> {
+
+ /**
+ * This is the Dummy, if there is a generic Cover without behavior
+ */
+ public GT_Cover_FacadeBase() {
+ super(FacadeData.class);
+ }
+
+ @Override
+ public boolean isSimpleCover() {
+ return true;
+ }
+
+ @Override
+ public FacadeData createDataObject(int aLegacyData) {
+ return new FacadeData();
+ }
+
+ @Override
+ public FacadeData createDataObject() {
+ return new FacadeData();
+ }
+
+ @Override
+ protected FacadeData onCoverScrewdriverClickImpl(ForgeDirection side, int aCoverID, FacadeData aCoverVariable,
+ ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ aCoverVariable.mFlags = ((aCoverVariable.mFlags + 1) & 15);
+ GT_Utility.sendChatToPlayer(
+ aPlayer,
+ ((aCoverVariable.mFlags & 1) != 0 ? GT_Utility.trans("128.1", "Redstone ") : "")
+ + ((aCoverVariable.mFlags & 2) != 0 ? GT_Utility.trans("129.1", "Energy ") : "")
+ + ((aCoverVariable.mFlags & 4) != 0 ? GT_Utility.trans("130.1", "Fluids ") : "")
+ + ((aCoverVariable.mFlags & 8) != 0 ? GT_Utility.trans("131.1", "Items ") : ""));
+ return aCoverVariable;
+ }
+
+ @Override
+ protected boolean letsRedstoneGoInImpl(ForgeDirection side, int aCoverID, FacadeData aCoverVariable,
+ ICoverable aTileEntity) {
+ return (aCoverVariable.mFlags & 1) != 0;
+ }
+
+ @Override
+ protected boolean letsRedstoneGoOutImpl(ForgeDirection side, int aCoverID, FacadeData aCoverVariable,
+ ICoverable aTileEntity) {
+ return (aCoverVariable.mFlags & 1) != 0;
+ }
+
+ @Override
+ protected boolean letsEnergyInImpl(ForgeDirection side, int aCoverID, FacadeData aCoverVariable,
+ ICoverable aTileEntity) {
+ return (aCoverVariable.mFlags & 2) != 0;
+ }
+
+ @Override
+ protected boolean letsEnergyOutImpl(ForgeDirection side, int aCoverID, FacadeData aCoverVariable,
+ ICoverable aTileEntity) {
+ return (aCoverVariable.mFlags & 2) != 0;
+ }
+
+ @Override
+ protected boolean letsFluidInImpl(ForgeDirection side, int aCoverID, FacadeData aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return (aCoverVariable.mFlags & 4) != 0;
+ }
+
+ @Override
+ protected boolean letsFluidOutImpl(ForgeDirection side, int aCoverID, FacadeData aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return (aCoverVariable.mFlags & 4) != 0;
+ }
+
+ @Override
+ protected boolean letsItemsInImpl(ForgeDirection side, int aCoverID, FacadeData aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return (aCoverVariable.mFlags & 8) != 0;
+ }
+
+ @Override
+ protected boolean letsItemsOutImpl(ForgeDirection side, int aCoverID, FacadeData aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return (aCoverVariable.mFlags & 8) != 0;
+ }
+
+ @Override
+ public void placeCover(ForgeDirection side, ItemStack aCover, ICoverable aTileEntity) {
+ aTileEntity.setCoverIdAndDataAtSide(
+ side,
+ GT_Utility.stackToInt(aCover),
+ new FacadeData(GT_Utility.copyAmount(1, aCover), 0));
+
+ if (aTileEntity.isClientSide()) GT_RenderingWorld.getInstance()
+ .register(
+ aTileEntity.getXCoord(),
+ aTileEntity.getYCoord(),
+ aTileEntity.getZCoord(),
+ getTargetBlock(aCover),
+ getTargetMeta(aCover));
+ }
+
+ @Override
+ protected ItemStack getDropImpl(ForgeDirection side, int aCoverID, FacadeData aCoverVariable,
+ ICoverable aTileEntity) {
+ return aCoverVariable.mStack;
+ }
+
+ @Override
+ protected ITexture getSpecialCoverFGTextureImpl(ForgeDirection side, int aCoverID, FacadeData aCoverVariable,
+ ICoverable aTileEntity) {
+ return getSpecialCoverTextureImpl(side, aCoverID, aCoverVariable, aTileEntity);
+ }
+
+ @Override
+ protected ITexture getSpecialCoverTextureImpl(ForgeDirection side, int aCoverID, FacadeData aCoverVariable,
+ ICoverable aTileEntity) {
+ if (GT_Utility.isStackInvalid(aCoverVariable.mStack)) return Textures.BlockIcons.ERROR_RENDERING[0];
+ Block block = getTargetBlock(aCoverVariable.mStack);
+ if (block == null) return Textures.BlockIcons.ERROR_RENDERING[0];
+ // TODO: change this when *someone* made the block render in both pass
+ if (block.getRenderBlockPass() != 0) return Textures.BlockIcons.ERROR_RENDERING[0];
+ return TextureFactory.builder()
+ .setFromBlock(block, getTargetMeta(aCoverVariable.mStack))
+ .useWorldCoord()
+ .setFromSide(side)
+ .build();
+ }
+
+ @Override
+ protected Block getFacadeBlockImpl(ForgeDirection side, int aCoverID, FacadeData aCoverVariable,
+ ICoverable aTileEntity) {
+ if (GT_Utility.isStackInvalid(aCoverVariable.mStack)) return null;
+ return getTargetBlock(aCoverVariable.mStack);
+ }
+
+ @Override
+ protected int getFacadeMetaImpl(ForgeDirection side, int aCoverID, FacadeData aCoverVariable,
+ ICoverable aTileEntity) {
+ if (GT_Utility.isStackInvalid(aCoverVariable.mStack)) return 0;
+ return getTargetMeta(aCoverVariable.mStack);
+ }
+
+ protected abstract Block getTargetBlock(ItemStack aFacadeStack);
+
+ protected abstract int getTargetMeta(ItemStack aFacadeStack);
+
+ @Override
+ protected boolean isDataNeededOnClientImpl(ForgeDirection side, int aCoverID, FacadeData aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected void onDataChangedImpl(ForgeDirection side, int aCoverID, FacadeData aCoverVariable,
+ ICoverable aTileEntity) {
+ if (aTileEntity.isClientSide()) GT_RenderingWorld.getInstance()
+ .register(
+ aTileEntity.getXCoord(),
+ aTileEntity.getYCoord(),
+ aTileEntity.getZCoord(),
+ getTargetBlock(aCoverVariable.mStack),
+ getTargetMeta(aCoverVariable.mStack));
+ }
+
+ @Override
+ protected void onDroppedImpl(ForgeDirection side, int aCoverID, FacadeData aCoverVariable, ICoverable aTileEntity) {
+ if (aTileEntity.isClientSide()) {
+ for (final ForgeDirection iSide : ForgeDirection.VALID_DIRECTIONS) {
+ if (iSide == side) continue;
+ // since we do not allow multiple type of facade per block, this check would be enough.
+ if (aTileEntity.getCoverBehaviorAtSideNew(iSide) instanceof GT_Cover_FacadeBase) return;
+ }
+ if (aCoverVariable.mStack != null)
+ // mStack == null -> cover removed before data reach client
+ GT_RenderingWorld.getInstance()
+ .unregister(
+ aTileEntity.getXCoord(),
+ aTileEntity.getYCoord(),
+ aTileEntity.getZCoord(),
+ getTargetBlock(aCoverVariable.mStack),
+ getTargetMeta(aCoverVariable.mStack));
+ }
+ }
+
+ @Override
+ protected boolean onCoverRightClickImpl(ForgeDirection side, int aCoverID, FacadeData aCoverVariable,
+ ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ // in case cover data didn't hit client somehow. maybe he had a ridiculous view distance
+ aTileEntity.issueCoverUpdate(side);
+ return super.onCoverRightClickImpl(side, aCoverID, aCoverVariable, aTileEntity, aPlayer, aX, aY, aZ);
+ }
+
+ @Override
+ public boolean isCoverPlaceable(ForgeDirection side, ItemStack aStack, ICoverable aTileEntity) {
+ // blocks that are not rendered in pass 0 are now accepted but rendered awkwardly
+ // to render it correctly require changing GT_Block_Machine to render in both pass, which is not really a good
+ // idea...
+ if (!super.isCoverPlaceable(side, aStack, aTileEntity)) return false;
+ final Block targetBlock = getTargetBlock(aStack);
+ if (targetBlock == null) return false;
+ // we allow one single type of facade on the same block for now
+ // otherwise it's not clear which block this block should impersonate
+ // this restriction can be lifted later by specifying a certain facade as dominate one as an extension to this
+ // class
+ for (final ForgeDirection iSide : ForgeDirection.VALID_DIRECTIONS) {
+ if (iSide == side) continue;
+ final CoverInfo coverInfo = aTileEntity.getCoverInfoAtSide(iSide);
+ if (!coverInfo.isValid()) continue;
+ final Block facadeBlock = coverInfo.getFacadeBlock();
+ if (facadeBlock == null) continue;
+ if (facadeBlock != targetBlock) return false;
+ if (coverInfo.getFacadeMeta() != getTargetMeta(aStack)) return false;
+ }
+ return true;
+ }
+
+ public static class FacadeData implements ISerializableObject {
+
+ ItemStack mStack;
+ int mFlags;
+
+ public FacadeData() {}
+
+ public FacadeData(ItemStack mStack, int mFlags) {
+ this.mStack = mStack;
+ this.mFlags = mFlags;
+ }
+
+ @Nonnull
+ @Override
+ public ISerializableObject copy() {
+ return new FacadeData(mStack, mFlags);
+ }
+
+ @Nonnull
+ @Override
+ public NBTBase saveDataToNBT() {
+ final NBTTagCompound tag = new NBTTagCompound();
+ if (mStack != null) tag.setTag("mStack", mStack.writeToNBT(new NBTTagCompound()));
+ tag.setByte("mFlags", (byte) mFlags);
+ return tag;
+ }
+
+ @Override
+ public void writeToByteBuf(ByteBuf aBuf) {
+ ByteBufUtils.writeItemStack(aBuf, mStack);
+ aBuf.writeByte(mFlags);
+ }
+
+ @Override
+ public void loadDataFromNBT(NBTBase aNBT) {
+ final NBTTagCompound tag = (NBTTagCompound) aNBT;
+ mStack = ItemStack.loadItemStackFromNBT(tag.getCompoundTag("mStack"));
+ mFlags = tag.getByte("mFlags");
+ }
+
+ @Nonnull
+ @Override
+ public ISerializableObject readFromPacket(ByteArrayDataInput aBuf, EntityPlayerMP aPlayer) {
+ mStack = ISerializableObject.readItemStackFromGreggyByteBuf(aBuf);
+ mFlags = aBuf.readByte();
+ return this;
+ }
+ }
+
+ // GUI stuff
+
+ @Override
+ public boolean hasCoverGUI() {
+ return true;
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ @Override
+ public ModularWindow createWindow(GT_CoverUIBuildContext buildContext) {
+ return new FacadeBaseUIFactory(buildContext).createWindow();
+ }
+
+ private class FacadeBaseUIFactory extends UIFactory {
+
+ private static final int startX = 10;
+ private static final int startY = 25;
+ private static final int spaceX = 18;
+ private static final int spaceY = 18;
+
+ public FacadeBaseUIFactory(GT_CoverUIBuildContext buildContext) {
+ super(buildContext);
+ }
+
+ @SuppressWarnings("PointlessArithmeticExpression")
+ @Override
+ protected void addUIWidgets(ModularWindow.Builder builder) {
+ builder.widget(
+ new CoverDataControllerWidget.CoverDataIndexedControllerWidget_ToggleButtons<>(
+ this::getCoverData,
+ this::setCoverData,
+ GT_Cover_FacadeBase.this,
+ this::isEnabled,
+ (id, coverData) -> {
+ coverData.mFlags = getNewCoverVariable(id, coverData);
+ return coverData;
+ }).addToggleButton(
+ 0,
+ CoverDataFollower_ToggleButtonWidget.ofCheckAndCross(),
+ widget -> widget.setPos(spaceX * 0, spaceY * 0))
+ .addToggleButton(
+ 1,
+ CoverDataFollower_ToggleButtonWidget.ofCheckAndCross(),
+ widget -> widget.setPos(spaceX * 0, spaceY * 1))
+ .addToggleButton(
+ 2,
+ CoverDataFollower_ToggleButtonWidget.ofCheckAndCross(),
+ widget -> widget.setPos(spaceX * 0, spaceY * 2))
+ .addToggleButton(
+ 3,
+ CoverDataFollower_ToggleButtonWidget.ofCheckAndCross(),
+ widget -> widget.setPos(spaceX * 0, spaceY * 3))
+ .setPos(startX, startY))
+ .widget(
+ new ItemDrawable(() -> getCoverData() != null ? getCoverData().mStack : null).asWidget()
+ .setPos(5, 5)
+ .setSize(16, 16))
+ .widget(
+ TextWidget.dynamicString(() -> getCoverData() != null ? getCoverData().mStack.getDisplayName() : "")
+ .setSynced(false)
+ .setDefaultColor(COLOR_TITLE.get())
+ .setPos(25, 9))
+ .widget(
+ new TextWidget(GT_Utility.trans("128", "Redstone")).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(3 + startX + spaceX * 1, 4 + startY + spaceY * 0))
+ .widget(
+ new TextWidget(GT_Utility.trans("129", "Energy")).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(3 + startX + spaceX * 1, 4 + startY + spaceY * 1))
+ .widget(
+ new TextWidget(GT_Utility.trans("130", "Fluids")).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(3 + startX + spaceX * 1, 4 + startY + spaceY * 2))
+ .widget(
+ new TextWidget(GT_Utility.trans("131", "Items")).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(3 + startX + spaceX * 1, 4 + startY + spaceY * 3));
+ }
+
+ @Override
+ protected void addTitleToUI(ModularWindow.Builder builder) {}
+
+ private int getNewCoverVariable(int id, FacadeData coverVariable) {
+ return switch (id) {
+ case 0 -> coverVariable.mFlags ^ 0x1;
+ case 1 -> coverVariable.mFlags ^ 0x2;
+ case 2 -> coverVariable.mFlags ^ 0x4;
+ case 3 -> coverVariable.mFlags ^ 0x8;
+ default -> coverVariable.mFlags;
+ };
+ }
+
+ private boolean isEnabled(int id, FacadeData coverVariable) {
+ return switch (id) {
+ case 0 -> (coverVariable.mFlags & 0x1) > 0;
+ case 1 -> (coverVariable.mFlags & 0x2) > 0;
+ case 2 -> (coverVariable.mFlags & 0x4) > 0;
+ case 3 -> (coverVariable.mFlags & 0x8) > 0;
+ default -> false;
+ };
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/GT_Cover_FluidLimiter.java b/src/main/java/gregtech/common/covers/GT_Cover_FluidLimiter.java
new file mode 100644
index 0000000000..142cb875c3
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/GT_Cover_FluidLimiter.java
@@ -0,0 +1,207 @@
+package gregtech.common.covers;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.nbt.NBTBase;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidTankInfo;
+import net.minecraftforge.fluids.IFluidHandler;
+
+import com.google.common.io.ByteArrayDataInput;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.api.gui.modularui.GT_CoverUIBuildContext;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.util.GT_CoverBehaviorBase;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.ISerializableObject;
+import gregtech.common.gui.modularui.widget.CoverDataControllerWidget;
+import gregtech.common.gui.modularui.widget.CoverDataFollower_NumericWidget;
+import io.netty.buffer.ByteBuf;
+
+/***
+ * @author TrainerSnow#5086
+ */
+public class GT_Cover_FluidLimiter extends GT_CoverBehaviorBase<GT_Cover_FluidLimiter.FluidLimiterData> {
+
+ public GT_Cover_FluidLimiter(ITexture coverTexture) {
+ super(FluidLimiterData.class, coverTexture);
+ }
+
+ @Override
+ protected FluidLimiterData onCoverScrewdriverClickImpl(ForgeDirection side, int aCoverID,
+ FluidLimiterData aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ if (aTileEntity instanceof IFluidHandler) {
+ adjustThreshold(aCoverVariable, !aPlayer.isSneaking());
+ GT_Utility.sendChatToPlayer(aPlayer, String.format("Threshold: %f", aCoverVariable.threshold));
+ }
+ return aCoverVariable;
+ }
+
+ @Override
+ protected boolean letsFluidInImpl(ForgeDirection side, int aCoverID, FluidLimiterData aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return allowsFluidIn(aCoverVariable, aTileEntity);
+ }
+
+ @Override
+ protected boolean alwaysLookConnectedImpl(ForgeDirection side, int aCoverID, FluidLimiterData aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ /*
+ * Helpers
+ */
+
+ private boolean allowsFluidIn(FluidLimiterData aCoverVariable, ICoverable c) {
+ if (c instanceof IFluidHandler) {
+ return aCoverVariable.threshold > getFillLevelInputSlots((IFluidHandler) c);
+ }
+ return false;
+ }
+
+ private void adjustThreshold(FluidLimiterData coverVariable, boolean way) {
+ if (way) {
+ if ((coverVariable.threshold + 0.05f) > 1F) {
+ coverVariable.threshold = 0F;
+ return;
+ }
+ coverVariable.threshold += 0.05F;
+ } else {
+ if ((Math.abs(coverVariable.threshold) - 0.05F) < 0F) {
+ coverVariable.threshold = 1F;
+ return;
+ }
+ coverVariable.threshold -= 0.05F;
+ }
+ }
+
+ private float getFillLevelInputSlots(IFluidHandler fh) {
+ FluidTankInfo[] tankInfo = fh.getTankInfo(ForgeDirection.UNKNOWN);
+ long tMax;
+ long tUsed;
+ if (tankInfo != null) {
+ // 0 Because we acces first slot only
+ FluidTankInfo inputSlot = tankInfo[0];
+ if (inputSlot.fluid != null) {
+ tMax = inputSlot.capacity;
+ tUsed = inputSlot.fluid.amount;
+ return (float) tUsed / (float) tMax;
+ }
+ }
+ return 0F;
+ }
+
+ /*
+ * Data
+ */
+
+ @Override
+ public FluidLimiterData createDataObject(int aLegacyData) {
+ return createDataObject();
+ }
+
+ @Override
+ public FluidLimiterData createDataObject() {
+ return new FluidLimiterData(1F);
+ }
+
+ public static class FluidLimiterData implements ISerializableObject {
+
+ private float threshold;
+
+ public FluidLimiterData(float threshold) {
+ this.threshold = threshold;
+ }
+
+ @Nonnull
+ @Override
+ public ISerializableObject copy() {
+ return new FluidLimiterData(threshold);
+ }
+
+ @Nonnull
+ @Override
+ public NBTBase saveDataToNBT() {
+ NBTTagCompound tag = new NBTTagCompound();
+ tag.setFloat("threshold", this.threshold);
+ return tag;
+ }
+
+ @Override
+ public void writeToByteBuf(ByteBuf aBuf) {
+ aBuf.writeFloat(this.threshold);
+ }
+
+ @Override
+ public void loadDataFromNBT(NBTBase aNBT) {
+ if (aNBT instanceof NBTTagCompound tag) {
+ this.threshold = tag.getFloat("threshold");
+ }
+ }
+
+ @Nonnull
+ @Override
+ public ISerializableObject readFromPacket(ByteArrayDataInput aBuf, @Nullable EntityPlayerMP aPlayer) {
+ this.threshold = aBuf.readFloat();
+ return this;
+ }
+ }
+
+ // GUI stuff
+
+ @Override
+ public boolean hasCoverGUI() {
+ return true;
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ @Override
+ public ModularWindow createWindow(GT_CoverUIBuildContext buildContext) {
+ return new FluidLimiterUIFactory(buildContext).createWindow();
+ }
+
+ private class FluidLimiterUIFactory extends UIFactory {
+
+ private static final int startX = 10;
+ private static final int startY = 25;
+ private static final int spaceX = 18;
+ private static final int spaceY = 18;
+
+ public FluidLimiterUIFactory(GT_CoverUIBuildContext buildContext) {
+ super(buildContext);
+ }
+
+ @Override
+ protected void addUIWidgets(ModularWindow.Builder builder) {
+ builder.widget(
+ new CoverDataControllerWidget<>(this::getCoverData, this::setCoverData, GT_Cover_FluidLimiter.this)
+ .addFollower(
+ new CoverDataFollower_NumericWidget<>(),
+ coverData -> (double) Math.round(coverData.threshold * 100),
+ (coverData, val) -> {
+ coverData.threshold = val.floatValue() / 100;
+ return coverData;
+ },
+ widget -> widget.setBounds(0, 100)
+ .setFocusOnGuiOpen(true)
+ .setPos(startX, startY + spaceY * 2 - 24)
+ .setSize(spaceX * 4 - 3, 12)))
+ .widget(
+ new TextWidget("Percent threshold").setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX, startY + spaceY * 2 - 35));
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/GT_Cover_FluidRegulator.java b/src/main/java/gregtech/common/covers/GT_Cover_FluidRegulator.java
new file mode 100644
index 0000000000..483f882e91
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/GT_Cover_FluidRegulator.java
@@ -0,0 +1,536 @@
+package gregtech.common.covers;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.nbt.NBTBase;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidStack;
+import net.minecraftforge.fluids.IFluidHandler;
+
+import com.google.common.io.ByteArrayDataInput;
+import com.gtnewhorizons.modularui.api.NumberFormatMUI;
+import com.gtnewhorizons.modularui.api.drawable.Text;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.api.gui.modularui.GT_CoverUIBuildContext;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.interfaces.tileentity.IMachineProgress;
+import gregtech.api.util.GT_CoverBehaviorBase;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.ISerializableObject;
+import gregtech.common.gui.modularui.widget.CoverDataControllerWidget;
+import gregtech.common.gui.modularui.widget.CoverDataFollower_NumericWidget;
+import gregtech.common.gui.modularui.widget.CoverDataFollower_ToggleButtonWidget;
+import io.netty.buffer.ByteBuf;
+
+/**
+ * Cover variable
+ *
+ * <pre>
+ * 1111 1111 1111 1111 1111 1111 1111 1111
+ * |- interval-| |- flow rate 2 compl. -|
+ * ^ export?
+ * </pre>
+ *
+ * Concat export and flow rate 2 compl. together to get actual flow rate. A positive actual flow rate is export, and
+ * vice versa.
+ * <p>
+ * Interval is an unsigned 11 bit integer minus 1, so the range is 1~2048. The stored bits will be flipped bitwise if
+ * speed is negative. This way, `0` means 1tick interval, while `-1` means 1 tick interval as well, preserving the
+ * legacy behavior.
+ */
+public class GT_Cover_FluidRegulator extends GT_CoverBehaviorBase<GT_Cover_FluidRegulator.FluidRegulatorData> {
+
+ private static final int SPEED_LENGTH = 20;
+ private static final int TICK_RATE_LENGTH = Integer.SIZE - SPEED_LENGTH - 1;
+ private static final int TICK_RATE_MIN = 1;
+ private static final int TICK_RATE_MAX = (-1 >>> (Integer.SIZE - TICK_RATE_LENGTH)) + TICK_RATE_MIN;
+ private static final int TICK_RATE_BITMASK = (TICK_RATE_MAX - TICK_RATE_MIN) << SPEED_LENGTH;
+
+ public final int mTransferRate;
+ private boolean allowFluid = false;
+
+ public GT_Cover_FluidRegulator(int aTransferRate, ITexture coverTexture) {
+ super(FluidRegulatorData.class, coverTexture);
+ if (aTransferRate > (-1 >>> (Integer.SIZE - SPEED_LENGTH)))
+ throw new IllegalArgumentException("aTransferRate too big: " + aTransferRate);
+ this.mTransferRate = aTransferRate;
+ }
+
+ @Override
+ public FluidRegulatorData createDataObject(int aLegacyData) {
+ return new FluidRegulatorData(aLegacyData);
+ }
+
+ @Override
+ public FluidRegulatorData createDataObject() {
+ return new FluidRegulatorData();
+ }
+
+ @Override
+ protected boolean isRedstoneSensitiveImpl(ForgeDirection side, int aCoverID, FluidRegulatorData aCoverVariable,
+ ICoverable aTileEntity, long aTimer) {
+ return aCoverVariable.condition.isRedstoneSensitive();
+ }
+
+ @Override
+ protected FluidRegulatorData doCoverThingsImpl(ForgeDirection side, byte aInputRedstone, int aCoverID,
+ FluidRegulatorData aCoverVariable, ICoverable aTileEntity, long aTimer) {
+ if (aCoverVariable.speed == 0 || !aCoverVariable.condition.isAllowedToWork(side, aCoverID, aTileEntity)) {
+ return aCoverVariable;
+ }
+ if ((aTileEntity instanceof IFluidHandler)) {
+ final IFluidHandler tTank1;
+ final IFluidHandler tTank2;
+ final ForgeDirection directionFrom;
+ final ForgeDirection directionTo;
+ if (aCoverVariable.speed > 0) {
+ tTank2 = aTileEntity.getITankContainerAtSide(side);
+ tTank1 = (IFluidHandler) aTileEntity;
+ directionFrom = side;
+ directionTo = side.getOpposite();
+ } else {
+ tTank1 = aTileEntity.getITankContainerAtSide(side);
+ tTank2 = (IFluidHandler) aTileEntity;
+ directionFrom = side.getOpposite();
+ directionTo = side;
+ }
+ if (tTank1 != null && tTank2 != null) {
+ allowFluid = true;
+ GT_Utility
+ .moveFluid(tTank1, tTank2, directionFrom, Math.abs(aCoverVariable.speed), this::canTransferFluid);
+ allowFluid = false;
+ }
+ }
+ return aCoverVariable;
+ }
+
+ private void adjustSpeed(EntityPlayer aPlayer, FluidRegulatorData aCoverVariable, int scale) {
+ int tSpeed = aCoverVariable.speed;
+ tSpeed += scale;
+ int tTickRate = aCoverVariable.tickRate;
+ if (Math.abs(tSpeed) > mTransferRate * tTickRate) {
+ tSpeed = mTransferRate * tTickRate * (tSpeed > 0 ? 1 : -1);
+ GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("316", "Pump speed limit reached!"));
+ }
+ if (tTickRate == 1) {
+ GT_Utility.sendChatToPlayer(
+ aPlayer,
+ GT_Utility.trans("048", "Pump speed: ") + tSpeed
+ + GT_Utility.trans("049", "L/tick ")
+ + tSpeed * 20
+ + GT_Utility.trans("050", "L/sec"));
+ } else {
+ GT_Utility.sendChatToPlayer(
+ aPlayer,
+ String.format(
+ GT_Utility.trans("207", "Pump speed: %dL every %d ticks, %.2f L/sec on average"),
+ tSpeed,
+ tTickRate,
+ tSpeed * 20d / tTickRate));
+ }
+ }
+
+ @Override
+ public FluidRegulatorData onCoverScrewdriverClickImpl(ForgeDirection side, int aCoverID,
+ FluidRegulatorData aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ if (GT_Utility.getClickedFacingCoords(side, aX, aY, aZ)[0] >= 0.5F) {
+ adjustSpeed(aPlayer, aCoverVariable, aPlayer.isSneaking() ? 256 : 16);
+ } else {
+ adjustSpeed(aPlayer, aCoverVariable, aPlayer.isSneaking() ? -256 : -16);
+ }
+ return aCoverVariable;
+ }
+
+ @Override
+ protected boolean onCoverRightClickImpl(ForgeDirection side, int aCoverID, FluidRegulatorData aCoverVariable,
+ ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ if (GT_Utility.getClickedFacingCoords(side, aX, aY, aZ)[0] >= 0.5F) {
+ adjustSpeed(aPlayer, aCoverVariable, 1);
+ } else {
+ adjustSpeed(aPlayer, aCoverVariable, -1);
+ }
+ return true;
+ }
+
+ protected boolean canTransferFluid(FluidStack fluid) {
+ return true;
+ }
+
+ @Override
+ public boolean letsRedstoneGoInImpl(ForgeDirection side, int aCoverID, FluidRegulatorData aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsRedstoneGoOutImpl(ForgeDirection side, int aCoverID, FluidRegulatorData aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsEnergyInImpl(ForgeDirection side, int aCoverID, FluidRegulatorData aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsEnergyOutImpl(ForgeDirection side, int aCoverID, FluidRegulatorData aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsItemsInImpl(ForgeDirection side, int aCoverID, FluidRegulatorData aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsItemsOutImpl(ForgeDirection side, int aCoverID, FluidRegulatorData aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsFluidInImpl(ForgeDirection side, int aCoverID, FluidRegulatorData aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return allowFluid;
+ }
+
+ @Override
+ public boolean letsFluidOutImpl(ForgeDirection side, int aCoverID, FluidRegulatorData aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return allowFluid;
+ }
+
+ @Override
+ protected boolean alwaysLookConnectedImpl(ForgeDirection side, int aCoverID, FluidRegulatorData aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected int getTickRateImpl(ForgeDirection side, int aCoverID, FluidRegulatorData aCoverVariable,
+ ICoverable aTileEntity) {
+ return aCoverVariable.tickRate;
+ }
+
+ // GUI stuff
+
+ @Override
+ public boolean hasCoverGUI() {
+ return true;
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ @Override
+ public ModularWindow createWindow(GT_CoverUIBuildContext buildContext) {
+ return new FluidRegulatorUIFactory(buildContext).createWindow();
+ }
+
+ private class FluidRegulatorUIFactory extends UIFactory {
+
+ private static final int startX = 10;
+ private static final int startY = 25;
+ private static final int spaceX = 18;
+ private static final int spaceY = 18;
+
+ private static final NumberFormatMUI numberFormat;
+ static {
+ numberFormat = new NumberFormatMUI();
+ numberFormat.setMaximumFractionDigits(2);
+ }
+
+ public FluidRegulatorUIFactory(GT_CoverUIBuildContext buildContext) {
+ super(buildContext);
+ }
+
+ @SuppressWarnings("PointlessArithmeticExpression")
+ @Override
+ protected void addUIWidgets(ModularWindow.Builder builder) {
+ AtomicBoolean warn = new AtomicBoolean(false);
+
+ builder.widget(
+ new CoverDataControllerWidget<>(this::getCoverData, this::setCoverData, GT_Cover_FluidRegulator.this)
+ .addFollower(
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ coverData -> coverData.speed >= 0,
+ (coverData, state) -> {
+ coverData.speed = Math.abs(coverData.speed);
+ return coverData;
+ },
+ widget -> widget.setStaticTexture(GT_UITextures.OVERLAY_BUTTON_EXPORT)
+ .addTooltip(GT_Utility.trans("006", "Export"))
+ .setPos(spaceX * 0, spaceY * 0))
+ .addFollower(
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ coverData -> coverData.speed <= 0,
+ (coverData, state) -> {
+ coverData.speed = -Math.abs(coverData.speed);
+ return coverData;
+ },
+ widget -> widget.setStaticTexture(GT_UITextures.OVERLAY_BUTTON_IMPORT)
+ .addTooltip(GT_Utility.trans("007", "Import"))
+ .setPos(spaceX * 1, spaceY * 0))
+ .addFollower(
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ coverData -> coverData.condition == Conditional.Always,
+ (coverData, state) -> {
+ coverData.condition = Conditional.Always;
+ return coverData;
+ },
+ widget -> widget.setStaticTexture(GT_UITextures.OVERLAY_BUTTON_CHECKMARK)
+ .addTooltip(GT_Utility.trans("224", "Always On"))
+ .setPos(spaceX * 0, spaceY * 1))
+ .addFollower(
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ coverData -> coverData.condition == Conditional.Conditional,
+ (coverData, state) -> {
+ coverData.condition = Conditional.Conditional;
+ return coverData;
+ },
+ widget -> widget.setStaticTexture(GT_UITextures.OVERLAY_BUTTON_USE_PROCESSING_STATE)
+ .addTooltip(GT_Utility.trans("343", "Use Machine Processing State"))
+ .setPos(spaceX * 1, spaceY * 1))
+ .addFollower(
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ coverData -> coverData.condition == Conditional.Inverted,
+ (coverData, state) -> {
+ coverData.condition = Conditional.Inverted;
+ return coverData;
+ },
+ widget -> widget.setStaticTexture(GT_UITextures.OVERLAY_BUTTON_USE_INVERTED_PROCESSING_STATE)
+ .addTooltip(GT_Utility.trans("343.1", "Use Inverted Machine Processing State"))
+ .setPos(spaceX * 2, spaceY * 1))
+ .addFollower(
+ new CoverDataFollower_NumericWidget<>(),
+ coverData -> (double) coverData.speed,
+ (coverData, state) -> {
+ coverData.speed = state.intValue();
+ return coverData;
+ },
+ widget -> widget.setBounds(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY)
+ .setValidator(val -> {
+ final int tickRate = getCoverData() != null ? getCoverData().tickRate : 0;
+ final long maxFlow = (long) mTransferRate
+ * GT_Utility.clamp(tickRate, TICK_RATE_MIN, TICK_RATE_MAX);
+ warn.set(false);
+ if (val > maxFlow) {
+ val = maxFlow;
+ warn.set(true);
+ } else if (val < -maxFlow) {
+ val = -maxFlow;
+ warn.set(true);
+ }
+ return val;
+ })
+ .setScrollValues(1, 144, 1000)
+ .setFocusOnGuiOpen(true)
+ .setPos(spaceX * 0, spaceY * 2 + 2)
+ .setSize(spaceX * 4 - 3, 12))
+ .addFollower(
+ new CoverDataFollower_NumericWidget<>(),
+ coverData -> (double) coverData.tickRate,
+ (coverData, state) -> {
+ coverData.tickRate = state.intValue();
+ return coverData;
+ },
+ widget -> widget.setBounds(0, TICK_RATE_MAX)
+ .setValidator(val -> {
+ final int speed = getCoverData() != null ? getCoverData().speed : 0;
+ warn.set(false);
+ if (val > TICK_RATE_MAX) {
+ val = (long) TICK_RATE_MAX;
+ warn.set(true);
+ } else if (Math.abs(speed) > mTransferRate * val) {
+ val = (long) Math
+ .min(TICK_RATE_MAX, (Math.abs(speed) + mTransferRate - 1) / mTransferRate);
+ warn.set(true);
+ } else if (val < TICK_RATE_MIN) {
+ val = 1L;
+ }
+ return val;
+ })
+ .setPos(spaceX * 5, spaceY * 2 + 2)
+ .setSize(spaceX * 2 - 3, 12))
+ .setPos(startX, startY))
+ .widget(
+ new TextWidget(GT_Utility.trans("229", "Export/Import")).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(3 + startX + spaceX * 4, 4 + startY + spaceY * 0))
+ .widget(
+ new TextWidget(GT_Utility.trans("230", "Conditional")).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(3 + startX + spaceX * 4, 4 + startY + spaceY * 1))
+ .widget(
+ new TextWidget(GT_Utility.trans("208", " L")).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * 4, 4 + startY + spaceY * 2))
+ .widget(
+ new TextWidget(GT_Utility.trans("209", " ticks")).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * 7, 4 + startY + spaceY * 2))
+ .widget(new TextWidget().setTextSupplier(() -> {
+ FluidRegulatorData coverVariable = getCoverData();
+ if (coverVariable == null) return new Text("");
+ return new Text(
+ GT_Utility.trans("210.1", "Average:") + " "
+ + numberFormat.format(
+ coverVariable.tickRate == 0 ? 0 : coverVariable.speed * 20d / coverVariable.tickRate)
+ + " "
+ + GT_Utility.trans("210.2", "L/sec"))
+ .color(warn.get() ? COLOR_TEXT_WARN.get() : COLOR_TEXT_GRAY.get());
+ })
+ .setPos(startX + spaceX * 0, 4 + startY + spaceY * 3));
+ }
+ }
+
+ @Override
+ public boolean allowsTickRateAddition() {
+ return false;
+ }
+
+ public enum Conditional {
+
+ Always(false) {
+
+ @Override
+ boolean isAllowedToWork(ForgeDirection side, int aCoverID, ICoverable aTileEntity) {
+ return true;
+ }
+ },
+ Conditional(true) {
+
+ @Override
+ boolean isAllowedToWork(ForgeDirection side, int aCoverID, ICoverable aTileEntity) {
+ return !(aTileEntity instanceof IMachineProgress) || ((IMachineProgress) aTileEntity).isAllowedToWork();
+ }
+ },
+ Inverted(true) {
+
+ @Override
+ boolean isAllowedToWork(ForgeDirection side, int aCoverID, ICoverable aTileEntity) {
+ return !(aTileEntity instanceof IMachineProgress)
+ || !((IMachineProgress) aTileEntity).isAllowedToWork();
+ }
+ };
+
+ static final Conditional[] VALUES = values();
+ private final boolean redstoneSensitive;
+
+ Conditional(boolean redstoneSensitive) {
+ this.redstoneSensitive = redstoneSensitive;
+ }
+
+ abstract boolean isAllowedToWork(ForgeDirection side, int aCoverID, ICoverable aTileEntity);
+
+ boolean isRedstoneSensitive() {
+ return redstoneSensitive;
+ }
+ }
+
+ public static class FluidRegulatorData implements ISerializableObject {
+
+ private int tickRate;
+ private int speed;
+ private Conditional condition;
+
+ private static int getSpeed(int aCoverVariable) {
+ // positive or 0 -> interval bits need to be set to zero
+ // negative -> interval bits need to be set to one
+ return aCoverVariable >= 0 ? aCoverVariable & ~TICK_RATE_BITMASK : aCoverVariable | TICK_RATE_BITMASK;
+ }
+
+ private static int getTickRate(int aCoverVariable) {
+ // range: TICK_RATE_MIN ~ TICK_RATE_MAX
+ return ((Math.abs(aCoverVariable) & TICK_RATE_BITMASK) >>> SPEED_LENGTH) + TICK_RATE_MIN;
+ }
+
+ public FluidRegulatorData() {
+ this(0);
+ }
+
+ public FluidRegulatorData(int legacy) {
+ this(getTickRate(legacy), getSpeed(legacy), Conditional.Always);
+ }
+
+ public FluidRegulatorData(int tickRate, int speed, Conditional condition) {
+ this.tickRate = tickRate;
+ this.speed = speed;
+ this.condition = condition;
+ }
+
+ @Nonnull
+ @Override
+ public ISerializableObject copy() {
+ return new FluidRegulatorData(tickRate, speed, condition);
+ }
+
+ @Nonnull
+ @Override
+ public NBTBase saveDataToNBT() {
+ NBTTagCompound tag = new NBTTagCompound();
+ tag.setInteger("mSpeed", speed);
+ tag.setInteger("mTickRate", tickRate);
+ tag.setByte("mCondition", (byte) condition.ordinal());
+ return tag;
+ }
+
+ @Override
+ public void writeToByteBuf(ByteBuf aBuf) {
+ aBuf.writeInt(tickRate)
+ .writeInt(speed)
+ .writeByte(condition.ordinal());
+ }
+
+ @Override
+ public void loadDataFromNBT(NBTBase aNBT) {
+ if (!(aNBT instanceof NBTTagCompound tag)) return; // not very good...
+ speed = tag.getInteger("mSpeed");
+ tickRate = tag.getInteger("mTickRate");
+ condition = Conditional.VALUES[tag.getByte("mCondition")];
+ }
+
+ @Nonnull
+ @Override
+ public ISerializableObject readFromPacket(ByteArrayDataInput aBuf, @Nullable EntityPlayerMP aPlayer) {
+ return new FluidRegulatorData(aBuf.readInt(), aBuf.readInt(), Conditional.VALUES[aBuf.readUnsignedByte()]);
+ }
+
+ public int getTickRate() {
+ return tickRate;
+ }
+
+ public void setTickRate(int tickRate) {
+ this.tickRate = tickRate;
+ }
+
+ public int getSpeed() {
+ return speed;
+ }
+
+ public void setSpeed(int speed) {
+ this.speed = speed;
+ }
+
+ public Conditional getCondition() {
+ return condition;
+ }
+
+ public void setCondition(Conditional condition) {
+ this.condition = condition;
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/GT_Cover_FluidStorageMonitor.java b/src/main/java/gregtech/common/covers/GT_Cover_FluidStorageMonitor.java
new file mode 100644
index 0000000000..7f9fda7cbc
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/GT_Cover_FluidStorageMonitor.java
@@ -0,0 +1,507 @@
+package gregtech.common.covers;
+
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FLUID_STORAGE_MONITOR0;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FLUID_STORAGE_MONITOR1;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FLUID_STORAGE_MONITOR10;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FLUID_STORAGE_MONITOR11;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FLUID_STORAGE_MONITOR12;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FLUID_STORAGE_MONITOR13;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FLUID_STORAGE_MONITOR14;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FLUID_STORAGE_MONITOR2;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FLUID_STORAGE_MONITOR3;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FLUID_STORAGE_MONITOR4;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FLUID_STORAGE_MONITOR5;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FLUID_STORAGE_MONITOR6;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FLUID_STORAGE_MONITOR7;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FLUID_STORAGE_MONITOR8;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FLUID_STORAGE_MONITOR9;
+
+import java.util.Optional;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import net.minecraft.client.renderer.texture.TextureMap;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTBase;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.IIcon;
+import net.minecraft.util.ResourceLocation;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidRegistry;
+import net.minecraftforge.fluids.FluidStack;
+import net.minecraftforge.fluids.FluidTankInfo;
+import net.minecraftforge.fluids.IFluidContainerItem;
+import net.minecraftforge.fluids.IFluidHandler;
+
+import com.google.common.io.ByteArrayDataInput;
+
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.ITextureBuilder;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_CoverBehaviorBase;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.ISerializableObject;
+import gregtech.common.tileentities.storage.GT_MetaTileEntity_DigitalTankBase;
+import io.netty.buffer.ByteBuf;
+
+/**
+ * TODO: Implement overlay rendering only with
+ * {@link GT_CoverBehaviorBase#getSpecialCoverFGTextureImpl(ForgeDirection, int, ISerializableObject, ICoverable)}
+ */
+public class GT_Cover_FluidStorageMonitor extends GT_CoverBehaviorBase<GT_Cover_FluidStorageMonitor.FluidStorageData> {
+
+ private static final IIconContainer[] icons = new IIconContainer[] { OVERLAY_FLUID_STORAGE_MONITOR0,
+ OVERLAY_FLUID_STORAGE_MONITOR1, OVERLAY_FLUID_STORAGE_MONITOR2, OVERLAY_FLUID_STORAGE_MONITOR3,
+ OVERLAY_FLUID_STORAGE_MONITOR4, OVERLAY_FLUID_STORAGE_MONITOR5, OVERLAY_FLUID_STORAGE_MONITOR6,
+ OVERLAY_FLUID_STORAGE_MONITOR7, OVERLAY_FLUID_STORAGE_MONITOR8, OVERLAY_FLUID_STORAGE_MONITOR9,
+ OVERLAY_FLUID_STORAGE_MONITOR10, OVERLAY_FLUID_STORAGE_MONITOR11, OVERLAY_FLUID_STORAGE_MONITOR12,
+ OVERLAY_FLUID_STORAGE_MONITOR13, OVERLAY_FLUID_STORAGE_MONITOR14, };
+
+ public GT_Cover_FluidStorageMonitor() {
+ super(FluidStorageData.class);
+ }
+
+ @Override
+ public FluidStorageData createDataObject(int aLegacyData) {
+ return new FluidStorageData();
+ }
+
+ @Override
+ public FluidStorageData createDataObject() {
+ return new FluidStorageData();
+ }
+
+ @Override
+ protected FluidStorageData doCoverThingsImpl(ForgeDirection side, byte aInputRedstone, int aCoverID,
+ FluidStorageData aCoverVariable, ICoverable aTileEntity, long aTimer) {
+ final FluidTankInfo[] tanks = getValidFluidTankInfosForDisplay(aTileEntity, aCoverVariable.side);
+ if (tanks == null) {
+ return aCoverVariable.disable()
+ .issueCoverUpdateIfNeeded(aTileEntity, side);
+ }
+ assert 0 < tanks.length;
+
+ if (aCoverVariable.slot < 0 || tanks.length <= aCoverVariable.slot) {
+ aCoverVariable.setSlot(0);
+ }
+
+ final FluidTankInfo tank = tanks[aCoverVariable.slot];
+ if (tank == null) {
+ return aCoverVariable.setNullTank()
+ .issueCoverUpdateIfNeeded(aTileEntity, side);
+ }
+
+ return aCoverVariable.setFluid(tank.fluid)
+ .setScale(getTankScale(tank))
+ .issueCoverUpdateIfNeeded(aTileEntity, side);
+ }
+
+ @Override
+ protected ITexture getSpecialCoverFGTextureImpl(ForgeDirection side, int aCoverID, FluidStorageData aCoverVariable,
+ ICoverable aTileEntity) {
+ return getSpecialCoverTextureImpl(side, aCoverID, aCoverVariable, aTileEntity);
+ }
+
+ @Override
+ protected ITexture getSpecialCoverTextureImpl(ForgeDirection side, int aCoverID, FluidStorageData aCoverVariable,
+ ICoverable aTileEntity) {
+ if (aCoverVariable.slot == -1 || aCoverVariable.fluid == null || aCoverVariable.scale == 0) {
+ return TextureFactory.of(OVERLAY_FLUID_STORAGE_MONITOR0);
+ }
+ final IIconContainer fluidIcon = new IIconContainer() {
+
+ @Override
+ public IIcon getIcon() {
+ return aCoverVariable.fluid.getStillIcon();
+ }
+
+ @Override
+ public IIcon getOverlayIcon() {
+ return null;
+ }
+
+ @Override
+ public ResourceLocation getTextureFile() {
+ return TextureMap.locationBlocksTexture;
+ }
+ };
+
+ final short[] fluidRGBA = colorToRGBA(aCoverVariable.fluid.getColor());
+ final ITextureBuilder fluidTextureBuilder = TextureFactory.builder()
+ .addIcon(fluidIcon)
+ .setRGBA(fluidRGBA);
+ if (aCoverVariable.fluid.getLuminosity() > 0) fluidTextureBuilder.glow();
+ return TextureFactory.of(fluidTextureBuilder.build(), TextureFactory.of(icons[aCoverVariable.scale]));
+ }
+
+ @Override
+ protected boolean onCoverRightClickImpl(ForgeDirection side, int aCoverID, FluidStorageData aCoverVariable,
+ ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ if (aPlayer == null || aPlayer.worldObj == null || aPlayer.worldObj.isRemote) {
+ return false;
+ }
+ final ItemStack heldItem = aPlayer.getHeldItem();
+ if (aPlayer.isSneaking() || heldItem == null) {
+ return false;
+ }
+ final FluidTankInfo[] tanks = getValidFluidTankInfos(aTileEntity, aCoverVariable.side);
+ if (tanks == null) {
+ return false;
+ }
+ if (aCoverVariable.slot < 0 || tanks.length <= aCoverVariable.slot) {
+ return false;
+ }
+ final FluidTankInfo tank = tanks[aCoverVariable.slot];
+ if (tank == null) {
+ return false;
+ }
+ IFluidHandler tankHandler = (IFluidHandler) aTileEntity;
+
+ final ItemStack heldItemSizedOne = GT_Utility.copyAmount(1, heldItem);
+ if (heldItemSizedOne == null || heldItemSizedOne.stackSize <= 0) {
+ return false;
+ }
+
+ ItemStack result;
+ result = fillToTank(heldItemSizedOne, tankHandler, aCoverVariable.side);
+ if (result != null) {
+ replaceHeldItemStack(aPlayer, heldItem, result);
+ return true;
+ }
+ result = fillToContainer(heldItemSizedOne, tank, tankHandler, aCoverVariable.side);
+ if (result != null) {
+ replaceHeldItemStack(aPlayer, heldItem, result);
+ return true;
+ }
+ return false;
+ }
+
+ protected static ItemStack fillToTank(@Nonnull ItemStack container, @Nonnull IFluidHandler tank,
+ ForgeDirection side) {
+ final FluidStack fluidToFill = GT_Utility.getFluidForFilledItem(container, true);
+ if (fluidToFill == null || fluidToFill.getFluid() == null || fluidToFill.amount <= 0) {
+ return null;
+ }
+ if (!tank.canFill(side, fluidToFill.getFluid())) {
+ return null;
+ }
+
+ if (container.getItem() instanceof IFluidContainerItem containerItem) {
+ final int filled = tank.fill(side, fluidToFill, true);
+ if (filled == 0) {
+ return null;
+ }
+ containerItem.drain(container, filled, true);
+ return container;
+ } else {
+ final int filled = tank.fill(side, fluidToFill, false);
+ if (filled != fluidToFill.amount) {
+ return null;
+ }
+ tank.fill(side, fluidToFill, true);
+ return GT_Utility.getContainerForFilledItem(container, false);
+ }
+ }
+
+ protected static ItemStack fillToContainer(@Nonnull ItemStack container, @Nonnull FluidTankInfo tankInfo,
+ @Nonnull IFluidHandler tank, ForgeDirection side) {
+ if (tankInfo.fluid == null || tankInfo.fluid.getFluid() == null || tankInfo.fluid.amount <= 0) {
+ return null;
+ }
+ if (!tank.canDrain(side, tankInfo.fluid.getFluid())) {
+ return null;
+ }
+
+ if (container.getItem() instanceof IFluidContainerItem containerItem) {
+ final int filled = Math.min(
+ Optional
+ .ofNullable(
+ tank.drain(
+ side,
+ new FluidStack(tankInfo.fluid.getFluid(), containerItem.getCapacity(container)),
+ false))
+ .filter(fs -> GT_Utility.areFluidsEqual(fs, tankInfo.fluid))
+ .map(fs -> fs.amount)
+ .orElse(0),
+ containerItem.fill(
+ container,
+ new FluidStack(tankInfo.fluid.getFluid(), containerItem.getCapacity(container)),
+ false));
+ if (filled == 0) {
+ return null;
+ }
+ containerItem.fill(container, new FluidStack(tankInfo.fluid.getFluid(), filled), true);
+ tank.drain(side, new FluidStack(tankInfo.fluid.getFluid(), filled), true);
+ return container;
+ } else {
+ final ItemStack filledContainer = GT_Utility.fillFluidContainer(tankInfo.fluid, container, false, false);
+ if (filledContainer == null) {
+ return null;
+ }
+ final FluidStack filledFluid = GT_Utility.getFluidForFilledItem(filledContainer, false);
+ if (filledFluid == null || filledFluid.getFluid() == null || filledFluid.amount <= 0) {
+ return null;
+ }
+ if (Optional.ofNullable(tank.drain(side, filledFluid, false))
+ .filter(fs -> GT_Utility.areFluidsEqual(fs, filledFluid))
+ .map(fs -> fs.amount)
+ .orElse(0) != filledFluid.amount) {
+ return null;
+ }
+ tank.drain(side, filledFluid, true);
+ return filledContainer;
+ }
+ }
+
+ protected static void replaceHeldItemStack(@Nonnull EntityPlayer player, @Nonnull ItemStack heldItem,
+ @Nonnull ItemStack result) {
+ heldItem.stackSize--;
+ GT_Utility.addItemToPlayerInventory(player, result);
+ player.inventoryContainer.detectAndSendChanges();
+ }
+
+ @Override
+ protected FluidStorageData onCoverScrewdriverClickImpl(ForgeDirection side, int aCoverID,
+ FluidStorageData aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ if (aPlayer.isSneaking()) {
+ aCoverVariable
+ .setSide(ForgeDirection.values()[(aCoverVariable.side.ordinal() + 1) % ForgeDirection.values().length])
+ .setSlot(0);
+ GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("SIDE", "Side: ") + aCoverVariable.side.name());
+ return aCoverVariable;
+ }
+ final FluidTankInfo[] tanks = getValidFluidTankInfos(aTileEntity, aCoverVariable.side);
+ if (tanks == null) {
+ return aCoverVariable.disable();
+ }
+ assert 0 < tanks.length;
+ if (aCoverVariable.slot < 0 || tanks.length <= aCoverVariable.slot) {
+ aCoverVariable.setSlot(0);
+ } else {
+ aCoverVariable
+ .setSlot((aCoverVariable.slot + tanks.length + (aPlayer.isSneaking() ? -1 : 1)) % tanks.length);
+ }
+ GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("053", "Slot: ") + aCoverVariable.slot);
+ return aCoverVariable;
+ }
+
+ @Override
+ protected boolean isDataNeededOnClientImpl(ForgeDirection side, int aCoverID, FluidStorageData aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected boolean letsFluidInImpl(ForgeDirection side, int aCoverID, FluidStorageData aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected boolean letsFluidOutImpl(ForgeDirection side, int aCoverID, FluidStorageData aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected int getTickRateImpl(ForgeDirection side, int aCoverID, FluidStorageData aCoverVariable,
+ ICoverable aTileEntity) {
+ return 10;
+ }
+
+ @Nullable
+ protected static FluidTankInfo[] getValidFluidTankInfos(@Nullable ICoverable tileEntity,
+ @Nonnull ForgeDirection side) {
+ if (tileEntity instanceof IFluidHandler) {
+ final FluidTankInfo[] tanks = ((IFluidHandler) tileEntity).getTankInfo(side);
+ if (tanks != null && tanks.length > 0) {
+ return tanks;
+ }
+ }
+ return null;
+ }
+
+ @Nullable
+ protected static FluidTankInfo[] getValidFluidTankInfosForDisplay(@Nullable ICoverable tileEntity,
+ @Nonnull ForgeDirection side) {
+ if (tileEntity instanceof IGregTechTileEntity baseMetaTileEntity
+ && baseMetaTileEntity.getMetaTileEntity() instanceof GT_MetaTileEntity_DigitalTankBase digitalTank) {
+ return digitalTank.getRealTankInfo(side);
+ }
+ return getValidFluidTankInfos(tileEntity, side);
+ }
+
+ protected static int getTankScale(@Nonnull FluidTankInfo tank) {
+ if (tank.fluid == null || tank.capacity <= 0) {
+ return 0;
+ }
+ return (int) Math.ceil(tank.fluid.amount / (double) tank.capacity * (icons.length - 1));
+ }
+
+ protected short[] colorToRGBA(int color) {
+ return new short[] { (short) (color >> 16 & 0xFF), (short) (color >> 8 & 0xFF), (short) (color & 0xFF),
+ (short) (0xFF) };
+ }
+
+ public static class FluidStorageData implements ISerializableObject {
+
+ private ForgeDirection side;
+ private int slot;
+ private Fluid fluid;
+ private int scale;
+ private boolean dirty;
+
+ public FluidStorageData() {
+ this(ForgeDirection.UNKNOWN, 0, null, 0, false);
+ }
+
+ public FluidStorageData(ForgeDirection side, int slot, Fluid fluid, int scale, boolean dirty) {
+ this.side = side;
+ this.slot = slot;
+ this.fluid = fluid;
+ this.scale = scale;
+ this.dirty = dirty;
+ }
+
+ public FluidStorageData setSide(ForgeDirection side) {
+ this.side = side;
+ return this;
+ }
+
+ /**
+ * @param slot 0-based index of the tank, -1 for no correct FluidTankInfo[] for the current side.
+ */
+ public FluidStorageData setSlot(int slot) {
+ if (this.slot != slot) {
+ if (this.slot == -1 || slot == -1) {
+ this.dirty = true;
+ }
+ this.slot = slot;
+ }
+ return this;
+ }
+
+ /**
+ * Means there is no correct FluidTankInfo[] for the current side.
+ */
+ public FluidStorageData disable() {
+ setSlot(-1);
+ return this;
+ }
+
+ public FluidStorageData setFluid(@Nullable Fluid fluid) {
+ if (!Util.areFluidsEqual(this.fluid, fluid)) {
+ this.fluid = fluid;
+ this.dirty = true;
+ }
+ return this;
+ }
+
+ public FluidStorageData setFluid(@Nullable FluidStack fluidStack) {
+ final Fluid fluid = fluidStack == null ? null : fluidStack.getFluid();
+ return setFluid(fluid);
+ }
+
+ public FluidStorageData setScale(int scale) {
+ if (this.scale != scale) {
+ this.scale = scale;
+ this.dirty = true;
+ }
+ return this;
+ }
+
+ public FluidStorageData setNullTank() {
+ return this.setFluid((Fluid) null)
+ .setScale(0);
+ }
+
+ public FluidStorageData issueCoverUpdateIfNeeded(ICoverable tileEntity, ForgeDirection side) {
+ if (this.dirty) {
+ tileEntity.issueCoverUpdate(side);
+ this.dirty = false;
+ }
+ return this;
+ }
+
+ // region ISerializableObject
+ @Nonnull
+ @Override
+ public ISerializableObject copy() {
+ return new FluidStorageData(side, slot, fluid, scale, dirty);
+ }
+
+ @Override
+ public void loadDataFromNBT(NBTBase aNBT) {
+ NBTTagCompound tag = (NBTTagCompound) aNBT;
+ side = ForgeDirection.getOrientation(tag.getByte("side"));
+ slot = tag.getInteger("slot");
+ fluid = Util.getFluid(tag.getString("fluidName"));
+ scale = tag.getInteger("scale");
+ dirty = tag.getBoolean("dirty");
+ }
+
+ @Nonnull
+ @Override
+ public NBTBase saveDataToNBT() {
+ NBTTagCompound tag = new NBTTagCompound();
+ tag.setByte("side", (byte) side.ordinal());
+ tag.setInteger("slot", slot);
+ tag.setString("fluidName", Util.getFluidName(fluid));
+ tag.setInteger("scale", scale);
+ tag.setBoolean("dirty", dirty);
+ return tag;
+ }
+
+ @Nonnull
+ @Override
+ public ISerializableObject readFromPacket(ByteArrayDataInput aBuf, @Nullable EntityPlayerMP aPlayer) {
+ final ForgeDirection side = ForgeDirection.getOrientation(aBuf.readByte());
+ final int slot = aBuf.readInt();
+ final Fluid fluid = Util.getFluid(aBuf.readInt());
+ final int scale = aBuf.readInt();
+ final boolean dirty = aBuf.readBoolean();
+ return new FluidStorageData(side, slot, fluid, scale, dirty);
+ }
+
+ @Override
+ public void writeToByteBuf(ByteBuf aBuf) {
+ aBuf.writeByte(side.ordinal());
+ aBuf.writeInt(slot);
+ aBuf.writeInt(Util.getFluidID(fluid));
+ aBuf.writeInt(scale);
+ aBuf.writeBoolean(dirty);
+ }
+ // endregion
+
+ }
+
+ protected static class Util {
+
+ public static int getFluidID(@Nullable Fluid fluid) {
+ return fluid == null ? -1 : fluid.getID();
+ }
+
+ public static String getFluidName(@Nullable Fluid fluid) {
+ return fluid == null ? "" : fluid.getName();
+ }
+
+ public static Fluid getFluid(int id) {
+ return id == -1 ? null : FluidRegistry.getFluid(id);
+ }
+
+ public static Fluid getFluid(String name) {
+ return name.isEmpty() ? null : FluidRegistry.getFluid(name);
+ }
+
+ public static boolean areFluidsEqual(@Nullable Fluid a, @Nullable Fluid b) {
+ return getFluidID(a) == getFluidID(b);
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/GT_Cover_Fluidfilter.java b/src/main/java/gregtech/common/covers/GT_Cover_Fluidfilter.java
new file mode 100644
index 0000000000..5a6999e055
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/GT_Cover_Fluidfilter.java
@@ -0,0 +1,422 @@
+package gregtech.common.covers;
+
+import static gregtech.api.enums.GT_Values.E;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTBase;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraftforge.common.util.Constants.NBT;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidRegistry;
+import net.minecraftforge.fluids.FluidStack;
+
+import com.google.common.io.ByteArrayDataInput;
+import com.gtnewhorizons.modularui.api.ModularUITextures;
+import com.gtnewhorizons.modularui.api.forge.ItemStackHandler;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.api.gui.modularui.GT_CoverUIBuildContext;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.util.GT_CoverBehaviorBase;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.ISerializableObject;
+import gregtech.common.gui.modularui.widget.CoverDataControllerWidget;
+import gregtech.common.gui.modularui.widget.CoverDataFollower_SlotWidget;
+import gregtech.common.gui.modularui.widget.CoverDataFollower_ToggleButtonWidget;
+import io.netty.buffer.ByteBuf;
+
+public class GT_Cover_Fluidfilter extends GT_CoverBehaviorBase<GT_Cover_Fluidfilter.FluidFilterData> {
+
+ // Uses the lower 3 bits of the cover variable, so we have 8 options to work with (0-7)
+ private final int FILTER_INPUT_DENY_OUTPUT = 0; // 000
+ private final int INVERT_INPUT_DENY_OUTPUT = 1; // 001
+ private final int FILTER_INPUT_ANY_OUTPUT = 2; // 010
+ private final int INVERT_INPUT_ANY_OUTPUT = 3; // 011
+ private final int DENY_INPUT_FILTER_OUTPUT = 4; // 100
+ private final int DENY_INPUT_INVERT_OUTPUT = 5; // 101
+ private final int ANY_INPUT_FILTER_OUTPUT = 6; // 110
+ private final int ANY_INPUT_INVERT_OUTPUT = 7; // 111
+
+ public GT_Cover_Fluidfilter(ITexture coverTexture) {
+ super(FluidFilterData.class, coverTexture);
+ }
+
+ @Override
+ public FluidFilterData createDataObject() {
+ return new FluidFilterData(-1, 0);
+ }
+
+ @Override
+ public FluidFilterData createDataObject(int aLegacyData) {
+ return new FluidFilterData(aLegacyData >>> 3, aLegacyData & 0x7);
+ }
+
+ @Override
+ protected String getDescriptionImpl(ForgeDirection side, int aCoverID, FluidFilterData aCoverVariable,
+ ICoverable aTileEntity) {
+ final Fluid fluid = FluidRegistry.getFluid(aCoverVariable.mFluidID);
+ if (fluid == null) return E;
+
+ final FluidStack sFluid = new FluidStack(fluid, 1000);
+ return (String
+ .format("Filtering Fluid: %s - %s", sFluid.getLocalizedName(), getFilterMode(aCoverVariable.mFilterMode)));
+ }
+
+ @Override
+ protected boolean isRedstoneSensitiveImpl(ForgeDirection side, int aCoverID, FluidFilterData aCoverVariable,
+ ICoverable aTileEntity, long aTimer) {
+ return false;
+ }
+
+ @Override
+ protected FluidFilterData doCoverThingsImpl(ForgeDirection side, byte aInputRedstone, int aCoverID,
+ FluidFilterData aCoverVariable, ICoverable aTileEntity, long aTimer) {
+ return aCoverVariable;
+ }
+
+ public String getFilterMode(int aFilterMode) {
+ return switch (aFilterMode) {
+ case FILTER_INPUT_DENY_OUTPUT -> GT_Utility.trans("043", "Filter input, Deny output");
+ case INVERT_INPUT_DENY_OUTPUT -> GT_Utility.trans("044", "Invert input, Deny output");
+ case FILTER_INPUT_ANY_OUTPUT -> GT_Utility.trans("045", "Filter input, Permit any output");
+ case INVERT_INPUT_ANY_OUTPUT -> GT_Utility.trans("046", "Invert input, Permit any output");
+ case DENY_INPUT_FILTER_OUTPUT -> GT_Utility.trans("307", "Deny input, Filter output");
+ case DENY_INPUT_INVERT_OUTPUT -> GT_Utility.trans("308", "Deny input, Invert output");
+ case ANY_INPUT_FILTER_OUTPUT -> GT_Utility.trans("309", "Permit any input, Filter output");
+ case ANY_INPUT_INVERT_OUTPUT -> GT_Utility.trans("310", "Permit any input, Invert output");
+ default -> ("UNKNOWN");
+ };
+ }
+
+ @Override
+ protected FluidFilterData onCoverScrewdriverClickImpl(ForgeDirection side, int aCoverID,
+ FluidFilterData aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ aCoverVariable.mFilterMode = (aCoverVariable.mFilterMode + (aPlayer.isSneaking() ? -1 : 1)) % 8;
+ if (aCoverVariable.mFilterMode < 0) {
+ aCoverVariable.mFilterMode = 7;
+ }
+
+ GT_Utility.sendChatToPlayer(aPlayer, getFilterMode(aCoverVariable.mFilterMode));
+
+ return aCoverVariable;
+ }
+
+ @Override
+ protected boolean onCoverRightClickImpl(ForgeDirection side, int aCoverID, FluidFilterData aCoverVariable,
+ ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ if (side == ForgeDirection.UNKNOWN) return false;
+ if (((aX > 0.375D) && (aX < 0.625D)) || ((side.offsetX != 0) && ((aY > 0.375D) && (aY < 0.625D)))
+ || (side.flag & (ForgeDirection.UP.flag | ForgeDirection.DOWN.flag)) != 0 && aZ > 0.375D && aZ < 0.625D
+ || (side.offsetZ != 0)) {
+ final ItemStack tStack = aPlayer.inventory.getCurrentItem();
+ if (tStack == null) return true;
+
+ final FluidStack tFluid = GT_Utility.getFluidForFilledItem(tStack, true);
+ if (tFluid != null) {
+ final int aFluid = tFluid.getFluidID();
+ aCoverVariable.mFluidID = aFluid;
+ aTileEntity.setCoverDataAtSide(side, aCoverVariable);
+ final FluidStack sFluid = new FluidStack(FluidRegistry.getFluid(aFluid), 1000);
+ GT_Utility
+ .sendChatToPlayer(aPlayer, GT_Utility.trans("047", "Filter Fluid: ") + sFluid.getLocalizedName());
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ protected boolean letsRedstoneGoInImpl(ForgeDirection side, int aCoverID, FluidFilterData aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected boolean letsRedstoneGoOutImpl(ForgeDirection side, int aCoverID, FluidFilterData aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected boolean letsEnergyInImpl(ForgeDirection side, int aCoverID, FluidFilterData aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected boolean letsEnergyOutImpl(ForgeDirection side, int aCoverID, FluidFilterData aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsItemsInImpl(ForgeDirection side, int aCoverID, FluidFilterData aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsItemsOutImpl(ForgeDirection side, int aCoverID, FluidFilterData aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected boolean letsFluidInImpl(ForgeDirection side, int aCoverID, FluidFilterData aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ if (aFluid == null) return true;
+
+ int aFilterMode = aCoverVariable.mFilterMode;
+ int aFilterFluid = aCoverVariable.mFluidID;
+
+ if (aFilterMode == DENY_INPUT_FILTER_OUTPUT || aFilterMode == DENY_INPUT_INVERT_OUTPUT) return false;
+ else if (aFilterMode == ANY_INPUT_FILTER_OUTPUT || aFilterMode == ANY_INPUT_INVERT_OUTPUT) return true;
+ else if (aFluid.getID() == aFilterFluid)
+ return aFilterMode == FILTER_INPUT_DENY_OUTPUT || aFilterMode == FILTER_INPUT_ANY_OUTPUT;
+ else return aFilterMode == INVERT_INPUT_DENY_OUTPUT || aFilterMode == INVERT_INPUT_ANY_OUTPUT;
+ }
+
+ @Override
+ protected boolean letsFluidOutImpl(ForgeDirection side, int aCoverID, FluidFilterData aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ if (aFluid == null) return true;
+
+ int aFilterMode = aCoverVariable.mFilterMode;
+ int aFilterFluid = aCoverVariable.mFluidID;
+
+ if (aFilterMode == FILTER_INPUT_DENY_OUTPUT || aFilterMode == INVERT_INPUT_DENY_OUTPUT) return false;
+ else if (aFilterMode == FILTER_INPUT_ANY_OUTPUT || aFilterMode == INVERT_INPUT_ANY_OUTPUT) return true;
+ else if (aFluid.getID() == aFilterFluid)
+ return aFilterMode == DENY_INPUT_FILTER_OUTPUT || aFilterMode == ANY_INPUT_FILTER_OUTPUT;
+ else return aFilterMode == DENY_INPUT_INVERT_OUTPUT || aFilterMode == ANY_INPUT_INVERT_OUTPUT;
+ }
+
+ @Override
+ protected boolean alwaysLookConnectedImpl(ForgeDirection side, int aCoverID, FluidFilterData aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected int getTickRateImpl(ForgeDirection side, int aCoverID, FluidFilterData aCoverVariable,
+ ICoverable aTileEntity) {
+ return 0;
+ }
+
+ // GUI stuff
+
+ @Override
+ public boolean hasCoverGUI() {
+ return true;
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ @Override
+ public ModularWindow createWindow(GT_CoverUIBuildContext buildContext) {
+ return new FluidFilterUIFactory(buildContext).createWindow();
+ }
+
+ private class FluidFilterUIFactory extends UIFactory {
+
+ private static final int startX = 10;
+ private static final int startY = 25;
+ private static final int spaceX = 18;
+ private static final int spaceY = 18;
+
+ public FluidFilterUIFactory(GT_CoverUIBuildContext buildContext) {
+ super(buildContext);
+ }
+
+ @SuppressWarnings("PointlessArithmeticExpression")
+ @Override
+ protected void addUIWidgets(ModularWindow.Builder builder) {
+ builder.widget(
+ new CoverDataControllerWidget.CoverDataIndexedControllerWidget_ToggleButtons<>(
+ this::getCoverData,
+ this::setCoverData,
+ GT_Cover_Fluidfilter.this,
+ (id, coverData) -> !getClickable(id, coverData),
+ (id, coverData) -> {
+ coverData.mFilterMode = getNewFilterMode(id, coverData);
+ return coverData;
+ }).addToggleButton(
+ 0,
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ widget -> widget.setStaticTexture(GT_UITextures.OVERLAY_BUTTON_IMPORT)
+ .addTooltip(GT_Utility.trans("232", "Filter Input"))
+ .setPos(spaceX * 0, spaceY * 0))
+ .addToggleButton(
+ 1,
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ widget -> widget.setStaticTexture(GT_UITextures.OVERLAY_BUTTON_EXPORT)
+ .addTooltip(GT_Utility.trans("233", "Filter Output"))
+ .setPos(spaceX * 1, spaceY * 0))
+ .addToggleButton(
+ 2,
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ widget -> widget.setStaticTexture(GT_UITextures.OVERLAY_BUTTON_BLOCK_INPUT)
+ .addTooltip(GT_Utility.trans("234", "Block Output"))
+ .setPos(spaceX * 0, spaceY * 2))
+ .addToggleButton(
+ 3,
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ widget -> widget.setStaticTexture(GT_UITextures.OVERLAY_BUTTON_ALLOW_INPUT)
+ .addTooltip(GT_Utility.trans("235", "Allow Output"))
+ .setPos(spaceX * 1, spaceY * 2))
+ .addToggleButton(
+ 4,
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ widget -> widget.setStaticTexture(GT_UITextures.OVERLAY_BUTTON_WHITELIST)
+ .addTooltip(GT_Utility.trans("236", "Whitelist Fluid"))
+ .setPos(spaceX * 0, spaceY * 1))
+ .addToggleButton(
+ 5,
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ widget -> widget.setStaticTexture(GT_UITextures.OVERLAY_BUTTON_BLACKLIST)
+ .addTooltip(GT_Utility.trans("237", "Blacklist Fluid"))
+ .setPos(spaceX * 1, spaceY * 1))
+ .addFollower(
+ new CoverDataFollower_SlotWidget<FluidFilterData>(new ItemStackHandler(), 0, true) {
+
+ @Override
+ protected void putClickedStack(ItemStack stack, int mouseButton) {
+ if (stack != null && GT_Utility.getFluidFromContainerOrFluidDisplay(stack) == null)
+ return;
+ super.putClickedStack(
+ GT_Utility.getFluidDisplayStack(
+ GT_Utility.getFluidFromContainerOrFluidDisplay(stack),
+ false),
+ mouseButton);
+ }
+ },
+ this::getFluidDisplayItem,
+ (coverData, stack) -> {
+ if (stack == null) {
+ coverData.mFluidID = -1;
+ } else {
+ FluidStack fluid = GT_Utility.getFluidFromDisplayStack(stack);
+ if (fluid != null && fluid.getFluid() != null) {
+ coverData.mFluidID = fluid.getFluid()
+ .getID();
+ }
+ }
+ return coverData;
+ },
+ widget -> widget.setBackground(ModularUITextures.FLUID_SLOT)
+ .setPos(0, spaceY * 3 + 2))
+ .setPos(startX, startY))
+ .widget(
+ new TextWidget(GT_Utility.trans("238", "Filter Direction")).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * 2, 3 + startY + spaceY * 0))
+ .widget(
+ new TextWidget(GT_Utility.trans("239", "Filter Type")).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * 2, 3 + startY + spaceY * 1))
+ .widget(
+ new TextWidget(GT_Utility.trans("240", "Block Flow")).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * 2, 3 + startY + spaceY * 2))
+ .widget(TextWidget.dynamicString(() -> {
+ if (getCoverData() != null) {
+ ItemStack fluidDisplay = getFluidDisplayItem(getCoverData());
+ if (fluidDisplay != null) {
+ return fluidDisplay.getDisplayName();
+ }
+ }
+ return GT_Utility.trans("315", "Filter Empty");
+ })
+ .setSynced(false)
+ .setDefaultColor(COLOR_TITLE.get())
+ .setPos(startX + spaceX + 3, 4 + startY + spaceY * 3));
+ }
+
+ private int getNewFilterMode(int id, FluidFilterData coverVariable) {
+ return switch (id) {
+ case 0 -> (coverVariable.mFilterMode & 0x3);
+ case 1 -> (coverVariable.mFilterMode | 0x4);
+ case 2 -> (coverVariable.mFilterMode & 0x5);
+ case 3 -> (coverVariable.mFilterMode | 0x2);
+ case 4 -> (coverVariable.mFilterMode & 0x6);
+ case 5 -> (coverVariable.mFilterMode | 0x1);
+ default -> coverVariable.mFilterMode;
+ };
+ }
+
+ private boolean getClickable(int id, FluidFilterData coverVariable) {
+ return switch (id) {
+ case 0, 1 -> (coverVariable.mFilterMode >> 2 & 0x1) != (id & 0x1);
+ case 2, 3 -> (coverVariable.mFilterMode >> 1 & 0x1) != (id & 0x1);
+ case 4, 5 -> (coverVariable.mFilterMode & 0x1) != (id & 0x1);
+ default -> false;
+ };
+ }
+
+ private ItemStack getFluidDisplayItem(FluidFilterData coverData) {
+ Fluid fluid = FluidRegistry.getFluid(coverData.mFluidID);
+ return GT_Utility.getFluidDisplayStack(fluid);
+ }
+ }
+
+ public static class FluidFilterData implements ISerializableObject {
+
+ private int mFluidID;
+ private int mFilterMode;
+
+ public FluidFilterData(int mFluidID, int mFilterMode) {
+ this.mFluidID = mFluidID;
+ this.mFilterMode = mFilterMode;
+ }
+
+ @Override
+ @Nonnull
+ public ISerializableObject copy() {
+ return new FluidFilterData(mFluidID, mFilterMode);
+ }
+
+ @Override
+ @Nonnull
+ public NBTBase saveDataToNBT() {
+ NBTTagCompound tNBT = new NBTTagCompound();
+ tNBT.setInteger("mFilterMode", mFilterMode);
+ if (mFluidID >= 0) tNBT.setString(
+ "mFluid",
+ FluidRegistry.getFluid(mFluidID)
+ .getName());
+ return tNBT;
+ }
+
+ @Override
+ public void writeToByteBuf(ByteBuf aBuf) {
+ aBuf.writeByte(mFilterMode)
+ .writeInt(mFluidID);
+ }
+
+ @Override
+ public void loadDataFromNBT(NBTBase aNBT) {
+ if (aNBT instanceof NBTTagCompound tNBT) {
+ mFilterMode = tNBT.getInteger("mFilterMode");
+ if (tNBT.hasKey("mFluid", NBT.TAG_STRING))
+ mFluidID = FluidRegistry.getFluidID(tNBT.getString("mFluid"));
+ else mFluidID = -1;
+ }
+ }
+
+ @Override
+ @Nonnull
+ public ISerializableObject readFromPacket(ByteArrayDataInput aBuf, EntityPlayerMP aPlayer) {
+ mFilterMode = aBuf.readByte();
+ mFluidID = aBuf.readInt();
+ return this;
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/GT_Cover_ItemFilter.java b/src/main/java/gregtech/common/covers/GT_Cover_ItemFilter.java
new file mode 100644
index 0000000000..d93c4b29d1
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/GT_Cover_ItemFilter.java
@@ -0,0 +1,303 @@
+package gregtech.common.covers;
+
+import static gregtech.api.util.GT_Utility.intToStack;
+import static gregtech.api.util.GT_Utility.moveMultipleItemStacks;
+
+import java.util.Collections;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTBase;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraftforge.common.util.Constants;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+
+import com.google.common.io.ByteArrayDataInput;
+import com.gtnewhorizons.modularui.api.forge.ItemStackHandler;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import cpw.mods.fml.common.network.ByteBufUtils;
+import gregtech.api.gui.modularui.GT_CoverUIBuildContext;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.util.GT_CoverBehaviorBase;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.ISerializableObject;
+import gregtech.common.gui.modularui.widget.CoverDataControllerWidget;
+import gregtech.common.gui.modularui.widget.CoverDataFollower_SlotWidget;
+import gregtech.common.gui.modularui.widget.CoverDataFollower_ToggleButtonWidget;
+import io.netty.buffer.ByteBuf;
+
+public class GT_Cover_ItemFilter extends GT_CoverBehaviorBase<GT_Cover_ItemFilter.ItemFilterData> {
+
+ private final boolean mExport;
+
+ public GT_Cover_ItemFilter(boolean isExport, ITexture coverTexture) {
+ super(ItemFilterData.class, coverTexture);
+ this.mExport = isExport;
+ }
+
+ @Override
+ public ItemFilterData createDataObject(int aLegacyData) {
+ return new ItemFilterData((aLegacyData & 0x1) == 0, intToStack(aLegacyData >>> 1));
+ }
+
+ @Override
+ public ItemFilterData createDataObject() {
+ return new ItemFilterData();
+ }
+
+ @Override
+ protected boolean isRedstoneSensitiveImpl(ForgeDirection side, int aCoverID, ItemFilterData aCoverVariable,
+ ICoverable aTileEntity, long aTimer) {
+ return false;
+ }
+
+ @Override
+ protected ItemFilterData doCoverThingsImpl(ForgeDirection side, byte aInputRedstone, int aCoverID,
+ ItemFilterData aCoverVariable, ICoverable aTileEntity, long aTimer) {
+ final TileEntity tTileEntity = aTileEntity.getTileEntityAtSide(side);
+ final Object fromEntity = mExport ? aTileEntity : tTileEntity;
+ final Object toEntity = !mExport ? aTileEntity : tTileEntity;
+ final ForgeDirection fromSide = !mExport ? side.getOpposite() : side;
+ final ForgeDirection toSide = mExport ? side.getOpposite() : side;
+
+ final List<ItemStack> filter = Collections.singletonList(aCoverVariable.mFilter);
+
+ moveMultipleItemStacks(
+ fromEntity,
+ toEntity,
+ fromSide,
+ toSide,
+ filter,
+ aCoverVariable.mWhitelist,
+ (byte) 64,
+ (byte) 1,
+ (byte) 64,
+ (byte) 1,
+ 64);
+
+ return aCoverVariable;
+ }
+
+ @Override
+ protected boolean onCoverRightClickImpl(ForgeDirection side, int aCoverID, ItemFilterData aCoverVariable,
+ ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ final ItemStack tStack = aPlayer.inventory.getCurrentItem();
+ if (tStack != null) {
+ aCoverVariable.mFilter = tStack;
+ GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("299", "Item Filter: ") + tStack.getDisplayName());
+ } else {
+ aCoverVariable.mFilter = null;
+ GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("300", "Filter Cleared!"));
+ }
+ return true;
+ }
+
+ @Override
+ protected ItemFilterData onCoverScrewdriverClickImpl(ForgeDirection side, int aCoverID,
+ ItemFilterData aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ aCoverVariable.mWhitelist = !aCoverVariable.mWhitelist;
+ GT_Utility.sendChatToPlayer(
+ aPlayer,
+ aCoverVariable.mWhitelist ? GT_Utility.trans("125.1", "Whitelist Mode")
+ : GT_Utility.trans("124.1", "Blacklist Mode"));
+ return aCoverVariable;
+ }
+
+ @Override
+ protected boolean letsRedstoneGoInImpl(ForgeDirection side, int aCoverID, ItemFilterData aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected boolean letsRedstoneGoOutImpl(ForgeDirection side, int aCoverID, ItemFilterData aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected boolean letsEnergyInImpl(ForgeDirection side, int aCoverID, ItemFilterData aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected boolean letsEnergyOutImpl(ForgeDirection side, int aCoverID, ItemFilterData aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected boolean letsFluidInImpl(ForgeDirection side, int aCoverID, ItemFilterData aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return false;
+ }
+
+ @Override
+ protected boolean letsFluidOutImpl(ForgeDirection side, int aCoverID, ItemFilterData aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return false;
+ }
+
+ @Override
+ protected boolean letsItemsInImpl(ForgeDirection side, int aCoverID, ItemFilterData aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected boolean letsItemsOutImpl(ForgeDirection side, int aCoverID, ItemFilterData aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected boolean alwaysLookConnectedImpl(ForgeDirection side, int aCoverID, ItemFilterData aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected int getTickRateImpl(ForgeDirection side, int aCoverID, ItemFilterData aCoverVariable,
+ ICoverable aTileEntity) {
+ return 1;
+ }
+
+ // GUI stuff
+
+ @Override
+ public boolean hasCoverGUI() {
+ return true;
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ @Override
+ public ModularWindow createWindow(GT_CoverUIBuildContext buildContext) {
+ return new ItemFilterUIFactory(buildContext).createWindow();
+ }
+
+ private class ItemFilterUIFactory extends UIFactory {
+
+ private static final int startX = 10;
+ private static final int startY = 25;
+ private static final int spaceX = 18;
+ private static final int spaceY = 18;
+
+ public ItemFilterUIFactory(GT_CoverUIBuildContext buildContext) {
+ super(buildContext);
+ }
+
+ @SuppressWarnings("PointlessArithmeticExpression")
+ @Override
+ protected void addUIWidgets(ModularWindow.Builder builder) {
+ ItemStackHandler filterInvHandler = new ItemStackHandler(1);
+ if (getCoverData() != null) {
+ filterInvHandler.setStackInSlot(0, setStackSize1(getCoverData().mFilter));
+ }
+ builder.widget(
+ new CoverDataControllerWidget<>(this::getCoverData, this::setCoverData, GT_Cover_ItemFilter.this)
+ .addFollower(
+ new CoverDataFollower_ToggleButtonWidget<>(),
+ coverData -> coverData.mWhitelist,
+ (coverData, state) -> {
+ coverData.mWhitelist = state;
+ return coverData;
+ },
+ widget -> widget
+ .setToggleTexture(
+ GT_UITextures.OVERLAY_BUTTON_BLACKLIST,
+ GT_UITextures.OVERLAY_BUTTON_WHITELIST)
+ .addTooltip(0, GT_Utility.trans("125.1", "Whitelist Mode"))
+ .addTooltip(1, GT_Utility.trans("124.1", "Blacklist Mode"))
+ .setPos(spaceX * 0, spaceY * 0))
+ .addFollower(
+ new CoverDataFollower_SlotWidget<>(filterInvHandler, 0, true),
+ coverData -> setStackSize1(coverData.mFilter),
+ (coverData, stack) -> {
+ coverData.mFilter = setStackSize1(stack);
+ return coverData;
+ },
+ widget -> widget.setBackground(GT_UITextures.SLOT_DARK_GRAY)
+ .setPos(spaceX * 0, spaceY * 2))
+ .setPos(startX, startY))
+ .widget(
+ new TextWidget(GT_Utility.trans("317", "Filter: ")).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * 0, 3 + startY + spaceY * 1))
+ .widget(
+ new TextWidget(GT_Utility.trans("318", "Check Mode")).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * 2, 3 + startY + spaceY * 0));
+ }
+
+ private ItemStack setStackSize1(ItemStack stack) {
+ if (stack != null) {
+ stack.stackSize = 1;
+ }
+ return stack;
+ }
+ }
+
+ public static class ItemFilterData implements ISerializableObject {
+
+ private boolean mWhitelist;
+ private ItemStack mFilter;
+
+ public ItemFilterData() {}
+
+ public ItemFilterData(boolean mWhitelist, ItemStack mFilter) {
+ this.mWhitelist = mWhitelist;
+ this.mFilter = mFilter;
+ }
+
+ @Nonnull
+ @Override
+ public ISerializableObject copy() {
+ return new ItemFilterData(mWhitelist, mFilter);
+ }
+
+ @Nonnull
+ @Override
+ public NBTBase saveDataToNBT() {
+ NBTTagCompound tag = new NBTTagCompound();
+ tag.setBoolean("mWhitelist", mWhitelist);
+ if (mFilter != null) tag.setTag("mFilter", mFilter.writeToNBT(new NBTTagCompound()));
+ return tag;
+ }
+
+ @Override
+ public void writeToByteBuf(ByteBuf aBuf) {
+ aBuf.writeBoolean(mWhitelist);
+ ByteBufUtils.writeItemStack(aBuf, mFilter);
+ }
+
+ @Override
+ public void loadDataFromNBT(NBTBase aNBT) {
+ NBTTagCompound tag = (NBTTagCompound) aNBT;
+ mWhitelist = tag.getBoolean("mWhitelist");
+ if (tag.hasKey("mFilter", Constants.NBT.TAG_COMPOUND))
+ mFilter = ItemStack.loadItemStackFromNBT(tag.getCompoundTag("mFilter"));
+ else mFilter = null;
+ }
+
+ @Nonnull
+ @Override
+ public ISerializableObject readFromPacket(ByteArrayDataInput aBuf, EntityPlayerMP aPlayer) {
+ mWhitelist = aBuf.readBoolean();
+ mFilter = ISerializableObject.readItemStackFromGreggyByteBuf(aBuf);
+ return this;
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/GT_Cover_ItemMeter.java b/src/main/java/gregtech/common/covers/GT_Cover_ItemMeter.java
new file mode 100644
index 0000000000..bb2364cf0e
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/GT_Cover_ItemMeter.java
@@ -0,0 +1,389 @@
+package gregtech.common.covers;
+
+import java.text.FieldPosition;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTBase;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+
+import com.google.common.io.ByteArrayDataInput;
+import com.gtnewhorizons.modularui.api.NumberFormatMUI;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.api.gui.modularui.GT_CoverUIBuildContext;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.util.GT_CoverBehaviorBase;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.ISerializableObject;
+import gregtech.common.gui.modularui.widget.CoverDataControllerWidget;
+import gregtech.common.gui.modularui.widget.CoverDataFollower_NumericWidget;
+import gregtech.common.gui.modularui.widget.CoverDataFollower_ToggleButtonWidget;
+import gregtech.common.gui.modularui.widget.ItemWatcherSlotWidget;
+import gregtech.common.tileentities.machines.GT_MetaTileEntity_Hatch_OutputBus_ME;
+import gregtech.common.tileentities.storage.GT_MetaTileEntity_DigitalChestBase;
+import io.netty.buffer.ByteBuf;
+
+public class GT_Cover_ItemMeter extends GT_CoverBehaviorBase<GT_Cover_ItemMeter.ItemMeterData> {
+
+ // Legacy data format
+ private static final int SLOT_MASK = 0x3FFFFFFF; // 0 = all, 1 = 0 ...
+ private static final int CONVERTED_BIT = 0x80000000;
+ private static final int INVERT_BIT = 0x40000000;
+
+ public GT_Cover_ItemMeter(ITexture coverTexture) {
+ super(ItemMeterData.class, coverTexture);
+ }
+
+ @Override
+ public ItemMeterData createDataObject(int aLegacyData) {
+ // Convert from ver. 5.09.33.50
+ if ((CONVERTED_BIT & aLegacyData) == 0) if (aLegacyData == 0) aLegacyData = CONVERTED_BIT;
+ else if (aLegacyData == 1) aLegacyData = CONVERTED_BIT | INVERT_BIT;
+ else if (aLegacyData > 1) aLegacyData = CONVERTED_BIT | Math.min((aLegacyData - 2), SLOT_MASK);
+
+ boolean invert = (aLegacyData & INVERT_BIT) == INVERT_BIT;
+ int slot = (aLegacyData & SLOT_MASK) - 1;
+
+ return new ItemMeterData(invert, slot, 0);
+ }
+
+ @Override
+ public ItemMeterData createDataObject() {
+ return new ItemMeterData();
+ }
+
+ @Override
+ protected boolean isRedstoneSensitiveImpl(ForgeDirection side, int aCoverID, ItemMeterData aCoverVariable,
+ ICoverable aTileEntity, long aTimer) {
+ return false;
+ }
+
+ public static byte computeSignalBasedOnItems(ICoverable tileEntity, boolean inverted, int threshold, int slot,
+ int ordinalSide) {
+ long max = 0;
+ long used = 0;
+ final IMetaTileEntity mte = ((IGregTechTileEntity) tileEntity).getMetaTileEntity();
+ if (mte instanceof GT_MetaTileEntity_DigitalChestBase dc) {
+ max = dc.getMaxItemCount();
+ used = dc.getProgresstime();
+ } else if (mte instanceof GT_MetaTileEntity_Hatch_OutputBus_ME) {
+ if (((GT_MetaTileEntity_Hatch_OutputBus_ME) mte).isLastOutputFailed()) {
+ max = 64;
+ used = 64;
+ }
+ } else {
+ final int[] slots = slot >= 0 ? new int[] { slot } : tileEntity.getAccessibleSlotsFromSide(ordinalSide);
+
+ for (int i : slots) {
+ if (i >= 0 && i < tileEntity.getSizeInventory()) {
+ max += 64;
+ final ItemStack stack = tileEntity.getStackInSlot(i);
+ if (stack != null) used += ((long) stack.stackSize << 6) / stack.getMaxStackSize();
+ }
+ }
+ }
+
+ return GT_Utility.convertRatioToRedstone(used, max, threshold, inverted);
+ }
+
+ @Override
+ protected ItemMeterData doCoverThingsImpl(ForgeDirection side, byte aInputRedstone, int aCoverID,
+ ItemMeterData aCoverVariable, ICoverable aTileEntity, long aTimer) {
+ byte signal = computeSignalBasedOnItems(
+ aTileEntity,
+ aCoverVariable.inverted,
+ aCoverVariable.threshold,
+ aCoverVariable.slot,
+ side.ordinal());
+ aTileEntity.setOutputRedstoneSignal(side, signal);
+
+ return aCoverVariable;
+ }
+
+ @Override
+ protected ItemMeterData onCoverScrewdriverClickImpl(ForgeDirection side, int aCoverID, ItemMeterData aCoverVariable,
+ ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ if (aPlayer.isSneaking()) {
+ if (aCoverVariable.inverted) {
+ aCoverVariable.inverted = false;
+ GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("055", "Normal"));
+ } else {
+ aCoverVariable.inverted = true;
+ GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("054", "Inverted"));
+ }
+ } else {
+ aCoverVariable.slot++;
+ if (aCoverVariable.slot > aTileEntity.getSizeInventory()) aCoverVariable.slot = -1;
+
+ if (aCoverVariable.slot == -1) GT_Utility
+ .sendChatToPlayer(aPlayer, GT_Utility.trans("053", "Slot: ") + GT_Utility.trans("ALL", "All"));
+ else GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("053", "Slot: ") + aCoverVariable.slot);
+ }
+
+ return aCoverVariable;
+ }
+
+ @Override
+ protected boolean letsEnergyInImpl(ForgeDirection side, int aCoverID, ItemMeterData aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected boolean letsEnergyOutImpl(ForgeDirection side, int aCoverID, ItemMeterData aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected boolean letsFluidInImpl(ForgeDirection side, int aCoverID, ItemMeterData aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected boolean letsFluidOutImpl(ForgeDirection side, int aCoverID, ItemMeterData aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected boolean letsItemsInImpl(ForgeDirection side, int aCoverID, ItemMeterData aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected boolean letsItemsOutImpl(ForgeDirection side, int aCoverID, ItemMeterData aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected boolean manipulatesSidedRedstoneOutputImpl(ForgeDirection side, int aCoverID,
+ ItemMeterData aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected int getTickRateImpl(ForgeDirection side, int aCoverID, ItemMeterData aCoverVariable,
+ ICoverable aTileEntity) {
+ return 5;
+ }
+
+ // GUI stuff
+
+ @Override
+ public boolean hasCoverGUI() {
+ return true;
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ @Override
+ public ModularWindow createWindow(GT_CoverUIBuildContext buildContext) {
+ return new ItemMeterUIFactory(buildContext).createWindow();
+ }
+
+ private class ItemMeterUIFactory extends UIFactory {
+
+ private static final int startX = 10;
+ private static final int startY = 25;
+ private static final int spaceX = 18;
+ private static final int spaceY = 18;
+
+ /**
+ * Display the text "All" instead of a number when the slot is set to -1.
+ */
+ protected static final NumberFormatMUI numberFormatAll = new NumberFormatMUI() {
+
+ @Override
+ public StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos) {
+ if (number < 0) {
+ return toAppendTo.append(GT_Utility.trans("ALL", "All"));
+ } else {
+ return super.format(number, toAppendTo, pos);
+ }
+ }
+ };
+
+ private int maxSlot;
+ private int maxThreshold;
+
+ public ItemMeterUIFactory(GT_CoverUIBuildContext buildContext) {
+ super(buildContext);
+ }
+
+ @Override
+ protected void addUIWidgets(ModularWindow.Builder builder) {
+ final String INVERTED = GT_Utility.trans("INVERTED", "Inverted");
+ final String NORMAL = GT_Utility.trans("NORMAL", "Normal");
+
+ setMaxSlot();
+ setMaxThreshold();
+
+ builder.widget(
+ new CoverDataControllerWidget<>(this::getCoverData, this::setCoverData, GT_Cover_ItemMeter.this)
+ .addFollower(
+ CoverDataFollower_ToggleButtonWidget.ofRedstone(),
+ coverData -> coverData.inverted,
+ (coverData, state) -> {
+ coverData.inverted = state;
+ return coverData;
+ },
+ widget -> widget.addTooltip(0, NORMAL)
+ .addTooltip(1, INVERTED)
+ .setPos(0, 0))
+ .addFollower(
+ new CoverDataFollower_NumericWidget<>(),
+ coverData -> (double) coverData.threshold,
+ (coverData, state) -> {
+ coverData.threshold = state.intValue();
+ return coverData;
+ },
+ widget -> widget.setBounds(0, maxThreshold)
+ .setScrollValues(1, 64, 1000)
+ .setFocusOnGuiOpen(true)
+ .setPos(0, 2 + spaceY)
+ .setSize(spaceX * 4 + 5, 12))
+ .addFollower(
+ new CoverDataFollower_NumericWidget<>(),
+ coverData -> (double) coverData.slot,
+ (coverData, state) -> {
+ coverData.slot = state.intValue();
+ return coverData;
+ },
+ widget -> widget.setBounds(-1, maxSlot)
+ .setDefaultValue(-1)
+ .setScrollValues(1, 100, 10)
+ .setNumberFormat(numberFormatAll)
+ .setPos(0, 2 + spaceY * 2)
+ .setSize(spaceX * 3 + 1, 12))
+ .setPos(startX, startY))
+ .widget(
+ new ItemWatcherSlotWidget().setGetter(this::getTargetItem)
+ .setPos(startX + spaceX * 3 + 8, startY + spaceY * 2))
+ .widget(
+ new TextWidget()
+ .setStringSupplier(
+ () -> getCoverData() != null ? getCoverData().inverted ? INVERTED : NORMAL : "")
+ .setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX, 4 + startY))
+ .widget(
+ new TextWidget(GT_Utility.trans("254", "Detect slot #")).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * 4 + 9, 4 + startY + spaceY * 2))
+ .widget(
+ new TextWidget(GT_Utility.trans("221", "Item threshold")).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * 4 + 9, 4 + startY + spaceY));
+ }
+
+ private void setMaxSlot() {
+ final ICoverable tile = getUIBuildContext().getTile();
+ if (!tile.isDead() && tile instanceof IGregTechTileEntity gtTile
+ && !(gtTile.getMetaTileEntity() instanceof GT_MetaTileEntity_DigitalChestBase)) {
+ maxSlot = Math.min(tile.getSizeInventory() - 1, SLOT_MASK - 1);
+ } else {
+ maxSlot = -1;
+ }
+ }
+
+ private void setMaxThreshold() {
+ final ICoverable tile = getUIBuildContext().getTile();
+ if (!tile.isDead() && tile instanceof IGregTechTileEntity gtTile
+ && gtTile.getMetaTileEntity() instanceof GT_MetaTileEntity_DigitalChestBase) {
+ maxThreshold = gtTile.getMaxItemCount();
+ } else {
+ maxThreshold = maxSlot > 0 ? maxSlot * 64 : Integer.MAX_VALUE;
+ }
+ }
+
+ private ItemStack getTargetItem() {
+ ItemMeterData coverVariable = getCoverData();
+ if (coverVariable == null || coverVariable.slot < 0) {
+ return null;
+ }
+ ICoverable tile = getUIBuildContext().getTile();
+ if (tile instanceof TileEntity && !tile.isDead()) {
+ if (tile.getSizeInventory() >= coverVariable.slot) {
+ return tile.getStackInSlot(coverVariable.slot);
+ }
+ }
+ return null;
+ }
+ }
+
+ public static class ItemMeterData implements ISerializableObject {
+
+ private boolean inverted;
+ /** The special value {@code -1} means all slots. */
+ private int slot;
+ /** The special value {@code 0} means threshold check is disabled. */
+ private int threshold;
+
+ public ItemMeterData() {
+ inverted = false;
+ slot = -1;
+ threshold = 0;
+ }
+
+ public ItemMeterData(boolean inverted, int slot, int threshold) {
+ this.inverted = inverted;
+ this.slot = slot;
+ this.threshold = threshold;
+ }
+
+ @Nonnull
+ @Override
+ public ISerializableObject copy() {
+ return new ItemMeterData(inverted, slot, threshold);
+ }
+
+ @Nonnull
+ @Override
+ public NBTBase saveDataToNBT() {
+ NBTTagCompound tag = new NBTTagCompound();
+ tag.setBoolean("invert", inverted);
+ tag.setInteger("slot", slot);
+ tag.setInteger("threshold", threshold);
+ return tag;
+ }
+
+ @Override
+ public void writeToByteBuf(ByteBuf aBuf) {
+ aBuf.writeBoolean(inverted);
+ aBuf.writeInt(slot);
+ aBuf.writeInt(threshold);
+ }
+
+ @Override
+ public void loadDataFromNBT(NBTBase aNBT) {
+ NBTTagCompound tag = (NBTTagCompound) aNBT;
+ inverted = tag.getBoolean("invert");
+ slot = tag.getInteger("slot");
+ threshold = tag.getInteger("threshold");
+ }
+
+ @Nonnull
+ @Override
+ public ISerializableObject readFromPacket(ByteArrayDataInput aBuf, EntityPlayerMP aPlayer) {
+ inverted = aBuf.readBoolean();
+ slot = aBuf.readInt();
+ threshold = aBuf.readInt();
+ return this;
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/GT_Cover_Lens.java b/src/main/java/gregtech/common/covers/GT_Cover_Lens.java
new file mode 100644
index 0000000000..94794e5892
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/GT_Cover_Lens.java
@@ -0,0 +1,28 @@
+package gregtech.common.covers;
+
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.util.GT_CoverBehavior;
+
+public class GT_Cover_Lens extends GT_CoverBehavior {
+
+ private final byte mColor;
+
+ public GT_Cover_Lens(byte aColor, ITexture coverTexture) {
+ super(coverTexture);
+ this.mColor = aColor;
+ }
+
+ @Override
+ public boolean isRedstoneSensitive(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ long aTimer) {
+ return false;
+ }
+
+ @Override
+ public byte getLensColor(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return this.mColor;
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/GT_Cover_LiquidMeter.java b/src/main/java/gregtech/common/covers/GT_Cover_LiquidMeter.java
new file mode 100644
index 0000000000..c3a4b4ff89
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/GT_Cover_LiquidMeter.java
@@ -0,0 +1,297 @@
+package gregtech.common.covers;
+
+import java.util.Arrays;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.nbt.NBTBase;
+import net.minecraft.nbt.NBTTagCompound;
+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.IFluidHandler;
+
+import com.google.common.io.ByteArrayDataInput;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.api.gui.modularui.GT_CoverUIBuildContext;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.metatileentity.BaseMetaTileEntity;
+import gregtech.api.util.GT_CoverBehaviorBase;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.ISerializableObject;
+import gregtech.common.gui.modularui.widget.CoverDataControllerWidget;
+import gregtech.common.gui.modularui.widget.CoverDataFollower_NumericWidget;
+import gregtech.common.gui.modularui.widget.CoverDataFollower_ToggleButtonWidget;
+import gregtech.common.tileentities.storage.GT_MetaTileEntity_DigitalTankBase;
+import io.netty.buffer.ByteBuf;
+
+/**
+ * TODO: Implement overlay rendering only with
+ * {@link GT_CoverBehaviorBase#getSpecialCoverFGTextureImpl(ForgeDirection, int, ISerializableObject, ICoverable)}
+ */
+public class GT_Cover_LiquidMeter extends GT_CoverBehaviorBase<GT_Cover_LiquidMeter.LiquidMeterData> {
+
+ public GT_Cover_LiquidMeter(ITexture coverTexture) {
+ super(LiquidMeterData.class, coverTexture);
+ }
+
+ @Override
+ public LiquidMeterData createDataObject(int aLegacyData) {
+ return new LiquidMeterData(aLegacyData == 0, 0);
+ }
+
+ @Override
+ public LiquidMeterData createDataObject() {
+ return new LiquidMeterData();
+ }
+
+ @Override
+ protected boolean isRedstoneSensitiveImpl(ForgeDirection side, int aCoverID, LiquidMeterData aCoverVariable,
+ ICoverable aTileEntity, long aTimer) {
+ return false;
+ }
+
+ public static byte computeSignalBasedOnFluid(ICoverable tileEntity, boolean inverted, int threshold) {
+ if (tileEntity instanceof IFluidHandler) {
+ FluidTankInfo[] tanks = ((IFluidHandler) tileEntity).getTankInfo(ForgeDirection.UNKNOWN);
+ long max = 0;
+ long used = 0;
+ if (tanks != null) {
+ for (FluidTankInfo tank : tanks) {
+ if (tank != null) {
+ if (tileEntity instanceof BaseMetaTileEntity && ((BaseMetaTileEntity) tileEntity)
+ .getMetaTileEntity() instanceof GT_MetaTileEntity_DigitalTankBase) {
+ max += ((GT_MetaTileEntity_DigitalTankBase) ((BaseMetaTileEntity) tileEntity)
+ .getMetaTileEntity()).getRealCapacity();
+ } else max += tank.capacity;
+ FluidStack tLiquid = tank.fluid;
+ if (tLiquid != null) {
+ used += tLiquid.amount;
+ }
+ }
+ }
+ }
+
+ return GT_Utility.convertRatioToRedstone(used, max, threshold, inverted);
+ } else {
+ return 0;
+ }
+ }
+
+ @Override
+ protected LiquidMeterData doCoverThingsImpl(ForgeDirection side, byte aInputRedstone, int aCoverID,
+ LiquidMeterData aCoverVariable, ICoverable aTileEntity, long aTimer) {
+ byte signal = computeSignalBasedOnFluid(aTileEntity, aCoverVariable.inverted, aCoverVariable.threshold);
+ aTileEntity.setOutputRedstoneSignal(side, signal);
+
+ return aCoverVariable;
+ }
+
+ @Override
+ protected LiquidMeterData onCoverScrewdriverClickImpl(ForgeDirection side, int aCoverID,
+ LiquidMeterData aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ if (aCoverVariable.inverted) {
+ aCoverVariable.inverted = false;
+ GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("055", "Normal"));
+ } else {
+ aCoverVariable.inverted = true;
+ GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("054", "Inverted"));
+ }
+ return aCoverVariable;
+ }
+
+ @Override
+ protected boolean letsEnergyInImpl(ForgeDirection side, int aCoverID, LiquidMeterData aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected boolean letsEnergyOutImpl(ForgeDirection side, int aCoverID, LiquidMeterData aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected boolean letsFluidInImpl(ForgeDirection side, int aCoverID, LiquidMeterData aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected boolean letsFluidOutImpl(ForgeDirection side, int aCoverID, LiquidMeterData aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected boolean letsItemsInImpl(ForgeDirection side, int aCoverID, LiquidMeterData aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected boolean letsItemsOutImpl(ForgeDirection side, int aCoverID, LiquidMeterData aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected boolean manipulatesSidedRedstoneOutputImpl(ForgeDirection side, int aCoverID,
+ LiquidMeterData aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected int getTickRateImpl(ForgeDirection side, int aCoverID, LiquidMeterData aCoverVariable,
+ ICoverable aTileEntity) {
+ return 5;
+ }
+
+ // GUI stuff
+
+ @Override
+ public boolean hasCoverGUI() {
+ return true;
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ @Override
+ public ModularWindow createWindow(GT_CoverUIBuildContext buildContext) {
+ return new LiquidMeterUIFactory(buildContext).createWindow();
+ }
+
+ private class LiquidMeterUIFactory extends UIFactory {
+
+ private static final int startX = 10;
+ private static final int startY = 25;
+ private static final int spaceX = 18;
+ private static final int spaceY = 18;
+ private int maxCapacity;
+
+ public LiquidMeterUIFactory(GT_CoverUIBuildContext buildContext) {
+ super(buildContext);
+ }
+
+ @SuppressWarnings("PointlessArithmeticExpression")
+ @Override
+ protected void addUIWidgets(ModularWindow.Builder builder) {
+ final String INVERTED = GT_Utility.trans("INVERTED", "Inverted");
+ final String NORMAL = GT_Utility.trans("NORMAL", "Normal");
+
+ setMaxCapacity();
+
+ builder.widget(
+ new CoverDataControllerWidget<>(this::getCoverData, this::setCoverData, GT_Cover_LiquidMeter.this)
+ .addFollower(
+ CoverDataFollower_ToggleButtonWidget.ofRedstone(),
+ coverData -> coverData.inverted,
+ (coverData, state) -> {
+ coverData.inverted = state;
+ return coverData;
+ },
+ widget -> widget.addTooltip(0, NORMAL)
+ .addTooltip(1, INVERTED)
+ .setPos(spaceX * 0, spaceY * 0))
+ .addFollower(
+ new CoverDataFollower_NumericWidget<>(),
+ coverData -> (double) coverData.threshold,
+ (coverData, state) -> {
+ coverData.threshold = state.intValue();
+ return coverData;
+ },
+ widget -> widget.setBounds(0, maxCapacity > 0 ? maxCapacity : Integer.MAX_VALUE)
+ .setScrollValues(1000, 144, 100000)
+ .setFocusOnGuiOpen(true)
+ .setPos(spaceX * 0, spaceY * 1 + 2)
+ .setSize(spaceX * 4 + 5, 12))
+ .setPos(startX, startY))
+ .widget(
+ new TextWidget()
+ .setStringSupplier(
+ () -> getCoverData() != null ? getCoverData().inverted ? INVERTED : NORMAL : "")
+ .setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * 1, 4 + startY + spaceY * 0))
+ .widget(
+ new TextWidget(GT_Utility.trans("222", "Fluid threshold")).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * 5 - 10, startY + spaceY * 1 + 4));
+ }
+
+ private void setMaxCapacity() {
+ final ICoverable tile = getUIBuildContext().getTile();
+ if (!tile.isDead() && tile instanceof IFluidHandler) {
+ FluidTankInfo[] tanks = ((IFluidHandler) tile).getTankInfo(ForgeDirection.UNKNOWN);
+ maxCapacity = Arrays.stream(tanks)
+ .mapToInt(tank -> tank.capacity)
+ .sum();
+ } else {
+ maxCapacity = -1;
+ }
+ }
+ }
+
+ public static class LiquidMeterData implements ISerializableObject {
+
+ private boolean inverted;
+ /**
+ * The special value {@code 0} means threshold check is disabled.
+ */
+ private int threshold;
+
+ public LiquidMeterData() {
+ inverted = false;
+ threshold = 0;
+ }
+
+ public LiquidMeterData(boolean inverted, int threshold) {
+ this.inverted = inverted;
+ this.threshold = threshold;
+ }
+
+ @Nonnull
+ @Override
+ public ISerializableObject copy() {
+ return new LiquidMeterData(inverted, threshold);
+ }
+
+ @Nonnull
+ @Override
+ public NBTBase saveDataToNBT() {
+ NBTTagCompound tag = new NBTTagCompound();
+ tag.setBoolean("invert", inverted);
+ tag.setInteger("threshold", threshold);
+ return tag;
+ }
+
+ @Override
+ public void writeToByteBuf(ByteBuf aBuf) {
+ aBuf.writeBoolean(inverted);
+ aBuf.writeInt(threshold);
+ }
+
+ @Override
+ public void loadDataFromNBT(NBTBase aNBT) {
+ NBTTagCompound tag = (NBTTagCompound) aNBT;
+ inverted = tag.getBoolean("invert");
+ threshold = tag.getInteger("threshold");
+ }
+
+ @Nonnull
+ @Override
+ public ISerializableObject readFromPacket(ByteArrayDataInput aBuf, EntityPlayerMP aPlayer) {
+ inverted = aBuf.readBoolean();
+ threshold = aBuf.readInt();
+ return this;
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/GT_Cover_Metrics_Transmitter.java b/src/main/java/gregtech/common/covers/GT_Cover_Metrics_Transmitter.java
new file mode 100644
index 0000000000..6d3cf529d3
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/GT_Cover_Metrics_Transmitter.java
@@ -0,0 +1,212 @@
+package gregtech.common.covers;
+
+import java.util.List;
+import java.util.UUID;
+
+import net.minecraft.entity.item.EntityItem;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTBase;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.StatCollector;
+import net.minecraftforge.common.MinecraftForge;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.io.ByteArrayDataInput;
+
+import gregtech.api.enums.ItemList;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetricsExporter;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.interfaces.tileentity.IGregTechDeviceInformation;
+import gregtech.api.metatileentity.BaseMetaTileEntity;
+import gregtech.api.util.GT_CoverBehaviorBase;
+import gregtech.api.util.ISerializableObject;
+import gregtech.common.events.MetricsCoverDataEvent;
+import gregtech.common.events.MetricsCoverSelfDestructEvent;
+import gregtech.common.misc.GlobalMetricsCoverDatabase;
+import gregtech.common.misc.GlobalMetricsCoverDatabase.State;
+import io.netty.buffer.ByteBuf;
+
+/**
+ * Used to transmit Nuclear Control information across dimensions. The only reason this is a cover is to artificially
+ * limit the number of total machines that transmit this data, for performance reasons.
+ * <p>
+ * This cover will retrieve information, preferentially, using {@link IMetricsExporter#reportMetrics()}. Absent this
+ * method, it will resort to {@link BaseMetaTileEntity#getInfoData()} instead.
+ */
+public class GT_Cover_Metrics_Transmitter
+ extends GT_CoverBehaviorBase<GT_Cover_Metrics_Transmitter.MetricsTransmitterData> {
+
+ @SuppressWarnings("SpellCheckingInspection")
+ public static final String FREQUENCY_MSB_KEY = "gt.metricscover.freq_msb";
+ @SuppressWarnings("SpellCheckingInspection")
+ public static final String FREQUENCY_LSB_KEY = "gt.metricscover.freq_lsb";
+ public static final String MACHINE_KEY = "machine_name";
+ public static final String CARD_STATE_KEY = "card_state";
+
+ @SuppressWarnings("unused")
+ public GT_Cover_Metrics_Transmitter() {
+ this(null);
+ }
+
+ public GT_Cover_Metrics_Transmitter(ITexture coverTexture) {
+ super(MetricsTransmitterData.class, coverTexture);
+ }
+
+ @Override
+ public MetricsTransmitterData createDataObject(int aLegacyData) {
+ // As a new cover, this shouldn't fire.
+ return new MetricsTransmitterData();
+ }
+
+ @Override
+ public MetricsTransmitterData createDataObject() {
+ return new MetricsTransmitterData();
+ }
+
+ @Override
+ protected int getTickRateImpl(ForgeDirection side, int aCoverID, MetricsTransmitterData aCoverVariable,
+ ICoverable aTileEntity) {
+ return 20;
+ }
+
+ @Override
+ public boolean isCoverPlaceable(ForgeDirection side, ItemStack aStack, ICoverable aTileEntity) {
+ return aTileEntity instanceof final IGregTechDeviceInformation device && device.isGivingInformation();
+ }
+
+ @Override
+ protected MetricsTransmitterData doCoverThingsImpl(ForgeDirection side, byte aInputRedstone, int aCoverID,
+ MetricsTransmitterData aCoverVariable, ICoverable aTileEntity, long aTimer) {
+ if (aTileEntity instanceof final BaseMetaTileEntity baseMTE && baseMTE.isGivingInformation()) {
+ final List<String> payload;
+
+ if (baseMTE.getMetaTileEntity() instanceof final IMetricsExporter metricsExporter) {
+ payload = metricsExporter.reportMetrics();
+ } else {
+ payload = ImmutableList.copyOf(baseMTE.getInfoData());
+ }
+
+ MinecraftForge.EVENT_BUS.post(new MetricsCoverDataEvent(
+ aCoverVariable.frequency,
+ payload,
+ new GlobalMetricsCoverDatabase.Coordinates(
+ baseMTE.getWorld().provider.getDimensionName(),
+ baseMTE.getXCoord(),
+ baseMTE.getYCoord(),
+ baseMTE.getZCoord()
+ )
+ ));
+ }
+
+ return aCoverVariable;
+ }
+
+ @Override
+ protected void onDroppedImpl(ForgeDirection side, int aCoverID, MetricsTransmitterData aCoverVariable,
+ ICoverable aTileEntity) {
+ MinecraftForge.EVENT_BUS.post(new MetricsCoverSelfDestructEvent(aCoverVariable.frequency));
+ }
+
+ @Override
+ public void onPlayerAttach(EntityPlayer player, ItemStack aCover, ICoverable aTileEntity, ForgeDirection side) {
+ final UUID newFrequency = UUID.randomUUID();
+ final ItemStack cardStack = ItemList.NC_AdvancedSensorCard.get(1);
+
+ if (cardStack == null) {
+ return;
+ }
+
+ final NBTTagCompound tagCompound = new NBTTagCompound();
+ tagCompound.setLong(FREQUENCY_MSB_KEY, newFrequency.getMostSignificantBits());
+ tagCompound.setLong(FREQUENCY_LSB_KEY, newFrequency.getLeastSignificantBits());
+ tagCompound.setInteger(CARD_STATE_KEY, State.OPERATIONAL.getType());
+
+ if (aTileEntity instanceof final BaseMetaTileEntity baseMTE) {
+ final ItemStack baseMTEStack = baseMTE.getStackForm(1);
+ if (baseMTEStack != null) {
+ tagCompound.setTag(MACHINE_KEY, baseMTEStack.writeToNBT(new NBTTagCompound()));
+ }
+ }
+
+ cardStack.setTagCompound(tagCompound);
+ aTileEntity.getCoverInfoAtSide(side)
+ .setCoverData(new MetricsTransmitterData(newFrequency));
+
+ final EntityItem cardEntity = new EntityItem(player.worldObj, player.posX, player.posY, player.posZ, cardStack);
+ cardEntity.delayBeforeCanPickup = 0;
+ player.worldObj.spawnEntityInWorld(cardEntity);
+ }
+
+ @Override
+ public boolean allowsCopyPasteTool() {
+ return false;
+ }
+
+ @Override
+ public List<String> getAdditionalTooltipImpl(MetricsTransmitterData data) {
+ return ImmutableList.of(
+ StatCollector.translateToLocalFormatted(
+ "gt.item.adv_sensor_card.tooltip.frequency",
+ EnumChatFormatting.UNDERLINE.toString() + EnumChatFormatting.YELLOW + data.frequency.toString()));
+ }
+
+ public static class MetricsTransmitterData implements ISerializableObject {
+
+ private UUID frequency;
+
+ public MetricsTransmitterData() {
+ this.frequency = UUID.randomUUID();
+ }
+
+ public MetricsTransmitterData(@NotNull UUID frequency) {
+ this.frequency = frequency;
+ }
+
+ @NotNull
+ public UUID getFrequency() {
+ return frequency;
+ }
+
+ @NotNull
+ @Override
+ public ISerializableObject copy() {
+ return new MetricsTransmitterData(frequency);
+ }
+
+ @NotNull
+ @Override
+ public NBTBase saveDataToNBT() {
+ NBTTagCompound tag = new NBTTagCompound();
+ tag.setLong(FREQUENCY_MSB_KEY, frequency.getMostSignificantBits());
+ tag.setLong(FREQUENCY_LSB_KEY, frequency.getLeastSignificantBits());
+ return tag;
+ }
+
+ @Override
+ public void loadDataFromNBT(NBTBase aNBT) {
+ if (aNBT instanceof final NBTTagCompound tag) {
+ frequency = new UUID(tag.getLong(FREQUENCY_MSB_KEY), tag.getLong(FREQUENCY_LSB_KEY));
+ }
+ }
+
+ @Override
+ public void writeToByteBuf(ByteBuf aBuf) {
+ aBuf.writeLong(frequency.getMostSignificantBits());
+ aBuf.writeLong(frequency.getLeastSignificantBits());
+ }
+
+ @NotNull
+ @Override
+ public ISerializableObject readFromPacket(ByteArrayDataInput aBuf, @Nullable EntityPlayerMP aPlayer) {
+ return new MetricsTransmitterData(new UUID(aBuf.readLong(), aBuf.readLong()));
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/GT_Cover_NeedMaintainance.java b/src/main/java/gregtech/common/covers/GT_Cover_NeedMaintainance.java
new file mode 100644
index 0000000000..55cae3241c
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/GT_Cover_NeedMaintainance.java
@@ -0,0 +1,303 @@
+package gregtech.common.covers;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.api.gui.modularui.GT_CoverUIBuildContext;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_MultiBlockBase;
+import gregtech.api.util.GT_CoverBehavior;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.ISerializableObject;
+import gregtech.common.gui.modularui.widget.CoverDataControllerWidget;
+import gregtech.common.gui.modularui.widget.CoverDataFollower_ToggleButtonWidget;
+
+public class GT_Cover_NeedMaintainance extends GT_CoverBehavior {
+
+ public GT_Cover_NeedMaintainance(ITexture coverTexture) {
+ super(coverTexture);
+ }
+
+ public static boolean isRotor(ItemStack rotor) {
+ return (rotor != null && rotor.getItem() instanceof GT_MetaGenerated_Tool
+ && rotor.getItemDamage() >= 170
+ && rotor.getItemDamage() <= 176);
+ }
+
+ @Override
+ public boolean isRedstoneSensitive(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ long aTimer) {
+ return false;
+ }
+
+ @Override
+ public int doCoverThings(ForgeDirection side, byte aInputRedstone, int aCoverID, int aCoverVariable,
+ ICoverable aTileEntity, long aTimer) {
+ boolean needsRepair = false;
+ if (aTileEntity instanceof IGregTechTileEntity tTileEntity) {
+ final IMetaTileEntity mTileEntity = tTileEntity.getMetaTileEntity();
+ if (mTileEntity instanceof GT_MetaTileEntity_MultiBlockBase multi) {
+ final int ideal = multi.getIdealStatus();
+ final int real = multi.getRepairStatus();
+ final ItemStack tRotor = multi.getRealInventory()[1];
+ final int coverVar = aCoverVariable >>> 1;
+ if (coverVar < 5) {
+ if (ideal - real > coverVar) needsRepair = true;
+ } else if (coverVar == 5 || coverVar == 6) {
+ if (isRotor(tRotor)) {
+ long tMax = GT_MetaGenerated_Tool.getToolMaxDamage(tRotor);
+ long tCur = GT_MetaGenerated_Tool.getToolDamage(tRotor);
+ if (coverVar == 5) {
+ needsRepair = (tCur >= tMax * 8 / 10);
+ } else {
+ long mExpectedDamage = Math.round(
+ Math.min(
+ multi.mEUt / multi.damageFactorLow,
+ Math.pow(multi.mEUt, multi.damageFactorHigh)));
+ needsRepair = tCur + mExpectedDamage * 2 >= tMax;
+ }
+ } else {
+ needsRepair = true;
+ }
+ }
+ }
+ }
+ if (aCoverVariable % 2 == 0) {
+ needsRepair = !needsRepair;
+ }
+
+ aTileEntity.setOutputRedstoneSignal(side, (byte) (needsRepair ? 0 : 15));
+ aTileEntity.setOutputRedstoneSignal(side.getOpposite(), (byte) (needsRepair ? 0 : 15));
+ return aCoverVariable;
+ }
+
+ @Override
+ public int onCoverScrewdriverclick(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ aCoverVariable = (aCoverVariable + (aPlayer.isSneaking() ? -1 : 1)) % 14;
+ if (aCoverVariable < 0) {
+ aCoverVariable = 13;
+ }
+ switch (aCoverVariable) {
+ case 0 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("056", "Emit if 1 Maintenance Needed"));
+ case 1 -> GT_Utility
+ .sendChatToPlayer(aPlayer, GT_Utility.trans("057", "Emit if 1 Maintenance Needed(inverted)"));
+ case 2 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("058", "Emit if 2 Maintenance Needed"));
+ case 3 -> GT_Utility
+ .sendChatToPlayer(aPlayer, GT_Utility.trans("059", "Emit if 2 Maintenance Needed(inverted)"));
+ case 4 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("060", "Emit if 3 Maintenance Needed"));
+ case 5 -> GT_Utility
+ .sendChatToPlayer(aPlayer, GT_Utility.trans("061", "Emit if 3 Maintenance Needed(inverted)"));
+ case 6 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("062", "Emit if 4 Maintenance Needed"));
+ case 7 -> GT_Utility
+ .sendChatToPlayer(aPlayer, GT_Utility.trans("063", "Emit if 4 Maintenance Needed(inverted)"));
+ case 8 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("064", "Emit if 5 Maintenance Needed"));
+ case 9 -> GT_Utility
+ .sendChatToPlayer(aPlayer, GT_Utility.trans("065", "Emit if 5 Maintenance Needed(inverted)"));
+ case 10 -> GT_Utility
+ .sendChatToPlayer(aPlayer, GT_Utility.trans("066", "Emit if rotor needs maintenance low accuracy mod"));
+ case 11 -> GT_Utility.sendChatToPlayer(
+ aPlayer,
+ GT_Utility.trans("067", "Emit if rotor needs maintenance low accuracy mod(inverted)"));
+ case 12 -> GT_Utility.sendChatToPlayer(
+ aPlayer,
+ GT_Utility.trans("068", "Emit if rotor needs maintenance high accuracy mod"));
+ case 13 -> GT_Utility.sendChatToPlayer(
+ aPlayer,
+ GT_Utility.trans("069", "Emit if rotor needs maintenance high accuracy mod(inverted)"));
+ }
+ return aCoverVariable;
+ }
+
+ @Override
+ public boolean letsEnergyIn(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsEnergyOut(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsFluidIn(ForgeDirection side, int aCoverID, int aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsFluidOut(ForgeDirection side, int aCoverID, int aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsItemsIn(ForgeDirection side, int aCoverID, int aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsItemsOut(ForgeDirection side, int aCoverID, int aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean manipulatesSidedRedstoneOutput(ForgeDirection side, int aCoverID, int aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public int getTickRate(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return 60;
+ }
+
+ // GUI stuff
+
+ @Override
+ public boolean hasCoverGUI() {
+ return true;
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ @Override
+ public ModularWindow createWindow(GT_CoverUIBuildContext buildContext) {
+ return new NeedMaintainanceUIFactory(buildContext).createWindow();
+ }
+
+ private class NeedMaintainanceUIFactory extends UIFactory {
+
+ private static final int startX = 10;
+ private static final int startY = 25;
+ private static final int spaceX = 18;
+ private static final int spaceY = 18;
+
+ public NeedMaintainanceUIFactory(GT_CoverUIBuildContext buildContext) {
+ super(buildContext);
+ }
+
+ @SuppressWarnings("PointlessArithmeticExpression")
+ @Override
+ protected void addUIWidgets(ModularWindow.Builder builder) {
+ final String[] tooltipText = { GT_Utility.trans("056", "Emit if 1 Maintenance Needed"),
+ GT_Utility.trans("058", "Emit if 2 Maintenance Needed"),
+ GT_Utility.trans("060", "Emit if 3 Maintenance Needed"),
+ GT_Utility.trans("062", "Emit if 4 Maintenance Needed"),
+ GT_Utility.trans("064", "Emit if 5 Maintenance Needed"),
+ GT_Utility.trans("066", "Emit if rotor needs maintenance low accuracy mod"),
+ GT_Utility.trans("068", "Emit if rotor needs maintenance high accuracy mod"), };
+
+ final String[] buttonText = { GT_Utility.trans("247", "1 Issue"), GT_Utility.trans("248", "2 Issues"),
+ GT_Utility.trans("249", "3 Issues"), GT_Utility.trans("250", "4 Issues"),
+ GT_Utility.trans("251", "5 Issues"), GT_Utility.trans("252", "Rotor < 80%"),
+ GT_Utility.trans("253", "Rotor < 100%"), GT_Utility.trans("INVERTED", "Inverted"),
+ GT_Utility.trans("NORMAL", "Normal"), };
+
+ builder
+ .widget(
+ new CoverDataControllerWidget.CoverDataIndexedControllerWidget_ToggleButtons<>(
+ this::getCoverData,
+ this::setCoverData,
+ GT_Cover_NeedMaintainance.this,
+ (index, coverData) -> isEnabled(index, convert(coverData)),
+ (index, coverData) -> new ISerializableObject.LegacyCoverData(
+ getNewCoverVariable(index, convert(coverData))))
+ .addToggleButton(
+ 0,
+ CoverDataFollower_ToggleButtonWidget.ofCheck(),
+ widget -> widget.addTooltip(tooltipText[0])
+ .setPos(spaceX * 0, spaceY * 0))
+ .addToggleButton(
+ 1,
+ CoverDataFollower_ToggleButtonWidget.ofCheck(),
+ widget -> widget.addTooltip(tooltipText[1])
+ .setPos(spaceX * 0, spaceY * 1))
+ .addToggleButton(
+ 2,
+ CoverDataFollower_ToggleButtonWidget.ofCheck(),
+ widget -> widget.addTooltip(tooltipText[2])
+ .setPos(spaceX * 0, spaceY * 2))
+ .addToggleButton(
+ 3,
+ CoverDataFollower_ToggleButtonWidget.ofCheck(),
+ widget -> widget.addTooltip(tooltipText[3])
+ .setPos(spaceX * 0, spaceY * 3))
+ .addToggleButton(
+ 4,
+ CoverDataFollower_ToggleButtonWidget.ofCheck(),
+ widget -> widget.addTooltip(tooltipText[4])
+ .setPos(spaceX * 4 + 4, spaceY * 0))
+ .addToggleButton(
+ 5,
+ CoverDataFollower_ToggleButtonWidget.ofCheck(),
+ widget -> widget.addTooltip(tooltipText[5])
+ .setPos(spaceX * 4 + 4, spaceY * 1))
+ .addToggleButton(
+ 6,
+ CoverDataFollower_ToggleButtonWidget.ofCheck(),
+ widget -> widget.addTooltip(tooltipText[6])
+ .setPos(spaceX * 4 + 4, spaceY * 2))
+ .addToggleButton(
+ 7,
+ CoverDataFollower_ToggleButtonWidget.ofRedstone(),
+ widget -> widget.setPos(spaceX * 4 + 4, spaceY * 3))
+ .setPos(startX, startY))
+ .widget(
+ new TextWidget(buttonText[0]).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * 1, 4 + startY + spaceY * 0))
+ .widget(
+ new TextWidget(buttonText[1]).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * 1, 4 + startY + spaceY * 1))
+ .widget(
+ new TextWidget(buttonText[2]).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * 1, 4 + startY + spaceY * 2))
+ .widget(
+ new TextWidget(buttonText[3]).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * 1, 4 + startY + spaceY * 3))
+ .widget(
+ new TextWidget(buttonText[4]).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * 5 + 4, 4 + startY + spaceY * 0))
+ .widget(
+ new TextWidget(buttonText[5]).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * 5 + 4, 4 + startY + spaceY * 1))
+ .widget(
+ new TextWidget(buttonText[6]).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * 5 + 4, 4 + startY + spaceY * 2))
+ .widget(
+ TextWidget
+ .dynamicString(() -> isEnabled(7, convert(getCoverData())) ? buttonText[7] : buttonText[8])
+ .setSynced(false)
+ .setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * 5 + 4, 4 + startY + spaceY * 3));
+ }
+
+ private int getNewCoverVariable(int id, int coverVariable) {
+ final boolean checked = (coverVariable & 0x1) > 0;
+ if (id == 7) {
+ if (checked) return coverVariable & ~0x1;
+ else return coverVariable | 0x1;
+ }
+ return (coverVariable & 0x1) | (id << 1);
+ }
+
+ private boolean isEnabled(int id, int coverVariable) {
+ if (id == 7) return (coverVariable & 0x1) > 0;
+ return (coverVariable >>> 1) == id;
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/GT_Cover_PlayerDetector.java b/src/main/java/gregtech/common/covers/GT_Cover_PlayerDetector.java
new file mode 100644
index 0000000000..d358c4e578
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/GT_Cover_PlayerDetector.java
@@ -0,0 +1,207 @@
+package gregtech.common.covers;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.api.gui.modularui.GT_CoverUIBuildContext;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.util.GT_CoverBehavior;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.ISerializableObject;
+import gregtech.common.gui.modularui.widget.CoverDataControllerWidget;
+import gregtech.common.gui.modularui.widget.CoverDataFollower_ToggleButtonWidget;
+
+public class GT_Cover_PlayerDetector extends GT_CoverBehavior {
+
+ private String placer = "";
+ private int range = 8;
+
+ public GT_Cover_PlayerDetector(ITexture coverTexture) {
+ super(coverTexture);
+ }
+
+ @Override
+ public boolean isRedstoneSensitive(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ long aTimer) {
+ return false;
+ }
+
+ @Override
+ public int doCoverThings(ForgeDirection side, byte aInputRedstone, int aCoverID, int aCoverVariable,
+ ICoverable aTileEntity, long aTimer) {
+ boolean playerDetected = false;
+
+ if (aTileEntity instanceof IGregTechTileEntity) {
+ if (aTileEntity.isUniversalEnergyStored(20)) {
+ aTileEntity.decreaseStoredEnergyUnits(20, true);
+ range = 32;
+ } else {
+ range = 8;
+ }
+ placer = ((IGregTechTileEntity) aTileEntity).getOwnerName();
+ }
+ for (Object tObject : aTileEntity.getWorld().playerEntities) {
+ if ((tObject instanceof EntityPlayerMP tEntity)) {
+ int dist = Math.max(
+ 1,
+ (int) tEntity.getDistance(
+ aTileEntity.getXCoord() + 0.5D,
+ aTileEntity.getYCoord() + 0.5D,
+ aTileEntity.getZCoord() + 0.5D));
+ if (dist < range) {
+ if (aCoverVariable == 0) {
+ playerDetected = true;
+ break;
+ }
+ if (tEntity.getDisplayName()
+ .equalsIgnoreCase(placer)) {
+ if (aCoverVariable == 1) {
+ playerDetected = true;
+ break;
+ }
+ } else if (aCoverVariable == 2) {
+ playerDetected = true;
+ break;
+ }
+ }
+ }
+ }
+
+ aTileEntity.setOutputRedstoneSignal(side, (byte) (playerDetected ? 15 : 0));
+ return aCoverVariable;
+ }
+
+ @Override
+ public int onCoverScrewdriverclick(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ aCoverVariable = (aCoverVariable + (aPlayer.isSneaking() ? -1 : 1)) % 3;
+ if (aCoverVariable < 0) {
+ aCoverVariable = 2;
+ }
+ switch (aCoverVariable) {
+ case 0 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("068.1", "Emit if any Player is close"));
+ case 1 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("069.1", "Emit if other Player is close"));
+ case 2 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("070", "Emit if you are close"));
+ }
+ return aCoverVariable;
+ }
+
+ @Override
+ public boolean letsEnergyIn(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsEnergyOut(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsFluidIn(ForgeDirection side, int aCoverID, int aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsFluidOut(ForgeDirection side, int aCoverID, int aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsItemsIn(ForgeDirection side, int aCoverID, int aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsItemsOut(ForgeDirection side, int aCoverID, int aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean manipulatesSidedRedstoneOutput(ForgeDirection side, int aCoverID, int aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public int getTickRate(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return 20;
+ }
+
+ // GUI stuff
+
+ @Override
+ public boolean hasCoverGUI() {
+ return true;
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ @Override
+ public ModularWindow createWindow(GT_CoverUIBuildContext buildContext) {
+ return new PlayerDetectorUIFactory(buildContext).createWindow();
+ }
+
+ private class PlayerDetectorUIFactory extends UIFactory {
+
+ private static final int startX = 10;
+ private static final int startY = 25;
+ private static final int spaceX = 18;
+ private static final int spaceY = 18;
+
+ public PlayerDetectorUIFactory(GT_CoverUIBuildContext buildContext) {
+ super(buildContext);
+ }
+
+ @SuppressWarnings("PointlessArithmeticExpression")
+ @Override
+ protected void addUIWidgets(ModularWindow.Builder builder) {
+ builder
+ .widget(
+ new CoverDataControllerWidget.CoverDataIndexedControllerWidget_ToggleButtons<>(
+ this::getCoverData,
+ this::setCoverData,
+ GT_Cover_PlayerDetector.this,
+ (index, coverData) -> index == convert(coverData),
+ (index, coverData) -> new ISerializableObject.LegacyCoverData(index))
+ .addToggleButton(
+ 0,
+ CoverDataFollower_ToggleButtonWidget.ofCheck(),
+ widget -> widget.addTooltip(GT_Utility.trans("068.1", "Emit if any Player is close"))
+ .setPos(spaceX * 0, spaceY * 0))
+ .addToggleButton(
+ 1,
+ CoverDataFollower_ToggleButtonWidget.ofCheck(),
+ widget -> widget.addTooltip(GT_Utility.trans("069.1", "Emit if other Player is close"))
+ .setPos(spaceX * 0, spaceY * 1))
+ .addToggleButton(
+ 2,
+ CoverDataFollower_ToggleButtonWidget.ofCheck(),
+ widget -> widget.addTooltip(GT_Utility.trans("070", "Emit if you are close"))
+ .setPos(spaceX * 0, spaceY * 2))
+ .setPos(startX, startY))
+ .widget(
+ new TextWidget(GT_Utility.trans("319", "Any player")).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * 1, 4 + startY + spaceY * 0))
+ .widget(
+ new TextWidget(GT_Utility.trans("320", "Other players")).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * 1, 4 + startY + spaceY * 1))
+ .widget(
+ new TextWidget(GT_Utility.trans("321", "Only owner")).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * 1, 4 + startY + spaceY * 2));
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/GT_Cover_Pump.java b/src/main/java/gregtech/common/covers/GT_Cover_Pump.java
new file mode 100644
index 0000000000..e1bbf950ce
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/GT_Cover_Pump.java
@@ -0,0 +1,339 @@
+package gregtech.common.covers;
+
+import java.util.Arrays;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidStack;
+import net.minecraftforge.fluids.IFluidHandler;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.api.gui.modularui.GT_CoverUIBuildContext;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.interfaces.tileentity.IMachineProgress;
+import gregtech.api.util.GT_CoverBehavior;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.ISerializableObject;
+import gregtech.common.gui.modularui.widget.CoverDataControllerWidget;
+import gregtech.common.gui.modularui.widget.CoverDataFollower_ToggleButtonWidget;
+
+public class GT_Cover_Pump extends GT_CoverBehavior {
+
+ public final int mTransferRate;
+
+ public GT_Cover_Pump(int aTransferRate, ITexture coverTexture) {
+ super(coverTexture);
+ this.mTransferRate = aTransferRate;
+ }
+
+ @Override
+ public boolean isRedstoneSensitive(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ long aTimer) {
+ return false;
+ }
+
+ @Override
+ public int doCoverThings(ForgeDirection side, byte aInputRedstone, int aCoverID, int aCoverVariable,
+ ICoverable aTileEntity, long aTimer) {
+ if ((aCoverVariable % 6 > 1) && ((aTileEntity instanceof IMachineProgress))) {
+ if (((IMachineProgress) aTileEntity).isAllowedToWork() != aCoverVariable % 6 < 4) {
+ return aCoverVariable;
+ }
+ }
+
+ if (aTileEntity instanceof IFluidHandler current) {
+ final IFluidHandler toAccess = aTileEntity.getITankContainerAtSide(side);
+ if (toAccess == null) return aCoverVariable;
+
+ transferFluid(current, toAccess, side, aCoverVariable % 2 == 0);
+ }
+ return aCoverVariable;
+ }
+
+ protected void transferFluid(IFluidHandler current, IFluidHandler toAccess, ForgeDirection side, boolean export) {
+ IFluidHandler source = export ? current : toAccess;
+ IFluidHandler dest = export ? toAccess : current;
+ ForgeDirection drainSide = export ? side : side.getOpposite();
+ GT_Utility.moveFluid(source, dest, drainSide, mTransferRate, this::canTransferFluid);
+ }
+
+ protected boolean canTransferFluid(FluidStack fluid) {
+ return true;
+ }
+
+ @Override
+ public int onCoverScrewdriverclick(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ aCoverVariable = (aCoverVariable + (aPlayer.isSneaking() ? -1 : 1)) % 12;
+ if (aCoverVariable < 0) {
+ aCoverVariable = 11;
+ }
+ switch (aCoverVariable) {
+ case 0 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("006", "Export"));
+ case 1 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("007", "Import"));
+ case 2 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("008", "Export (conditional)"));
+ case 3 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("009", "Import (conditional)"));
+ case 4 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("010", "Export (invert cond)"));
+ case 5 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("011", "Import (invert cond)"));
+ case 6 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("012", "Export allow Input"));
+ case 7 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("013", "Import allow Output"));
+ case 8 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("014", "Export allow Input (conditional)"));
+ case 9 -> GT_Utility
+ .sendChatToPlayer(aPlayer, GT_Utility.trans("015", "Import allow Output (conditional)"));
+ case 10 -> GT_Utility
+ .sendChatToPlayer(aPlayer, GT_Utility.trans("016", "Export allow Input (invert cond)"));
+ case 11 -> GT_Utility
+ .sendChatToPlayer(aPlayer, GT_Utility.trans("017", "Import allow Output (invert cond)"));
+ }
+ return aCoverVariable;
+ }
+
+ @Override
+ public boolean letsRedstoneGoIn(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsRedstoneGoOut(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsEnergyIn(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsEnergyOut(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsItemsIn(ForgeDirection side, int aCoverID, int aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsItemsOut(ForgeDirection side, int aCoverID, int aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsFluidIn(ForgeDirection side, int aCoverID, int aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ if ((aCoverVariable > 1) && ((aTileEntity instanceof IMachineProgress))) {
+ if (((IMachineProgress) aTileEntity).isAllowedToWork() != aCoverVariable % 6 < 4) {
+ return false;
+ }
+ }
+ return (aCoverVariable >= 6) || (aCoverVariable % 2 != 0);
+ }
+
+ @Override
+ public boolean letsFluidOut(ForgeDirection side, int aCoverID, int aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ if ((aCoverVariable > 1) && ((aTileEntity instanceof IMachineProgress))) {
+ if (((IMachineProgress) aTileEntity).isAllowedToWork() != aCoverVariable % 6 < 4) {
+ return false;
+ }
+ }
+ return (aCoverVariable >= 6) || (aCoverVariable % 2 == 0);
+ }
+
+ @Override
+ public boolean alwaysLookConnected(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public int getTickRate(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return 1;
+ }
+
+ // GUI stuff
+
+ @Override
+ public boolean hasCoverGUI() {
+ return true;
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ @Override
+ public ModularWindow createWindow(GT_CoverUIBuildContext buildContext) {
+ return new PumpUIFactory(buildContext).createWindow();
+ }
+
+ private class PumpUIFactory extends UIFactory {
+
+ private static final int startX = 10;
+ private static final int startY = 25;
+ private static final int spaceX = 18;
+ private static final int spaceY = 18;
+
+ private CoverDataFollower_ToggleButtonWidget<ISerializableObject.LegacyCoverData> mBlockWidget = null;
+ private CoverDataFollower_ToggleButtonWidget<ISerializableObject.LegacyCoverData> mAllowWidget = null;
+
+ public PumpUIFactory(GT_CoverUIBuildContext buildContext) {
+ super(buildContext);
+ }
+
+ @SuppressWarnings("PointlessArithmeticExpression")
+ @Override
+ protected void addUIWidgets(ModularWindow.Builder builder) {
+ builder.widget(
+ new CoverDataControllerWidget.CoverDataIndexedControllerWidget_ToggleButtons<>(
+ this::getCoverData,
+ this::setCoverData,
+ GT_Cover_Pump.this,
+ (id, coverData) -> !getClickable(id, convert(coverData)),
+ (id, coverData) -> new ISerializableObject.LegacyCoverData(
+ getNewCoverVariable(id, convert(coverData))))
+ .addToggleButton(
+ 0,
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ widget -> widget.setStaticTexture(GT_UITextures.OVERLAY_BUTTON_EXPORT)
+ .addTooltip(GT_Utility.trans("006", "Export"))
+ .setPos(spaceX * 0, spaceY * 0))
+ .addToggleButton(
+ 1,
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ widget -> widget.setStaticTexture(GT_UITextures.OVERLAY_BUTTON_IMPORT)
+ .addTooltip(GT_Utility.trans("007", "Import"))
+ .setPos(spaceX * 1, spaceY * 0))
+ .addToggleButton(
+ 2,
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ widget -> widget.setStaticTexture(GT_UITextures.OVERLAY_BUTTON_CHECKMARK)
+ .addTooltip(GT_Utility.trans("224", "Always On"))
+ .setPos(spaceX * 0, spaceY * 1))
+ .addToggleButton(
+ 3,
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ widget -> widget.setStaticTexture(GT_UITextures.OVERLAY_BUTTON_USE_PROCESSING_STATE)
+ .addTooltip(GT_Utility.trans("343", "Use Machine Processing State"))
+ .setPos(spaceX * 1, spaceY * 1))
+ .addToggleButton(
+ 4,
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ widget -> widget
+ .setStaticTexture(GT_UITextures.OVERLAY_BUTTON_USE_INVERTED_PROCESSING_STATE)
+ .addTooltip(GT_Utility.trans("343.1", "Use Inverted Machine Processing State"))
+ .setPos(spaceX * 2, spaceY * 1))
+ .addToggleButton(5, CoverDataFollower_ToggleButtonWidget.ofDisableable(), widget -> {
+ mAllowWidget = widget;
+ widget.setTextureGetter(i -> {
+ ISerializableObject.LegacyCoverData coverData = getCoverData();
+ return coverData == null || coverData.get() % 2 == 0
+ ? GT_UITextures.OVERLAY_BUTTON_ALLOW_INPUT
+ : GT_UITextures.OVERLAY_BUTTON_ALLOW_OUTPUT;
+ })
+ .dynamicTooltip(() -> {
+ ISerializableObject.LegacyCoverData coverData = getCoverData();
+ return Arrays.asList(
+ coverData == null || coverData.get() % 2 == 0
+ ? GT_Utility.trans("314", "Allow Input")
+ : GT_Utility.trans("312", "Allow Output"));
+ })
+ .setPos(spaceX * 0, spaceY * 2);
+ })
+ .addToggleButton(6, CoverDataFollower_ToggleButtonWidget.ofDisableable(), widget -> {
+ mBlockWidget = widget;
+ widget.setTextureGetter(i -> {
+ ISerializableObject.LegacyCoverData coverData = getCoverData();
+ return coverData == null || coverData.get() % 2 == 0
+ ? GT_UITextures.OVERLAY_BUTTON_BLOCK_INPUT
+ : GT_UITextures.OVERLAY_BUTTON_BLOCK_OUTPUT;
+ })
+ .dynamicTooltip(() -> {
+ ISerializableObject.LegacyCoverData coverData = getCoverData();
+ return Arrays.asList(
+ coverData == null || coverData.get() % 2 == 0
+ ? GT_Utility.trans("313", "Block Input")
+ : GT_Utility.trans("311", "Block Output"));
+ })
+ .setPos(spaceX * 1, spaceY * 2);
+ })
+ .setPos(startX, startY))
+ .widget(
+ new TextWidget(GT_Utility.trans("229", "Export/Import")).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(3 + startX + spaceX * 3, 4 + startY + spaceY * 0))
+ .widget(
+ new TextWidget(GT_Utility.trans("230", "Conditional")).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(3 + startX + spaceX * 3, 4 + startY + spaceY * 1))
+ .widget(TextWidget.dynamicString(() -> {
+ ISerializableObject.LegacyCoverData coverData = getCoverData();
+ return coverData == null || coverData.get() % 2 == 0 ? GT_Utility.trans("344", "Input Blocking")
+ : GT_Utility.trans("344.1", "Output Blocking");
+ })
+ .setSynced(false)
+ .setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(3 + startX + spaceX * 3, 4 + startY + spaceY * 2));
+ }
+
+ private int getNewCoverVariable(int id, int coverVariable) {
+ switch (id) {
+ case 0 -> {
+ if (mBlockWidget != null) {
+ mBlockWidget.notifyTooltipChange();
+ }
+ if (mAllowWidget != null) {
+ mAllowWidget.notifyTooltipChange();
+ }
+ return coverVariable & ~0x1;
+ }
+ case 1 -> {
+ if (mBlockWidget != null) {
+ mBlockWidget.notifyTooltipChange();
+ }
+ if (mAllowWidget != null) {
+ mAllowWidget.notifyTooltipChange();
+ }
+ return coverVariable | 0x1;
+ }
+ case 2 -> {
+ if (coverVariable > 5) return 0x6 | (coverVariable & ~0xE);
+ return (coverVariable & ~0xE);
+ }
+ case 3 -> {
+ if (coverVariable > 5) return 0x8 | (coverVariable & ~0xE);
+ return 0x2 | (coverVariable & ~0xE);
+ }
+ case 4 -> {
+ if (coverVariable > 5) return 0xA | (coverVariable & ~0xE);
+ return (0x4 | (coverVariable & ~0xE));
+ }
+ case 5 -> {
+ if (coverVariable <= 5) return coverVariable + 6;
+ }
+ case 6 -> {
+ if (coverVariable > 5) return coverVariable - 6;
+ }
+ }
+ return coverVariable;
+ }
+
+ private boolean getClickable(int id, int coverVariable) {
+ if (coverVariable < 0 | 11 < coverVariable) return false;
+ return switch (id) {
+ case 0, 1 -> (0x1 & coverVariable) != id;
+ case 2 -> (coverVariable % 6) >= 2;
+ case 3 -> (coverVariable % 6) < 2 | 4 <= (coverVariable % 6);
+ case 4 -> (coverVariable % 6) < 4;
+ case 5 -> coverVariable < 6;
+ case 6 -> coverVariable >= 6;
+ default -> false;
+ };
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/GT_Cover_RedstoneConductor.java b/src/main/java/gregtech/common/covers/GT_Cover_RedstoneConductor.java
new file mode 100644
index 0000000000..edaec13a81
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/GT_Cover_RedstoneConductor.java
@@ -0,0 +1,101 @@
+package gregtech.common.covers;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.util.GT_CoverBehavior;
+import gregtech.api.util.GT_Utility;
+
+@SuppressWarnings("unused") // Legacy from GT4. TODO: Consider re-enable registration
+public class GT_Cover_RedstoneConductor extends GT_CoverBehavior {
+
+ GT_Cover_RedstoneConductor(ITexture coverTexture) {
+ super(coverTexture);
+ }
+
+ @Override
+ public boolean isRedstoneSensitive(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ long aTimer) {
+ return false;
+ }
+
+ @Override
+ public int doCoverThings(ForgeDirection side, byte aInputRedstone, int aCoverID, int aCoverVariable,
+ ICoverable aTileEntity, long aTimer) {
+ if (aCoverVariable == 0) {
+ aTileEntity.setOutputRedstoneSignal(side, aTileEntity.getStrongestRedstone());
+ } else if (aCoverVariable < 7) {
+ aTileEntity.setOutputRedstoneSignal(
+ side,
+ aTileEntity.getInternalInputRedstoneSignal(ForgeDirection.getOrientation((aCoverVariable - 1))));
+ }
+ return aCoverVariable;
+ }
+
+ @Override
+ public int onCoverScrewdriverclick(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ aCoverVariable = (aCoverVariable + (aPlayer.isSneaking() ? -1 : 1)) % 7;
+ if (aCoverVariable < 0) {
+ aCoverVariable = 6;
+ }
+ switch (aCoverVariable) {
+ case 0 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("071", "Conducts strongest Input"));
+ case 1 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("072", "Conducts from bottom Input"));
+ case 2 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("073", "Conducts from top Input"));
+ case 3 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("074", "Conducts from north Input"));
+ case 4 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("075", "Conducts from south Input"));
+ case 5 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("076", "Conducts from west Input"));
+ case 6 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("077", "Conducts from east Input"));
+ }
+ return aCoverVariable;
+ }
+
+ @Override
+ public boolean letsEnergyIn(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsEnergyOut(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsFluidIn(ForgeDirection side, int aCoverID, int aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsFluidOut(ForgeDirection side, int aCoverID, int aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsItemsIn(ForgeDirection side, int aCoverID, int aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsItemsOut(ForgeDirection side, int aCoverID, int aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean manipulatesSidedRedstoneOutput(ForgeDirection side, int aCoverID, int aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public int getTickRate(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return 1;
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/GT_Cover_RedstoneReceiverExternal.java b/src/main/java/gregtech/common/covers/GT_Cover_RedstoneReceiverExternal.java
new file mode 100644
index 0000000000..eabf90f4de
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/GT_Cover_RedstoneReceiverExternal.java
@@ -0,0 +1,41 @@
+package gregtech.common.covers;
+
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.ICoverable;
+
+public class GT_Cover_RedstoneReceiverExternal extends GT_Cover_RedstoneWirelessBase {
+
+ public GT_Cover_RedstoneReceiverExternal(ITexture coverTexture) {
+ super(coverTexture);
+ }
+
+ @Override
+ public boolean isRedstoneSensitive(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ long aTimer) {
+ return false;
+ }
+
+ @Override
+ public int doCoverThings(ForgeDirection side, byte aInputRedstone, int aCoverID, int aCoverVariable,
+ ICoverable aTileEntity, long aTimer) {
+ aTileEntity.setOutputRedstoneSignal(
+ side,
+ GregTech_API.sWirelessRedstone.get(aCoverVariable) == null ? 0
+ : GregTech_API.sWirelessRedstone.get(aCoverVariable));
+ return aCoverVariable;
+ }
+
+ @Override
+ public boolean manipulatesSidedRedstoneOutput(ForgeDirection side, int aCoverID, int aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public int getTickRate(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return 1;
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/GT_Cover_RedstoneReceiverInternal.java b/src/main/java/gregtech/common/covers/GT_Cover_RedstoneReceiverInternal.java
new file mode 100644
index 0000000000..3edd7f7e43
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/GT_Cover_RedstoneReceiverInternal.java
@@ -0,0 +1,46 @@
+package gregtech.common.covers;
+
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.interfaces.tileentity.IMachineProgress;
+import gregtech.api.util.ISerializableObject;
+
+public class GT_Cover_RedstoneReceiverInternal extends GT_Cover_RedstoneWirelessBase {
+
+ public GT_Cover_RedstoneReceiverInternal(ITexture coverTexture) {
+ super(coverTexture);
+ }
+
+ @Override
+ public int doCoverThings(ForgeDirection side, byte aInputRedstone, int aCoverID, int aCoverVariable,
+ ICoverable aTileEntity, long aTimer) {
+ if (aTileEntity instanceof IMachineProgress) {
+ if (getRedstoneInput(side, aInputRedstone, aCoverID, aCoverVariable, aTileEntity) > 0)
+ ((IMachineProgress) aTileEntity).enableWorking();
+ else((IMachineProgress) aTileEntity).disableWorking();
+ ((IMachineProgress) aTileEntity).setWorkDataValue(aInputRedstone);
+ }
+ return aCoverVariable;
+ }
+
+ @Override
+ protected boolean isRedstoneSensitiveImpl(ForgeDirection side, int aCoverID,
+ ISerializableObject.LegacyCoverData aCoverVariable, ICoverable aTileEntity, long aTimer) {
+ return true;
+ }
+
+ @Override
+ public byte getRedstoneInput(ForgeDirection side, byte aInputRedstone, int aCoverID, int aCoverVariable,
+ ICoverable aTileEntity) {
+ return GregTech_API.sWirelessRedstone.get(aCoverVariable) == null ? 0
+ : GregTech_API.sWirelessRedstone.get(aCoverVariable);
+ }
+
+ @Override
+ public int getTickRate(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return 1;
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/GT_Cover_RedstoneSignalizer.java b/src/main/java/gregtech/common/covers/GT_Cover_RedstoneSignalizer.java
new file mode 100644
index 0000000000..4eead134c8
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/GT_Cover_RedstoneSignalizer.java
@@ -0,0 +1,99 @@
+package gregtech.common.covers;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.interfaces.tileentity.IMachineProgress;
+import gregtech.api.util.GT_CoverBehavior;
+import gregtech.api.util.GT_Utility;
+
+@SuppressWarnings("unused") // TODO: Consider re-registering this
+public class GT_Cover_RedstoneSignalizer extends GT_CoverBehavior {
+
+ GT_Cover_RedstoneSignalizer(ITexture coverTexture) {
+ super(coverTexture);
+ }
+
+ @Override
+ public boolean isRedstoneSensitive(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ long aTimer) {
+ return false;
+ }
+
+ @Override
+ public int onCoverScrewdriverclick(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ aCoverVariable = (aCoverVariable + 1) % 48;
+ switch (aCoverVariable / 16) {
+ case 0 -> GT_Utility
+ .sendChatToPlayer(aPlayer, GT_Utility.trans("078", "Signal = ") + (aCoverVariable & 0xF));
+ case 1 -> GT_Utility
+ .sendChatToPlayer(aPlayer, GT_Utility.trans("079", "Conditional Signal = ") + (aCoverVariable & 0xF));
+ case 2 -> GT_Utility.sendChatToPlayer(
+ aPlayer,
+ GT_Utility.trans("080", "Inverted Conditional Signal = ") + (aCoverVariable & 0xF));
+ }
+ return aCoverVariable;
+ }
+
+ @Override
+ public boolean letsRedstoneGoIn(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsEnergyIn(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsEnergyOut(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsFluidIn(ForgeDirection side, int aCoverID, int aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsFluidOut(ForgeDirection side, int aCoverID, int aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsItemsIn(ForgeDirection side, int aCoverID, int aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsItemsOut(ForgeDirection side, int aCoverID, int aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public byte getRedstoneInput(ForgeDirection side, byte aInputRedstone, int aCoverID, int aCoverVariable,
+ ICoverable aTileEntity) {
+ if (aCoverVariable < 16) {
+ return (byte) (aCoverVariable & 0xF);
+ }
+ if ((aTileEntity instanceof IMachineProgress)) {
+ if (((IMachineProgress) aTileEntity).isAllowedToWork()) {
+ if (aCoverVariable / 16 == 1) {
+ return (byte) (aCoverVariable & 0xF);
+ }
+ } else if (aCoverVariable / 16 == 2) {
+ return (byte) (aCoverVariable & 0xF);
+ }
+ return 0;
+ }
+ return (byte) (aCoverVariable & 0xF);
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/GT_Cover_RedstoneTransmitterExternal.java b/src/main/java/gregtech/common/covers/GT_Cover_RedstoneTransmitterExternal.java
new file mode 100644
index 0000000000..1ee0a05837
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/GT_Cover_RedstoneTransmitterExternal.java
@@ -0,0 +1,53 @@
+package gregtech.common.covers;
+
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.covers.IControlsWorkCover;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.util.ISerializableObject;
+
+public class GT_Cover_RedstoneTransmitterExternal extends GT_Cover_RedstoneWirelessBase {
+
+ public GT_Cover_RedstoneTransmitterExternal(ITexture coverTexture) {
+ super(coverTexture);
+ }
+
+ @Override
+ public int doCoverThings(ForgeDirection side, byte aInputRedstone, int aCoverID, int aCoverVariable,
+ ICoverable aTileEntity, long aTimer) {
+ // TODO remove next line after 2.3.0
+ if (!IControlsWorkCover.makeSureOnlyOne(side, aTileEntity)) return aCoverVariable;
+ GregTech_API.sWirelessRedstone.put(aCoverVariable, aInputRedstone);
+ return aCoverVariable;
+ }
+
+ @Override
+ protected boolean isRedstoneSensitiveImpl(ForgeDirection side, int aCoverID,
+ ISerializableObject.LegacyCoverData aCoverVariable, ICoverable aTileEntity, long aTimer) {
+ return true;
+ }
+
+ @Override
+ public boolean letsRedstoneGoIn(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public int getTickRate(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return 1;
+ }
+
+ @Override
+ public boolean isCoverPlaceable(ForgeDirection side, ItemStack aStack, ICoverable aTileEntity) {
+ if (!super.isCoverPlaceable(side, aStack, aTileEntity)) return false;
+ for (final ForgeDirection tSide : ForgeDirection.VALID_DIRECTIONS) {
+ if (aTileEntity.getCoverBehaviorAtSideNew(tSide) instanceof IControlsWorkCover) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/GT_Cover_RedstoneTransmitterInternal.java b/src/main/java/gregtech/common/covers/GT_Cover_RedstoneTransmitterInternal.java
new file mode 100644
index 0000000000..a812a49990
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/GT_Cover_RedstoneTransmitterInternal.java
@@ -0,0 +1,43 @@
+package gregtech.common.covers;
+
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.ICoverable;
+
+public class GT_Cover_RedstoneTransmitterInternal extends GT_Cover_RedstoneWirelessBase {
+
+ public GT_Cover_RedstoneTransmitterInternal(ITexture coverTexture) {
+ super(coverTexture);
+ }
+
+ @Override
+ public boolean isRedstoneSensitive(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ long aTimer) {
+ return false;
+ }
+
+ @Override
+ public int doCoverThings(ForgeDirection side, byte aInputRedstone, int aCoverID, int aCoverVariable,
+ ICoverable aTileEntity, long aTimer) {
+ GregTech_API.sWirelessRedstone.put(aCoverVariable, aTileEntity.getOutputRedstoneSignal(side));
+ return aCoverVariable;
+ }
+
+ @Override
+ public boolean letsRedstoneGoOut(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public int getTickRate(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return 1;
+ }
+
+ @Override
+ public boolean manipulatesSidedRedstoneOutput(ForgeDirection side, int aCoverID, int aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/GT_Cover_RedstoneWirelessBase.java b/src/main/java/gregtech/common/covers/GT_Cover_RedstoneWirelessBase.java
new file mode 100644
index 0000000000..df298c2489
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/GT_Cover_RedstoneWirelessBase.java
@@ -0,0 +1,233 @@
+package gregtech.common.covers;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.gui.modularui.GT_CoverUIBuildContext;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.util.GT_CoverBehavior;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.ISerializableObject;
+import gregtech.common.gui.modularui.widget.CoverDataControllerWidget;
+import gregtech.common.gui.modularui.widget.CoverDataFollower_NumericWidget;
+import gregtech.common.gui.modularui.widget.CoverDataFollower_ToggleButtonWidget;
+
+public abstract class GT_Cover_RedstoneWirelessBase extends GT_CoverBehavior {
+
+ private static final int MAX_CHANNEL = 65535;
+ private static final int PRIVATE_MASK = 0xFFFE0000;
+ private static final int PUBLIC_MASK = 0x0000FFFF;
+ private static final int CHECKBOX_MASK = 0x00010000;
+
+ public GT_Cover_RedstoneWirelessBase(ITexture coverTexture) {
+ super(coverTexture);
+ }
+
+ @Override
+ public boolean onCoverRemoval(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ boolean aForced) {
+ GregTech_API.sWirelessRedstone.put(aCoverVariable, (byte) 0);
+ return true;
+ }
+
+ @Override
+ protected boolean onCoverRightClickImpl(ForgeDirection side, int aCoverID,
+ ISerializableObject.LegacyCoverData aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, float aX,
+ float aY, float aZ) {
+ if (((aX > 0.375D) && (aX < 0.625D)) || ((side.offsetX != 0) && ((aY > 0.375D) && (aY < 0.625D)))) {
+ GregTech_API.sWirelessRedstone.put(aCoverVariable.get(), (byte) 0);
+ aCoverVariable.set(
+ (aCoverVariable.get() & (PRIVATE_MASK | CHECKBOX_MASK))
+ | (((Integer) GT_Utility.stackToInt(aPlayer.inventory.getCurrentItem())).hashCode() & PUBLIC_MASK));
+ GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("081", "Frequency: ") + aCoverVariable);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ @SuppressWarnings("deprecation")
+ public boolean onCoverRightclick(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ if (((aX > 0.375D) && (aX < 0.625D)) || ((side.offsetX != 0) && ((aY > 0.375D) && (aY < 0.625D)))) {
+ GregTech_API.sWirelessRedstone.put(aCoverVariable, (byte) 0);
+
+ int val = GT_Utility.stackToInt(aPlayer.inventory.getCurrentItem())
+ * (1 + aPlayer.inventory.getCurrentItem()
+ .getItemDamage());
+
+ aCoverVariable = (aCoverVariable & (PRIVATE_MASK | CHECKBOX_MASK)) | (val & PUBLIC_MASK);
+
+ aTileEntity.setCoverDataAtSide(side, aCoverVariable);
+ GT_Utility
+ .sendChatToPlayer(aPlayer, GT_Utility.trans("081", "Frequency: ") + (aCoverVariable & PUBLIC_MASK));
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ protected boolean isGUIClickableImpl(ForgeDirection side, int aCoverID,
+ ISerializableObject.LegacyCoverData aCoverVariable, ICoverable aTileEntity) {
+ return false;
+ }
+
+ @Override
+ public int onCoverScrewdriverclick(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ if (((aX > 0.375D) && (aX < 0.625D))
+ || ((side.offsetX == 0) || (((aY > 0.375D) && (aY < 0.625D)) || ((((aZ <= 0.375D) || (aZ >= 0.625D))))))) {
+ GregTech_API.sWirelessRedstone.put(aCoverVariable, (byte) 0);
+ final float[] tCoords = GT_Utility.getClickedFacingCoords(side, aX, aY, aZ);
+
+ final short tAdjustVal = switch ((byte) ((byte) (int) (tCoords[0] * 2.0F)
+ + 2 * (byte) (int) (tCoords[1] * 2.0F))) {
+ case 0 -> -32;
+ case 1 -> 32;
+ case 2 -> -1024;
+ case 3 -> 1024;
+ default -> 0;
+ };
+
+ final int tPublicChannel = (aCoverVariable & PUBLIC_MASK) + tAdjustVal;
+
+ if (tPublicChannel < 0) {
+ aCoverVariable = aCoverVariable & ~PUBLIC_MASK;
+ } else if (tPublicChannel > MAX_CHANNEL) {
+ aCoverVariable = (aCoverVariable & (PRIVATE_MASK | CHECKBOX_MASK)) | MAX_CHANNEL;
+ } else {
+ aCoverVariable = (aCoverVariable & (PRIVATE_MASK | CHECKBOX_MASK)) | tPublicChannel;
+ }
+ }
+ GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("081", "Frequency: ") + (aCoverVariable & PUBLIC_MASK));
+ return aCoverVariable;
+ }
+
+ @Override
+ public boolean letsEnergyIn(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsEnergyOut(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsFluidIn(ForgeDirection side, int aCoverID, int aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsFluidOut(ForgeDirection side, int aCoverID, int aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsItemsIn(ForgeDirection side, int aCoverID, int aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsItemsOut(ForgeDirection side, int aCoverID, int aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public String getDescription(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return GT_Utility.trans("081", "Frequency: ") + aCoverVariable;
+ }
+
+ @Override
+ public int getTickRate(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return 1;
+ }
+
+ // GUI stuff
+
+ @Override
+ public boolean hasCoverGUI() {
+ return true;
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ @Override
+ public ModularWindow createWindow(GT_CoverUIBuildContext buildContext) {
+ return new RedstoneWirelessBaseUIFactory(buildContext).createWindow();
+ }
+
+ private class RedstoneWirelessBaseUIFactory extends UIFactory {
+
+ private static final int startX = 10;
+ private static final int startY = 25;
+ private static final int spaceX = 18;
+ private static final int spaceY = 18;
+
+ public RedstoneWirelessBaseUIFactory(GT_CoverUIBuildContext buildContext) {
+ super(buildContext);
+ }
+
+ @Override
+ protected int getGUIWidth() {
+ return 250;
+ }
+
+ @SuppressWarnings("PointlessArithmeticExpression")
+ @Override
+ protected void addUIWidgets(ModularWindow.Builder builder) {
+ builder
+ .widget(
+ new CoverDataControllerWidget<>(
+ this::getCoverData,
+ this::setCoverData,
+ GT_Cover_RedstoneWirelessBase.this)
+
+ .addFollower(
+ new CoverDataFollower_NumericWidget<>(),
+ coverData -> (double) getFlagFrequency(convert(coverData)),
+ (coverData, state) -> new ISerializableObject.LegacyCoverData(
+ state.intValue() | getFlagCheckbox(convert(coverData))),
+ widget -> widget.setBounds(0, MAX_CHANNEL)
+ .setScrollValues(1, 1000, 10)
+ .setFocusOnGuiOpen(true)
+ .setPos(spaceX * 0, spaceY * 0 + 2)
+ .setSize(spaceX * 4 - 3, 12))
+ .addFollower(
+ CoverDataFollower_ToggleButtonWidget.ofCheck(),
+ coverData -> getFlagCheckbox(convert(coverData)) > 0,
+ (coverData, state) -> new ISerializableObject.LegacyCoverData(
+ getFlagFrequency(convert(coverData)) | (state ? CHECKBOX_MASK : 0)),
+ widget -> widget.setPos(spaceX * 0, spaceY * 2))
+ .setPos(startX, startY))
+ .widget(
+ new TextWidget(GT_Utility.trans("246", "Frequency")).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * 4, 4 + startY + spaceY * 0))
+ .widget(
+ new TextWidget(GT_Utility.trans("602", "Use Private Frequency"))
+ .setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * 1, startY + spaceY * 2 + 4));
+ }
+
+ private int getFlagFrequency(int coverVariable) {
+ return coverVariable & PUBLIC_MASK;
+ }
+
+ private int getFlagCheckbox(int coverVariable) {
+ return coverVariable & CHECKBOX_MASK;
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/GT_Cover_Screen.java b/src/main/java/gregtech/common/covers/GT_Cover_Screen.java
new file mode 100644
index 0000000000..fab2b81b0b
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/GT_Cover_Screen.java
@@ -0,0 +1,100 @@
+package gregtech.common.covers;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.util.GT_CoverBehavior;
+
+public class GT_Cover_Screen extends GT_CoverBehavior {
+
+ public GT_Cover_Screen(ITexture coverTexture) {
+ super(coverTexture);
+ }
+
+ @Override
+ public boolean isRedstoneSensitive(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ long aTimer) {
+ return false;
+ }
+
+ @Override
+ public float getBlastProofLevel(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return 20.0F;
+ }
+
+ @Override
+ public boolean letsRedstoneGoIn(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return false;
+ }
+
+ @Override
+ public boolean letsRedstoneGoOut(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return false;
+ }
+
+ @Override
+ public boolean letsEnergyIn(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return false;
+ }
+
+ @Override
+ public boolean letsEnergyOut(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return false;
+ }
+
+ @Override
+ public boolean letsFluidIn(ForgeDirection side, int aCoverID, int aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return false;
+ }
+
+ @Override
+ public boolean letsFluidOut(ForgeDirection side, int aCoverID, int aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return false;
+ }
+
+ @Override
+ public boolean letsItemsIn(ForgeDirection side, int aCoverID, int aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return false;
+ }
+
+ @Override
+ public boolean letsItemsOut(ForgeDirection side, int aCoverID, int aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return false;
+ }
+
+ @Override
+ public boolean isGUIClickable(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean manipulatesSidedRedstoneOutput(ForgeDirection side, int aCoverID, int aCoverVariable,
+ ICoverable aTileEntity) {
+ return false;
+ }
+
+ @Override
+ public boolean onCoverRightclick(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ return false;
+ }
+
+ @Override
+ public boolean onCoverRemoval(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ boolean aForced) {
+ return true;
+ }
+
+ @Override
+ public int doCoverThings(ForgeDirection side, byte aInputRedstone, int aCoverID, int aCoverVariable,
+ ICoverable aTileEntity, long aTimer) {
+ return 0;
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/GT_Cover_Shutter.java b/src/main/java/gregtech/common/covers/GT_Cover_Shutter.java
new file mode 100644
index 0000000000..670506141c
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/GT_Cover_Shutter.java
@@ -0,0 +1,201 @@
+package gregtech.common.covers;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.api.gui.modularui.GT_CoverUIBuildContext;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.interfaces.tileentity.IMachineProgress;
+import gregtech.api.metatileentity.BaseMetaPipeEntity;
+import gregtech.api.util.GT_CoverBehavior;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.ISerializableObject;
+import gregtech.common.gui.modularui.widget.CoverDataControllerWidget;
+import gregtech.common.gui.modularui.widget.CoverDataFollower_ToggleButtonWidget;
+
+public class GT_Cover_Shutter extends GT_CoverBehavior {
+
+ public GT_Cover_Shutter(ITexture coverTexture) {
+ super(coverTexture);
+ }
+
+ @Override
+ public boolean isRedstoneSensitive(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ long aTimer) {
+ return false;
+ }
+
+ @Override
+ public int doCoverThings(ForgeDirection side, byte aInputRedstone, int aCoverID, int aCoverVariable,
+ ICoverable aTileEntity, long aTimer) {
+ return aCoverVariable;
+ }
+
+ @Override
+ public int onCoverScrewdriverclick(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ aCoverVariable = (aCoverVariable + (aPlayer.isSneaking() ? -1 : 1)) % 4;
+ if (aCoverVariable < 0) {
+ aCoverVariable = 3;
+ }
+ switch (aCoverVariable) {
+ case 0 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("082", "Open if work enabled"));
+ case 1 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("083", "Open if work disabled"));
+ case 2 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("084", "Only Output allowed"));
+ case 3 -> GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("085", "Only Input allowed"));
+ }
+ if (aTileEntity instanceof BaseMetaPipeEntity) {
+ ((BaseMetaPipeEntity) aTileEntity).reloadLocks();
+ }
+ return aCoverVariable;
+ }
+
+ @Override
+ public boolean letsRedstoneGoIn(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return aCoverVariable >= 2 ? aCoverVariable == 3
+ : !(aTileEntity instanceof IMachineProgress)
+ || (((IMachineProgress) aTileEntity).isAllowedToWork() == (aCoverVariable % 2 == 0));
+ }
+
+ @Override
+ public boolean letsRedstoneGoOut(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return aCoverVariable >= 2 ? aCoverVariable == 2
+ : !(aTileEntity instanceof IMachineProgress)
+ || (((IMachineProgress) aTileEntity).isAllowedToWork() == (aCoverVariable % 2 == 0));
+ }
+
+ @Override
+ public boolean letsEnergyIn(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return aCoverVariable >= 2 ? aCoverVariable == 3
+ : !(aTileEntity instanceof IMachineProgress)
+ || (((IMachineProgress) aTileEntity).isAllowedToWork() == (aCoverVariable % 2 == 0));
+ }
+
+ @Override
+ public boolean letsEnergyOut(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return aCoverVariable >= 2 ? aCoverVariable == 2
+ : !(aTileEntity instanceof IMachineProgress)
+ || ((IMachineProgress) aTileEntity).isAllowedToWork() == (aCoverVariable % 2 == 0);
+ }
+
+ @Override
+ public boolean letsFluidIn(ForgeDirection side, int aCoverID, int aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return aCoverVariable >= 2 ? aCoverVariable == 3
+ : !(aTileEntity instanceof IMachineProgress)
+ || ((IMachineProgress) aTileEntity).isAllowedToWork() == (aCoverVariable % 2 == 0);
+ }
+
+ @Override
+ public boolean letsFluidOut(ForgeDirection side, int aCoverID, int aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return aCoverVariable >= 2 ? aCoverVariable == 2
+ : !(aTileEntity instanceof IMachineProgress)
+ || ((IMachineProgress) aTileEntity).isAllowedToWork() == (aCoverVariable % 2 == 0);
+ }
+
+ @Override
+ public boolean letsItemsIn(ForgeDirection side, int aCoverID, int aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return aCoverVariable >= 2 ? aCoverVariable == 3
+ : !(aTileEntity instanceof IMachineProgress)
+ || ((IMachineProgress) aTileEntity).isAllowedToWork() == (aCoverVariable % 2 == 0);
+ }
+
+ @Override
+ public boolean letsItemsOut(ForgeDirection side, int aCoverID, int aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return aCoverVariable >= 2 ? aCoverVariable == 2
+ : !(aTileEntity instanceof IMachineProgress)
+ || ((IMachineProgress) aTileEntity).isAllowedToWork() == (aCoverVariable % 2 == 0);
+ }
+
+ @Override
+ public boolean alwaysLookConnected(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public int getTickRate(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return 0;
+ }
+
+ // GUI stuff
+
+ @Override
+ public boolean hasCoverGUI() {
+ return true;
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ @Override
+ public ModularWindow createWindow(GT_CoverUIBuildContext buildContext) {
+ return new ShutterUIFactory(buildContext).createWindow();
+ }
+
+ private class ShutterUIFactory extends UIFactory {
+
+ private static final int startX = 10;
+ private static final int startY = 25;
+ private static final int spaceX = 18;
+ private static final int spaceY = 18;
+
+ public ShutterUIFactory(GT_CoverUIBuildContext buildContext) {
+ super(buildContext);
+ }
+
+ @SuppressWarnings("PointlessArithmeticExpression")
+ @Override
+ protected void addUIWidgets(ModularWindow.Builder builder) {
+ builder
+ .widget(
+ new CoverDataControllerWidget.CoverDataIndexedControllerWidget_ToggleButtons<>(
+ this::getCoverData,
+ this::setCoverData,
+ GT_Cover_Shutter.this,
+ (index, coverData) -> index == convert(coverData),
+ (index, coverData) -> new ISerializableObject.LegacyCoverData(index))
+ .addToggleButton(
+ 0,
+ CoverDataFollower_ToggleButtonWidget.ofCheck(),
+ widget -> widget.setPos(spaceX * 0, spaceY * 0))
+ .addToggleButton(
+ 1,
+ CoverDataFollower_ToggleButtonWidget.ofCheck(),
+ widget -> widget.setPos(spaceX * 0, spaceY * 1))
+ .addToggleButton(
+ 2,
+ CoverDataFollower_ToggleButtonWidget.ofCheck(),
+ widget -> widget.setPos(spaceX * 0, spaceY * 2))
+ .addToggleButton(
+ 3,
+ CoverDataFollower_ToggleButtonWidget.ofCheck(),
+ widget -> widget.setPos(spaceX * 0, spaceY * 3))
+ .setPos(startX, startY))
+ .widget(
+ new TextWidget(GT_Utility.trans("082", "Open if work enabled"))
+ .setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(3 + startX + spaceX * 1, 4 + startY + spaceY * 0))
+ .widget(
+ new TextWidget(GT_Utility.trans("083", "Open if work disabled"))
+ .setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(3 + startX + spaceX * 1, 4 + startY + spaceY * 1))
+ .widget(
+ new TextWidget(GT_Utility.trans("084", "Only Output allowed"))
+ .setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(3 + startX + spaceX * 1, 4 + startY + spaceY * 2))
+ .widget(
+ new TextWidget(GT_Utility.trans("085", "Only Input allowed")).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(3 + startX + spaceX * 1, 4 + startY + spaceY * 3));
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/GT_Cover_SolarPanel.java b/src/main/java/gregtech/common/covers/GT_Cover_SolarPanel.java
new file mode 100644
index 0000000000..4b88a90194
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/GT_Cover_SolarPanel.java
@@ -0,0 +1,139 @@
+package gregtech.common.covers;
+
+import static gregtech.api.objects.XSTR.XSTR_INSTANCE;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Items;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.util.GT_CoverBehavior;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.ISerializableObject;
+
+public class GT_Cover_SolarPanel extends GT_CoverBehavior {
+
+ private final int mVoltage;
+
+ public GT_Cover_SolarPanel(int aVoltage) {
+ this.mVoltage = aVoltage;
+ }
+
+ @Override
+ public boolean isRedstoneSensitive(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ long aTimer) {
+ return false;
+ }
+
+ @Override
+ public int doCoverThings(ForgeDirection side, byte aInputRedstone, int aCoverID, int aCoverVariable,
+ ICoverable aTileEntity, long aTimer) {
+ if (side != ForgeDirection.UP) return 0;
+ int coverState = aCoverVariable & 0x3;
+ int coverNum = aCoverVariable >> 2;
+ if (aTimer % 100L == 0L) {
+ if (aTileEntity.getWorld()
+ .isThundering()) {
+ return aTileEntity.getBiome().rainfall > 0.0F && aTileEntity.getSkyAtSide(side)
+ ? Math.min(20, coverNum) << 2
+ : coverNum << 2;
+ } else {
+ if (aTileEntity.getWorld()
+ .isRaining() && aTileEntity.getBiome().rainfall > 0.0F) { // really rains
+ if (aTileEntity.getSkyAtSide(side)) coverNum = Math.min(30, coverNum);
+ if (aTileEntity.getWorld().skylightSubtracted >= 4) {
+ if (aTileEntity.getWorld()
+ .isDaytime()) {
+ coverState = 2;
+ } else {
+ return coverNum << 2;
+ }
+ }
+ } else { // not rains
+ if (aTileEntity.getWorld()
+ .isDaytime()) {
+ coverState = 1;
+ } else {
+ coverState = 2;
+ }
+ }
+ }
+ }
+ if (coverState == 1) {
+ aTileEntity.injectEnergyUnits(
+ ForgeDirection.UNKNOWN,
+ ((100L - (long) coverNum) * ((long) this.mVoltage)) / 100L,
+ 1L);
+ }
+ if (aTimer % 28800L == 0L && coverNum < 100 && (coverNum > 10 || XSTR_INSTANCE.nextInt(3) == 2)) coverNum++;
+ return coverState + (coverNum << 2);
+ }
+
+ @Override
+ protected boolean onCoverRightClickImpl(ForgeDirection side, int aCoverID,
+ ISerializableObject.LegacyCoverData aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, float aX,
+ float aY, float aZ) {
+ if (aPlayer.capabilities.isCreativeMode) {
+ GT_Utility.sendChatToPlayer(aPlayer, "Cleaned solar panel from " + (aCoverVariable.get() >> 2) + "% dirt");
+ aCoverVariable.set(aCoverVariable.get() & 0x3);
+ return true;
+ }
+ for (int i = 0; i < aPlayer.inventory.mainInventory.length; i++) {
+ ItemStack is = aPlayer.inventory.mainInventory[i];
+ if (is == null) continue;
+ if (is.getUnlocalizedName()
+ .equals(new ItemStack(Items.water_bucket).getUnlocalizedName())) {
+ aPlayer.inventory.mainInventory[i] = new ItemStack(Items.bucket);
+ if (aPlayer.inventoryContainer != null) aPlayer.inventoryContainer.detectAndSendChanges();
+ GT_Utility
+ .sendChatToPlayer(aPlayer, "Cleaned solar panel from " + (aCoverVariable.get() >> 2) + "% dirt");
+ aCoverVariable.set(aCoverVariable.get() & 0x3);
+ return true;
+ }
+ }
+ GT_Utility.sendChatToPlayer(aPlayer, "You need water bucket in inventory to clean the panel.");
+ return false;
+ }
+
+ @Override
+ @SuppressWarnings("deprecation")
+ public boolean onCoverRightclick(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ if (aPlayer.capabilities.isCreativeMode) {
+ GT_Utility.sendChatToPlayer(aPlayer, "Cleaned solar panel from " + (aCoverVariable >> 2) + "% dirt");
+ aTileEntity.setCoverDataAtSide(side, (aCoverVariable & 0x3));
+ return true;
+ }
+ for (int i = 0; i < aPlayer.inventory.mainInventory.length; i++) {
+ ItemStack is = aPlayer.inventory.mainInventory[i];
+ if (is == null) continue;
+ if (is.getUnlocalizedName()
+ .equals(new ItemStack(Items.water_bucket).getUnlocalizedName())) {
+ aPlayer.inventory.mainInventory[i] = new ItemStack(Items.bucket);
+ if (aPlayer.inventoryContainer != null) aPlayer.inventoryContainer.detectAndSendChanges();
+ GT_Utility.sendChatToPlayer(aPlayer, "Cleaned solar panel from " + (aCoverVariable >> 2) + "% dirt");
+ aTileEntity.setCoverDataAtSide(side, (aCoverVariable & 0x3));
+ return true;
+ }
+ }
+ GT_Utility.sendChatToPlayer(aPlayer, "You need water bucket in inventory to clean the panel.");
+ return false;
+ }
+
+ @Override
+ protected boolean isGUIClickableImpl(ForgeDirection side, int aCoverID,
+ ISerializableObject.LegacyCoverData aCoverVariable, ICoverable aTileEntity) {
+ return false;
+ }
+
+ @Override
+ public boolean alwaysLookConnected(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public int getTickRate(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return 1;
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/GT_Cover_SteamRegulator.java b/src/main/java/gregtech/common/covers/GT_Cover_SteamRegulator.java
new file mode 100644
index 0000000000..e67e8b05d1
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/GT_Cover_SteamRegulator.java
@@ -0,0 +1,18 @@
+package gregtech.common.covers;
+
+import net.minecraftforge.fluids.FluidStack;
+
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.util.GT_ModHandler;
+
+public class GT_Cover_SteamRegulator extends GT_Cover_FluidRegulator {
+
+ public GT_Cover_SteamRegulator(int aTransferRate, ITexture coverTexture) {
+ super(aTransferRate, coverTexture);
+ }
+
+ @Override
+ protected boolean canTransferFluid(FluidStack fluid) {
+ return GT_ModHandler.isAnySteam(fluid) || GT_ModHandler.isSuperHeatedSteam(fluid);
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/GT_Cover_SteamValve.java b/src/main/java/gregtech/common/covers/GT_Cover_SteamValve.java
new file mode 100644
index 0000000000..5787a99c0b
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/GT_Cover_SteamValve.java
@@ -0,0 +1,26 @@
+package gregtech.common.covers;
+
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidStack;
+
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.util.GT_ModHandler;
+
+public class GT_Cover_SteamValve extends GT_Cover_Pump {
+
+ public GT_Cover_SteamValve(int aTransferRate, ITexture coverTexture) {
+ super(aTransferRate, coverTexture);
+ }
+
+ @Override
+ public boolean isRedstoneSensitive(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ long aTimer) {
+ return false;
+ }
+
+ @Override
+ protected boolean canTransferFluid(FluidStack fluid) {
+ return GT_ModHandler.isAnySteam(fluid) || GT_ModHandler.isSuperHeatedSteam(fluid);
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/GT_Cover_Vent.java b/src/main/java/gregtech/common/covers/GT_Cover_Vent.java
new file mode 100644
index 0000000000..e2be64b475
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/GT_Cover_Vent.java
@@ -0,0 +1,111 @@
+package gregtech.common.covers;
+
+import static gregtech.api.objects.XSTR.XSTR_INSTANCE;
+
+import net.minecraft.block.Block;
+import net.minecraft.init.Blocks;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidRegistry;
+import net.minecraftforge.fluids.FluidStack;
+import net.minecraftforge.fluids.IFluidHandler;
+
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.interfaces.tileentity.IMachineProgress;
+import gregtech.api.util.GT_CoverBehavior;
+import gregtech.api.util.GT_Utility;
+
+public class GT_Cover_Vent extends GT_CoverBehavior {
+
+ private final int mEfficiency;
+ private final Fluid IC2_HOT_COOLANT = FluidRegistry.getFluid("ic2hotcoolant");
+ private final Fluid IC2_COOLANT = FluidRegistry.getFluid("ic2coolant");
+
+ public GT_Cover_Vent(int aEfficiency) {
+ this.mEfficiency = aEfficiency;
+ }
+
+ @Override
+ public boolean isRedstoneSensitive(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity,
+ long aTimer) {
+ return false;
+ }
+
+ @Override
+ public int doCoverThings(ForgeDirection side, byte aInputRedstone, int aCoverID, int aCoverVariable,
+ ICoverable aTileEntity, long aTimer) {
+ if (side == ForgeDirection.UNKNOWN) return 0;
+ int ret = 0;
+ if (aTileEntity instanceof IFluidHandler) {
+ ret = doCoolFluid(side, aTileEntity);
+ }
+ if ((aTileEntity instanceof IMachineProgress)) {
+ ret = doProgressEfficiency(side, (IMachineProgress) aTileEntity, aCoverID);
+ }
+ return ret;
+ }
+
+ @Override
+ public boolean alwaysLookConnected(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public int getTickRate(ForgeDirection side, int aCoverID, int aCoverVariable, ICoverable aTileEntity) {
+ return 100;
+ }
+
+ protected int doProgressEfficiency(final ForgeDirection side, final IMachineProgress aTileEntity,
+ final int aCoverVariable) {
+ final int offsetX = aTileEntity.getOffsetX(side, 1);
+ final int offsetY = aTileEntity.getOffsetY(side, 1);
+ final int offsetZ = aTileEntity.getOffsetZ(side, 1);
+ final World world = aTileEntity.getWorld();
+ if (aTileEntity.hasThingsToDo() && aCoverVariable != aTileEntity.getProgress()
+ && !GT_Utility.hasBlockHitBox(world, offsetX, offsetY, offsetZ)) {
+ aTileEntity.increaseProgress(this.mEfficiency);
+ }
+ return aTileEntity.getProgress();
+ }
+
+ protected int doCoolFluid(final ForgeDirection side, final ICoverable aTileEntity) {
+ final int offsetX = aTileEntity.getOffsetX(side, 1);
+ final int offsetY = aTileEntity.getOffsetY(side, 1);
+ final int offsetZ = aTileEntity.getOffsetZ(side, 1);
+ final World world = aTileEntity.getWorld();
+ final IFluidHandler fluidHandler = (IFluidHandler) aTileEntity;
+ if (!fluidHandler.canDrain(ForgeDirection.UNKNOWN, IC2_HOT_COOLANT)) {
+ return 0;
+ }
+ final int chances; // 10000 = 100%
+ final Block blockAtSide = aTileEntity.getBlockAtSide(side);
+ if (blockAtSide == null) {
+ return 0;
+ }
+ if (blockAtSide == Blocks.water || blockAtSide == Blocks.flowing_water) {
+ chances = switch (mEfficiency) {
+ case 3 -> 10000; // 100% chances for Diamond reactor vent with water
+ case 2 -> 5000; // 50% chances for Gold and Overclocked reactor vents with water
+ default -> 2500; // 25% chances for Basic reactor vent with water
+ };
+ } else if (blockAtSide.isAir(world, offsetX, offsetY, offsetZ)) {
+ switch (mEfficiency) {
+ case 3 -> chances = 2500; // 25% chances for Diamond reactor vent with air
+ case 2 -> chances = 1250; // 12.5% chances for Gold and Overclocked reactor vents with air
+ default -> {
+ return 0; // Basic reactor vent cannot be used with air
+ }
+ }
+ } else {
+ return 0; // Vent cover need water or air
+ }
+ if (chances > XSTR_INSTANCE.nextInt(10000)) {
+ final FluidStack hotFluidStack = fluidHandler.drain(ForgeDirection.UNKNOWN, Integer.MAX_VALUE, true);
+ final FluidStack coldFluidStack = new FluidStack(IC2_COOLANT, hotFluidStack.amount);
+ fluidHandler.fill(ForgeDirection.UNKNOWN, coldFluidStack, true);
+ return hotFluidStack.amount;
+ }
+ return 0;
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/redstone/GT_Cover_AdvancedRedstoneReceiverBase.java b/src/main/java/gregtech/common/covers/redstone/GT_Cover_AdvancedRedstoneReceiverBase.java
new file mode 100644
index 0000000000..afd0f67b37
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/redstone/GT_Cover_AdvancedRedstoneReceiverBase.java
@@ -0,0 +1,202 @@
+package gregtech.common.covers.redstone;
+
+import java.util.Arrays;
+import java.util.UUID;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.nbt.NBTBase;
+import net.minecraft.nbt.NBTTagCompound;
+
+import com.google.common.io.ByteArrayDataInput;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.api.gui.modularui.GT_CoverUIBuildContext;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.ISerializableObject;
+import gregtech.common.gui.modularui.widget.CoverDataControllerWidget;
+import gregtech.common.gui.modularui.widget.CoverDataFollower_ToggleButtonWidget;
+import io.netty.buffer.ByteBuf;
+
+public abstract class GT_Cover_AdvancedRedstoneReceiverBase
+ extends GT_Cover_AdvancedWirelessRedstoneBase<GT_Cover_AdvancedRedstoneReceiverBase.ReceiverData> {
+
+ public GT_Cover_AdvancedRedstoneReceiverBase(ITexture coverTexture) {
+ super(ReceiverData.class, coverTexture);
+ }
+
+ @Override
+ public ReceiverData createDataObject() {
+ return new ReceiverData();
+ }
+
+ @Override
+ public ReceiverData createDataObject(int aLegacyData) {
+ return createDataObject();
+ }
+
+ // GUI stuff
+
+ @Override
+ public ModularWindow createWindow(GT_CoverUIBuildContext buildContext) {
+ return new AdvancedRedstoneReceiverBaseUIFactory(buildContext).createWindow();
+ }
+
+ private class AdvancedRedstoneReceiverBaseUIFactory extends AdvancedWirelessRedstoneBaseUIFactory {
+
+ public AdvancedRedstoneReceiverBaseUIFactory(GT_CoverUIBuildContext buildContext) {
+ super(buildContext);
+ }
+
+ @Override
+ protected int getFrequencyRow() {
+ return 0;
+ }
+
+ @Override
+ protected int getButtonRow() {
+ return 1;
+ }
+
+ @Override
+ protected boolean isShiftPrivateLeft() {
+ return false;
+ }
+
+ @Override
+ protected void addUIWidgets(ModularWindow.Builder builder) {
+ super.addUIWidgets(builder);
+ builder.widget(
+ new TextWidget(GT_Utility.trans("335", "Gate Mode")).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * 5, 4 + startY + spaceY * 2));
+ }
+
+ @SuppressWarnings("PointlessArithmeticExpression")
+ @Override
+ protected void addUIForDataController(CoverDataControllerWidget<ReceiverData> controller) {
+ super.addUIForDataController(controller);
+ controller.addFollower(
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ coverData -> coverData.mode == GateMode.AND,
+ (coverData, state) -> {
+ coverData.mode = GateMode.AND;
+ return coverData;
+ },
+ widget -> widget.setStaticTexture(GT_UITextures.OVERLAY_BUTTON_GATE_AND)
+ .addTooltip(GT_Utility.trans("331", "AND Gate"))
+ .setPos(spaceX * 0, spaceY * 2))
+ .addFollower(
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ coverData -> coverData.mode == GateMode.NAND,
+ (coverData, state) -> {
+ coverData.mode = GateMode.NAND;
+ return coverData;
+ },
+ widget -> widget.setStaticTexture(GT_UITextures.OVERLAY_BUTTON_GATE_NAND)
+ .addTooltip(GT_Utility.trans("332", "NAND Gate"))
+ .setPos(spaceX * 1, spaceY * 2))
+ .addFollower(
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ coverData -> coverData.mode == GateMode.OR,
+ (coverData, state) -> {
+ coverData.mode = GateMode.OR;
+ return coverData;
+ },
+ widget -> widget.setStaticTexture(GT_UITextures.OVERLAY_BUTTON_GATE_OR)
+ .addTooltip(GT_Utility.trans("333", "OR Gate"))
+ .setPos(spaceX * 2, spaceY * 2))
+ .addFollower(
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ coverData -> coverData.mode == GateMode.NOR,
+ (coverData, state) -> {
+ coverData.mode = GateMode.NOR;
+ return coverData;
+ },
+ widget -> widget.setStaticTexture(GT_UITextures.OVERLAY_BUTTON_GATE_NOR)
+ .addTooltip(GT_Utility.trans("334", "NOR Gate"))
+ .setPos(spaceX * 3, spaceY * 2))
+ .addFollower(
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ coverData -> coverData.mode == GateMode.SINGLE_SOURCE,
+ (coverData, state) -> {
+ coverData.mode = GateMode.SINGLE_SOURCE;
+ return coverData;
+ },
+ widget -> widget.setStaticTexture(GT_UITextures.OVERLAY_BUTTON_ANALOG)
+ .addTooltips(
+ Arrays.asList(
+ "ANALOG Mode",
+ "Only use this mode with ONE transmitter in total,",
+ "no logic involved"))
+ .setPos(spaceX * 4, spaceY * 2));
+ }
+ }
+
+ public enum GateMode {
+ AND,
+ NAND,
+ OR,
+ NOR,
+ SINGLE_SOURCE
+ }
+
+ public static class ReceiverData extends GT_Cover_AdvancedWirelessRedstoneBase.WirelessData {
+
+ private GateMode mode;
+
+ public ReceiverData(int frequency, UUID uuid, GateMode mode) {
+ super(frequency, uuid);
+ this.mode = mode;
+ }
+
+ public ReceiverData() {
+ this(0, null, GateMode.AND);
+ }
+
+ public GateMode getGateMode() {
+ return mode;
+ }
+
+ @Nonnull
+ @Override
+ public ISerializableObject copy() {
+ return new ReceiverData(frequency, uuid, mode);
+ }
+
+ @Nonnull
+ @Override
+ public NBTBase saveDataToNBT() {
+ NBTTagCompound tag = (NBTTagCompound) super.saveDataToNBT();
+ tag.setByte("mode", (byte) mode.ordinal());
+
+ return tag;
+ }
+
+ @Override
+ public void writeToByteBuf(ByteBuf aBuf) {
+ super.writeToByteBuf(aBuf);
+ aBuf.writeByte(mode.ordinal());
+ }
+
+ @Override
+ public void loadDataFromNBT(NBTBase aNBT) {
+ super.loadDataFromNBT(aNBT);
+
+ NBTTagCompound tag = (NBTTagCompound) aNBT;
+ mode = GateMode.values()[tag.getByte("mode")];
+ }
+
+ @Nonnull
+ @Override
+ public ISerializableObject readFromPacket(ByteArrayDataInput aBuf, EntityPlayerMP aPlayer) {
+ super.readFromPacket(aBuf, aPlayer);
+ mode = GateMode.values()[aBuf.readByte()];
+
+ return this;
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/redstone/GT_Cover_AdvancedRedstoneReceiverExternal.java b/src/main/java/gregtech/common/covers/redstone/GT_Cover_AdvancedRedstoneReceiverExternal.java
new file mode 100644
index 0000000000..a8a30de9b1
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/redstone/GT_Cover_AdvancedRedstoneReceiverExternal.java
@@ -0,0 +1,35 @@
+package gregtech.common.covers.redstone;
+
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.ICoverable;
+
+public class GT_Cover_AdvancedRedstoneReceiverExternal extends GT_Cover_AdvancedRedstoneReceiverBase {
+
+ public GT_Cover_AdvancedRedstoneReceiverExternal(ITexture coverTexture) {
+ super(coverTexture);
+ }
+
+ @Override
+ public ReceiverData doCoverThingsImpl(ForgeDirection side, byte aInputRedstone, int aCoverID,
+ ReceiverData aCoverVariable, ICoverable aTileEntity, long aTimer) {
+ aTileEntity.setOutputRedstoneSignal(
+ side,
+ getSignalAt(aCoverVariable.getUuid(), aCoverVariable.getFrequency(), aCoverVariable.getGateMode()));
+
+ return aCoverVariable;
+ }
+
+ @Override
+ protected boolean isRedstoneSensitiveImpl(ForgeDirection side, int aCoverID, ReceiverData aCoverVariable,
+ ICoverable aTileEntity, long aTimer) {
+ return false;
+ }
+
+ @Override
+ protected boolean manipulatesSidedRedstoneOutputImpl(ForgeDirection side, int aCoverID, ReceiverData aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/redstone/GT_Cover_AdvancedRedstoneReceiverInternal.java b/src/main/java/gregtech/common/covers/redstone/GT_Cover_AdvancedRedstoneReceiverInternal.java
new file mode 100644
index 0000000000..5553cb7c9c
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/redstone/GT_Cover_AdvancedRedstoneReceiverInternal.java
@@ -0,0 +1,42 @@
+package gregtech.common.covers.redstone;
+
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.interfaces.tileentity.IMachineProgress;
+
+public class GT_Cover_AdvancedRedstoneReceiverInternal extends GT_Cover_AdvancedRedstoneReceiverBase {
+
+ public GT_Cover_AdvancedRedstoneReceiverInternal(ITexture coverTexture) {
+ super(coverTexture);
+ }
+
+ @Override
+ public ReceiverData doCoverThingsImpl(ForgeDirection side, byte aInputRedstone, int aCoverID,
+ ReceiverData aCoverVariable, ICoverable aTileEntity, long aTimer) {
+ if (aTileEntity instanceof IMachineProgress machine) {
+ if (getRedstoneInput(side, aInputRedstone, aCoverID, aCoverVariable, aTileEntity) > 0) {
+ machine.enableWorking();
+ } else {
+ machine.disableWorking();
+ }
+
+ machine.setWorkDataValue(aInputRedstone);
+ }
+
+ return aCoverVariable;
+ }
+
+ @Override
+ protected byte getRedstoneInputImpl(ForgeDirection side, byte aInputRedstone, int aCoverID,
+ ReceiverData aCoverVariable, ICoverable aTileEntity) {
+ return getSignalAt(aCoverVariable.getUuid(), aCoverVariable.getFrequency(), aCoverVariable.getGateMode());
+ }
+
+ @Override
+ protected boolean isRedstoneSensitiveImpl(ForgeDirection side, int aCoverID, ReceiverData aCoverVariable,
+ ICoverable aTileEntity, long aTimer) {
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/redstone/GT_Cover_AdvancedRedstoneTransmitterBase.java b/src/main/java/gregtech/common/covers/redstone/GT_Cover_AdvancedRedstoneTransmitterBase.java
new file mode 100644
index 0000000000..3417542bec
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/redstone/GT_Cover_AdvancedRedstoneTransmitterBase.java
@@ -0,0 +1,188 @@
+package gregtech.common.covers.redstone;
+
+import java.util.Objects;
+import java.util.UUID;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.nbt.NBTBase;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.google.common.io.ByteArrayDataInput;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.api.gui.modularui.GT_CoverUIBuildContext;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.ISerializableObject;
+import gregtech.common.gui.modularui.widget.CoverDataControllerWidget;
+import gregtech.common.gui.modularui.widget.CoverDataFollower_ToggleButtonWidget;
+import io.netty.buffer.ByteBuf;
+
+public abstract class GT_Cover_AdvancedRedstoneTransmitterBase<T extends GT_Cover_AdvancedRedstoneTransmitterBase.TransmitterData>
+ extends GT_Cover_AdvancedWirelessRedstoneBase<T> {
+
+ public GT_Cover_AdvancedRedstoneTransmitterBase(Class<T> typeToken, ITexture coverTexture) {
+ super(typeToken, coverTexture);
+ }
+
+ private static void unregisterSignal(ForgeDirection side, TransmitterData aCoverVariable, ICoverable aTileEntity) {
+ final long hash = hashCoverCoords(aTileEntity, side);
+ removeSignalAt(aCoverVariable.uuid, aCoverVariable.frequency, hash);
+ }
+
+ @Override
+ public boolean onCoverRemovalImpl(ForgeDirection side, int aCoverID, TransmitterData aCoverVariable,
+ ICoverable aTileEntity, boolean aForced) {
+ unregisterSignal(side, aCoverVariable, aTileEntity);
+ return true;
+ }
+
+ @Override
+ protected void onBaseTEDestroyedImpl(ForgeDirection side, int aCoverID, TransmitterData aCoverVariable,
+ ICoverable aTileEntity) {
+ unregisterSignal(side, aCoverVariable, aTileEntity);
+ }
+
+ @Override
+ protected T onCoverScrewdriverClickImpl(ForgeDirection side, int aCoverID, T aCoverVariable, ICoverable aTileEntity,
+ EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ aCoverVariable.invert = !aCoverVariable.invert;
+ GT_Utility.sendChatToPlayer(
+ aPlayer,
+ aCoverVariable.invert ? GT_Utility.trans("054", "Inverted") : GT_Utility.trans("055", "Normal"));
+
+ return aCoverVariable;
+ }
+
+ @Override
+ protected void preDataChangedImpl(ForgeDirection side, int aCoverID, int aNewCoverId, T aCoverVariable,
+ T aNewCoverVariable, ICoverable aTileEntity) {
+ if (aCoverVariable.frequency != aNewCoverVariable.frequency
+ || !Objects.equals(aCoverVariable.uuid, aNewCoverVariable.uuid)) {
+ unregisterSignal(side, aCoverVariable, aTileEntity);
+ }
+ }
+
+ public static class TransmitterData extends GT_Cover_AdvancedWirelessRedstoneBase.WirelessData {
+
+ protected boolean invert;
+
+ public TransmitterData(int frequency, UUID uuid, boolean invert) {
+ super(frequency, uuid);
+ this.invert = invert;
+ }
+
+ public TransmitterData() {
+ this(0, null, false);
+ }
+
+ public boolean isInvert() {
+ return invert;
+ }
+
+ @Nonnull
+ @Override
+ public ISerializableObject copy() {
+ return new TransmitterData(frequency, uuid, invert);
+ }
+
+ @Nonnull
+ @Override
+ public NBTBase saveDataToNBT() {
+ NBTTagCompound tag = (NBTTagCompound) super.saveDataToNBT();
+ tag.setBoolean("invert", invert);
+
+ return tag;
+ }
+
+ @Override
+ public void writeToByteBuf(ByteBuf aBuf) {
+ super.writeToByteBuf(aBuf);
+ aBuf.writeBoolean(invert);
+ }
+
+ @Override
+ public void loadDataFromNBT(NBTBase aNBT) {
+ super.loadDataFromNBT(aNBT);
+
+ NBTTagCompound tag = (NBTTagCompound) aNBT;
+ invert = tag.getBoolean("invert");
+ }
+
+ @Nonnull
+ @Override
+ public ISerializableObject readFromPacket(ByteArrayDataInput aBuf, EntityPlayerMP aPlayer) {
+ super.readFromPacket(aBuf, aPlayer);
+ invert = aBuf.readBoolean();
+
+ return this;
+ }
+ }
+
+ // GUI stuff
+
+ @Override
+ public ModularWindow createWindow(GT_CoverUIBuildContext buildContext) {
+ return new AdvancedRedstoneTransmitterBaseUIFactory(buildContext).createWindow();
+ }
+
+ protected class AdvancedRedstoneTransmitterBaseUIFactory extends AdvancedWirelessRedstoneBaseUIFactory {
+
+ public AdvancedRedstoneTransmitterBaseUIFactory(GT_CoverUIBuildContext buildContext) {
+ super(buildContext);
+ }
+
+ @Override
+ protected int getFrequencyRow() {
+ return 0;
+ }
+
+ @Override
+ protected int getButtonRow() {
+ return 1;
+ }
+
+ @Override
+ protected boolean isShiftPrivateLeft() {
+ return true;
+ }
+
+ @Override
+ protected void addUIWidgets(ModularWindow.Builder builder) {
+ super.addUIWidgets(builder);
+ builder.widget(TextWidget.dynamicString(() -> {
+ T coverData = getCoverData();
+ if (coverData != null) {
+ return getCoverData().invert ? GT_Utility.trans("INVERTED", "Inverted")
+ : GT_Utility.trans("NORMAL", "Normal");
+ } else {
+ return "";
+ }
+ })
+ .setSynced(false)
+ .setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * 10, 4 + startY + spaceY * getButtonRow()));
+ }
+
+ @Override
+ protected void addUIForDataController(CoverDataControllerWidget<T> controller) {
+ super.addUIForDataController(controller);
+ controller.addFollower(
+ CoverDataFollower_ToggleButtonWidget.ofRedstone(),
+ coverData -> coverData.invert,
+ (coverData, state) -> {
+ coverData.invert = state;
+ return coverData;
+ },
+ widget -> widget.addTooltip(0, GT_Utility.trans("NORMAL", "Normal"))
+ .addTooltip(1, GT_Utility.trans("INVERTED", "Inverted"))
+ .setPos(spaceX * 9, spaceY * getButtonRow()));
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/redstone/GT_Cover_AdvancedRedstoneTransmitterExternal.java b/src/main/java/gregtech/common/covers/redstone/GT_Cover_AdvancedRedstoneTransmitterExternal.java
new file mode 100644
index 0000000000..139ec64843
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/redstone/GT_Cover_AdvancedRedstoneTransmitterExternal.java
@@ -0,0 +1,51 @@
+package gregtech.common.covers.redstone;
+
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.ICoverable;
+
+public class GT_Cover_AdvancedRedstoneTransmitterExternal
+ extends GT_Cover_AdvancedRedstoneTransmitterBase<GT_Cover_AdvancedRedstoneTransmitterBase.TransmitterData> {
+
+ public GT_Cover_AdvancedRedstoneTransmitterExternal(ITexture coverTexture) {
+ super(TransmitterData.class, coverTexture);
+ }
+
+ @Override
+ public TransmitterData createDataObject() {
+ return new TransmitterData();
+ }
+
+ @Override
+ public TransmitterData createDataObject(int aLegacyData) {
+ return createDataObject();
+ }
+
+ @Override
+ public TransmitterData doCoverThingsImpl(ForgeDirection side, byte aInputRedstone, int aCoverID,
+ TransmitterData aCoverVariable, ICoverable aTileEntity, long aTimer) {
+ byte outputRedstone = aInputRedstone;
+ if (aCoverVariable.isInvert()) {
+ if (outputRedstone > 0) outputRedstone = 0;
+ else outputRedstone = 15;
+ }
+
+ final long hash = hashCoverCoords(aTileEntity, side);
+ setSignalAt(aCoverVariable.getUuid(), aCoverVariable.getFrequency(), hash, outputRedstone);
+
+ return aCoverVariable;
+ }
+
+ @Override
+ protected boolean isRedstoneSensitiveImpl(ForgeDirection side, int aCoverID, TransmitterData aCoverVariable,
+ ICoverable aTileEntity, long aTimer) {
+ return true;
+ }
+
+ @Override
+ public boolean letsRedstoneGoInImpl(ForgeDirection side, int aCoverID, TransmitterData aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/redstone/GT_Cover_AdvancedRedstoneTransmitterInternal.java b/src/main/java/gregtech/common/covers/redstone/GT_Cover_AdvancedRedstoneTransmitterInternal.java
new file mode 100644
index 0000000000..01a46fcc86
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/redstone/GT_Cover_AdvancedRedstoneTransmitterInternal.java
@@ -0,0 +1,50 @@
+package gregtech.common.covers.redstone;
+
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.ICoverable;
+
+public class GT_Cover_AdvancedRedstoneTransmitterInternal
+ extends GT_Cover_AdvancedRedstoneTransmitterBase<GT_Cover_AdvancedRedstoneTransmitterBase.TransmitterData> {
+
+ public GT_Cover_AdvancedRedstoneTransmitterInternal(ITexture coverTexture) {
+ super(TransmitterData.class, coverTexture);
+ }
+
+ @Override
+ public TransmitterData createDataObject() {
+ return new TransmitterData();
+ }
+
+ @Override
+ public TransmitterData createDataObject(int aLegacyData) {
+ return createDataObject();
+ }
+
+ @Override
+ public TransmitterData doCoverThingsImpl(ForgeDirection side, byte aInputRedstone, int aCoverID,
+ TransmitterData aCoverVariable, ICoverable aTileEntity, long aTimer) {
+ byte outputRedstone = aTileEntity.getOutputRedstoneSignal(side);
+ if (aCoverVariable.isInvert()) {
+ if (outputRedstone > 0) outputRedstone = 0;
+ else outputRedstone = 15;
+ }
+
+ final long hash = hashCoverCoords(aTileEntity, side);
+ setSignalAt(aCoverVariable.getUuid(), aCoverVariable.getFrequency(), hash, outputRedstone);
+ return aCoverVariable;
+ }
+
+ @Override
+ public boolean letsRedstoneGoOutImpl(ForgeDirection side, int aCoverID, TransmitterData aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected boolean manipulatesSidedRedstoneOutputImpl(ForgeDirection side, int aCoverID,
+ TransmitterData aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/redstone/GT_Cover_AdvancedWirelessRedstoneBase.java b/src/main/java/gregtech/common/covers/redstone/GT_Cover_AdvancedWirelessRedstoneBase.java
new file mode 100644
index 0000000000..d19db38177
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/redstone/GT_Cover_AdvancedWirelessRedstoneBase.java
@@ -0,0 +1,303 @@
+package gregtech.common.covers.redstone;
+
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.nbt.NBTBase;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+
+import com.google.common.io.ByteArrayDataInput;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.gui.modularui.GT_CoverUIBuildContext;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.util.GT_CoverBehaviorBase;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.ISerializableObject;
+import gregtech.common.gui.modularui.widget.CoverDataControllerWidget;
+import gregtech.common.gui.modularui.widget.CoverDataFollower_NumericWidget;
+import gregtech.common.gui.modularui.widget.CoverDataFollower_ToggleButtonWidget;
+import io.netty.buffer.ByteBuf;
+
+public abstract class GT_Cover_AdvancedWirelessRedstoneBase<T extends GT_Cover_AdvancedWirelessRedstoneBase.WirelessData>
+ extends GT_CoverBehaviorBase<T> {
+
+ public GT_Cover_AdvancedWirelessRedstoneBase(Class<T> typeToken, ITexture coverTexture) {
+ super(typeToken, coverTexture);
+ }
+
+ public static Byte getSignalAt(UUID uuid, int frequency, GT_Cover_AdvancedRedstoneReceiverBase.GateMode mode) {
+ Map<Integer, Map<Long, Byte>> frequencies = GregTech_API.sAdvancedWirelessRedstone.get(String.valueOf(uuid));
+ if (frequencies == null) return 0;
+
+ Map<Long, Byte> signals = frequencies.get(frequency);
+ if (signals == null) signals = new ConcurrentHashMap<>();
+
+ switch (mode) {
+ case AND -> {
+ return (byte) (signals.values()
+ .stream()
+ .map(signal -> signal > 0)
+ .reduce(true, (signalA, signalB) -> signalA && signalB) ? 15 : 0);
+ }
+ case NAND -> {
+ return (byte) (signals.values()
+ .stream()
+ .map(signal -> signal > 0)
+ .reduce(true, (signalA, signalB) -> signalA && signalB) ? 0 : 15);
+ }
+ case OR -> {
+ return (byte) (signals.values()
+ .stream()
+ .map(signal -> signal > 0)
+ .reduce(false, (signalA, signalB) -> signalA || signalB) ? 15 : 0);
+ }
+ case NOR -> {
+ return (byte) (signals.values()
+ .stream()
+ .map(signal -> signal > 0)
+ .reduce(false, (signalA, signalB) -> signalA || signalB) ? 0 : 15);
+ }
+ case SINGLE_SOURCE -> {
+ if (signals.values()
+ .isEmpty()) {
+ return 0;
+ }
+ return signals.values()
+ .iterator()
+ .next();
+ }
+ default -> {
+ return 0;
+ }
+ }
+ }
+
+ public static void removeSignalAt(UUID uuid, int frequency, long hash) {
+ Map<Integer, Map<Long, Byte>> frequencies = GregTech_API.sAdvancedWirelessRedstone.get(String.valueOf(uuid));
+ if (frequencies == null) return;
+ frequencies.computeIfPresent(frequency, (freq, longByteMap) -> {
+ longByteMap.remove(hash);
+ return longByteMap.isEmpty() ? null : longByteMap;
+ });
+ }
+
+ public static void setSignalAt(UUID uuid, int frequency, long hash, byte value) {
+ Map<Integer, Map<Long, Byte>> frequencies = GregTech_API.sAdvancedWirelessRedstone
+ .computeIfAbsent(String.valueOf(uuid), k -> new ConcurrentHashMap<>());
+ Map<Long, Byte> signals = frequencies.computeIfAbsent(frequency, k -> new ConcurrentHashMap<>());
+ signals.put(hash, value);
+ }
+
+ /**
+ * x hashed into first 20 bytes y hashed into second 20 bytes z hashed into fifth 10 bytes dim hashed into sixth 10
+ * bytes side hashed into last 4 bytes
+ */
+ public static long hashCoverCoords(ICoverable tile, ForgeDirection side) {
+ return (((((long) tile.getXCoord() << 20) + tile.getZCoord() << 10) + tile.getYCoord() << 10)
+ + tile.getWorld().provider.dimensionId << 4) + side.ordinal();
+ }
+
+ @Override
+ public boolean letsEnergyInImpl(ForgeDirection side, int aCoverID, T aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsEnergyOutImpl(ForgeDirection side, int aCoverID, T aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsFluidInImpl(ForgeDirection side, int aCoverID, T aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsFluidOutImpl(ForgeDirection side, int aCoverID, T aCoverVariable, Fluid aFluid,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsItemsInImpl(ForgeDirection side, int aCoverID, T aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public boolean letsItemsOutImpl(ForgeDirection side, int aCoverID, T aCoverVariable, int aSlot,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public String getDescriptionImpl(ForgeDirection side, int aCoverID, T aCoverVariable, ICoverable aTileEntity) {
+ return GT_Utility.trans("081", "Frequency: ") + aCoverVariable.frequency
+ + ", Transmission: "
+ + (aCoverVariable.uuid == null ? "Public" : "Private");
+ }
+
+ @Override
+ public int getTickRateImpl(ForgeDirection side, int aCoverID, T aCoverVariable, ICoverable aTileEntity) {
+ return 5;
+ }
+
+ public abstract static class WirelessData implements ISerializableObject {
+
+ protected int frequency;
+
+ /**
+ * If UUID is set to null, the cover frequency is public, rather than private
+ **/
+ protected UUID uuid;
+
+ public WirelessData(int frequency, UUID uuid) {
+ this.frequency = frequency;
+ this.uuid = uuid;
+ }
+
+ public UUID getUuid() {
+ return uuid;
+ }
+
+ public int getFrequency() {
+ return frequency;
+ }
+
+ @Nonnull
+ @Override
+ public NBTBase saveDataToNBT() {
+ NBTTagCompound tag = new NBTTagCompound();
+ tag.setInteger("frequency", frequency);
+ if (uuid != null) {
+ tag.setString("uuid", uuid.toString());
+ }
+
+ return tag;
+ }
+
+ @Override
+ public void writeToByteBuf(ByteBuf aBuf) {
+ aBuf.writeInt(frequency);
+ aBuf.writeBoolean(uuid != null);
+ if (uuid != null) {
+ aBuf.writeLong(uuid.getLeastSignificantBits());
+ aBuf.writeLong(uuid.getMostSignificantBits());
+ }
+ }
+
+ @Override
+ public void loadDataFromNBT(NBTBase aNBT) {
+ NBTTagCompound tag = (NBTTagCompound) aNBT;
+ frequency = tag.getInteger("frequency");
+ if (tag.hasKey("uuid")) {
+ uuid = UUID.fromString(tag.getString("uuid"));
+ }
+ }
+
+ @Nonnull
+ @Override
+ public ISerializableObject readFromPacket(ByteArrayDataInput aBuf, EntityPlayerMP aPlayer) {
+ frequency = aBuf.readInt();
+ if (aBuf.readBoolean()) {
+ uuid = new UUID(aBuf.readLong(), aBuf.readLong());
+ }
+
+ return this;
+ }
+ }
+
+ // GUI stuff
+
+ @Override
+ public boolean hasCoverGUI() {
+ return true;
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ protected abstract class AdvancedWirelessRedstoneBaseUIFactory extends UIFactory {
+
+ protected static final int startX = 10;
+ protected static final int startY = 25;
+ protected static final int spaceX = 18;
+ protected static final int spaceY = 18;
+
+ public AdvancedWirelessRedstoneBaseUIFactory(GT_CoverUIBuildContext buildContext) {
+ super(buildContext);
+ }
+
+ @Override
+ protected int getGUIWidth() {
+ return 250;
+ }
+
+ @Override
+ protected void addUIWidgets(ModularWindow.Builder builder) {
+ final int privateExtraColumn = isShiftPrivateLeft() ? 1 : 5;
+
+ CoverDataControllerWidget<T> dataController = new CoverDataControllerWidget<>(
+ this::getCoverData,
+ this::setCoverData,
+ GT_Cover_AdvancedWirelessRedstoneBase.this);
+ dataController.setPos(startX, startY);
+ addUIForDataController(dataController);
+
+ builder.widget(dataController)
+ .widget(
+ new TextWidget(GT_Utility.trans("246", "Frequency")).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * 5, 4 + startY + spaceY * getFrequencyRow()))
+ .widget(
+ new TextWidget(GT_Utility.trans("602", "Use Private Frequency"))
+ .setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * privateExtraColumn, 4 + startY + spaceY * getButtonRow()));
+ }
+
+ protected void addUIForDataController(CoverDataControllerWidget<T> controller) {
+ controller.addFollower(
+ new CoverDataFollower_NumericWidget<>(),
+ coverData -> (double) coverData.frequency,
+ (coverData, state) -> {
+ coverData.frequency = state.intValue();
+ return coverData;
+ },
+ widget -> widget.setScrollValues(1, 1000, 10)
+ .setBounds(0, Integer.MAX_VALUE)
+ .setPos(1, 2 + spaceY * getFrequencyRow())
+ .setSize(spaceX * 5 - 4, 12))
+ .addFollower(
+ CoverDataFollower_ToggleButtonWidget.ofCheck(),
+ coverData -> coverData.uuid != null,
+ (coverData, state) -> {
+ if (state) {
+ coverData.uuid = getUIBuildContext().getPlayer()
+ .getUniqueID();
+ } else {
+ coverData.uuid = null;
+ }
+ return coverData;
+ },
+ widget -> widget.setPos(0, spaceY * getButtonRow()));
+ }
+
+ protected abstract int getFrequencyRow();
+
+ protected abstract int getButtonRow();
+
+ protected abstract boolean isShiftPrivateLeft();
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/redstone/GT_Cover_WirelessDoesWorkDetector.java b/src/main/java/gregtech/common/covers/redstone/GT_Cover_WirelessDoesWorkDetector.java
new file mode 100644
index 0000000000..724f12b8f8
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/redstone/GT_Cover_WirelessDoesWorkDetector.java
@@ -0,0 +1,245 @@
+package gregtech.common.covers.redstone;
+
+import java.util.UUID;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.nbt.NBTBase;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.google.common.io.ByteArrayDataInput;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.api.gui.modularui.GT_CoverUIBuildContext;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.interfaces.tileentity.IMachineProgress;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.ISerializableObject;
+import gregtech.common.covers.redstone.GT_Cover_WirelessDoesWorkDetector.ActivityMode;
+import gregtech.common.gui.modularui.widget.CoverDataControllerWidget;
+import gregtech.common.gui.modularui.widget.CoverDataFollower_ToggleButtonWidget;
+import io.netty.buffer.ByteBuf;
+
+public class GT_Cover_WirelessDoesWorkDetector
+ extends GT_Cover_AdvancedRedstoneTransmitterBase<GT_Cover_WirelessDoesWorkDetector.ActivityTransmitterData> {
+
+ public GT_Cover_WirelessDoesWorkDetector(ITexture coverTexture) {
+ super(ActivityTransmitterData.class, coverTexture);
+ }
+
+ @Override
+ public ActivityTransmitterData createDataObject() {
+ return new ActivityTransmitterData();
+ }
+
+ @Override
+ public ActivityTransmitterData createDataObject(int aLegacyData) {
+ return createDataObject();
+ }
+
+ private static byte computeSignalBasedOnActivity(ActivityTransmitterData coverVariable, ICoverable tileEntity) {
+
+ if (tileEntity instanceof IMachineProgress) {
+ IMachineProgress mProgress = (IMachineProgress) tileEntity;
+ boolean inverted = coverVariable.invert;
+ int signal = 0;
+
+ switch (coverVariable.mode) {
+ case MACHINE_ENABLED -> signal = inverted == mProgress.isAllowedToWork() ? 0 : 15;
+ case MACHINE_IDLE -> signal = inverted == (mProgress.getMaxProgress() == 0) ? 0 : 15;
+ case RECIPE_PROGRESS -> {
+ int tScale = mProgress.getMaxProgress() / 15;
+
+ if (tScale > 0 && mProgress.hasThingsToDo()) {
+ signal = inverted ? (15 - mProgress.getProgress() / tScale)
+ : (mProgress.getProgress() / tScale);
+ } else {
+ signal = inverted ? 15 : 0;
+ }
+ }
+ }
+
+ return (byte) signal;
+ } else {
+ return (byte) 0;
+ }
+
+ }
+
+ @Override
+ public ActivityTransmitterData doCoverThingsImpl(ForgeDirection side, byte aInputRedstone, int aCoverID,
+ ActivityTransmitterData aCoverVariable, ICoverable aTileEntity, long aTimer) {
+ final byte signal = computeSignalBasedOnActivity(aCoverVariable, aTileEntity);
+ final long hash = hashCoverCoords(aTileEntity, side);
+ setSignalAt(aCoverVariable.getUuid(), aCoverVariable.getFrequency(), hash, signal);
+
+ return aCoverVariable;
+ }
+
+ @Override
+ public boolean letsRedstoneGoOutImpl(ForgeDirection side, int aCoverID, ActivityTransmitterData aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected boolean manipulatesSidedRedstoneOutputImpl(ForgeDirection side, int aCoverID,
+ ActivityTransmitterData aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public int getTickRateImpl(ForgeDirection side, int aCoverID, ActivityTransmitterData aCoverVariable,
+ ICoverable aTileEntity) {
+ return 5;
+ }
+
+ public enum ActivityMode {
+ RECIPE_PROGRESS,
+ MACHINE_IDLE,
+ MACHINE_ENABLED,
+ }
+
+ public static class ActivityTransmitterData extends GT_Cover_AdvancedRedstoneTransmitterBase.TransmitterData {
+
+ private ActivityMode mode;
+
+ public ActivityTransmitterData(int frequency, UUID uuid, boolean invert, ActivityMode mode) {
+ super(frequency, uuid, invert);
+ this.mode = mode;
+ }
+
+ public ActivityTransmitterData() {
+ super();
+ this.mode = ActivityMode.MACHINE_IDLE;
+ }
+
+ @Nonnull
+ @Override
+ public ISerializableObject copy() {
+ return new ActivityTransmitterData(frequency, uuid, invert, mode);
+ }
+
+ @Nonnull
+ @Override
+ public NBTBase saveDataToNBT() {
+ NBTTagCompound tag = (NBTTagCompound) super.saveDataToNBT();
+ tag.setInteger("mode", mode.ordinal());
+
+ return tag;
+ }
+
+ @Override
+ public void writeToByteBuf(ByteBuf aBuf) {
+ super.writeToByteBuf(aBuf);
+ aBuf.writeInt(mode.ordinal());
+ }
+
+ @Override
+ public void loadDataFromNBT(NBTBase aNBT) {
+ super.loadDataFromNBT(aNBT);
+
+ NBTTagCompound tag = (NBTTagCompound) aNBT;
+ mode = ActivityMode.values()[tag.getInteger("mode")];
+ }
+
+ @Nonnull
+ @Override
+ public ISerializableObject readFromPacket(ByteArrayDataInput aBuf, EntityPlayerMP aPlayer) {
+ super.readFromPacket(aBuf, aPlayer);
+ mode = ActivityMode.values()[aBuf.readInt()];
+
+ return this;
+ }
+ }
+
+ @Override
+ public ModularWindow createWindow(GT_CoverUIBuildContext buildContext) {
+ return new WirelessActivityDetectorUIFactory(buildContext).createWindow();
+ }
+
+ private class WirelessActivityDetectorUIFactory extends AdvancedRedstoneTransmitterBaseUIFactory {
+
+ public WirelessActivityDetectorUIFactory(GT_CoverUIBuildContext buildContext) {
+ super(buildContext);
+ }
+
+ @Override
+ protected int getGUIHeight() {
+ return 107;
+ }
+
+ @Override
+ protected int getFrequencyRow() {
+ return 0;
+ }
+
+ @Override
+ protected int getButtonRow() {
+ return 1;
+ }
+
+ @Override
+ protected void addUIWidgets(ModularWindow.Builder builder) {
+ super.addUIWidgets(builder);
+ builder.widget(TextWidget.dynamicString(() -> {
+
+ ActivityMode mode = getCoverData().mode;
+
+ if (mode == ActivityMode.MACHINE_ENABLED) {
+ return GT_Utility.trans("271", "Machine enabled");
+ } else if (mode == ActivityMode.MACHINE_IDLE) {
+ return GT_Utility.trans("242", "Machine idle");
+ } else {
+ return GT_Utility.trans("241", "Recipe progress");
+ }
+
+ })
+ .setSynced(false)
+ .setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * 3, 4 + startY + spaceY * 2));
+ }
+
+ @Override
+ protected void addUIForDataController(CoverDataControllerWidget<ActivityTransmitterData> controller) {
+ super.addUIForDataController(controller);
+
+ controller.addFollower(
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ coverData -> coverData.mode == ActivityMode.RECIPE_PROGRESS,
+ (coverData, state) -> {
+ coverData.mode = ActivityMode.RECIPE_PROGRESS;
+ return coverData;
+ },
+ widget -> widget.setStaticTexture(GT_UITextures.OVERLAY_BUTTON_PROGRESS)
+ .addTooltip(GT_Utility.trans("241", "Recipe progress"))
+ .setPos(spaceX * 0, spaceY * 2))
+ .addFollower(
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ coverData -> coverData.mode == ActivityMode.MACHINE_IDLE,
+ (coverData, state) -> {
+ coverData.mode = ActivityMode.MACHINE_IDLE;
+ return coverData;
+ },
+ widget -> widget.setStaticTexture(GT_UITextures.OVERLAY_BUTTON_CHECKMARK)
+ .addTooltip(GT_Utility.trans("242", "Machine idle"))
+ .setPos(spaceX * 1, spaceY * 2))
+ .addFollower(
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ coverData -> coverData.mode == ActivityMode.MACHINE_ENABLED,
+ (coverData, state) -> {
+ coverData.mode = ActivityMode.MACHINE_ENABLED;
+ return coverData;
+ },
+ widget -> widget.setStaticTexture(GT_UITextures.OVERLAY_BUTTON_POWER_SWITCH_ON)
+ .addTooltip(GT_Utility.trans("271", "Machine enabled"))
+ .setPos(spaceX * 2, spaceY * 2));
+ }
+ }
+
+}
diff --git a/src/main/java/gregtech/common/covers/redstone/GT_Cover_WirelessFluidDetector.java b/src/main/java/gregtech/common/covers/redstone/GT_Cover_WirelessFluidDetector.java
new file mode 100644
index 0000000000..9a9d419be6
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/redstone/GT_Cover_WirelessFluidDetector.java
@@ -0,0 +1,186 @@
+package gregtech.common.covers.redstone;
+
+import java.util.Arrays;
+import java.util.UUID;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.nbt.NBTBase;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidTankInfo;
+import net.minecraftforge.fluids.IFluidHandler;
+
+import com.google.common.io.ByteArrayDataInput;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.api.gui.modularui.GT_CoverUIBuildContext;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.ISerializableObject;
+import gregtech.common.covers.GT_Cover_LiquidMeter;
+import gregtech.common.gui.modularui.widget.CoverDataControllerWidget;
+import gregtech.common.gui.modularui.widget.CoverDataFollower_NumericWidget;
+import io.netty.buffer.ByteBuf;
+
+public class GT_Cover_WirelessFluidDetector
+ extends GT_Cover_AdvancedRedstoneTransmitterBase<GT_Cover_WirelessFluidDetector.FluidTransmitterData> {
+
+ public GT_Cover_WirelessFluidDetector(ITexture coverTexture) {
+ super(FluidTransmitterData.class, coverTexture);
+ }
+
+ @Override
+ public FluidTransmitterData createDataObject() {
+ return new FluidTransmitterData();
+ }
+
+ @Override
+ public FluidTransmitterData createDataObject(int aLegacyData) {
+ return createDataObject();
+ }
+
+ @Override
+ public FluidTransmitterData doCoverThingsImpl(ForgeDirection side, byte aInputRedstone, int aCoverID,
+ FluidTransmitterData aCoverVariable, ICoverable aTileEntity, long aTimer) {
+ final byte signal = GT_Cover_LiquidMeter
+ .computeSignalBasedOnFluid(aTileEntity, aCoverVariable.invert, aCoverVariable.threshold);
+ final long hash = hashCoverCoords(aTileEntity, side);
+ setSignalAt(aCoverVariable.getUuid(), aCoverVariable.getFrequency(), hash, signal);
+
+ return aCoverVariable;
+ }
+
+ @Override
+ public boolean letsRedstoneGoOutImpl(ForgeDirection side, int aCoverID, FluidTransmitterData aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected boolean manipulatesSidedRedstoneOutputImpl(ForgeDirection side, int aCoverID,
+ FluidTransmitterData aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ public static class FluidTransmitterData extends GT_Cover_AdvancedRedstoneTransmitterBase.TransmitterData {
+
+ /** The special value {@code 0} means threshold check is disabled. */
+ private int threshold;
+
+ public FluidTransmitterData(int frequency, UUID uuid, boolean invert, int threshold) {
+ super(frequency, uuid, invert);
+ this.threshold = threshold;
+ }
+
+ public FluidTransmitterData() {
+ super();
+ this.threshold = 0;
+ }
+
+ @Nonnull
+ @Override
+ public ISerializableObject copy() {
+ return new FluidTransmitterData(frequency, uuid, invert, threshold);
+ }
+
+ @Nonnull
+ @Override
+ public NBTBase saveDataToNBT() {
+ NBTTagCompound tag = (NBTTagCompound) super.saveDataToNBT();
+ tag.setInteger("threshold", threshold);
+
+ return tag;
+ }
+
+ @Override
+ public void writeToByteBuf(ByteBuf aBuf) {
+ super.writeToByteBuf(aBuf);
+ aBuf.writeInt(threshold);
+ }
+
+ @Override
+ public void loadDataFromNBT(NBTBase aNBT) {
+ super.loadDataFromNBT(aNBT);
+
+ NBTTagCompound tag = (NBTTagCompound) aNBT;
+ threshold = tag.getInteger("threshold");
+ }
+
+ @Nonnull
+ @Override
+ public ISerializableObject readFromPacket(ByteArrayDataInput aBuf, EntityPlayerMP aPlayer) {
+ super.readFromPacket(aBuf, aPlayer);
+ threshold = aBuf.readInt();
+
+ return this;
+ }
+ }
+
+ // GUI stuff
+
+ @Override
+ public ModularWindow createWindow(GT_CoverUIBuildContext buildContext) {
+ return new WirelessFluidDetectorUIFactory(buildContext).createWindow();
+ }
+
+ private class WirelessFluidDetectorUIFactory extends AdvancedRedstoneTransmitterBaseUIFactory {
+
+ private int maxCapacity;
+
+ public WirelessFluidDetectorUIFactory(GT_CoverUIBuildContext buildContext) {
+ super(buildContext);
+ }
+
+ @Override
+ protected int getFrequencyRow() {
+ return 0;
+ }
+
+ @Override
+ protected int getButtonRow() {
+ return 1;
+ }
+
+ @Override
+ protected void addUIWidgets(ModularWindow.Builder builder) {
+ setMaxCapacity();
+ super.addUIWidgets(builder);
+ builder.widget(
+ new TextWidget(GT_Utility.trans("222", "Fluid threshold")).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * 5, 4 + startY + spaceY * 2));
+ }
+
+ @Override
+ protected void addUIForDataController(CoverDataControllerWidget<FluidTransmitterData> controller) {
+ super.addUIForDataController(controller);
+ controller.addFollower(
+ new CoverDataFollower_NumericWidget<>(),
+ coverData -> (double) coverData.threshold,
+ (coverData, state) -> {
+ coverData.threshold = state.intValue();
+ return coverData;
+ },
+ widget -> widget.setBounds(0, maxCapacity > 0 ? maxCapacity : Integer.MAX_VALUE)
+ .setScrollValues(1000, 144, 100000)
+ .setFocusOnGuiOpen(true)
+ .setPos(1, 2 + spaceY * 2)
+ .setSize(spaceX * 5 - 4, 12));
+ }
+
+ private void setMaxCapacity() {
+ final ICoverable tile = getUIBuildContext().getTile();
+ if (!tile.isDead() && tile instanceof IFluidHandler) {
+ FluidTankInfo[] tanks = ((IFluidHandler) tile).getTankInfo(ForgeDirection.UNKNOWN);
+ maxCapacity = Arrays.stream(tanks)
+ .mapToInt(tank -> tank.capacity)
+ .sum();
+ } else {
+ maxCapacity = -1;
+ }
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/redstone/GT_Cover_WirelessItemDetector.java b/src/main/java/gregtech/common/covers/redstone/GT_Cover_WirelessItemDetector.java
new file mode 100644
index 0000000000..3cc7f60984
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/redstone/GT_Cover_WirelessItemDetector.java
@@ -0,0 +1,262 @@
+package gregtech.common.covers.redstone;
+
+import java.text.FieldPosition;
+import java.util.UUID;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTBase;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.google.common.io.ByteArrayDataInput;
+import com.gtnewhorizons.modularui.api.NumberFormatMUI;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.api.gui.modularui.GT_CoverUIBuildContext;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.ISerializableObject;
+import gregtech.common.covers.GT_Cover_ItemMeter;
+import gregtech.common.gui.modularui.widget.CoverDataControllerWidget;
+import gregtech.common.gui.modularui.widget.CoverDataFollower_NumericWidget;
+import gregtech.common.gui.modularui.widget.ItemWatcherSlotWidget;
+import gregtech.common.tileentities.storage.GT_MetaTileEntity_DigitalChestBase;
+import io.netty.buffer.ByteBuf;
+
+public class GT_Cover_WirelessItemDetector
+ extends GT_Cover_AdvancedRedstoneTransmitterBase<GT_Cover_WirelessItemDetector.ItemTransmitterData> {
+
+ public GT_Cover_WirelessItemDetector(ITexture coverTexture) {
+ super(ItemTransmitterData.class, coverTexture);
+ }
+
+ @Override
+ public ItemTransmitterData createDataObject() {
+ return new ItemTransmitterData();
+ }
+
+ @Override
+ public ItemTransmitterData createDataObject(int aLegacyData) {
+ return createDataObject();
+ }
+
+ @Override
+ public ItemTransmitterData doCoverThingsImpl(ForgeDirection side, byte aInputRedstone, int aCoverID,
+ ItemTransmitterData aCoverVariable, ICoverable aTileEntity, long aTimer) {
+ byte signal = GT_Cover_ItemMeter.computeSignalBasedOnItems(
+ aTileEntity,
+ aCoverVariable.invert,
+ aCoverVariable.threshold,
+ aCoverVariable.slot,
+ side.ordinal());
+ final long hash = hashCoverCoords(aTileEntity, side);
+ setSignalAt(aCoverVariable.getUuid(), aCoverVariable.getFrequency(), hash, signal);
+
+ return aCoverVariable;
+ }
+
+ @Override
+ public boolean letsRedstoneGoOutImpl(ForgeDirection side, int aCoverID, ItemTransmitterData aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected boolean manipulatesSidedRedstoneOutputImpl(ForgeDirection side, int aCoverID,
+ ItemTransmitterData aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ public static class ItemTransmitterData extends GT_Cover_AdvancedRedstoneTransmitterBase.TransmitterData {
+
+ /**
+ * The special value {@code -1} means all slots.
+ */
+ private int slot;
+ /**
+ * The special value {@code 0} means threshold check is disabled.
+ */
+ private int threshold;
+
+ public ItemTransmitterData(int frequency, UUID uuid, boolean invert, int threshold, int slot) {
+ super(frequency, uuid, invert);
+ this.threshold = threshold;
+ this.slot = slot;
+ }
+
+ public ItemTransmitterData() {
+ super();
+ this.threshold = 0;
+ this.slot = -1;
+ }
+
+ @Nonnull
+ @Override
+ public ISerializableObject copy() {
+ return new ItemTransmitterData(frequency, uuid, invert, threshold, slot);
+ }
+
+ @Nonnull
+ @Override
+ public NBTBase saveDataToNBT() {
+ NBTTagCompound tag = (NBTTagCompound) super.saveDataToNBT();
+ tag.setInteger("threshold", threshold);
+ tag.setInteger("slot", slot);
+
+ return tag;
+ }
+
+ @Override
+ public void writeToByteBuf(ByteBuf aBuf) {
+ super.writeToByteBuf(aBuf);
+ aBuf.writeInt(threshold);
+ aBuf.writeInt(slot);
+ }
+
+ @Override
+ public void loadDataFromNBT(NBTBase aNBT) {
+ super.loadDataFromNBT(aNBT);
+
+ NBTTagCompound tag = (NBTTagCompound) aNBT;
+ threshold = tag.getInteger("threshold");
+ slot = tag.getInteger("slot");
+ }
+
+ @Nonnull
+ @Override
+ public ISerializableObject readFromPacket(ByteArrayDataInput aBuf, EntityPlayerMP aPlayer) {
+ super.readFromPacket(aBuf, aPlayer);
+ threshold = aBuf.readInt();
+ slot = aBuf.readInt();
+
+ return this;
+ }
+ }
+
+ // GUI stuff
+
+ @Override
+ public ModularWindow createWindow(GT_CoverUIBuildContext buildContext) {
+ return new WirelessItemDetectorUIFactory(buildContext).createWindow();
+ }
+
+ private class WirelessItemDetectorUIFactory extends AdvancedRedstoneTransmitterBaseUIFactory {
+
+ private int maxSlot;
+ private int maxThreshold;
+ /**
+ * Display the text "All" instead of a number when the slot is set to -1.
+ */
+ private static final NumberFormatMUI numberFormatAll = new NumberFormatMUI() {
+
+ @Override
+ public StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos) {
+ if (number < 0) {
+ return toAppendTo.append(GT_Utility.trans("ALL", "All"));
+ } else {
+ return super.format(number, toAppendTo, pos);
+ }
+ }
+ };
+
+ public WirelessItemDetectorUIFactory(GT_CoverUIBuildContext buildContext) {
+ super(buildContext);
+ }
+
+ @Override
+ protected int getFrequencyRow() {
+ return 0;
+ }
+
+ @Override
+ protected int getButtonRow() {
+ return 1;
+ }
+
+ @Override
+ protected void addUIWidgets(ModularWindow.Builder builder) {
+ setMaxSlot();
+ setMaxThreshold();
+ super.addUIWidgets(builder);
+ builder.widget(
+ new ItemWatcherSlotWidget().setGetter(this::getTargetItem)
+ .setPos(startX + spaceX * 4 - 1, startY + spaceY * 3))
+ .widget(
+ new TextWidget(GT_Utility.trans("221", "Item threshold")).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * 5, 4 + startY + spaceY * 2))
+ .widget(
+ new TextWidget(GT_Utility.trans("254", "Detect Slot #")).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * 5, 4 + startY + spaceY * 3));
+ }
+
+ @Override
+ protected void addUIForDataController(CoverDataControllerWidget<ItemTransmitterData> controller) {
+ super.addUIForDataController(controller);
+ controller.addFollower(
+ new CoverDataFollower_NumericWidget<>(),
+ coverData -> (double) coverData.threshold,
+ (coverData, state) -> {
+ coverData.threshold = state.intValue();
+ return coverData;
+ },
+ widget -> widget.setBounds(0, maxThreshold)
+ .setScrollValues(1, 64, 1000)
+ .setFocusOnGuiOpen(true)
+ .setPos(1, 2 + spaceY * 2)
+ .setSize(spaceX * 5 - 4, 12))
+ .addFollower(
+ new CoverDataFollower_NumericWidget<>(),
+ coverData -> (double) coverData.slot,
+ (coverData, state) -> {
+ coverData.slot = state.intValue();
+ return coverData;
+ },
+ widget -> widget.setBounds(-1, maxSlot)
+ .setDefaultValue(-1)
+ .setScrollValues(1, 100, 10)
+ .setNumberFormat(numberFormatAll)
+ .setPos(1, 2 + spaceY * 3)
+ .setSize(spaceX * 4 - 8, 12));
+ }
+
+ private void setMaxSlot() {
+ final ICoverable tile = getUIBuildContext().getTile();
+ if (!tile.isDead() && tile instanceof IGregTechTileEntity gtTile
+ && !(gtTile.getMetaTileEntity() instanceof GT_MetaTileEntity_DigitalChestBase)) {
+ maxSlot = tile.getSizeInventory() - 1;
+ } else {
+ maxSlot = -1;
+ }
+ }
+
+ private void setMaxThreshold() {
+ final ICoverable tile = getUIBuildContext().getTile();
+ if (!tile.isDead() && tile instanceof IGregTechTileEntity gtTile
+ && gtTile.getMetaTileEntity() instanceof GT_MetaTileEntity_DigitalChestBase) {
+ maxThreshold = gtTile.getMaxItemCount();
+ } else {
+ maxThreshold = maxSlot > 0 ? maxSlot * 64 : Integer.MAX_VALUE;
+ }
+ }
+
+ private ItemStack getTargetItem() {
+ final ICoverable tile = getUIBuildContext().getTile();
+ final ItemTransmitterData coverVariable = getCoverData();
+ if (coverVariable != null && coverVariable.slot >= 0
+ && tile instanceof TileEntity
+ && !tile.isDead()
+ && tile.getSizeInventory() >= coverVariable.slot) {
+ return tile.getStackInSlot(coverVariable.slot);
+ } else {
+ return null;
+ }
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/covers/redstone/GT_Cover_WirelessMaintenanceDetector.java b/src/main/java/gregtech/common/covers/redstone/GT_Cover_WirelessMaintenanceDetector.java
new file mode 100644
index 0000000000..d9cc765ef8
--- /dev/null
+++ b/src/main/java/gregtech/common/covers/redstone/GT_Cover_WirelessMaintenanceDetector.java
@@ -0,0 +1,242 @@
+package gregtech.common.covers.redstone;
+
+import java.util.UUID;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTBase;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.google.common.io.ByteArrayDataInput;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.api.gui.modularui.GT_CoverUIBuildContext;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_MultiBlockBase;
+import gregtech.api.util.ISerializableObject;
+import gregtech.common.covers.GT_Cover_NeedMaintainance;
+import gregtech.common.gui.modularui.widget.CoverDataControllerWidget;
+import gregtech.common.gui.modularui.widget.CoverDataFollower_ToggleButtonWidget;
+import io.netty.buffer.ByteBuf;
+
+public class GT_Cover_WirelessMaintenanceDetector
+ extends GT_Cover_AdvancedRedstoneTransmitterBase<GT_Cover_WirelessMaintenanceDetector.MaintenanceTransmitterData> {
+
+ public GT_Cover_WirelessMaintenanceDetector(ITexture coverTexture) {
+ super(MaintenanceTransmitterData.class, coverTexture);
+ }
+
+ @Override
+ public MaintenanceTransmitterData createDataObject() {
+ return new MaintenanceTransmitterData();
+ }
+
+ @Override
+ public MaintenanceTransmitterData createDataObject(int aLegacyData) {
+ return createDataObject();
+ }
+
+ private static byte computeSignalBasedOnMaintenance(MaintenanceTransmitterData coverVariable,
+ ICoverable tileEntity) {
+ boolean signal = false;
+
+ if (tileEntity instanceof IGregTechTileEntity) {
+ IMetaTileEntity metaTE = ((IGregTechTileEntity) tileEntity).getMetaTileEntity();
+ if (metaTE instanceof GT_MetaTileEntity_MultiBlockBase multiTE) {
+ int ideal = multiTE.getIdealStatus();
+ int real = multiTE.getRepairStatus();
+
+ switch (coverVariable.mode) {
+ case NO_ISSUE -> signal = ideal == real;
+ case ONE_ISSUE, TWO_ISSUES, THREE_ISSUES, FOUR_ISSUES, FIVE_ISSUES -> signal = ideal - real
+ >= coverVariable.mode.ordinal();
+ case ROTOR_80, ROTOR_100 -> {
+ ItemStack rotor = multiTE.getRealInventory()[1];
+ if (GT_Cover_NeedMaintainance.isRotor(rotor)) {
+ long max = GT_MetaGenerated_Tool.getToolMaxDamage(rotor);
+ long current = GT_MetaGenerated_Tool.getToolDamage(rotor);
+
+ if (coverVariable.mode == MaintenanceMode.ROTOR_80) {
+ signal = current >= max * 8 / 10;
+ } else {
+ long expectedDamage = Math.round(
+ Math.min(
+ (double) multiTE.mEUt / multiTE.damageFactorLow,
+ Math.pow(multiTE.mEUt, multiTE.damageFactorHigh)));
+ signal = current + expectedDamage * 2 >= max;
+ }
+ } else {
+ signal = true;
+ }
+ }
+ }
+ }
+ }
+
+ if (coverVariable.invert) {
+ signal = !signal;
+ }
+
+ return (byte) (signal ? 15 : 0);
+ }
+
+ @Override
+ public MaintenanceTransmitterData doCoverThingsImpl(ForgeDirection side, byte aInputRedstone, int aCoverID,
+ MaintenanceTransmitterData aCoverVariable, ICoverable aTileEntity, long aTimer) {
+ final byte signal = computeSignalBasedOnMaintenance(aCoverVariable, aTileEntity);
+ final long hash = hashCoverCoords(aTileEntity, side);
+ setSignalAt(aCoverVariable.getUuid(), aCoverVariable.getFrequency(), hash, signal);
+
+ return aCoverVariable;
+ }
+
+ @Override
+ public boolean letsRedstoneGoOutImpl(ForgeDirection side, int aCoverID, MaintenanceTransmitterData aCoverVariable,
+ ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ protected boolean manipulatesSidedRedstoneOutputImpl(ForgeDirection side, int aCoverID,
+ MaintenanceTransmitterData aCoverVariable, ICoverable aTileEntity) {
+ return true;
+ }
+
+ @Override
+ public int getTickRateImpl(ForgeDirection side, int aCoverID, MaintenanceTransmitterData aCoverVariable,
+ ICoverable aTileEntity) {
+ return 60;
+ }
+
+ public enum MaintenanceMode {
+ NO_ISSUE,
+ ONE_ISSUE,
+ TWO_ISSUES,
+ THREE_ISSUES,
+ FOUR_ISSUES,
+ FIVE_ISSUES,
+ ROTOR_80,
+ ROTOR_100
+ }
+
+ public static class MaintenanceTransmitterData extends GT_Cover_AdvancedRedstoneTransmitterBase.TransmitterData {
+
+ private MaintenanceMode mode;
+
+ public MaintenanceTransmitterData(int frequency, UUID uuid, boolean invert, MaintenanceMode mode) {
+ super(frequency, uuid, invert);
+ this.mode = mode;
+ }
+
+ public MaintenanceTransmitterData() {
+ super();
+ this.mode = MaintenanceMode.ONE_ISSUE;
+ }
+
+ @Nonnull
+ @Override
+ public ISerializableObject copy() {
+ return new MaintenanceTransmitterData(frequency, uuid, invert, mode);
+ }
+
+ @Nonnull
+ @Override
+ public NBTBase saveDataToNBT() {
+ NBTTagCompound tag = (NBTTagCompound) super.saveDataToNBT();
+ tag.setInteger("mode", mode.ordinal());
+
+ return tag;
+ }
+
+ @Override
+ public void writeToByteBuf(ByteBuf aBuf) {
+ super.writeToByteBuf(aBuf);
+ aBuf.writeInt(mode.ordinal());
+ }
+
+ @Override
+ public void loadDataFromNBT(NBTBase aNBT) {
+ super.loadDataFromNBT(aNBT);
+
+ NBTTagCompound tag = (NBTTagCompound) aNBT;
+ mode = MaintenanceMode.values()[tag.getInteger("mode")];
+ }
+
+ @Nonnull
+ @Override
+ public ISerializableObject readFromPacket(ByteArrayDataInput aBuf, EntityPlayerMP aPlayer) {
+ super.readFromPacket(aBuf, aPlayer);
+ mode = MaintenanceMode.values()[aBuf.readInt()];
+
+ return this;
+ }
+ }
+
+ // GUI stuff
+
+ private static final String[] extraTexts = new String[] { "No Issues", ">= 1 Issue", ">= 2 Issues", ">= 3 Issues",
+ ">= 4 Issues", ">= 5 Issues", "Rotor < 80%", "Rotor < 100%" };
+
+ @Override
+ public ModularWindow createWindow(GT_CoverUIBuildContext buildContext) {
+ return new WirelessMaintenanceDetectorUIFactory(buildContext).createWindow();
+ }
+
+ private class WirelessMaintenanceDetectorUIFactory extends AdvancedRedstoneTransmitterBaseUIFactory {
+
+ public WirelessMaintenanceDetectorUIFactory(GT_CoverUIBuildContext buildContext) {
+ super(buildContext);
+ }
+
+ @Override
+ protected int getGUIHeight() {
+ return 143;
+ }
+
+ @Override
+ protected int getFrequencyRow() {
+ return 0;
+ }
+
+ @Override
+ protected int getButtonRow() {
+ return 1;
+ }
+
+ @Override
+ protected void addUIWidgets(ModularWindow.Builder builder) {
+ super.addUIWidgets(builder);
+ for (int i = 0; i < 8; i++) {
+ builder.widget(
+ new TextWidget(extraTexts[i]).setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(startX + spaceX * (i % 2 == 0 ? 1 : 7), 4 + startY + spaceY * (2 + i / 2)));
+ }
+ }
+
+ @Override
+ protected void addUIForDataController(CoverDataControllerWidget<MaintenanceTransmitterData> controller) {
+ super.addUIForDataController(controller);
+ for (int i = 0; i < 8; i++) {
+ final int index = i;
+ controller.addFollower(
+ CoverDataFollower_ToggleButtonWidget.ofDisableable(),
+ coverData -> coverData.mode == MaintenanceMode.values()[index],
+ (coverData, state) -> {
+ coverData.mode = MaintenanceMode.values()[index];
+ return coverData;
+ },
+ widget -> widget.setToggleTexture(GT_UITextures.OVERLAY_BUTTON_CHECKMARK, GT_UITextures.TRANSPARENT)
+ .setPos(spaceX * (index % 2 == 0 ? 0 : 6), spaceY * (2 + index / 2)));
+ }
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/entities/GT_EntityFXPollution.java b/src/main/java/gregtech/common/entities/GT_EntityFXPollution.java
new file mode 100644
index 0000000000..d5121a38ad
--- /dev/null
+++ b/src/main/java/gregtech/common/entities/GT_EntityFXPollution.java
@@ -0,0 +1,59 @@
+package gregtech.common.entities;
+
+import java.util.Random;
+
+import net.minecraft.client.particle.EntityFX;
+import net.minecraft.world.World;
+
+public class GT_EntityFXPollution extends EntityFX {
+
+ public GT_EntityFXPollution(World world, double x, double y, double z) {
+ super(world, x, y, z, 0, 0, 0);
+
+ this.particleRed = 0.25F;
+ this.particleGreen = 0.2F;
+ this.particleBlue = 0.25F;
+
+ this.motionX *= 0.1D;
+ this.motionY *= -0.1D;
+ this.motionZ *= 0.1F;
+
+ Random random = world.rand;
+ this.motionX += random.nextFloat() * -1.9D * random.nextFloat() * 0.1D;
+ this.motionY += random.nextFloat() * -0.5D * random.nextFloat() * 0.1D * 5.0D;
+ this.motionZ += random.nextFloat() * -1.9D * random.nextFloat() * 0.1D;
+
+ this.particleTextureIndexX = 0;
+ this.particleTextureIndexY = 0;
+
+ this.particleMaxAge = (int) ((double) 20 / ((double) random.nextFloat() * 0.8D + 0.2D));
+
+ this.particleScale *= 0.75F;
+ this.noClip = true;
+ }
+
+ @Override
+ public void onUpdate() {
+ this.prevPosX = this.posX;
+ this.prevPosY = this.posY;
+ this.prevPosZ = this.posZ;
+
+ if (this.particleAge++ >= this.particleMaxAge) {
+ this.setDead();
+ } else {
+ this.motionY -= 5.0E-4D;
+ this.moveEntity(this.motionX, this.motionY, this.motionZ);
+ if (this.posY == this.prevPosY) {
+ this.motionX *= 1.1D;
+ this.motionZ *= 1.1D;
+ }
+ this.motionX *= 0.96D;
+ this.motionY *= 0.96D;
+ this.motionZ *= 0.96D;
+ if (this.onGround) {
+ this.motionX *= 0.7D;
+ this.motionZ *= 0.7D;
+ }
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/entities/GT_Entity_Arrow.java b/src/main/java/gregtech/common/entities/GT_Entity_Arrow.java
new file mode 100644
index 0000000000..758888c720
--- /dev/null
+++ b/src/main/java/gregtech/common/entities/GT_Entity_Arrow.java
@@ -0,0 +1,438 @@
+package gregtech.common.entities;
+
+import java.util.List;
+import java.util.UUID;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.material.Material;
+import net.minecraft.enchantment.Enchantment;
+import net.minecraft.enchantment.EnchantmentHelper;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.monster.EntityCreeper;
+import net.minecraft.entity.monster.EntityEnderman;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.entity.projectile.EntityArrow;
+import net.minecraft.init.Blocks;
+import net.minecraft.init.Items;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.network.play.server.S2BPacketChangeGameState;
+import net.minecraft.potion.Potion;
+import net.minecraft.util.AxisAlignedBB;
+import net.minecraft.util.DamageSource;
+import net.minecraft.util.MathHelper;
+import net.minecraft.util.MovingObjectPosition;
+import net.minecraft.util.Vec3;
+import net.minecraft.world.World;
+import net.minecraft.world.WorldServer;
+import net.minecraftforge.common.util.FakePlayerFactory;
+
+import com.mojang.authlib.GameProfile;
+
+import gregtech.api.enums.ParticleFX;
+import gregtech.api.objects.ItemData;
+import gregtech.api.util.GT_OreDictUnificator;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.WorldSpawnedEventBuilder;
+
+public class GT_Entity_Arrow extends EntityArrow {
+
+ private int mHitBlockX = -1;
+ private int mHitBlockY = -1;
+ private int mHitBlockZ = -1;
+ private Block mHitBlock = Blocks.air;
+ private int mHitBlockMeta = 0;
+ private boolean inGround = false;
+ private int mTicksAlive = 0;
+ private int ticksInAir = 0;
+ private int mKnockback = 0;
+ private ItemStack mArrow = null;
+
+ public GT_Entity_Arrow(World aWorld) {
+ super(aWorld);
+ }
+
+ public GT_Entity_Arrow(World aWorld, double aX, double aY, double aZ) {
+ super(aWorld, aX, aY, aZ);
+ }
+
+ public GT_Entity_Arrow(World aWorld, EntityLivingBase aEntity, float aSpeed) {
+ super(aWorld, aEntity, aSpeed);
+ }
+
+ public GT_Entity_Arrow(EntityArrow aArrow, ItemStack aStack) {
+ super(aArrow.worldObj);
+ NBTTagCompound tNBT = new NBTTagCompound();
+ aArrow.writeToNBT(tNBT);
+ readFromNBT(tNBT);
+ setArrowItem(aStack);
+ }
+
+ @Override
+ public void onUpdate() {
+ onEntityUpdate();
+ if ((this.mArrow == null) && (!this.worldObj.isRemote)) {
+ setDead();
+ return;
+ }
+ Entity tShootingEntity = this.shootingEntity;
+ if ((this.prevRotationPitch == 0.0F) && (this.prevRotationYaw == 0.0F)) {
+ float f = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
+ this.prevRotationYaw = (this.rotationYaw = (float) (Math.atan2(this.motionX, this.motionZ) * 180.0D
+ / Math.PI));
+ this.prevRotationPitch = (this.rotationPitch = (float) (Math.atan2(this.motionY, f) * 180.0D / Math.PI));
+ }
+ if (this.mTicksAlive++ == 3000) {
+ setDead();
+ }
+ Block tBlock = this.worldObj.getBlock(this.mHitBlockX, this.mHitBlockY, this.mHitBlockZ);
+ if (tBlock.getMaterial() != Material.air) {
+ tBlock.setBlockBoundsBasedOnState(this.worldObj, this.mHitBlockX, this.mHitBlockY, this.mHitBlockZ);
+ AxisAlignedBB axisalignedbb = tBlock
+ .getCollisionBoundingBoxFromPool(this.worldObj, this.mHitBlockX, this.mHitBlockY, this.mHitBlockZ);
+ if ((axisalignedbb != null)
+ && (axisalignedbb.isVecInside(Vec3.createVectorHelper(this.posX, this.posY, this.posZ)))) {
+ this.inGround = true;
+ }
+ }
+ if (this.arrowShake > 0) {
+ this.arrowShake -= 1;
+ }
+ if (this.inGround) {
+ int j = this.worldObj.getBlockMetadata(this.mHitBlockX, this.mHitBlockY, this.mHitBlockZ);
+ if ((tBlock != this.mHitBlock) || (j != this.mHitBlockMeta)) {
+ this.inGround = false;
+ this.motionX *= this.rand.nextFloat() * 0.2F;
+ this.motionY *= this.rand.nextFloat() * 0.2F;
+ this.motionZ *= this.rand.nextFloat() * 0.2F;
+ this.mTicksAlive = 0;
+ this.ticksInAir = 0;
+ }
+ } else {
+ this.ticksInAir += 1;
+ Vec3 vec31 = Vec3.createVectorHelper(this.posX, this.posY, this.posZ);
+ Vec3 vec3 = Vec3
+ .createVectorHelper(this.posX + this.motionX, this.posY + this.motionY, this.posZ + this.motionZ);
+ MovingObjectPosition tVector = this.worldObj.func_147447_a(vec31, vec3, false, true, false);
+ vec31 = Vec3.createVectorHelper(this.posX, this.posY, this.posZ);
+ vec3 = Vec3
+ .createVectorHelper(this.posX + this.motionX, this.posY + this.motionY, this.posZ + this.motionZ);
+ if (tVector != null) {
+ vec3 = Vec3.createVectorHelper(tVector.hitVec.xCoord, tVector.hitVec.yCoord, tVector.hitVec.zCoord);
+ }
+ Entity tHitEntity = null;
+ List<Entity> tAllPotentiallyHitEntities = this.worldObj.getEntitiesWithinAABBExcludingEntity(
+ this,
+ this.boundingBox.addCoord(this.motionX, this.motionY, this.motionZ)
+ .expand(1.0D, 1.0D, 1.0D));
+ double tLargestDistance = Double.MAX_VALUE;
+ for (Entity potentiallyHitEntity : tAllPotentiallyHitEntities) {
+ if ((potentiallyHitEntity.canBeCollidedWith())
+ && ((potentiallyHitEntity != tShootingEntity) || (this.ticksInAir >= 5))) {
+ AxisAlignedBB axisalignedbb1 = potentiallyHitEntity.boundingBox.expand(0.3D, 0.3D, 0.3D);
+ MovingObjectPosition movingobjectposition1 = axisalignedbb1.calculateIntercept(vec31, vec3);
+ if (movingobjectposition1 != null) {
+ double tDistance = vec31.distanceTo(movingobjectposition1.hitVec);
+ if (tDistance < tLargestDistance) {
+ tHitEntity = potentiallyHitEntity;
+ tLargestDistance = tDistance;
+ }
+ }
+ }
+ }
+ if (tHitEntity != null) {
+ tVector = new MovingObjectPosition(tHitEntity);
+ }
+ if ((tVector != null) && ((tVector.entityHit instanceof EntityPlayer entityplayer))) {
+ if ((entityplayer.capabilities.disableDamage) || (((tShootingEntity instanceof EntityPlayer))
+ && (!((EntityPlayer) tShootingEntity).canAttackPlayer(entityplayer)))) {
+ tVector = null;
+ }
+ }
+ if (tVector != null) {
+ if (tVector.entityHit != null) {
+ ItemData tData = GT_OreDictUnificator.getItemData(this.mArrow);
+
+ float tMagicDamage = (tVector.entityHit instanceof EntityLivingBase)
+ ? EnchantmentHelper
+ .func_152377_a(this.mArrow, ((EntityLivingBase) tVector.entityHit).getCreatureAttribute())
+ : 0.0F;
+ float tDamage = MathHelper.ceiling_double_int(
+ MathHelper.sqrt_double(
+ this.motionX * this.motionX + this.motionY * this.motionY + this.motionZ * this.motionZ)
+ * (getDamage()
+ + ((tData != null) && (tData.mMaterial != null) && (tData.mMaterial.mMaterial != null)
+ ? tData.mMaterial.mMaterial.mToolQuality / 2.0F - 1.0F
+ : 0.0F)));
+ if (getIsCritical()) {
+ tDamage += this.rand.nextInt((int) (tDamage / 2.0D + 2.0D));
+ }
+ int tFireDamage = (isBurning() ? 5 : 0)
+ + 4 * EnchantmentHelper.getEnchantmentLevel(Enchantment.fireAspect.effectId, this.mArrow);
+ int tKnockback = this.mKnockback
+ + EnchantmentHelper.getEnchantmentLevel(Enchantment.knockback.effectId, this.mArrow);
+ int tHitTimer = -1;
+
+ int[] tDamages = onHitEntity(
+ tVector.entityHit,
+ tShootingEntity == null ? this : tShootingEntity,
+ this.mArrow == null ? new ItemStack(Items.arrow, 1) : this.mArrow,
+ (int) (tDamage * 2.0F),
+ (int) (tMagicDamage * 2.0F),
+ tKnockback,
+ tFireDamage,
+ tHitTimer);
+ if (tDamages != null) {
+ tDamage = tDamages[0] / 2.0F;
+ tMagicDamage = tDamages[1] / 2.0F;
+ tKnockback = tDamages[2];
+ tFireDamage = tDamages[3];
+ tHitTimer = tDamages[4];
+ if ((tFireDamage > 0) && (!(tVector.entityHit instanceof EntityEnderman))) {
+ tVector.entityHit.setFire(tFireDamage);
+ }
+ if ((!(tHitEntity instanceof EntityPlayer))
+ && (EnchantmentHelper.getEnchantmentLevel(Enchantment.looting.effectId, this.mArrow) > 0)) {
+ EntityPlayer tPlayer = null;
+ if ((this.worldObj instanceof WorldServer)) {
+ tPlayer = FakePlayerFactory.get(
+ (WorldServer) this.worldObj,
+ new GameProfile(
+ new UUID(0L, 0L),
+ (tShootingEntity instanceof EntityLivingBase)
+ ? tShootingEntity.getCommandSenderName()
+ : "Arrow"));
+ }
+ if (tPlayer != null) {
+ tPlayer.inventory.currentItem = 0;
+ tPlayer.inventory.setInventorySlotContents(0, getArrowItem());
+ tShootingEntity = tPlayer;
+ tPlayer.setDead();
+ }
+ }
+ DamageSource tDamageSource = DamageSource
+ .causeArrowDamage(this, tShootingEntity == null ? this : tShootingEntity);
+ if ((tDamage + tMagicDamage > 0.0F)
+ && (tVector.entityHit.attackEntityFrom(tDamageSource, tDamage + tMagicDamage))) {
+ if ((tVector.entityHit instanceof EntityLivingBase tHitLivingEntity)) {
+ if (tHitTimer >= 0) {
+ tVector.entityHit.hurtResistantTime = tHitTimer;
+ }
+ if (((tVector.entityHit instanceof EntityCreeper)) && (EnchantmentHelper
+ .getEnchantmentLevel(Enchantment.fireAspect.effectId, this.mArrow) > 0)) {
+ ((EntityCreeper) tVector.entityHit).func_146079_cb();
+ }
+ if (!this.worldObj.isRemote) {
+ tHitLivingEntity
+ .setArrowCountInEntity(tHitLivingEntity.getArrowCountInEntity() + 1);
+ }
+ if (tKnockback > 0) {
+ float tKnockbackDivider = MathHelper
+ .sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
+ if (tKnockbackDivider > 0.0F) {
+ tHitLivingEntity.addVelocity(
+ this.motionX * tKnockback * 0.6000000238418579D / tKnockbackDivider,
+ 0.1D,
+ this.motionZ * tKnockback * 0.6000000238418579D / tKnockbackDivider);
+ }
+ }
+ GT_Utility.GT_EnchantmentHelper.applyBullshitA(
+ tHitLivingEntity,
+ tShootingEntity == null ? this : tShootingEntity,
+ this.mArrow);
+ GT_Utility.GT_EnchantmentHelper.applyBullshitB(
+ (tShootingEntity instanceof EntityLivingBase) ? (EntityLivingBase) tShootingEntity
+ : null,
+ tHitLivingEntity,
+ this.mArrow);
+ if ((tHitLivingEntity != tShootingEntity)
+ && ((tHitLivingEntity instanceof EntityPlayer))
+ && ((tShootingEntity instanceof EntityPlayerMP))) {
+ ((EntityPlayerMP) tShootingEntity).playerNetServerHandler
+ .sendPacket(new S2BPacketChangeGameState(6, 0.0F));
+ }
+ }
+ if (((tShootingEntity instanceof EntityPlayer)) && (tMagicDamage > 0.0F)) {
+ ((EntityPlayer) tShootingEntity).onEnchantmentCritical(tVector.entityHit);
+ }
+ if ((!(tVector.entityHit instanceof EntityEnderman))
+ || (((EntityEnderman) tVector.entityHit).getActivePotionEffect(Potion.weakness)
+ != null)) {
+ if (tFireDamage > 0) {
+ tVector.entityHit.setFire(tFireDamage);
+ }
+ playSound("random.bowhit", 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));
+ setDead();
+ }
+ } else {
+ this.motionX *= -0.1000000014901161D;
+ this.motionY *= -0.1000000014901161D;
+ this.motionZ *= -0.1000000014901161D;
+ this.rotationYaw += 180.0F;
+ this.prevRotationYaw += 180.0F;
+ this.ticksInAir = 0;
+ }
+ }
+ } else {
+ this.mHitBlockX = tVector.blockX;
+ this.mHitBlockY = tVector.blockY;
+ this.mHitBlockZ = tVector.blockZ;
+ this.mHitBlock = this.worldObj.getBlock(this.mHitBlockX, this.mHitBlockY, this.mHitBlockZ);
+ this.mHitBlockMeta = this.worldObj
+ .getBlockMetadata(this.mHitBlockX, this.mHitBlockY, this.mHitBlockZ);
+ this.motionX = ((float) (tVector.hitVec.xCoord - this.posX));
+ this.motionY = ((float) (tVector.hitVec.yCoord - this.posY));
+ this.motionZ = ((float) (tVector.hitVec.zCoord - this.posZ));
+ float f2 = MathHelper.sqrt_double(
+ this.motionX * this.motionX + this.motionY * this.motionY + this.motionZ * this.motionZ);
+ this.posX -= this.motionX / f2 * 0.0500000007450581D;
+ this.posY -= this.motionY / f2 * 0.0500000007450581D;
+ this.posZ -= this.motionZ / f2 * 0.0500000007450581D;
+ playSound("random.bowhit", 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));
+ this.inGround = true;
+ this.arrowShake = 7;
+ setIsCritical(false);
+ if (this.mHitBlock.getMaterial() != Material.air) {
+ this.mHitBlock.onEntityCollidedWithBlock(
+ this.worldObj,
+ this.mHitBlockX,
+ this.mHitBlockY,
+ this.mHitBlockZ,
+ this);
+ }
+ if ((!this.worldObj.isRemote)
+ && (EnchantmentHelper.getEnchantmentLevel(Enchantment.fireAspect.effectId, this.mArrow) > 2)) {
+ GT_Utility
+ .setCoordsOnFire(this.worldObj, this.mHitBlockX, this.mHitBlockY, this.mHitBlockZ, true);
+ }
+ if (breaksOnImpact()) {
+ setDead();
+ }
+ }
+ }
+ WorldSpawnedEventBuilder.ParticleEventBuilder events = new WorldSpawnedEventBuilder.ParticleEventBuilder()
+ .setWorld(this.worldObj);
+
+ if (getIsCritical()) {
+ events.setIdentifier(ParticleFX.CRIT)
+ .setMotion(-this.motionX, -this.motionY + 0.2D, -this.motionZ).<WorldSpawnedEventBuilder
+ .ParticleEventBuilder>times(
+ 4,
+ (x, i) -> x
+ .setPosition(
+ this.posX + this.motionX * i / 4.0D,
+ this.posY + this.motionY * i / 4.0D,
+ this.posZ + this.motionZ * i / 4.0D)
+ .run());
+ }
+ this.posX += this.motionX;
+ this.posY += this.motionY;
+ this.posZ += this.motionZ;
+
+ this.rotationYaw = ((float) (Math.atan2(this.motionX, this.motionZ) * 180.0D / Math.PI));
+ for (this.rotationPitch = ((float) (Math
+ .atan2(this.motionY, MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ))
+ * 180.0D
+ / Math.PI)); this.rotationPitch - this.prevRotationPitch < -180.0F; this.prevRotationPitch -= 360.0F) {}
+ while (this.rotationPitch - this.prevRotationPitch >= 180.0F) {
+ this.prevRotationPitch += 360.0F;
+ }
+ while (this.rotationYaw - this.prevRotationYaw < -180.0F) {
+ this.prevRotationYaw -= 360.0F;
+ }
+ while (this.rotationYaw - this.prevRotationYaw >= 180.0F) {
+ this.prevRotationYaw += 360.0F;
+ }
+ this.rotationPitch = (this.prevRotationPitch + (this.rotationPitch - this.prevRotationPitch) * 0.2F);
+ this.rotationYaw = (this.prevRotationYaw + (this.rotationYaw - this.prevRotationYaw) * 0.2F);
+ float tFrictionMultiplier = 0.99F;
+ if (isInWater()) {
+ events.setMotion(-this.motionX, -this.motionY + 0.2D, -this.motionZ)
+ .setIdentifier(ParticleFX.BUBBLE)
+ .setPosition(
+ this.posX - this.motionX * 0.25D,
+ this.posY - this.motionY * 0.25D,
+ this.posZ - this.motionZ * 0.25D)
+ .times(4, Runnable::run);
+ tFrictionMultiplier = 0.8F;
+ }
+ if (isWet()) {
+ extinguish();
+ }
+ this.motionX *= tFrictionMultiplier;
+ this.motionY *= tFrictionMultiplier;
+ this.motionZ *= tFrictionMultiplier;
+ this.motionY -= 0.0500000007450581D;
+ setPosition(this.posX, this.posY, this.posZ);
+ func_145775_I();
+ }
+ }
+
+ @Override
+ public void writeEntityToNBT(NBTTagCompound aNBT) {
+ super.writeEntityToNBT(aNBT);
+ aNBT.setShort("xTile", (short) this.mHitBlockX);
+ aNBT.setShort("yTile", (short) this.mHitBlockY);
+ aNBT.setShort("zTile", (short) this.mHitBlockZ);
+ aNBT.setShort("life", (short) this.mTicksAlive);
+ aNBT.setByte("inTile", (byte) Block.getIdFromBlock(this.mHitBlock));
+ aNBT.setByte("inData", (byte) this.mHitBlockMeta);
+ aNBT.setByte("shake", (byte) this.arrowShake);
+ aNBT.setByte("inGround", (byte) (this.inGround ? 1 : 0));
+ aNBT.setByte("pickup", (byte) this.canBePickedUp);
+ aNBT.setDouble("damage", getDamage());
+ aNBT.setTag("mArrow", this.mArrow == null ? null : this.mArrow.writeToNBT(new NBTTagCompound()));
+ }
+
+ @Override
+ public void readEntityFromNBT(NBTTagCompound aNBT) {
+ super.readEntityFromNBT(aNBT);
+ this.mHitBlockX = aNBT.getShort("xTile");
+ this.mHitBlockY = aNBT.getShort("yTile");
+ this.mHitBlockZ = aNBT.getShort("zTile");
+ this.mTicksAlive = aNBT.getShort("life");
+ this.mHitBlock = Block.getBlockById(aNBT.getByte("inTile") & 0xFF);
+ this.mHitBlockMeta = (aNBT.getByte("inData") & 0xFF);
+ this.arrowShake = (aNBT.getByte("shake") & 0xFF);
+ this.inGround = (aNBT.getByte("inGround") == 1);
+ setDamage(aNBT.getDouble("damage"));
+ this.canBePickedUp = aNBT.getByte("pickup");
+ this.mArrow = GT_Utility.loadItem(aNBT, "mArrow");
+ }
+
+ @Override
+ public void onCollideWithPlayer(EntityPlayer aPlayer) {
+ if ((!this.worldObj.isRemote) && (this.inGround)
+ && (this.arrowShake <= 0)
+ && (this.canBePickedUp == 1)
+ && (aPlayer.inventory.addItemStackToInventory(getArrowItem()))) {
+ playSound("random.pop", 0.2F, ((this.rand.nextFloat() - this.rand.nextFloat()) * 0.7F + 1.0F) * 2.0F);
+ aPlayer.onItemPickup(this, 1);
+ setDead();
+ }
+ }
+
+ public int[] onHitEntity(Entity aHitEntity, Entity aShootingEntity, ItemStack aArrow, int aRegularDamage,
+ int aMagicDamage, int aKnockback, int aFireDamage, int aHitTimer) {
+ return new int[] { aRegularDamage, aMagicDamage, aKnockback, aFireDamage, aHitTimer };
+ }
+
+ public ItemStack getArrowItem() {
+ return GT_Utility.copyOrNull(this.mArrow);
+ }
+
+ public void setArrowItem(ItemStack aStack) {
+ this.mArrow = GT_Utility.updateItemStack(GT_Utility.copyAmount(1, aStack));
+ }
+
+ public boolean breaksOnImpact() {
+ return false;
+ }
+
+ @Override
+ public void setKnockbackStrength(int aKnockback) {
+ this.mKnockback = aKnockback;
+ }
+}
diff --git a/src/main/java/gregtech/common/entities/GT_Entity_Arrow_Potion.java b/src/main/java/gregtech/common/entities/GT_Entity_Arrow_Potion.java
new file mode 100644
index 0000000000..9b520831b6
--- /dev/null
+++ b/src/main/java/gregtech/common/entities/GT_Entity_Arrow_Potion.java
@@ -0,0 +1,78 @@
+package gregtech.common.entities;
+
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.potion.PotionEffect;
+import net.minecraft.world.World;
+
+public class GT_Entity_Arrow_Potion extends GT_Entity_Arrow {
+
+ private int[] mPotions = new int[0];
+
+ public GT_Entity_Arrow_Potion(World aWorld) {
+ super(aWorld);
+ }
+
+ public GT_Entity_Arrow_Potion(World aWorld, double aX, double aY, double aZ) {
+ super(aWorld, aX, aY, aZ);
+ }
+
+ public GT_Entity_Arrow_Potion(World aWorld, EntityLivingBase aEntity, float aSpeed) {
+ super(aWorld, aEntity, aSpeed);
+ }
+
+ @Override
+ public void writeEntityToNBT(NBTTagCompound aNBT) {
+ super.writeEntityToNBT(aNBT);
+ aNBT.setIntArray("mPotions", this.mPotions);
+ }
+
+ @Override
+ public void readEntityFromNBT(NBTTagCompound aNBT) {
+ super.readEntityFromNBT(aNBT);
+ setPotions(aNBT.getIntArray("mPotions"));
+ }
+
+ @Override
+ public boolean breaksOnImpact() {
+ return true;
+ }
+
+ public int[] getPotions() {
+ return this.mPotions;
+ }
+
+ public void setPotions(int... aPotions) {
+ if (aPotions != null) {
+ this.mPotions = aPotions;
+ }
+ }
+
+ @Override
+ public int[] onHitEntity(Entity aHitEntity, Entity aShootingEntity, ItemStack aArrow, int aRegularDamage,
+ int aMagicDamage, int aKnockback, int aFireDamage, int aHitTimer) {
+ if ((aHitEntity instanceof EntityLivingBase)) {
+ for (int i = 3; i < this.mPotions.length; i += 4) {
+ if (aHitEntity.worldObj.rand.nextInt(100) < this.mPotions[i]) {
+ ((EntityLivingBase) aHitEntity).addPotionEffect(
+ new PotionEffect(
+ this.mPotions[(i - 3)],
+ this.mPotions[(i - 2)],
+ this.mPotions[(i - 1)],
+ false));
+ }
+ }
+ }
+ return super.onHitEntity(
+ aHitEntity,
+ aShootingEntity,
+ aArrow,
+ 1,
+ aMagicDamage,
+ aKnockback,
+ aFireDamage,
+ aHitTimer);
+ }
+}
diff --git a/src/main/java/gregtech/common/events/BaseMetricsCoverEvent.java b/src/main/java/gregtech/common/events/BaseMetricsCoverEvent.java
new file mode 100644
index 0000000000..953d6fbfcf
--- /dev/null
+++ b/src/main/java/gregtech/common/events/BaseMetricsCoverEvent.java
@@ -0,0 +1,21 @@
+package gregtech.common.events;
+
+import java.util.UUID;
+
+import org.jetbrains.annotations.NotNull;
+
+import cpw.mods.fml.common.eventhandler.Event;
+
+public abstract class BaseMetricsCoverEvent extends Event {
+
+ protected final UUID frequency;
+
+ public BaseMetricsCoverEvent(@NotNull UUID frequency) {
+ this.frequency = frequency;
+ }
+
+ @NotNull
+ public UUID getFrequency() {
+ return frequency;
+ }
+}
diff --git a/src/main/java/gregtech/common/events/MetricsCoverDataEvent.java b/src/main/java/gregtech/common/events/MetricsCoverDataEvent.java
new file mode 100644
index 0000000000..92a5aa663a
--- /dev/null
+++ b/src/main/java/gregtech/common/events/MetricsCoverDataEvent.java
@@ -0,0 +1,37 @@
+package gregtech.common.events;
+
+import java.util.List;
+import java.util.UUID;
+
+import org.jetbrains.annotations.NotNull;
+
+import gregtech.common.misc.GlobalMetricsCoverDatabase;
+
+/**
+ * Event fired when the Metrics Transmitter cover sends an information packet.
+ */
+public class MetricsCoverDataEvent extends BaseMetricsCoverEvent {
+
+ @NotNull
+ private final List<String> payload;
+
+ @NotNull
+ private final GlobalMetricsCoverDatabase.Coordinates coordinates;
+
+ public MetricsCoverDataEvent(@NotNull UUID frequency, @NotNull List<String> payload,
+ @NotNull GlobalMetricsCoverDatabase.Coordinates coordinates) {
+ super(frequency);
+ this.payload = payload;
+ this.coordinates = coordinates;
+ }
+
+ @NotNull
+ public List<String> getPayload() {
+ return payload;
+ }
+
+ @NotNull
+ public GlobalMetricsCoverDatabase.Coordinates getCoordinates() {
+ return coordinates;
+ }
+}
diff --git a/src/main/java/gregtech/common/events/MetricsCoverHostDeconstructedEvent.java b/src/main/java/gregtech/common/events/MetricsCoverHostDeconstructedEvent.java
new file mode 100644
index 0000000000..490bd7d0b0
--- /dev/null
+++ b/src/main/java/gregtech/common/events/MetricsCoverHostDeconstructedEvent.java
@@ -0,0 +1,16 @@
+package gregtech.common.events;
+
+import java.util.UUID;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Event fired when the machine housing a Metrics Transmitter cover is deconstructed, but the cover remains
+ * attached.
+ */
+public class MetricsCoverHostDeconstructedEvent extends BaseMetricsCoverEvent {
+
+ public MetricsCoverHostDeconstructedEvent(@NotNull UUID frequency) {
+ super(frequency);
+ }
+}
diff --git a/src/main/java/gregtech/common/events/MetricsCoverSelfDestructEvent.java b/src/main/java/gregtech/common/events/MetricsCoverSelfDestructEvent.java
new file mode 100644
index 0000000000..d554cbcc2b
--- /dev/null
+++ b/src/main/java/gregtech/common/events/MetricsCoverSelfDestructEvent.java
@@ -0,0 +1,15 @@
+package gregtech.common.events;
+
+import java.util.UUID;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Event fired when a Metrics Transmitter cover is detached from its machine with a crowbar.
+ */
+public class MetricsCoverSelfDestructEvent extends BaseMetricsCoverEvent {
+
+ public MetricsCoverSelfDestructEvent(@NotNull UUID frequency) {
+ super(frequency);
+ }
+}
diff --git a/src/main/java/gregtech/common/fluid/GT_Fluid.java b/src/main/java/gregtech/common/fluid/GT_Fluid.java
new file mode 100644
index 0000000000..6ba8d7d23a
--- /dev/null
+++ b/src/main/java/gregtech/common/fluid/GT_Fluid.java
@@ -0,0 +1,209 @@
+package gregtech.common.fluid;
+
+import static gregtech.api.recipe.RecipeMaps.fluidCannerRecipes;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.ResourceLocation;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidContainerRegistry;
+import net.minecraftforge.fluids.FluidRegistry;
+import net.minecraftforge.fluids.FluidStack;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.FluidState;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.enums.Materials;
+import gregtech.api.interfaces.fluid.IGT_Fluid;
+import gregtech.api.interfaces.fluid.IGT_RegisteredFluid;
+import gregtech.api.util.GT_LanguageManager;
+import gregtech.api.util.GT_Utility;
+
+public class GT_Fluid extends Fluid implements IGT_Fluid, IGT_RegisteredFluid, Runnable {
+
+ private final String localizedName;
+ private final ResourceLocation stillIconResourceLocation;
+ private final ResourceLocation flowingIconResourceLocation;
+ private final short[] colorRGBA;
+ private final FluidState fluidState;
+ private final Fluid iconsFrom;
+ private Fluid registeredFluid;
+
+ /**
+ * Constructs this {@link IGT_Fluid} implementation from an {@link GT_FluidBuilder} instance
+ *
+ * @param builder The {@link GT_FluidBuilder} instance to construct this {@link IGT_Fluid} implementation
+ */
+ protected GT_Fluid(@Nonnull final GT_FluidBuilder builder) {
+ super(builder.fluidName);
+ this.localizedName = builder.localizedName;
+ this.stillIconResourceLocation = builder.stillIconResourceLocation;
+ this.flowingIconResourceLocation = builder.flowingIconResourceLocation;
+ this.iconsFrom = builder.iconsFrom;
+ this.block = builder.fluidBlock;
+ this.colorRGBA = builder.colorRGBA;
+ this.fluidState = builder.fluidState;
+ this.temperature = builder.temperature;
+ configureFromStateTemperature();
+ }
+
+ /**
+ * Adjusts this {@link Fluid}'s settings based on this {@link IGT_Fluid}'s state
+ */
+ protected void configureFromStateTemperature() {
+ switch (fluidState) {
+ case SLURRY:
+ setGaseous(false).setViscosity(10000);
+ break;
+ case GAS:
+ setGaseous(true).setDensity(-100)
+ .setViscosity(200);
+ break;
+ case PLASMA:
+ setGaseous(true).setDensity(55536)
+ .setViscosity(10)
+ .setLuminosity(15);
+ break;
+ case MOLTEN:
+ final int luminosity;
+ if (temperature >= 3500) {
+ luminosity = 15;
+ } else {
+ luminosity = temperature < 1000 ? 0 : 14 * (temperature - 1000) / 2500 + 1;
+ }
+ setLuminosity(luminosity);
+ case LIQUID:
+ default:
+ setGaseous(false).setViscosity(1000);
+ break;
+ }
+ }
+
+ // ----- Fluid implementations -----
+
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public int getColor() {
+ return (Math.max(0, Math.min(255, colorRGBA[0])) << 16) | (Math.max(0, Math.min(255, colorRGBA[1])) << 8)
+ | Math.max(0, Math.min(255, colorRGBA[2]));
+ }
+
+ // ----- IGT_Fluid interface implementations -----
+
+ public IGT_RegisteredFluid addFluid() {
+ if (FluidRegistry.registerFluid(GT_Fluid.this)) {
+ // Registered as a new Fluid
+ registeredFluid = this;
+ // Adds a server-side localized-name
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName(), localizedName);
+ } else {
+ // Fluid already registered, get it from the registry
+ registeredFluid = FluidRegistry.getFluid(GT_Fluid.this.fluidName);
+ // Sets temperature of already registered fluids if they use the default (temperature = 300)
+ if (registeredFluid.getTemperature() == new Fluid("test").getTemperature()) {
+ registeredFluid.setTemperature(GT_Fluid.this.temperature);
+ }
+ }
+ // Schedules the fluid for the block icons loader run() tasks
+ GregTech_API.sGTBlockIconload.add(this);
+ return this;
+ }
+
+ // ----- IGT_RegisteredFluid interface implementations -----
+
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public IGT_RegisteredFluid registerContainers(final ItemStack fullContainer, final ItemStack emptyContainer,
+ final int containerSize) {
+ if (fullContainer != null && emptyContainer != null) {
+ final FluidStack fluidStack = new FluidStack(registeredFluid, containerSize);
+ if (!FluidContainerRegistry.registerFluidContainer(fluidStack, fullContainer, emptyContainer)) {
+ GT_Values.RA.stdBuilder()
+ .itemInputs(fullContainer)
+ .itemOutputs(GT_Utility.getContainerItem(fullContainer, false))
+ .fluidOutputs(fluidStack)
+ .duration(fluidStack.amount / 62)
+ .eut(1)
+ .addTo(fluidCannerRecipes);
+ }
+ }
+ return this;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public IGT_RegisteredFluid registerBContainers(final ItemStack fullContainer, final ItemStack emptyContainer) {
+ return registerContainers(fullContainer, emptyContainer, 1000);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public IGT_RegisteredFluid registerPContainers(final ItemStack fullContainer, final ItemStack emptyContainer) {
+ return registerContainers(fullContainer, emptyContainer, 250);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public IGT_RegisteredFluid configureMaterials(final Materials material) {
+ if (material != null) {
+ switch (fluidState) {
+ case SLURRY -> material.mSolid = registeredFluid;
+ case GAS -> material.mGas = registeredFluid;
+ case PLASMA -> material.mPlasma = registeredFluid;
+ case MOLTEN -> material.mStandardMoltenFluid = registeredFluid;
+ default -> material.mFluid = registeredFluid;
+ }
+ Materials.FLUID_MAP.put(registeredFluid, material);
+ }
+ return this;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public Fluid asFluid() {
+ return registeredFluid;
+ }
+
+ // ----- Runnable interface implementations -----
+
+ /**
+ * This {@link Runnable#run()} implementation is scheduled within the {@link GregTech_API#sGTBlockIconload} to load
+ * this {@link IGT_Fluid}'s texture icons.
+ *
+ * @see Runnable#run()
+ */
+ @Override
+ public void run() {
+ if (iconsFrom instanceof GT_Fluid) {
+ // Needs the GT_Fluid to have registered its icons
+ ((GT_Fluid) iconsFrom).run();
+ stillIcon = iconsFrom.getStillIcon();
+ flowingIcon = iconsFrom.getFlowingIcon();
+ } else {
+ if (stillIconResourceLocation != null) {
+ stillIcon = GregTech_API.sBlockIcons.registerIcon(stillIconResourceLocation.toString());
+ }
+ if (flowingIconResourceLocation != null) {
+ flowingIcon = GregTech_API.sBlockIcons.registerIcon(flowingIconResourceLocation.toString());
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "GT_Fluid{" + "fluidName='" + fluidName + '\'' + '}';
+ }
+}
diff --git a/src/main/java/gregtech/common/fluid/GT_FluidBuilder.java b/src/main/java/gregtech/common/fluid/GT_FluidBuilder.java
new file mode 100644
index 0000000000..9a18b8d812
--- /dev/null
+++ b/src/main/java/gregtech/common/fluid/GT_FluidBuilder.java
@@ -0,0 +1,146 @@
+package gregtech.common.fluid;
+
+import static gregtech.api.enums.Mods.GregTech;
+
+import java.util.Locale;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.block.Block;
+import net.minecraft.util.IIcon;
+import net.minecraft.util.ResourceLocation;
+import net.minecraftforge.fluids.Fluid;
+
+import gregtech.api.enums.Dyes;
+import gregtech.api.enums.FluidState;
+import gregtech.api.interfaces.fluid.IGT_Fluid;
+import gregtech.api.interfaces.fluid.IGT_FluidBuilder;
+import gregtech.api.interfaces.fluid.IGT_RegisteredFluid;
+
+public class GT_FluidBuilder implements IGT_FluidBuilder {
+
+ final String fluidName;
+ String localizedName;
+ ResourceLocation stillIconResourceLocation = null, flowingIconResourceLocation = null;
+ short[] colorRGBA = Dyes._NULL.getRGBA();
+ Block fluidBlock = null;
+ FluidState fluidState;
+ int temperature;
+ IIcon stillIcon;
+ IIcon flowingIcon;
+ Fluid iconsFrom;
+
+ public GT_FluidBuilder(final String fluidName) {
+ this.fluidName = fluidName.toLowerCase(Locale.ENGLISH);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public IGT_FluidBuilder withColorRGBA(final short[] colorRGBA) {
+ this.colorRGBA = colorRGBA;
+ return this;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public IGT_FluidBuilder withLocalizedName(final String localizedName) {
+ this.localizedName = localizedName;
+ return this;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public IGT_FluidBuilder withStateAndTemperature(final FluidState fluidState, final int temperature) {
+ this.fluidState = fluidState;
+ this.temperature = temperature;
+ return this;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public IGT_FluidBuilder withStillIconResourceLocation(final ResourceLocation stillIconResourceLocation) {
+ this.stillIconResourceLocation = stillIconResourceLocation;
+ return this;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public IGT_FluidBuilder withFlowingIconResourceLocation(final ResourceLocation flowingIconResourceLocation) {
+ this.flowingIconResourceLocation = flowingIconResourceLocation;
+ return this;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public IGT_FluidBuilder withTextureName(final String textureName) {
+ this.stillIconResourceLocation = new ResourceLocation(GregTech.ID, "fluids/fluid." + textureName);
+ this.flowingIconResourceLocation = null;
+ return this;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public IGT_FluidBuilder withIconsFrom(@Nonnull final Fluid fromFluid) {
+ this.iconsFrom = fromFluid;
+ return this;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public IGT_FluidBuilder withFluidBlock(final Block fluidBlock) {
+ this.fluidBlock = fluidBlock;
+ return this;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public IGT_FluidBuilder withTextures(final ResourceLocation stillIconResourceLocation,
+ final ResourceLocation flowingIconResourceLocation) {
+ this.stillIconResourceLocation = stillIconResourceLocation;
+ this.flowingIconResourceLocation = flowingIconResourceLocation;
+ return this;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public IGT_Fluid build() {
+ if (colorRGBA == null) {
+ colorRGBA = Dyes._NULL.getRGBA();
+ }
+ if (stillIconResourceLocation == null) {
+ withTextureName(fluidName.toLowerCase(Locale.ENGLISH));
+ }
+ if (localizedName == null) {
+ localizedName = fluidName;
+ }
+ return new GT_Fluid(this);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public IGT_RegisteredFluid buildAndRegister() {
+ return build().addFluid();
+ }
+}
diff --git a/src/main/java/gregtech/common/gui/ComplexParallelMachineGUIProvider.java b/src/main/java/gregtech/common/gui/ComplexParallelMachineGUIProvider.java
new file mode 100644
index 0000000000..89b42c8500
--- /dev/null
+++ b/src/main/java/gregtech/common/gui/ComplexParallelMachineGUIProvider.java
@@ -0,0 +1,32 @@
+package gregtech.common.gui;
+
+import javax.annotation.Nonnull;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow.Builder;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+
+import gregtech.api.gui.GUIHost;
+import gregtech.api.logic.ComplexParallelProcessingLogic;
+import gregtech.api.logic.interfaces.PowerLogicHost;
+import gregtech.api.logic.interfaces.ProcessingLogicHost;
+
+/**
+ * Default GUI class for machines with complex parallel
+ */
+public class ComplexParallelMachineGUIProvider<T extends GUIHost & ProcessingLogicHost<? extends ComplexParallelProcessingLogic<?>> & PowerLogicHost>
+ extends MachineGUIProvider<T> {
+
+ public ComplexParallelMachineGUIProvider(@Nonnull T host) {
+ super(host);
+ }
+
+ @Override
+ protected void attachSynchHandlers(@Nonnull Builder builder, @Nonnull UIBuildContext uiContext) {
+
+ }
+
+ @Override
+ protected void addWidgets(@Nonnull Builder builder, @Nonnull UIBuildContext uiContext) {
+
+ }
+}
diff --git a/src/main/java/gregtech/common/gui/MachineGUIProvider.java b/src/main/java/gregtech/common/gui/MachineGUIProvider.java
new file mode 100644
index 0000000000..3cc889f000
--- /dev/null
+++ b/src/main/java/gregtech/common/gui/MachineGUIProvider.java
@@ -0,0 +1,510 @@
+package gregtech.common.gui;
+
+import static gregtech.api.metatileentity.BaseTileEntity.BUTTON_FORBIDDEN_TOOLTIP;
+import static gregtech.api.metatileentity.BaseTileEntity.TOOLTIP_DELAY;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.util.StatCollector;
+
+import com.gtnewhorizons.modularui.api.ModularUITextures;
+import com.gtnewhorizons.modularui.api.NumberFormatMUI;
+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.math.Pos2d;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow.Builder;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.api.widget.IWidgetBuilder;
+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.MultiChildWidget;
+import com.gtnewhorizons.modularui.common.widget.TabButton;
+import com.gtnewhorizons.modularui.common.widget.TabContainer;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.api.enums.InventoryType;
+import gregtech.api.enums.SoundResource;
+import gregtech.api.enums.VoidingMode;
+import gregtech.api.gui.GUIHost;
+import gregtech.api.gui.GUIProvider;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.gui.modularui.GUITextureSet;
+import gregtech.api.logic.MuTEProcessingLogic;
+import gregtech.api.logic.PowerLogic;
+import gregtech.api.logic.interfaces.PowerLogicHost;
+import gregtech.api.logic.interfaces.ProcessingLogicHost;
+
+/**
+ * Default GUI a machine will use to show its information
+ */
+public class MachineGUIProvider<T extends GUIHost & ProcessingLogicHost<? extends MuTEProcessingLogic<?>> & PowerLogicHost>
+ extends GUIProvider<T> {
+
+ private static final int LOGO_SIZE = 17;
+ @Nonnull
+ protected static final Pos2d POWER_SWITCH_BUTTON_DEFAULT_POS = new Pos2d(144, 0);
+ @Nonnull
+ protected static final Pos2d VOIDING_MODE_BUTTON_DEFAULT_POS = new Pos2d(54, 0);
+ @Nonnull
+ protected static final Pos2d INPUT_SEPARATION_BUTTON_DEFAULT_POS = new Pos2d(36, 0);
+ @Nonnull
+ protected static final Pos2d BATCH_MODE_BUTTON_DEFAULT_POS = new Pos2d(18, 0);
+ @Nonnull
+ protected static final Pos2d RECIPE_LOCKING_BUTTON_DEFAULT_POS = new Pos2d(0, 0);
+
+ protected static final NumberFormatMUI numberFormat = new NumberFormatMUI();
+
+ public MachineGUIProvider(@Nonnull T host) {
+ super(host);
+ }
+
+ @Override
+ protected void attachSynchHandlers(@Nonnull Builder builder, @Nonnull UIBuildContext uiContext) {
+
+ }
+
+ @Override
+ protected void addWidgets(@Nonnull Builder builder, @Nonnull UIBuildContext uiContext) {
+ int page = 0;
+ builder.setBackground(GT_UITextures.BACKGROUND_SINGLEBLOCK_DEFAULT);
+ MultiChildWidget mainTab = new MultiChildWidget();
+ mainTab.setSize(host.getWidth(), host.getHeight());
+ createMainTab(mainTab, builder, uiContext);
+ 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(host.getAsItem()).withFixedSize(16, 16)
+ .withOffset(2, 4))
+ .setBackground(
+ true,
+ ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0.5f, 1f, 1f),
+ new ItemDrawable(host.getAsItem()).withFixedSize(16, 16)
+ .withOffset(2, 4))
+ .addTooltip(host.getMachineName())
+ .setPos(20 * (page - 1), -20))
+ .addPage(mainTab);
+ if (host.hasItemInput()) {
+ MultiChildWidget itemInputTab = new MultiChildWidget();
+ itemInputTab.setSize(host.getWidth(), host.getHeight());
+ createItemInputTab(itemInputTab, builder, uiContext);
+ 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))
+ .addTooltip("Item Input Inventory")
+ .setPos(20 * (page - 1), -20))
+ .addPage(itemInputTab.addChild(getLogo().setPos(147, 86)));
+ }
+
+ if (host.hasItemOutput()) {
+ MultiChildWidget itemOutputTab = new MultiChildWidget();
+ itemOutputTab.setSize(host.getWidth(), host.getHeight());
+ createItemOutputTab(itemOutputTab, builder, uiContext);
+ 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))
+ .addTooltip("Item Output Inventory")
+ .setPos(20 * (page - 1), -20))
+ .addPage(itemOutputTab.addChild(getLogo().setPos(147, 86)));
+ }
+
+ if (host.hasFluidInput()) {
+ MultiChildWidget fluidInputTab = new MultiChildWidget();
+ fluidInputTab.setSize(host.getWidth(), host.getHeight());
+ createFluidInputTab(fluidInputTab, builder, uiContext);
+ 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))
+ .addTooltip("Fluid Input Tanks")
+ .setPos(20 * (page - 1), -20))
+ .addPage(fluidInputTab.addChild(getLogo().setPos(147, 86)));
+ }
+
+ if (host.hasFluidOutput()) {
+ MultiChildWidget fluidOutputTab = new MultiChildWidget();
+ fluidOutputTab.setSize(host.getWidth(), host.getHeight());
+ createFluidOutputTab(fluidOutputTab, builder, uiContext);
+ 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))
+ .addTooltip("Fluid Output Tanks")
+ .setPos(20 * (page - 1), -20))
+ .addPage(fluidOutputTab.addChild(getLogo().setPos(147, 86)));
+ }
+ MultiChildWidget powerInfoTab = new MultiChildWidget();
+ powerInfoTab.setSize(host.getWidth(), host.getHeight());
+ createPowerTab(powerInfoTab, builder, uiContext);
+ 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))
+ .addTooltip("Power Information")
+ .setPos(20 * (page - 1), -20))
+ .addPage(powerInfoTab.addChild(getLogo().setPos(147, 86)));
+ builder.widget(tabs);
+ }
+
+ protected void createMainTab(@Nonnull MultiChildWidget tab, @Nonnull Builder builder,
+ @Nonnull UIBuildContext uiBuildContext) {
+ MultiChildWidget buttons = new MultiChildWidget();
+ buttons.setSize(16, 167)
+ .setPos(7, 86);
+ buttons.addChild(createPowerSwitchButton(builder))
+ .addChild(createVoidExcessButton(builder))
+ .addChild(createInputSeparationButton(builder))
+ .addChild(createBatchModeButton(builder))
+ .addChild(createLockToSingleRecipeButton(builder));
+ tab.addChild(
+ new DrawableWidget().setDrawable(GT_UITextures.PICTURE_SCREEN_BLACK)
+ .setPos(7, 4)
+ .setSize(160, 75))
+ .addChild(buttons);
+ }
+
+ protected void createItemInputTab(@Nonnull MultiChildWidget tab, @Nonnull Builder builder,
+ @Nonnull UIBuildContext uiBuildContext) {
+ tab.addChild(
+ host.getItemLogic(InventoryType.Input, null)
+ .getGuiPart()
+ .setSize(18 * 4 + 9, 5 * 18)
+ .setPos(host.getWidth() / 2 - 2 * 18, 10));
+ }
+
+ protected void createItemOutputTab(@Nonnull MultiChildWidget tab, @Nonnull Builder builder,
+ @Nonnull UIBuildContext uiBuildContext) {
+ tab.addChild(
+ host.getItemLogic(InventoryType.Output, null)
+ .getGuiPart()
+ .setSize(18 * 4 + 9, 5 * 18)
+ .setPos(host.getWidth() / 2 - 2 * 18, 10));
+ }
+
+ protected void createFluidInputTab(@Nonnull MultiChildWidget tab, @Nonnull Builder builder,
+ @Nonnull UIBuildContext uiBuildContext) {
+ tab.addChild(
+ host.getFluidLogic(InventoryType.Input, null)
+ .getGuiPart()
+ .setSize(18 * 4 + 9, 5 * 18)
+ .setPos(host.getWidth() / 2 - 2 * 18, 10));
+ }
+
+ protected void createFluidOutputTab(@Nonnull MultiChildWidget tab, @Nonnull Builder builder,
+ @Nonnull UIBuildContext uiBuildContext) {
+ tab.addChild(
+ host.getFluidLogic(InventoryType.Output, null)
+ .getGuiPart()
+ .setSize(18 * 4 + 9, 5 * 18)
+ .setPos(host.getWidth() / 2 - 2 * 18, 10));
+ }
+
+ protected void createPowerTab(@Nonnull MultiChildWidget tab, @Nonnull Builder builder,
+ @Nonnull UIBuildContext uiBuildContext) {
+ PowerLogic power = host.getPowerLogic();
+ tab.addChild(
+ new TextWidget()
+ .setStringSupplier(
+ () -> numberFormat.format(power.getStoredEnergy()) + "/"
+ + numberFormat.format(power.getCapacity())
+ + " EU")
+ .setPos(10, 30))
+ .addChild(
+ new TextWidget()
+ .setStringSupplier(
+ () -> numberFormat.format(power.getVoltage()) + " EU/t"
+ + "("
+ + numberFormat.format(power.getMaxAmperage())
+ + " A)")
+ .setPos(10, 60));
+ }
+
+ /**
+ * Should return the logo you want to use that is pasted on each tab. Default is the GT logo.
+ */
+ @Nonnull
+ protected Widget getLogo() {
+ DrawableWidget logo = new DrawableWidget();
+ logo.setDrawable(GUITextureSet.DEFAULT.getGregTechLogo())
+ .setSize(LOGO_SIZE, LOGO_SIZE);
+ return logo;
+ }
+
+ protected Pos2d getPowerSwitchButtonPos() {
+ return POWER_SWITCH_BUTTON_DEFAULT_POS;
+ }
+
+ protected ButtonWidget createPowerSwitchButton(IWidgetBuilder<?> builder) {
+ ButtonWidget button = new ButtonWidget();
+ button.setOnClick((clickData, widget) -> {
+ if (host.isAllowedToWork()) {
+ host.disableWorking();
+ } else {
+ host.enableWorking();
+ }
+ })
+ .setPlayClickSoundResource(
+ () -> host.isAllowedToWork() ? SoundResource.GUI_BUTTON_UP.resourceLocation
+ : SoundResource.GUI_BUTTON_DOWN.resourceLocation)
+ .setBackground(() -> {
+ if (host.isAllowedToWork()) {
+ return new IDrawable[] { GT_UITextures.BUTTON_STANDARD_PRESSED,
+ GT_UITextures.OVERLAY_BUTTON_POWER_SWITCH_ON };
+ } else {
+ return new IDrawable[] { GT_UITextures.BUTTON_STANDARD,
+ GT_UITextures.OVERLAY_BUTTON_POWER_SWITCH_OFF };
+ }
+ })
+ .attachSyncer(new FakeSyncWidget.BooleanSyncer(host::isAllowedToWork, host::setAllowedToWork), builder)
+ .addTooltip(StatCollector.translateToLocal("GT5U.gui.button.power_switch"))
+ .setTooltipShowUpDelay(TOOLTIP_DELAY)
+ .setPos(getPowerSwitchButtonPos())
+ .setSize(16, 16);
+ return button;
+ }
+
+ @Nonnull
+ protected Pos2d getVoidingModeButtonPos() {
+ return VOIDING_MODE_BUTTON_DEFAULT_POS;
+ }
+
+ @Nonnull
+ protected ButtonWidget createVoidExcessButton(IWidgetBuilder<?> builder) {
+ ButtonWidget button = new ButtonWidget();
+ button.setOnClick((clickData, widget) -> {
+ if (host.supportsVoidProtection()) {
+ Set<VoidingMode> allowed = host.getAllowedVoidingModes();
+ switch (clickData.mouseButton) {
+ case 0 -> host.setVoidingMode(
+ host.getVoidingMode()
+ .nextInCollection(allowed));
+ case 1 -> host.setVoidingMode(
+ host.getVoidingMode()
+ .previousInCollection(allowed));
+ }
+ widget.notifyTooltipChange();
+ }
+ })
+ .setPlayClickSound(host.supportsVoidProtection())
+ .setBackground(() -> {
+ List<UITexture> ret = new ArrayList<>();
+ ret.add(host.getVoidingMode().buttonTexture);
+ ret.add(host.getVoidingMode().buttonOverlay);
+ if (!host.supportsVoidProtection()) {
+ ret.add(GT_UITextures.OVERLAY_BUTTON_FORBIDDEN);
+ }
+ return ret.toArray(new IDrawable[0]);
+ })
+ .attachSyncer(
+ new FakeSyncWidget.IntegerSyncer(
+ () -> host.getVoidingMode()
+ .ordinal(),
+ val -> host.setVoidingMode(VoidingMode.fromOrdinal(val))),
+ builder)
+ .dynamicTooltip(
+ () -> Arrays.asList(
+ StatCollector.translateToLocal("GT5U.gui.button.voiding_mode"),
+ StatCollector.translateToLocal(
+ host.getVoidingMode()
+ .getTransKey())))
+ .setTooltipShowUpDelay(TOOLTIP_DELAY)
+ .setPos(getVoidingModeButtonPos())
+ .setSize(16, 16);
+ if (!host.supportsVoidProtection()) {
+ button.addTooltip(StatCollector.translateToLocal(BUTTON_FORBIDDEN_TOOLTIP));
+ }
+ return button;
+ }
+
+ @Nonnull
+ protected Pos2d getInputSeparationButtonPos() {
+ return INPUT_SEPARATION_BUTTON_DEFAULT_POS;
+ }
+
+ protected ButtonWidget createInputSeparationButton(IWidgetBuilder<?> builder) {
+ ButtonWidget button = new ButtonWidget();
+ button.setOnClick((clickData, widget) -> {
+ if (host.supportsInputSeparation()) {
+ host.setInputSeparation(!host.isInputSeparated());
+ }
+ })
+ .setPlayClickSound(host.supportsInputSeparation())
+ .setBackground(() -> {
+ List<UITexture> ret = new ArrayList<>();
+ if (host.isInputSeparated()) {
+ ret.add(GT_UITextures.BUTTON_STANDARD_PRESSED);
+ if (host.supportsInputSeparation()) {
+ ret.add(GT_UITextures.OVERLAY_BUTTON_INPUT_SEPARATION_ON);
+ } else {
+ ret.add(GT_UITextures.OVERLAY_BUTTON_INPUT_SEPARATION_ON_DISABLED);
+ }
+ } else {
+ ret.add(GT_UITextures.BUTTON_STANDARD);
+ if (host.supportsInputSeparation()) {
+ ret.add(GT_UITextures.OVERLAY_BUTTON_INPUT_SEPARATION_OFF);
+ } else {
+ ret.add(GT_UITextures.OVERLAY_BUTTON_INPUT_SEPARATION_OFF_DISABLED);
+ }
+ }
+ if (!host.supportsInputSeparation()) {
+ ret.add(GT_UITextures.OVERLAY_BUTTON_FORBIDDEN);
+ }
+ return ret.toArray(new IDrawable[0]);
+ })
+ .attachSyncer(new FakeSyncWidget.BooleanSyncer(host::isInputSeparated, host::setInputSeparation), builder)
+ .addTooltip(StatCollector.translateToLocal("GT5U.gui.button.input_separation"))
+ .setTooltipShowUpDelay(TOOLTIP_DELAY)
+ .setPos(getInputSeparationButtonPos())
+ .setSize(16, 16);
+ if (!host.supportsInputSeparation()) {
+ button.addTooltip(StatCollector.translateToLocal(BUTTON_FORBIDDEN_TOOLTIP));
+ }
+ return button;
+ }
+
+ @Nonnull
+ protected Pos2d getBatchModeButtonPos() {
+ return BATCH_MODE_BUTTON_DEFAULT_POS;
+ }
+
+ protected ButtonWidget createBatchModeButton(IWidgetBuilder<?> builder) {
+ ButtonWidget button = new ButtonWidget();
+ button.setOnClick((clickData, widget) -> {
+ if (host.supportsBatchMode()) {
+ host.setBatchMode(!host.isBatchModeEnabled());
+ }
+ })
+ .setPlayClickSound(host.supportsBatchMode())
+ .setBackground(() -> {
+ List<UITexture> ret = new ArrayList<>();
+ if (host.isBatchModeEnabled()) {
+ ret.add(GT_UITextures.BUTTON_STANDARD_PRESSED);
+ if (host.supportsBatchMode()) {
+ ret.add(GT_UITextures.OVERLAY_BUTTON_BATCH_MODE_ON);
+ } else {
+ ret.add(GT_UITextures.OVERLAY_BUTTON_BATCH_MODE_ON_DISABLED);
+ }
+ } else {
+ ret.add(GT_UITextures.BUTTON_STANDARD);
+ if (host.supportsBatchMode()) {
+ ret.add(GT_UITextures.OVERLAY_BUTTON_BATCH_MODE_OFF);
+ } else {
+ ret.add(GT_UITextures.OVERLAY_BUTTON_BATCH_MODE_OFF_DISABLED);
+ }
+ }
+ if (!host.supportsBatchMode()) {
+ ret.add(GT_UITextures.OVERLAY_BUTTON_FORBIDDEN);
+ }
+ return ret.toArray(new IDrawable[0]);
+ })
+ .attachSyncer(new FakeSyncWidget.BooleanSyncer(host::isBatchModeEnabled, host::setBatchMode), builder)
+ .addTooltip(StatCollector.translateToLocal("GT5U.gui.button.batch_mode"))
+ .setTooltipShowUpDelay(TOOLTIP_DELAY)
+ .setPos(getBatchModeButtonPos())
+ .setSize(16, 16);
+ if (!host.supportsBatchMode()) {
+ button.addTooltip(StatCollector.translateToLocal(BUTTON_FORBIDDEN_TOOLTIP));
+ }
+ return button;
+ }
+
+ @Nonnull
+ protected Pos2d getRecipeLockingButtonPos() {
+ return RECIPE_LOCKING_BUTTON_DEFAULT_POS;
+ }
+
+ protected ButtonWidget createLockToSingleRecipeButton(IWidgetBuilder<?> builder) {
+ ButtonWidget button = new ButtonWidget();
+ button.setOnClick((clickData, widget) -> {
+ if (host.supportsSingleRecipeLocking()) {
+ host.setRecipeLocking(!host.isRecipeLockingEnabled());
+ }
+ })
+ .setPlayClickSound(host.supportsSingleRecipeLocking())
+ .setBackground(() -> {
+ List<UITexture> ret = new ArrayList<>();
+ if (host.isRecipeLockingEnabled()) {
+ ret.add(GT_UITextures.BUTTON_STANDARD_PRESSED);
+ if (host.supportsSingleRecipeLocking()) {
+ ret.add(GT_UITextures.OVERLAY_BUTTON_RECIPE_LOCKED);
+ } else {
+ ret.add(GT_UITextures.OVERLAY_BUTTON_RECIPE_LOCKED_DISABLED);
+ }
+ } else {
+ ret.add(GT_UITextures.BUTTON_STANDARD);
+ if (host.supportsSingleRecipeLocking()) {
+ ret.add(GT_UITextures.OVERLAY_BUTTON_RECIPE_UNLOCKED);
+ } else {
+ ret.add(GT_UITextures.OVERLAY_BUTTON_RECIPE_UNLOCKED_DISABLED);
+ }
+ }
+ if (!host.supportsSingleRecipeLocking()) {
+ ret.add(GT_UITextures.OVERLAY_BUTTON_FORBIDDEN);
+ }
+ return ret.toArray(new IDrawable[0]);
+ })
+ .attachSyncer(
+ new FakeSyncWidget.BooleanSyncer(host::isRecipeLockingEnabled, host::setRecipeLocking),
+ builder)
+ .addTooltip(StatCollector.translateToLocal("GT5U.gui.button.lock_recipe"))
+ .setTooltipShowUpDelay(TOOLTIP_DELAY)
+ .setPos(getRecipeLockingButtonPos())
+ .setSize(16, 16);
+ if (!host.supportsSingleRecipeLocking()) {
+ button.addTooltip(StatCollector.translateToLocal(BUTTON_FORBIDDEN_TOOLTIP));
+ }
+ return button;
+ }
+}
diff --git a/src/main/java/gregtech/common/gui/PartGUIProvider.java b/src/main/java/gregtech/common/gui/PartGUIProvider.java
new file mode 100644
index 0000000000..7600444f71
--- /dev/null
+++ b/src/main/java/gregtech/common/gui/PartGUIProvider.java
@@ -0,0 +1,33 @@
+package gregtech.common.gui;
+
+import javax.annotation.Nonnull;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow.Builder;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+
+import gregtech.api.gui.GUIHost;
+import gregtech.api.gui.GUIProvider;
+import gregtech.api.logic.interfaces.FluidInventoryLogicHost;
+import gregtech.api.logic.interfaces.ItemInventoryLogicHost;
+import gregtech.api.logic.interfaces.PowerLogicHost;
+
+public class PartGUIProvider<T extends GUIHost & ItemInventoryLogicHost & PowerLogicHost & FluidInventoryLogicHost>
+ extends GUIProvider<T> {
+
+ public PartGUIProvider(@Nonnull T host) {
+ super(host);
+ }
+
+ @Override
+ protected void attachSynchHandlers(@Nonnull Builder builder, @Nonnull UIBuildContext uiContext) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'attachSynchHandlers'");
+ }
+
+ @Override
+ protected void addWidgets(@Nonnull Builder builder, @Nonnull UIBuildContext uiContext) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'addWidgets'");
+ }
+
+}
diff --git a/src/main/java/gregtech/common/gui/modularui/UIHelper.java b/src/main/java/gregtech/common/gui/modularui/UIHelper.java
new file mode 100644
index 0000000000..64d686d350
--- /dev/null
+++ b/src/main/java/gregtech/common/gui/modularui/UIHelper.java
@@ -0,0 +1,200 @@
+package gregtech.common.gui.modularui;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import javax.annotation.Nullable;
+import javax.annotation.ParametersAreNonnullByDefault;
+
+import com.gtnewhorizons.modularui.api.drawable.IDrawable;
+import com.gtnewhorizons.modularui.api.math.Pos2d;
+
+import gregtech.api.enums.SteamVariant;
+import gregtech.api.gui.modularui.SteamTexture;
+import gregtech.api.recipe.BasicUIProperties;
+import gregtech.api.util.MethodsReturnNonnullByDefault;
+
+@ParametersAreNonnullByDefault
+@MethodsReturnNonnullByDefault
+public class UIHelper {
+
+ /**
+ * Iterates over candidates for slot placement.
+ */
+ @SuppressWarnings("SimplifyStreamApiCallChains")
+ public static void forEachSlots(ForEachSlot forEachItemInputSlot, ForEachSlot forEachItemOutputSlot,
+ ForEachSlot forEachSpecialSlot, ForEachSlot forEachFluidInputSlot, ForEachSlot forEachFluidOutputSlot,
+ IDrawable itemSlotBackground, IDrawable fluidSlotBackground, BasicUIProperties uiProperties, int itemInputCount,
+ int itemOutputCount, int fluidInputCount, int fluidOutputCount, SteamVariant steamVariant, Pos2d offset) {
+ List<Pos2d> itemInputPositions = uiProperties.itemInputPositionsGetter.apply(itemInputCount)
+ .stream()
+ .map(p -> p.add(offset))
+ .collect(Collectors.toList());
+ for (int i = 0; i < itemInputPositions.size(); i++) {
+ forEachItemInputSlot.accept(
+ i,
+ getBackgroundsForSlot(itemSlotBackground, uiProperties, false, false, i, false, steamVariant),
+ itemInputPositions.get(i));
+ }
+
+ List<Pos2d> itemOutputPositions = uiProperties.itemOutputPositionsGetter.apply(itemOutputCount)
+ .stream()
+ .map(p -> p.add(offset))
+ .collect(Collectors.toList());
+ for (int i = 0; i < itemOutputPositions.size(); i++) {
+ forEachItemOutputSlot.accept(
+ i,
+ getBackgroundsForSlot(itemSlotBackground, uiProperties, false, true, i, false, steamVariant),
+ itemOutputPositions.get(i));
+ }
+
+ forEachSpecialSlot.accept(
+ 0,
+ getBackgroundsForSlot(itemSlotBackground, uiProperties, false, false, 0, true, steamVariant),
+ uiProperties.specialItemPositionGetter.get()
+ .add(offset));
+
+ List<Pos2d> fluidInputPositions = uiProperties.fluidInputPositionsGetter.apply(fluidInputCount)
+ .stream()
+ .map(p -> p.add(offset))
+ .collect(Collectors.toList());
+ for (int i = 0; i < fluidInputPositions.size(); i++) {
+ forEachFluidInputSlot.accept(
+ i,
+ getBackgroundsForSlot(fluidSlotBackground, uiProperties, true, false, i, false, steamVariant),
+ fluidInputPositions.get(i));
+ }
+
+ List<Pos2d> fluidOutputPositions = uiProperties.fluidOutputPositionsGetter.apply(fluidOutputCount)
+ .stream()
+ .map(p -> p.add(offset))
+ .collect(Collectors.toList());
+ for (int i = 0; i < fluidOutputPositions.size(); i++) {
+ forEachFluidOutputSlot.accept(
+ i,
+ getBackgroundsForSlot(fluidSlotBackground, uiProperties, true, true, i, false, steamVariant),
+ fluidOutputPositions.get(i));
+ }
+ }
+
+ /**
+ * @return Display positions for GUI, including border (18x18 size)
+ */
+ public static List<Pos2d> getItemInputPositions(int itemInputCount) {
+ return switch (itemInputCount) {
+ case 0 -> Collections.emptyList();
+ case 1 -> getGridPositions(itemInputCount, 52, 24, 1, 1);
+ case 2 -> getGridPositions(itemInputCount, 34, 24, 2, 1);
+ case 3 -> getGridPositions(itemInputCount, 16, 24, 3, 1);
+ case 4 -> getGridPositions(itemInputCount, 34, 15, 2, 2);
+ case 5, 6 -> getGridPositions(itemInputCount, 16, 15, 3, 2);
+ default -> getGridPositions(itemInputCount, 16, 6, 3);
+ };
+ }
+
+ /**
+ * @return Display positions for GUI, including border (18x18 size)
+ */
+ public static List<Pos2d> getItemOutputPositions(int itemOutputCount) {
+ return switch (itemOutputCount) {
+ case 0 -> Collections.emptyList();
+ case 1 -> getGridPositions(itemOutputCount, 106, 24, 1, 1);
+ case 2 -> getGridPositions(itemOutputCount, 106, 24, 2, 1);
+ case 3 -> getGridPositions(itemOutputCount, 106, 24, 3, 1);
+ case 4 -> getGridPositions(itemOutputCount, 106, 15, 2, 2);
+ case 5, 6 -> getGridPositions(itemOutputCount, 106, 15, 3, 2);
+ default -> getGridPositions(itemOutputCount, 106, 6, 3);
+ };
+ }
+
+ /**
+ * @return Display position for GUI, including border (18x18 size)
+ */
+ public static Pos2d getSpecialItemPosition() {
+ return new Pos2d(124, 62);
+ }
+
+ /**
+ * @return Display positions for GUI, including border (18x18 size)
+ */
+ public static List<Pos2d> getFluidInputPositions(int fluidInputCount) {
+ List<Pos2d> results = new ArrayList<>();
+ int x = 52;
+ for (int i = 0; i < fluidInputCount; i++) {
+ results.add(new Pos2d(x, 62));
+ x -= 18;
+ }
+ return results;
+ }
+
+ /**
+ * @return Display positions for GUI, including border (18x18 size)
+ */
+ public static List<Pos2d> getFluidOutputPositions(int fluidOutputCount) {
+ List<Pos2d> results = new ArrayList<>();
+ int x = 106;
+ for (int i = 0; i < fluidOutputCount; i++) {
+ results.add(new Pos2d(x, 62));
+ x += 18;
+ }
+ return results;
+ }
+
+ public static List<Pos2d> getGridPositions(int totalCount, int xOrigin, int yOrigin, int xDirMaxCount,
+ int yDirMaxCount) {
+ // 18 pixels to get to a new grid for placing an item tile since they are 16x16 and have 1 pixel buffers
+ // around them.
+ int distance = 18;
+
+ List<Pos2d> results = new ArrayList<>();
+ int count = 0;
+ loop: for (int j = 0; j < yDirMaxCount; j++) {
+ for (int i = 0; i < xDirMaxCount; i++) {
+ if (count >= totalCount) break loop;
+ results.add(new Pos2d(xOrigin + i * distance, yOrigin + j * distance));
+ count++;
+ }
+ }
+ return results;
+ }
+
+ public static List<Pos2d> getGridPositions(int totalCount, int xOrigin, int yOrigin, int xDirMaxCount) {
+ return getGridPositions(totalCount, xOrigin, yOrigin, xDirMaxCount, 100);
+ }
+
+ private static IDrawable[] getBackgroundsForSlot(IDrawable base, BasicUIProperties uiProperties, boolean isFluid,
+ boolean isOutput, int index, boolean isSpecial, SteamVariant steamVariant) {
+ IDrawable overlay = getOverlay(uiProperties, isFluid, isOutput, index, isSpecial, steamVariant);
+ if (overlay != null) {
+ return new IDrawable[] { base, overlay };
+ } else {
+ return new IDrawable[] { base };
+ }
+ }
+
+ @Nullable
+ private static IDrawable getOverlay(BasicUIProperties uiProperties, boolean isFluid, boolean isOutput, int index,
+ boolean isSpecial, SteamVariant steamVariant) {
+ if (isSpecial && !uiProperties.useSpecialSlot) {
+ return null;
+ }
+ if (steamVariant != SteamVariant.NONE) {
+ SteamTexture steamTexture = uiProperties.getOverlayForSlotSteam(index, isFluid, isOutput, isSpecial);
+ if (steamTexture != null) {
+ return steamTexture.get(steamVariant);
+ } else {
+ return null;
+ }
+ } else {
+ return uiProperties.getOverlayForSlot(index, isFluid, isOutput, isSpecial);
+ }
+ }
+
+ @FunctionalInterface
+ public interface ForEachSlot {
+
+ void accept(int index, IDrawable[] backgrounds, Pos2d pos);
+ }
+}
diff --git a/src/main/java/gregtech/common/gui/modularui/uifactory/SelectItemUIFactory.java b/src/main/java/gregtech/common/gui/modularui/uifactory/SelectItemUIFactory.java
new file mode 100644
index 0000000000..452ca36c0c
--- /dev/null
+++ b/src/main/java/gregtech/common/gui/modularui/uifactory/SelectItemUIFactory.java
@@ -0,0 +1,229 @@
+package gregtech.common.gui.modularui.uifactory;
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.StatCollector;
+
+import com.gtnewhorizons.modularui.api.GlStateManager;
+import com.gtnewhorizons.modularui.api.ModularUITextures;
+import com.gtnewhorizons.modularui.api.drawable.GuiHelper;
+import com.gtnewhorizons.modularui.api.drawable.IDrawable;
+import com.gtnewhorizons.modularui.api.drawable.ItemDrawable;
+import com.gtnewhorizons.modularui.api.drawable.Text;
+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.DrawableWidget;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.api.enums.Dyes;
+import gregtech.api.gui.GT_GUIColorOverride;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.util.GT_Util;
+import gregtech.api.util.GT_Utility;
+
+/**
+ * Creates UI for selecting item from given list. This is client-only UI to allow using client-preferred settings.
+ */
+public class SelectItemUIFactory {
+
+ private final String header;
+ private final ItemStack headerItem;
+ public static final int UNSELECTED = -1;
+ private static final int cols = 9;
+ private final Consumer<ItemStack> selectedCallback;
+ // passed in stack
+ private final List<ItemStack> stacks;
+ private final boolean noDeselect;
+ private int selected;
+ private boolean anotherWindow = false;
+ private AtomicBoolean dialogOpened;
+ private int guiTint = GT_Util.getRGBInt(Dyes.MACHINE_METAL.getRGBA());
+ private Supplier<ItemStack> currentGetter;
+
+ private final GT_GUIColorOverride colorOverride = GT_GUIColorOverride.get("SelectItemUIFactory");
+
+ private int getTextColorOrDefault(String textType, int defaultColor) {
+ return colorOverride.getTextColorOrDefault(textType, defaultColor);
+ }
+
+ private final Supplier<Integer> COLOR_TITLE = () -> getTextColorOrDefault("title", 0x222222);
+ private final Supplier<Integer> COLOR_TEXT_GRAY = () -> getTextColorOrDefault("text_gray", 0x555555);
+
+ public SelectItemUIFactory(String header, ItemStack headerItem, Consumer<ItemStack> selectedCallback,
+ List<ItemStack> stacks) {
+ this(header, headerItem, selectedCallback, stacks, UNSELECTED);
+ }
+
+ public SelectItemUIFactory(String header, ItemStack headerItem, Consumer<ItemStack> selectedCallback,
+ List<ItemStack> stacks, int selected) {
+ this(header, headerItem, selectedCallback, stacks, selected, false);
+ }
+
+ /**
+ * Constructor for a dialog to select an item from given list. Given callback may be called zero or more times
+ * depending on user action.
+ *
+ * @param header Header text
+ * @param headerItem ItemStack to use as Dialog icon
+ * @param selectedCallback callback upon selected
+ * @param stacks list to choose from
+ * @param selected preselected item. Use {@link #UNSELECTED} for unselected. Invalid selected will be
+ * clamped to 0 or highest index
+ * @param noDeselect true if player cannot deselect, false otherwise. If this is set to true, selectedCallback
+ * is guaranteed to be called with a nonnull stack
+ */
+ public SelectItemUIFactory(String header, ItemStack headerItem, Consumer<ItemStack> selectedCallback,
+ List<ItemStack> stacks, int selected, boolean noDeselect) {
+ this.header = header;
+ this.headerItem = headerItem;
+ this.selectedCallback = selectedCallback;
+ this.stacks = stacks;
+ this.noDeselect = noDeselect;
+ this.selected = noDeselect ? Math.max(0, selected) : selected;
+ }
+
+ /**
+ * @param anotherWindow If UI is shown on top of another window
+ * @param dialogOpened Flag to store whether this UI is opened and hence it should block duplicated creation of
+ * this UI
+ */
+ public SelectItemUIFactory setAnotherWindow(boolean anotherWindow, AtomicBoolean dialogOpened) {
+ this.anotherWindow = anotherWindow;
+ this.dialogOpened = dialogOpened;
+ return this;
+ }
+
+ public SelectItemUIFactory setGuiTint(int guiTint) {
+ this.guiTint = guiTint;
+ return this;
+ }
+
+ /**
+ * @param currentGetter Getter for "current" item displayed that may change from external reasons
+ */
+ public SelectItemUIFactory setCurrentGetter(Supplier<ItemStack> currentGetter) {
+ this.currentGetter = currentGetter;
+ return this;
+ }
+
+ public ModularWindow createWindow(UIBuildContext buildContext) {
+ ModularWindow.Builder builder = ModularWindow
+ .builder(getGUIWidth(), 53 + 18 * ((stacks.size() - 1) / cols + 1));
+ builder.setBackground(ModularUITextures.VANILLA_BACKGROUND);
+ builder.setGuiTint(guiTint);
+
+ if (headerItem != null) {
+ builder.widget(
+ new ItemDrawable(headerItem).asWidget()
+ .setPos(5, 5)
+ .setSize(16, 16));
+ }
+ builder.widget(
+ new TextWidget(header).setDefaultColor(COLOR_TITLE.get())
+ .setPos(25, 9));
+
+ int currentSlotX = 9
+ + getFontRenderer().getStringWidth(StatCollector.translateToLocal("GT5U.gui.select.current"));
+ int currentSlotY = 24;
+ builder.widget(new DrawableWidget() {
+
+ @Override
+ public void onScreenUpdate() {
+ super.onScreenUpdate();
+ if (currentGetter != null) {
+ ItemStack current = currentGetter.get();
+ selected = GT_Utility.findMatchingStackInList(stacks, current);
+ }
+ }
+ }.setDrawable(GT_UITextures.SLOT_DARK_GRAY)
+ .setPos(currentSlotX, currentSlotY)
+ .setSize(18, 18))
+ .widget(
+ new ItemDrawable(() -> getCandidate(getSelected())).asWidgetWithTooltip()
+ .setPos(currentSlotX + 1, currentSlotY + 1));
+ builder.widget(
+ new TextWidget(StatCollector.translateToLocal("GT5U.gui.select.current"))
+ .setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(8, 25 + (18 - getFontRenderer().FONT_HEIGHT) / 2));
+
+ for (int i = 0; i < stacks.size(); i++) {
+ final int index = i;
+ builder.widget(new ButtonWidget() {
+
+ @Override
+ public void draw(float partialTicks) {
+ GlStateManager.pushMatrix();
+ // so that item z levels are properly ordered
+ GlStateManager.translate(0, 0, 150 * getWindowLayer());
+ new ItemDrawable(stacks.get(index)).draw(1, 1, 16, 16, partialTicks);
+ GlStateManager.popMatrix();
+ }
+ }.setOnClick((clickData, widget) -> {
+ if (clickData.mouseButton == 0) {
+ setSelected(index);
+ } else {
+ setSelected(UNSELECTED);
+ }
+ selectedCallback.accept(getCandidate(getSelected()));
+ })
+ .setSynced(false, false)
+ .dynamicTooltip(() -> GuiHelper.getItemTooltip(stacks.get(index)))
+ .setUpdateTooltipEveryTick(true)
+ .setBackground(
+ () -> new IDrawable[] {
+ index == selected ? GT_UITextures.SLOT_DARK_GRAY : ModularUITextures.ITEM_SLOT, })
+ .setPos(7 + 18 * (index % cols), 43 + 18 * (index / cols))
+ .setSize(18, 18));
+ }
+
+ if (anotherWindow) {
+ dialogOpened.set(true);
+ builder.widget(new ButtonWidget() {
+
+ @Override
+ public void onDestroy() {
+ dialogOpened.set(false);
+ }
+ }.setOnClick(
+ (clickData, widget) -> widget.getWindow()
+ .tryClose())
+ .setSynced(false, false)
+ .setBackground(ModularUITextures.VANILLA_BACKGROUND, new Text("x"))
+ .setPos(getGUIWidth() - 15, 3)
+ .setSize(12, 12));
+ }
+
+ return builder.build();
+ }
+
+ public int getSelected() {
+ return selected;
+ }
+
+ public void setSelected(int selected) {
+ if (selected == this.selected) return;
+ int newSelected = GT_Utility.clamp(selected, UNSELECTED, stacks.size() - 1);
+ if (noDeselect && newSelected == UNSELECTED) return;
+
+ this.selected = newSelected;
+ }
+
+ private ItemStack getCandidate(int listIndex) {
+ return listIndex < 0 || listIndex >= stacks.size() ? null : stacks.get(listIndex);
+ }
+
+ private FontRenderer getFontRenderer() {
+ return Minecraft.getMinecraft().fontRenderer;
+ }
+
+ private int getGUIWidth() {
+ return 176;
+ }
+}
diff --git a/src/main/java/gregtech/common/gui/modularui/widget/AESlotWidget.java b/src/main/java/gregtech/common/gui/modularui/widget/AESlotWidget.java
new file mode 100644
index 0000000000..368f219ef4
--- /dev/null
+++ b/src/main/java/gregtech/common/gui/modularui/widget/AESlotWidget.java
@@ -0,0 +1,64 @@
+package gregtech.common.gui.modularui.widget;
+
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.renderer.entity.RenderItem;
+import net.minecraft.client.renderer.texture.TextureManager;
+import net.minecraft.inventory.Slot;
+import net.minecraft.item.ItemStack;
+
+import com.gtnewhorizons.modularui.common.internal.wrapper.BaseSlot;
+import com.gtnewhorizons.modularui.common.internal.wrapper.ModularGui;
+import com.gtnewhorizons.modularui.common.widget.SlotWidget;
+
+import appeng.api.storage.IItemDisplayRegistry.ItemRenderHook;
+import appeng.client.render.AppEngRenderItem;
+import appeng.core.AELog;
+import appeng.util.Platform;
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+
+public class AESlotWidget extends SlotWidget {
+
+ private static class HookHolder {
+
+ static ItemRenderHook SKIP_ITEM_STACK_SIZE_HOOK = new ItemRenderHook() {
+
+ @Override
+ public boolean renderOverlay(FontRenderer fr, TextureManager tm, ItemStack is, int x, int y) {
+ return true;
+ }
+
+ @Override
+ public boolean showStackSize(ItemStack is) {
+ return false;
+ }
+ };
+ }
+
+ public AESlotWidget(BaseSlot slot) {
+ super(slot);
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ protected void drawSlot(Slot slotIn) {
+ final AppEngRenderItem aeRenderItem = new AppEngRenderItem();
+ AppEngRenderItem.POST_HOOKS.add(HookHolder.SKIP_ITEM_STACK_SIZE_HOOK);
+ final RenderItem pIR = this.setItemRender(aeRenderItem);
+ try {
+ aeRenderItem.setAeStack(Platform.getAEStackInSlot(slotIn));
+ super.drawSlot(slotIn, true);
+ } catch (final Exception err) {
+ AELog.warn("[AppEng] AE prevented crash while drawing slot: " + err);
+ }
+ AppEngRenderItem.POST_HOOKS.remove(HookHolder.SKIP_ITEM_STACK_SIZE_HOOK);
+ this.setItemRender(pIR);
+ }
+
+ @SideOnly(Side.CLIENT)
+ private RenderItem setItemRender(final RenderItem item) {
+ final RenderItem ri = ModularGui.getItemRenderer();
+ ModularGui.setItemRenderer(item);
+ return ri;
+ }
+}
diff --git a/src/main/java/gregtech/common/gui/modularui/widget/CheckRecipeResultSyncer.java b/src/main/java/gregtech/common/gui/modularui/widget/CheckRecipeResultSyncer.java
new file mode 100644
index 0000000000..9028c66be8
--- /dev/null
+++ b/src/main/java/gregtech/common/gui/modularui/widget/CheckRecipeResultSyncer.java
@@ -0,0 +1,26 @@
+package gregtech.common.gui.modularui.widget;
+
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+import com.gtnewhorizons.modularui.common.internal.network.NetworkUtils;
+import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget;
+
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+
+public class CheckRecipeResultSyncer extends FakeSyncWidget<CheckRecipeResult> {
+
+ public CheckRecipeResultSyncer(Supplier<CheckRecipeResult> getter, Consumer<CheckRecipeResult> setter) {
+ super(getter, setter, (buffer, result) -> {
+ NetworkUtils.writeStringSafe(buffer, result.getID());
+ result.encode(buffer);
+ }, buffer -> {
+ String id = NetworkUtils.readStringSafe(buffer);
+ CheckRecipeResult result = CheckRecipeResultRegistry.getSampleFromRegistry(id)
+ .newInstance();
+ result.decode(buffer);
+ return result;
+ });
+ }
+}
diff --git a/src/main/java/gregtech/common/gui/modularui/widget/CoverCycleButtonWidget.java b/src/main/java/gregtech/common/gui/modularui/widget/CoverCycleButtonWidget.java
new file mode 100644
index 0000000000..4d1c6649ae
--- /dev/null
+++ b/src/main/java/gregtech/common/gui/modularui/widget/CoverCycleButtonWidget.java
@@ -0,0 +1,91 @@
+package gregtech.common.gui.modularui.widget;
+
+import org.lwjgl.opengl.GL11;
+
+import com.gtnewhorizons.modularui.api.drawable.IDrawable;
+import com.gtnewhorizons.modularui.api.drawable.UITexture;
+import com.gtnewhorizons.modularui.common.widget.CycleButtonWidget;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.api.gui.modularui.GT_UITextures;
+
+/**
+ * Fires click action on mouse release, not on press. Draws different backgrounds depending on whether the mouse is
+ * being pressed or the widget is hovered.
+ */
+public class CoverCycleButtonWidget extends CycleButtonWidget {
+
+ private static final UITexture BUTTON_NORMAL_NOT_PRESSED = GT_UITextures.BUTTON_COVER_NORMAL
+ .getSubArea(0, 0, 1, 0.5f);
+ private static final UITexture BUTTON_NORMAL_PRESSED = GT_UITextures.BUTTON_COVER_NORMAL.getSubArea(0, 0.5f, 1, 1);
+ private static final UITexture BUTTON_HOVERED_NOT_PRESSED = GT_UITextures.BUTTON_COVER_NORMAL_HOVERED
+ .getSubArea(0, 0, 1, 0.5f);
+ private static final UITexture BUTTON_HOVERED_PRESSED = GT_UITextures.BUTTON_COVER_NORMAL_HOVERED
+ .getSubArea(0, 0.5f, 1, 1);
+
+ private boolean clickPressed;
+
+ private static final int TOOLTIP_DELAY = 5;
+
+ public CoverCycleButtonWidget() {
+ setSize(16, 16);
+ setTooltipShowUpDelay(TOOLTIP_DELAY);
+ }
+
+ @Override
+ public ClickResult onClick(int buttonId, boolean doubleClick) {
+ updateState();
+ if (!canClick()) return ClickResult.REJECT;
+ clickPressed = true;
+ return ClickResult.SUCCESS;
+ }
+
+ @Override
+ public boolean onClickReleased(int buttonId) {
+ clickPressed = false;
+ updateState();
+ if (!isHovering() || !canClick()) return false;
+ return onClickImpl(buttonId);
+ }
+
+ protected boolean onClickImpl(int buttonId) {
+ super.onClick(buttonId, false);
+ return true;
+ }
+
+ @SuppressWarnings("BooleanMethodIsAlwaysInverted")
+ protected boolean canClick() {
+ return true;
+ }
+
+ @SideOnly(Side.CLIENT)
+ protected void updateState() {}
+
+ public boolean isClickPressed() {
+ return clickPressed;
+ }
+
+ @Override
+ public void drawBackground(float partialTicks) {
+ GL11.glColor4f(1, 1, 1, 1);
+ super.drawBackground(partialTicks);
+ }
+
+ @Override
+ public IDrawable[] getBackground() {
+ if (isHovering()) {
+ if (clickPressed) {
+ return new IDrawable[] { BUTTON_HOVERED_PRESSED };
+ } else {
+ return new IDrawable[] { BUTTON_HOVERED_NOT_PRESSED };
+ }
+ } else {
+ if (clickPressed) {
+ return new IDrawable[] { BUTTON_NORMAL_PRESSED };
+ } else {
+ return new IDrawable[] { BUTTON_NORMAL_NOT_PRESSED };
+ }
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/gui/modularui/widget/CoverDataControllerWidget.java b/src/main/java/gregtech/common/gui/modularui/widget/CoverDataControllerWidget.java
new file mode 100644
index 0000000000..4543980ce1
--- /dev/null
+++ b/src/main/java/gregtech/common/gui/modularui/widget/CoverDataControllerWidget.java
@@ -0,0 +1,133 @@
+package gregtech.common.gui.modularui.widget;
+
+import java.io.IOException;
+import java.util.function.BiFunction;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+import net.minecraft.network.PacketBuffer;
+
+import com.gtnewhorizons.modularui.api.widget.Widget;
+import com.gtnewhorizons.modularui.common.internal.network.NetworkUtils;
+
+import gregtech.api.gui.modularui.IDataFollowerWidget;
+import gregtech.api.util.GT_CoverBehaviorBase;
+import gregtech.api.util.ISerializableObject;
+
+public class CoverDataControllerWidget<T extends ISerializableObject> extends DataControllerWidget<T> {
+
+ protected final GT_CoverBehaviorBase<T> coverBehavior;
+
+ /**
+ * @param dataGetter () -> cover data this widget handles
+ * @param dataSetter data to set -> if setting cover data is successful
+ * @param coverBehavior cover this widget handles data update
+ */
+ public CoverDataControllerWidget(Supplier<T> dataGetter, Function<T, Boolean> dataSetter,
+ GT_CoverBehaviorBase<T> coverBehavior) {
+ super(dataGetter, dataSetter);
+ this.coverBehavior = coverBehavior;
+ }
+
+ @Override
+ public <U, W extends Widget & IDataFollowerWidget<T, U>> CoverDataControllerWidget<T> addFollower(W widget,
+ Function<T, U> dataToStateGetter, BiFunction<T, U, T> dataUpdater, Consumer<W> applyForWidget) {
+ super.addFollower(widget, dataToStateGetter, dataUpdater, applyForWidget);
+ return this;
+ }
+
+ @Override
+ protected void writeToPacket(PacketBuffer buffer, T data) {
+ try {
+ NetworkUtils.writeNBTBase(buffer, data.saveDataToNBT());
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ protected T readFromPacket(PacketBuffer buffer) throws IOException {
+ return coverBehavior.createDataObject(NetworkUtils.readNBTBase(buffer));
+ }
+
+ /**
+ * Uses int index to determine toggle button behaviors.
+ */
+ public static class CoverDataIndexedControllerWidget_ToggleButtons<T extends ISerializableObject>
+ extends CoverDataControllerWidget<T> {
+
+ private final BiFunction<Integer, T, Boolean> dataToStateGetter;
+ private final BiFunction<Integer, T, T> dataUpdater;
+
+ /**
+ * @param coverDataGetter () -> cover data this widget handles
+ * @param coverDataSetter data to set -> if setting cover data is successful
+ * @param coverBehavior cover this widget handles data update
+ * @param dataToStateGetter (index of button, given cover data) -> button state
+ * @param dataUpdater (index of button, current cover data) -> new cover data
+ */
+ public CoverDataIndexedControllerWidget_ToggleButtons(Supplier<T> coverDataGetter,
+ Function<T, Boolean> coverDataSetter, GT_CoverBehaviorBase<T> coverBehavior,
+ BiFunction<Integer, T, Boolean> dataToStateGetter, BiFunction<Integer, T, T> dataUpdater) {
+ super(coverDataGetter, coverDataSetter, coverBehavior);
+ this.dataToStateGetter = dataToStateGetter;
+ this.dataUpdater = dataUpdater;
+ }
+
+ /**
+ * @param index index of widget to add
+ * @param widget widget to add
+ * @param applyForWidget methods to call for widget to add
+ */
+ public <W extends CoverDataFollower_ToggleButtonWidget<T>> CoverDataIndexedControllerWidget_ToggleButtons<T> addToggleButton(
+ int index, W widget, Consumer<CoverDataFollower_ToggleButtonWidget<T>> applyForWidget) {
+ addFollower(
+ widget,
+ data -> dataToStateGetter.apply(index, data),
+ (data, state) -> dataUpdater.apply(index, data),
+ applyForWidget);
+ return this;
+ }
+ }
+
+ /**
+ * Uses int index to determine cycle button behaviors.
+ */
+ public static class CoverDataIndexedControllerWidget_CycleButtons<T extends ISerializableObject>
+ extends CoverDataControllerWidget<T> {
+
+ private final BiFunction<Integer, T, Integer> dataToStateGetter;
+ private final BiFunction<Integer, T, T> dataUpdater;
+
+ /**
+ * @param coverDataGetter () -> cover data this widget handles
+ * @param coverDataSetter data to set -> if setting cover data is successful
+ * @param coverBehavior cover this widget handles data update
+ * @param dataToStateGetter (index of button, given cover data) -> button state
+ * @param dataUpdater (index of button, current cover data) -> new cover data
+ */
+ public CoverDataIndexedControllerWidget_CycleButtons(Supplier<T> coverDataGetter,
+ Function<T, Boolean> coverDataSetter, GT_CoverBehaviorBase<T> coverBehavior,
+ BiFunction<Integer, T, Integer> dataToStateGetter, BiFunction<Integer, T, T> dataUpdater) {
+ super(coverDataGetter, coverDataSetter, coverBehavior);
+ this.dataToStateGetter = dataToStateGetter;
+ this.dataUpdater = dataUpdater;
+ }
+
+ /**
+ * @param index index of widget to add
+ * @param widget widget to add
+ * @param applyForWidget methods to call for the widget to add
+ */
+ public <W extends CoverDataFollower_CycleButtonWidget<T>> CoverDataIndexedControllerWidget_CycleButtons<T> addCycleButton(
+ int index, W widget, Consumer<CoverDataFollower_CycleButtonWidget<T>> applyForWidget) {
+ addFollower(
+ widget,
+ data -> dataToStateGetter.apply(index, data),
+ (data, state) -> dataUpdater.apply(index, data),
+ applyForWidget);
+ return this;
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/gui/modularui/widget/CoverDataFollower_CycleButtonWidget.java b/src/main/java/gregtech/common/gui/modularui/widget/CoverDataFollower_CycleButtonWidget.java
new file mode 100644
index 0000000000..ec7d31ca7e
--- /dev/null
+++ b/src/main/java/gregtech/common/gui/modularui/widget/CoverDataFollower_CycleButtonWidget.java
@@ -0,0 +1,39 @@
+package gregtech.common.gui.modularui.widget;
+
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+import gregtech.api.gui.modularui.IDataFollowerWidget;
+import gregtech.api.util.ISerializableObject;
+
+/**
+ * Determines button state with cover data.
+ */
+public class CoverDataFollower_CycleButtonWidget<T extends ISerializableObject> extends CoverCycleButtonWidget
+ implements IDataFollowerWidget<T, Integer> {
+
+ private Function<T, Integer> dataToStateGetter;
+
+ public CoverDataFollower_CycleButtonWidget() {
+ super();
+ setGetter(() -> 0); // fake getter; used only for init
+ setSynced(false, false);
+ }
+
+ @Override
+ public CoverDataFollower_CycleButtonWidget<T> setDataToStateGetter(Function<T, Integer> dataToStateGetter) {
+ this.dataToStateGetter = dataToStateGetter;
+ return this;
+ }
+
+ @Override
+ public CoverDataFollower_CycleButtonWidget<T> setStateSetter(Consumer<Integer> setter) {
+ super.setSetter(setter);
+ return this;
+ }
+
+ @Override
+ public void updateState(T data) {
+ setState(dataToStateGetter.apply(data), false, false);
+ }
+}
diff --git a/src/main/java/gregtech/common/gui/modularui/widget/CoverDataFollower_NumericWidget.java b/src/main/java/gregtech/common/gui/modularui/widget/CoverDataFollower_NumericWidget.java
new file mode 100644
index 0000000000..f641ed090b
--- /dev/null
+++ b/src/main/java/gregtech/common/gui/modularui/widget/CoverDataFollower_NumericWidget.java
@@ -0,0 +1,60 @@
+package gregtech.common.gui.modularui.widget;
+
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+import com.gtnewhorizons.modularui.api.math.Alignment;
+import com.gtnewhorizons.modularui.api.math.Color;
+import com.gtnewhorizons.modularui.common.widget.textfield.NumericWidget;
+
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.gui.modularui.IDataFollowerWidget;
+import gregtech.api.util.ISerializableObject;
+
+public class CoverDataFollower_NumericWidget<T extends ISerializableObject> extends NumericWidget
+ implements IDataFollowerWidget<T, Double> {
+
+ private Function<T, Double> dataToStateGetter;
+
+ public CoverDataFollower_NumericWidget() {
+ super();
+ setGetter(() -> 0); // fake getter; used only for init
+ setSynced(false, false);
+ setTextColor(Color.WHITE.dark(1));
+ setTextAlignment(Alignment.CenterLeft);
+ setBackground(GT_UITextures.BACKGROUND_TEXT_FIELD.withOffset(-1, -1, 2, 2));
+ }
+
+ @Override
+ public void onPostInit() {
+ // Widget#onPostInit is called earlier than IDataFollowerWidget#onPostInit,
+ // so we make sure cursor is set after text is set
+ super.onPostInit();
+
+ // On first call #handler does not contain text.
+ // On second call, it contains correct text to update #lastText,
+ // but #shouldGetFocus call is skipped by Cursor#updateFocused,
+ // so we need to manually call this.
+ if (focusOnGuiOpen) {
+ shouldGetFocus();
+ }
+ }
+
+ @Override
+ public CoverDataFollower_NumericWidget<T> setDataToStateGetter(Function<T, Double> dataToStateGetter) {
+ this.dataToStateGetter = dataToStateGetter;
+ return this;
+ }
+
+ @Override
+ public CoverDataFollower_NumericWidget<T> setStateSetter(Consumer<Double> setter) {
+ super.setSetter(setter::accept);
+ return this;
+ }
+
+ @Override
+ public void updateState(T data) {
+ setValue(dataToStateGetter.apply(data));
+ }
+
+}
diff --git a/src/main/java/gregtech/common/gui/modularui/widget/CoverDataFollower_SlotWidget.java b/src/main/java/gregtech/common/gui/modularui/widget/CoverDataFollower_SlotWidget.java
new file mode 100644
index 0000000000..0b827bfbc6
--- /dev/null
+++ b/src/main/java/gregtech/common/gui/modularui/widget/CoverDataFollower_SlotWidget.java
@@ -0,0 +1,101 @@
+package gregtech.common.gui.modularui.widget;
+
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+import net.minecraft.item.ItemStack;
+
+import com.gtnewhorizons.modularui.api.forge.IItemHandlerModifiable;
+import com.gtnewhorizons.modularui.api.widget.Interactable;
+import com.gtnewhorizons.modularui.common.internal.network.NetworkUtils;
+import com.gtnewhorizons.modularui.common.internal.wrapper.BaseSlot;
+import com.gtnewhorizons.modularui.common.widget.SlotWidget;
+
+import gregtech.api.gui.modularui.IDataFollowerWidget;
+import gregtech.api.util.ISerializableObject;
+
+public class CoverDataFollower_SlotWidget<T extends ISerializableObject> extends SlotWidget
+ implements IDataFollowerWidget<T, ItemStack> {
+
+ private Function<T, ItemStack> dataToStateGetter;
+ private Consumer<ItemStack> dataSetter;
+
+ public CoverDataFollower_SlotWidget(BaseSlot slot) {
+ super(slot);
+ }
+
+ public CoverDataFollower_SlotWidget(IItemHandlerModifiable handler, int index, boolean phantom) {
+ this(new BaseSlot(handler, index, phantom));
+ }
+
+ public CoverDataFollower_SlotWidget(IItemHandlerModifiable handler, int index) {
+ this(handler, index, false);
+ }
+
+ @Override
+ public CoverDataFollower_SlotWidget<T> setDataToStateGetter(Function<T, ItemStack> dataToStateGetter) {
+ this.dataToStateGetter = dataToStateGetter;
+ return this;
+ }
+
+ @Override
+ public CoverDataFollower_SlotWidget<T> setStateSetter(Consumer<ItemStack> setter) {
+ this.dataSetter = setter;
+ return this;
+ }
+
+ @Override
+ public void updateState(T data) {
+ getMcSlot().putStack(dataToStateGetter.apply(data));
+ }
+
+ @Override
+ public void detectAndSendChanges(boolean init) {}
+
+ // Slot sync is handled differently from other DataFollowers,
+ // so we need to also sync slot content directly to server.
+
+ @Override
+ public ClickResult onClick(int buttonId, boolean doubleClick) {
+ if (interactionDisabled) return ClickResult.REJECT;
+ if (isPhantom()) {
+ ClickData clickData = ClickData.create(buttonId, doubleClick);
+ syncToServer(2, clickData::writeToPacket);
+ phantomClick(clickData);
+ dataSetter.accept(getMcSlot().getStack());
+ return ClickResult.ACCEPT;
+ }
+ return ClickResult.REJECT;
+ }
+
+ @Override
+ public boolean onMouseScroll(int direction) {
+ if (interactionDisabled) return false;
+ if (isPhantom()) {
+ if (Interactable.hasShiftDown()) {
+ direction *= 8;
+ }
+ final int finalDirection = direction;
+ syncToServer(3, buffer -> buffer.writeVarIntToBuffer(finalDirection));
+ phantomScroll(finalDirection);
+ dataSetter.accept(getMcSlot().getStack());
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean handleDragAndDrop(ItemStack draggedStack, int button) {
+ if (interactionDisabled) return false;
+ if (!isPhantom()) return false;
+ ClickData clickData = ClickData.create(button, false);
+ syncToServer(5, buffer -> {
+ clickData.writeToPacket(buffer);
+ NetworkUtils.writeItemStack(buffer, draggedStack);
+ });
+ phantomClick(clickData, draggedStack);
+ dataSetter.accept(getMcSlot().getStack());
+ draggedStack.stackSize = 0;
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/common/gui/modularui/widget/CoverDataFollower_TextFieldWidget.java b/src/main/java/gregtech/common/gui/modularui/widget/CoverDataFollower_TextFieldWidget.java
new file mode 100644
index 0000000000..1907aaf22f
--- /dev/null
+++ b/src/main/java/gregtech/common/gui/modularui/widget/CoverDataFollower_TextFieldWidget.java
@@ -0,0 +1,134 @@
+package gregtech.common.gui.modularui.widget;
+
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+import net.minecraft.client.gui.GuiScreen;
+
+import com.gtnewhorizon.gtnhlib.util.parsing.MathExpressionParser;
+import com.gtnewhorizons.modularui.api.math.Alignment;
+import com.gtnewhorizons.modularui.api.math.Color;
+import com.gtnewhorizons.modularui.common.widget.textfield.TextFieldWidget;
+
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.gui.modularui.IDataFollowerWidget;
+import gregtech.api.util.ISerializableObject;
+
+public class CoverDataFollower_TextFieldWidget<T extends ISerializableObject> extends TextFieldWidget
+ implements IDataFollowerWidget<T, String> {
+
+ private Function<T, String> dataToStateGetter;
+
+ public CoverDataFollower_TextFieldWidget() {
+ super();
+ setGetter(() -> ""); // fake getter; used only for init
+ setSynced(false, false);
+ setTextColor(Color.WHITE.dark(1));
+ setTextAlignment(Alignment.CenterLeft);
+ setBackground(GT_UITextures.BACKGROUND_TEXT_FIELD.withOffset(-1, -1, 2, 2));
+ }
+
+ @Override
+ public void onPostInit() {
+ // Widget#onPostInit is called earlier than IDataFollowerWidget#onPostInit,
+ // so we make sure cursor is set after text is set
+ super.onPostInit();
+
+ // On first call #handler does not contain text.
+ // On second call, it contains correct text to update #lastText,
+ // but #shouldGetFocus call is skipped by Cursor#updateFocused,
+ // so we need to manually call this.
+ if (focusOnGuiOpen) {
+ shouldGetFocus();
+ }
+ }
+
+ @Override
+ public CoverDataFollower_TextFieldWidget<T> setDataToStateGetter(Function<T, String> dataToStateGetter) {
+ this.dataToStateGetter = dataToStateGetter;
+ return this;
+ }
+
+ @Override
+ public CoverDataFollower_TextFieldWidget<T> setStateSetter(Consumer<String> setter) {
+ super.setSetter(setter);
+ return this;
+ }
+
+ @Override
+ public void updateState(T data) {
+ setText(dataToStateGetter.apply(data));
+ }
+
+ /**
+ * @deprecated Use {@link CoverDataFollower_NumericWidget}
+ */
+ @Deprecated
+ public CoverDataFollower_TextFieldWidget<T> setOnScrollNumbers(int baseStep, int ctrlStep, int shiftStep) {
+ setOnScrollNumbers((val, direction) -> {
+ int step = (GuiScreen.isShiftKeyDown() ? shiftStep : GuiScreen.isCtrlKeyDown() ? ctrlStep : baseStep)
+ * direction;
+ try {
+ val = Math.addExact(val, step);
+ } catch (ArithmeticException ignored) {
+ val = Integer.MAX_VALUE;
+ }
+ return val;
+ });
+ return this;
+ }
+
+ /**
+ * @deprecated Use {@link CoverDataFollower_NumericWidget}
+ */
+ @Deprecated
+ public CoverDataFollower_TextFieldWidget<T> setOnScrollNumbers() {
+ return setOnScrollNumbers(1, 50, 1000);
+ }
+
+ /**
+ * @deprecated Use {@link CoverDataFollower_NumericWidget}
+ */
+ @Deprecated
+ public CoverDataFollower_TextFieldWidget<T> setOnScrollText(int baseStep, int ctrlStep, int shiftStep) {
+ setOnScroll((text, direction) -> {
+ int val = (int) MathExpressionParser.parse(text);
+ int step = (GuiScreen.isShiftKeyDown() ? shiftStep : GuiScreen.isCtrlKeyDown() ? ctrlStep : baseStep)
+ * direction;
+ try {
+ val = Math.addExact(val, step);
+ } catch (ArithmeticException ignored) {
+ val = Integer.MAX_VALUE;
+ }
+ return this.getDecimalFormatter()
+ .format(val);
+ });
+ return this;
+ }
+
+ /**
+ * @deprecated Use {@link CoverDataFollower_NumericWidget}
+ */
+ @Deprecated
+ public CoverDataFollower_TextFieldWidget<T> setOnScrollText() {
+ return setOnScrollText(1, 5, 50);
+ }
+
+ /**
+ * @deprecated Use {@link CoverDataFollower_NumericWidget}
+ */
+ @Deprecated
+ public CoverDataFollower_TextFieldWidget<T> setOnScrollNumbersLong(long baseStep, long ctrlStep, long shiftStep) {
+ setOnScrollNumbersLong((val, direction) -> {
+ long step = (GuiScreen.isShiftKeyDown() ? shiftStep : GuiScreen.isCtrlKeyDown() ? ctrlStep : baseStep)
+ * direction;
+ try {
+ val = Math.addExact(val, step);
+ } catch (ArithmeticException ignored) {
+ val = Long.MAX_VALUE;
+ }
+ return val;
+ });
+ return this;
+ }
+}
diff --git a/src/main/java/gregtech/common/gui/modularui/widget/CoverDataFollower_ToggleButtonWidget.java b/src/main/java/gregtech/common/gui/modularui/widget/CoverDataFollower_ToggleButtonWidget.java
new file mode 100644
index 0000000000..6f798a93d5
--- /dev/null
+++ b/src/main/java/gregtech/common/gui/modularui/widget/CoverDataFollower_ToggleButtonWidget.java
@@ -0,0 +1,86 @@
+package gregtech.common.gui.modularui.widget;
+
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+import com.gtnewhorizons.modularui.api.drawable.IDrawable;
+
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.gui.modularui.IDataFollowerWidget;
+import gregtech.api.util.ISerializableObject;
+
+public class CoverDataFollower_ToggleButtonWidget<T extends ISerializableObject> extends CoverCycleButtonWidget
+ implements IDataFollowerWidget<T, Boolean> {
+
+ private Function<T, Boolean> dataToStateGetter;
+
+ public CoverDataFollower_ToggleButtonWidget() {
+ super();
+ setGetter(() -> 0); // fake getter; used only for init
+ setSynced(false, false);
+ setLength(2);
+ }
+
+ @Override
+ public CoverDataFollower_ToggleButtonWidget<T> setDataToStateGetter(Function<T, Boolean> dataToStateGetter) {
+ this.dataToStateGetter = dataToStateGetter;
+ return this;
+ }
+
+ @Override
+ public CoverDataFollower_ToggleButtonWidget<T> setStateSetter(Consumer<Boolean> setter) {
+ super.setSetter(val -> setter.accept(val == 1));
+ return this;
+ }
+
+ @Override
+ public void updateState(T data) {
+ setState(dataToStateGetter.apply(data) ? 1 : 0, false, false);
+ }
+
+ public CoverDataFollower_ToggleButtonWidget<T> setToggleTexture(IDrawable active, IDrawable inactive) {
+ setTextureGetter(state -> state == 1 ? active : inactive);
+ return this;
+ }
+
+ public static <T extends ISerializableObject> CoverDataFollower_ToggleButtonWidget<T> ofCheckAndCross() {
+ return new CoverDataFollower_ToggleButtonWidget<T>()
+ .setToggleTexture(GT_UITextures.OVERLAY_BUTTON_CHECKMARK, GT_UITextures.OVERLAY_BUTTON_CROSS);
+ }
+
+ public static <T extends ISerializableObject> CoverDataFollower_ToggleButtonWidget<T> ofCheck() {
+ return new CoverDataFollower_ToggleButtonWidget<T>()
+ .setToggleTexture(GT_UITextures.OVERLAY_BUTTON_CHECKMARK, GT_UITextures.TRANSPARENT);
+ }
+
+ public static <T extends ISerializableObject> CoverDataFollower_ToggleButtonWidget<T> ofRedstone() {
+ return new CoverDataFollower_ToggleButtonWidget<T>()
+ .setToggleTexture(GT_UITextures.OVERLAY_BUTTON_REDSTONE_ON, GT_UITextures.OVERLAY_BUTTON_REDSTONE_OFF);
+ }
+
+ public static <T extends ISerializableObject> CoverDataFollower_ToggleButtonWidget<T> ofDisableable() {
+ return new CoverDataFollower_DisableableToggleButtonWidget<>();
+ }
+
+ /**
+ * Disables clicking if button is already pressed.
+ */
+ public static class CoverDataFollower_DisableableToggleButtonWidget<T extends ISerializableObject>
+ extends CoverDataFollower_ToggleButtonWidget<T> {
+
+ public CoverDataFollower_DisableableToggleButtonWidget() {
+ super();
+ }
+
+ @Override
+ protected boolean canClick() {
+ return getState() == 0;
+ }
+
+ @Override
+ public IDrawable[] getBackground() {
+ if (!canClick()) return new IDrawable[] { GT_UITextures.BUTTON_COVER_NORMAL_DISABLED };
+ return super.getBackground();
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/gui/modularui/widget/DataControllerWidget.java b/src/main/java/gregtech/common/gui/modularui/widget/DataControllerWidget.java
new file mode 100644
index 0000000000..3717b128bb
--- /dev/null
+++ b/src/main/java/gregtech/common/gui/modularui/widget/DataControllerWidget.java
@@ -0,0 +1,166 @@
+package gregtech.common.gui.modularui.widget;
+
+import java.io.IOException;
+import java.util.function.BiFunction;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+import net.minecraft.network.PacketBuffer;
+
+import com.gtnewhorizons.modularui.api.widget.ISyncedWidget;
+import com.gtnewhorizons.modularui.api.widget.Widget;
+import com.gtnewhorizons.modularui.common.internal.network.NetworkUtils;
+import com.gtnewhorizons.modularui.common.widget.MultiChildWidget;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.api.gui.modularui.IDataFollowerWidget;
+import gregtech.api.util.ISerializableObject;
+
+/**
+ * Controls state of child widgets with specific data, and allows centralized control of multiple widgets. e.g. clicking
+ * button B will set machine mode to B, so button A, whose state is bound to the mode, will be automatically deactivated
+ * by this widget. <br>
+ * This widget wraps data and handles validation, e.g. tell client to close GUI when tile is broken or cover is removed.
+ * <br>
+ * Data can be anything, e.g. {@link ISerializableObject} or machine recipe mode.
+ *
+ * @param <T> Data type stored in this widget
+ * @see IDataFollowerWidget
+ */
+public abstract class DataControllerWidget<T> extends MultiChildWidget implements ISyncedWidget {
+
+ private final Supplier<T> dataGetter;
+ private final Function<T, Boolean> dataSetter;
+
+ protected T lastData;
+
+ private boolean needsUpdate;
+
+ /**
+ * @param dataGetter () -> data this widget handles
+ * @param dataSetter data to set -> if setting data is successful
+ */
+ public DataControllerWidget(Supplier<T> dataGetter, Function<T, Boolean> dataSetter) {
+ this.dataGetter = dataGetter;
+ this.dataSetter = dataSetter;
+ }
+
+ protected T getLastData() {
+ return lastData;
+ }
+
+ @Override
+ public void onPostInit() {
+ // client _should_ have received initial cover data from `GT_UIInfos#openCoverUI`
+ lastData = dataGetter.get();
+ if (NetworkUtils.isClient()) {
+ updateChildren(true);
+ }
+ }
+
+ @Override
+ public void detectAndSendChanges(boolean init) {
+ T actualValue = dataGetter.get();
+ if (actualValue == null) {
+ // data is in invalid state e.g. tile is broken, cover is removed
+ getWindow().tryClose();
+ return;
+ }
+ if (init || !actualValue.equals(getLastData())) {
+ // init sync or someone else edited data
+ lastData = actualValue;
+ syncDataToClient(actualValue);
+ }
+ }
+
+ protected void syncDataToClient(T data) {
+ syncToClient(0, buffer -> writeToPacket(buffer, data));
+ }
+
+ protected void syncDataToServer(T data) {
+ syncToServer(0, buffer -> writeToPacket(buffer, data));
+ updateChildren();
+ }
+
+ @Override
+ public void readOnClient(int id, PacketBuffer buf) throws IOException {
+ if (id == 0) {
+ lastData = readFromPacket(buf);
+ dataSetter.apply(getLastData());
+ updateChildren();
+ }
+ }
+
+ @Override
+ public void readOnServer(int id, PacketBuffer buf) throws IOException {
+ if (id == 0) {
+ lastData = readFromPacket(buf);
+ if (dataSetter.apply(getLastData())) {
+ markForUpdate();
+ } else {
+ getWindow().closeWindow();
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @SideOnly(Side.CLIENT)
+ protected void updateChildren(boolean postInit) {
+ for (Widget child : getChildren()) {
+ if (child instanceof IDataFollowerWidget) {
+ ((IDataFollowerWidget<T, ?>) child).updateState(getLastData());
+ if (postInit) {
+ ((IDataFollowerWidget<T, ?>) child).onPostInit();
+ }
+ }
+ }
+ }
+
+ @SideOnly(Side.CLIENT)
+ protected void updateChildren() {
+ updateChildren(false);
+ }
+
+ protected abstract void writeToPacket(PacketBuffer buffer, T data);
+
+ protected abstract T readFromPacket(PacketBuffer buffer) throws IOException;
+
+ @Override
+ public void markForUpdate() {
+ needsUpdate = true;
+ }
+
+ @Override
+ public void unMarkForUpdate() {
+ needsUpdate = false;
+ }
+
+ @Override
+ public boolean isMarkedForUpdate() {
+ return needsUpdate;
+ }
+
+ /**
+ * @param widget widget to add that implements {@link IDataFollowerWidget}
+ * @param dataToStateGetter given data -> state of the widget to add
+ * @param dataUpdater (current data, state of the widget to add) -> new data to set
+ * @param applyForWidget methods to call for the widget to add
+ * @param <U> state type stored in the widget to add
+ * @param <W> widget type to add
+ */
+ public <U, W extends Widget & IDataFollowerWidget<T, U>> DataControllerWidget<T> addFollower(W widget,
+ Function<T, U> dataToStateGetter, BiFunction<T, U, T> dataUpdater, Consumer<W> applyForWidget) {
+ widget.setDataToStateGetter(dataToStateGetter);
+ widget.setStateSetter(state -> {
+ T newData = dataUpdater.apply(getLastData(), state);
+ lastData = newData;
+ dataSetter.apply(getLastData());
+ syncDataToServer(newData);
+ });
+ applyForWidget.accept(widget);
+ addChild(widget);
+ return this;
+ }
+}
diff --git a/src/main/java/gregtech/common/gui/modularui/widget/FluidLockWidget.java b/src/main/java/gregtech/common/gui/modularui/widget/FluidLockWidget.java
new file mode 100644
index 0000000000..5627a4fb8b
--- /dev/null
+++ b/src/main/java/gregtech/common/gui/modularui/widget/FluidLockWidget.java
@@ -0,0 +1,17 @@
+package gregtech.common.gui.modularui.widget;
+
+import com.gtnewhorizons.modularui.common.widget.FluidNameHolderWidget;
+
+import gregtech.api.interfaces.metatileentity.IFluidLockable;
+
+public class FluidLockWidget extends FluidNameHolderWidget {
+
+ public FluidLockWidget(IFluidLockable fluidLockable) {
+ super(fluidLockable::getLockedFluidName, name -> {
+ if (fluidLockable.acceptsFluidLock(name)) {
+ fluidLockable.setLockedFluidName(name);
+ fluidLockable.lockFluid(name != null);
+ }
+ });
+ }
+}
diff --git a/src/main/java/gregtech/common/gui/modularui/widget/ItemWatcherSlotWidget.java b/src/main/java/gregtech/common/gui/modularui/widget/ItemWatcherSlotWidget.java
new file mode 100644
index 0000000000..5200c1a416
--- /dev/null
+++ b/src/main/java/gregtech/common/gui/modularui/widget/ItemWatcherSlotWidget.java
@@ -0,0 +1,50 @@
+package gregtech.common.gui.modularui.widget;
+
+import java.util.function.Supplier;
+
+import net.minecraft.item.ItemStack;
+
+import com.gtnewhorizons.modularui.api.forge.IItemHandlerModifiable;
+import com.gtnewhorizons.modularui.api.forge.ItemStackHandler;
+import com.gtnewhorizons.modularui.common.internal.wrapper.BaseSlot;
+import com.gtnewhorizons.modularui.common.widget.SlotWidget;
+
+import gregtech.api.util.GT_Utility;
+
+/**
+ * Watches specific ItemStack and pulls changes from it. Player cannot interact with slot, other than viewing NEI recipe
+ * or adding bookmark.
+ */
+public class ItemWatcherSlotWidget extends SlotWidget {
+
+ private ItemStack lastItem;
+ private Supplier<ItemStack> getter;
+
+ public ItemWatcherSlotWidget() {
+ super(BaseSlot.phantom(new ItemStackHandler(), 0));
+ disableInteraction();
+ }
+
+ public ItemWatcherSlotWidget setGetter(Supplier<ItemStack> getter) {
+ this.getter = getter;
+ return this;
+ }
+
+ @Override
+ public void detectAndSendChanges(boolean init) {
+ ItemStack target = getter.get();
+ if (init || !GT_Utility.areStacksEqual(lastItem, target)) {
+ ItemStack toPut;
+ if (target != null) {
+ toPut = target.copy();
+ toPut.stackSize = 1;
+ } else {
+ toPut = null;
+ }
+ ((IItemHandlerModifiable) getMcSlot().getItemHandler()).setStackInSlot(0, toPut);
+ lastItem = target;
+ getMcSlot().onSlotChanged();
+ }
+ super.detectAndSendChanges(init);
+ }
+}
diff --git a/src/main/java/gregtech/common/gui/modularui/widget/ShutDownReasonSyncer.java b/src/main/java/gregtech/common/gui/modularui/widget/ShutDownReasonSyncer.java
new file mode 100644
index 0000000000..21c19e524c
--- /dev/null
+++ b/src/main/java/gregtech/common/gui/modularui/widget/ShutDownReasonSyncer.java
@@ -0,0 +1,26 @@
+package gregtech.common.gui.modularui.widget;
+
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+import com.gtnewhorizons.modularui.common.internal.network.NetworkUtils;
+import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget;
+
+import gregtech.api.util.shutdown.ShutDownReason;
+import gregtech.api.util.shutdown.ShutDownReasonRegistry;
+
+public class ShutDownReasonSyncer extends FakeSyncWidget<ShutDownReason> {
+
+ public ShutDownReasonSyncer(Supplier<ShutDownReason> getter, Consumer<ShutDownReason> setter) {
+ super(getter, setter, (buffer, result) -> {
+ NetworkUtils.writeStringSafe(buffer, result.getID());
+ result.encode(buffer);
+ }, buffer -> {
+ String id = NetworkUtils.readStringSafe(buffer);
+ ShutDownReason result = ShutDownReasonRegistry.getSampleFromRegistry(id)
+ .newInstance();
+ result.decode(buffer);
+ return result;
+ });
+ }
+}
diff --git a/src/main/java/gregtech/common/items/CombType.java b/src/main/java/gregtech/common/items/CombType.java
new file mode 100644
index 0000000000..96850727fd
--- /dev/null
+++ b/src/main/java/gregtech/common/items/CombType.java
@@ -0,0 +1,284 @@
+package gregtech.common.items;
+
+import java.util.Arrays;
+
+import gregtech.api.enums.Materials;
+import gregtech.api.util.GT_LanguageManager;
+
+public enum CombType {
+
+ // Organic Line
+ LIGNIE(0, "lignite", true, Materials.Lignite, 100, 0x58300B, 0x906237, ItemComb.Voltage.LV),
+ COAL(1, "coal", true, Materials.Coal, 100, 0x525252, 0x666666, ItemComb.Voltage.LV),
+ STICKY(2, "stickyresin", true, Materials._NULL, 50, 0x2E8F5B, 0xDCC289, ItemComb.Voltage.LV),
+ OIL(3, "oil", true, Materials._NULL, 100, 0x333333, 0x4C4C4C, ItemComb.Voltage.LV),
+ APATITE(4, "apatite", true, Materials.Apatite, 100, 0xc1c1f6, 0x676784, ItemComb.Voltage.LV),
+ ASH(5, "ash", true, Materials.Ash, 100, 0x1e1a18, 0xc6c6c6, ItemComb.Voltage.LV),
+
+ // IC2 Line
+ COOLANT(6, "coolant", true, Materials._NULL, 100, 0x144F5A, 0x2494A2, ItemComb.Voltage.HV),
+ ENERGY(7, "energy", true, Materials._NULL, 80, 0xC11F1F, 0xEBB9B9, ItemComb.Voltage.HV),
+ LAPOTRON(8, "lapotron", true, Materials._NULL, 60, 0x1414FF, 0x6478FF, ItemComb.Voltage.HV),
+ PYROTHEUM(9, "pyrotheum", true, Materials.Pyrotheum, 50, 0xffebc4, 0xe36400, ItemComb.Voltage.HV),
+ CRYOTHEUM(10, "cryotheum", true, Materials.Cryotheum, 50, 0x2660ff, 0x5af7ff, ItemComb.Voltage.HV),
+
+ // Alloy Line
+ REDALLOY(11, "redalloy", true, Materials.RedAlloy, 100, 0xE60000, 0xB80000, ItemComb.Voltage.LV),
+ REDSTONEALLOY(12, "redstonealloy", true, Materials.RedstoneAlloy, 90, 0xB80000, 0xA50808, ItemComb.Voltage.LV),
+ CONDUCTIVEIRON(13, "conductiveiron", true, Materials.ConductiveIron, 80, 0x817671, 0xCEADA3, ItemComb.Voltage.MV),
+ VIBRANTALLOY(14, "vibrantalloy", true, Materials.VibrantAlloy, 50, 0x86A12D, 0xC4F2AE, ItemComb.Voltage.HV),
+ ENERGETICALLOY(15, "energeticalloy", true, Materials.EnergeticAlloy, 70, 0xFF9933, 0xFFAD5C, ItemComb.Voltage.HV),
+ ELECTRICALSTEEL(16, "electricalsteel", true, Materials.ElectricalSteel, 90, 0x787878, 0xD8D8D8,
+ ItemComb.Voltage.LV),
+ DARKSTEEL(17, "darksteel", true, Materials.DarkSteel, 80, 0x252525, 0x443B44, ItemComb.Voltage.MV),
+ PULSATINGIRON(18, "pulsatingiron", true, Materials.PulsatingIron, 80, 0x006600, 0x6DD284, ItemComb.Voltage.HV),
+ STAINLESSSTEEL(19, "stainlesssteel", true, Materials.StainlessSteel, 75, 0x778899, 0xC8C8DC, ItemComb.Voltage.HV),
+ ENDERIUM(20, "enderium", true, Materials.Enderium, 40, 0x2E8B57, 0x599087, ItemComb.Voltage.HV),
+
+ // Thaumcraft Line
+ THAUMIUMDUST(21, "thaumiumdust", true, Materials.Thaumium, 100, 0x7A007A, 0x5C005C, ItemComb.Voltage.MV),
+ THAUMIUMSHARD(22, "thaumiumshard", true, Materials._NULL, 85, 0x9966FF, 0xAD85FF, ItemComb.Voltage.LV),
+ AMBER(23, "amber", true, Materials.Amber, 90, 0x774B15, 0xEE7700, ItemComb.Voltage.LV),
+ QUICKSILVER(24, "quicksilver", true, Materials.Mercury, 90, 0xc7c7ea, 0xb5b3df, ItemComb.Voltage.LV),
+ SALISMUNDUS(25, "salismundus", true, Materials._NULL, 75, 0xF7ADDE, 0x592582, ItemComb.Voltage.MV),
+ TAINTED(26, "tainted", true, Materials._NULL, 80, 0x904BB8, 0xE800FF, ItemComb.Voltage.LV),
+ MITHRIL(27, "mithril", true, Materials.Mithril, 70, 0xF0E68C, 0xFFFFD2, ItemComb.Voltage.HV),
+ ASTRALSILVER(28, "astralsilver", true, Materials.AstralSilver, 70, 0xAFEEEE, 0xE6E6FF, ItemComb.Voltage.HV),
+ THAUMINITE(29, "thauminite", true, Materials._NULL, 50, 0x2E2D79, 0x7581E0, ItemComb.Voltage.HV),
+ SHADOWMETAL(30, "shadowmetal", true, Materials.Shadow, 50, 0x100322, 0x100342, ItemComb.Voltage.HV),
+ DIVIDED(31, "divided", true, Materials.Unstable, 40, 0xF0F0F0, 0xDCDCDC, ItemComb.Voltage.HV),
+ SPARKELING(32, "sparkling", true, Materials.NetherStar, 40, 0x7A007A, 0xFFFFFF, ItemComb.Voltage.EV),
+
+ // Gem Line
+ STONE(33, "stone", true, Materials._NULL, 70, 0x808080, 0x999999, ItemComb.Voltage.LV),
+ CERTUS(34, "certus", true, Materials.CertusQuartz, 100, 0x57CFFB, 0xBBEEFF, ItemComb.Voltage.LV),
+ FLUIX(35, "fluix", true, Materials.Fluix, 100, 0xA375FF, 0xB591FF, ItemComb.Voltage.LV),
+ REDSTONE(36, "redstone", true, Materials.Redstone, 100, 0x7D0F0F, 0xD11919, ItemComb.Voltage.LV),
+ RAREEARTH(37, "rareearth", true, Materials.RareEarth, 100, 0x555643, 0x343428, ItemComb.Voltage.LV),
+ LAPIS(38, "lapis", true, Materials.Lapis, 100, 0x1947D1, 0x476CDA, ItemComb.Voltage.LV),
+ RUBY(39, "ruby", true, Materials.Ruby, 100, 0xE6005C, 0xCC0052, ItemComb.Voltage.LV),
+ REDGARNET(40, "redgarnet", true, Materials.GarnetRed, 100, 0xBD4C4C, 0xECCECE, ItemComb.Voltage.LV),
+ YELLOWGARNET(41, "yellowgarnet", true, Materials.GarnetYellow, 100, 0xA3A341, 0xEDEDCE, ItemComb.Voltage.LV),
+ SAPPHIRE(42, "sapphire", true, Materials.Sapphire, 100, 0x0033CC, 0x00248F, ItemComb.Voltage.LV),
+ DIAMOND(43, "diamond", true, Materials.Diamond, 100, 0xCCFFFF, 0xA3CCCC, ItemComb.Voltage.LV),
+ OLIVINE(44, "olivine", true, Materials.Olivine, 100, 0x248F24, 0xCCFFCC, ItemComb.Voltage.LV),
+ EMERALD(45, "emerald", true, Materials.Emerald, 100, 0x248F24, 0x2EB82E, ItemComb.Voltage.LV),
+ PYROPE(46, "pyrope", true, Materials.Pyrope, 100, 0x763162, 0x8B8B8B, ItemComb.Voltage.LV),
+ GROSSULAR(47, "grossular", true, Materials.Grossular, 100, 0x9B4E00, 0x8B8B8B, ItemComb.Voltage.LV),
+ FIRESTONE(48, "firestone", true, Materials.Firestone, 100, 0xC00000, 0xFF0000, ItemComb.Voltage.LV),
+
+ // Metals Line
+ SLAG(49, "slag", true, Materials._NULL, 50, 0xD4D4D4, 0x58300B, ItemComb.Voltage.LV),
+ COPPER(50, "copper", true, Materials.Copper, 100, 0xFF6600, 0xE65C00, ItemComb.Voltage.LV),
+ TIN(51, "tin", true, Materials.Tin, 100, 0xD4D4D4, 0xDDDDDD, ItemComb.Voltage.LV),
+ LEAD(52, "lead", true, Materials.Lead, 100, 0x666699, 0xA3A3CC, ItemComb.Voltage.LV),
+ IRON(53, "iron", true, Materials.Iron, 100, 0xDA9147, 0xDE9C59, ItemComb.Voltage.LV),
+ STEEL(54, "steel", true, Materials.Steel, 95, 0x808080, 0x999999, ItemComb.Voltage.LV),
+ NICKEL(55, "nickel", true, Materials.Nickel, 100, 0x8585AD, 0x9D9DBD, ItemComb.Voltage.LV),
+ ZINC(56, "zinc", true, Materials.Zinc, 100, 0xF0DEF0, 0xF2E1F2, ItemComb.Voltage.LV),
+ SILVER(57, "silver", true, Materials.Silver, 100, 0xC2C2D6, 0xCECEDE, ItemComb.Voltage.LV),
+ GOLD(58, "gold", true, Materials.Gold, 100, 0xE6B800, 0xCFA600, ItemComb.Voltage.LV),
+ SULFUR(59, "sulfur", true, Materials.Sulfur, 100, 0x6F6F01, 0x8B8B8B, ItemComb.Voltage.LV),
+ GALLIUM(60, "gallium", true, Materials.Gallium, 75, 0x8B8B8B, 0xC5C5E4, ItemComb.Voltage.LV),
+ ARSENIC(61, "arsenic", true, Materials.Arsenic, 75, 0x736C52, 0x292412, ItemComb.Voltage.LV),
+
+ // Rare Metals Line
+ BAUXITE(62, "bauxite", true, Materials.Bauxite, 85, 0x6B3600, 0x8B8B8B, ItemComb.Voltage.LV),
+ ALUMINIUM(63, "aluminium", true, Materials.Aluminium, 60, 0x008AB8, 0xD6D6FF, ItemComb.Voltage.LV),
+ MANGANESE(64, "manganese", true, Materials.Manganese, 30, 0xD5D5D5, 0xAAAAAA, ItemComb.Voltage.LV),
+ MAGNESIUM(65, "magnesium", true, Materials.Magnesium, 75, 0xF1D9D9, 0x8B8B8B, ItemComb.Voltage.LV),
+ TITANIUM(66, "titanium", true, Materials.Ilmenite, 100, 0xCC99FF, 0xDBB8FF, ItemComb.Voltage.IV),
+ CHROME(67, "chromium", true, Materials.Chrome, 50, 0xEBA1EB, 0xF2C3F2, ItemComb.Voltage.HV),
+ TUNGSTEN(68, "tungsten", true, Materials.Tungstate, 100, 0x62626D, 0x161620, ItemComb.Voltage.IV),
+ PLATINUM(69, "platinum", true, Materials.Platinum, 40, 0xE6E6E6, 0xFFFFCC, ItemComb.Voltage.HV),
+ IRIDIUM(70, "iridium", true, Materials.Iridium, 20, 0xDADADA, 0xD1D1E0, ItemComb.Voltage.IV),
+ MOLYBDENUM(71, "molybdenum", true, Materials.Molybdenum, 20, 0xAEAED4, 0x8B8B8B, ItemComb.Voltage.LV),
+ OSMIUM(72, "osmium", true, Materials.Osmium, 15, 0x2B2BDA, 0x8B8B8B, ItemComb.Voltage.IV),
+ LITHIUM(73, "lithium", true, Materials.Lithium, 75, 0xF0328C, 0xE1DCFF, ItemComb.Voltage.MV),
+ SALT(74, "salt", true, Materials.Salt, 90, 0xF0C8C8, 0xFAFAFA, ItemComb.Voltage.MV),
+ ELECTROTINE(75, "electrotine", true, Materials.Electrotine, 75, 0x1E90FF, 0x3CB4C8, ItemComb.Voltage.HV),
+ ALMANDINE(76, "almandine", true, Materials.Almandine, 85, 0xC60000, 0x8B8B8B, ItemComb.Voltage.LV),
+
+ // Radioactive Line
+ URANIUM(77, "uranium", true, Materials.Uranium, 50, 0x19AF19, 0x169E16, ItemComb.Voltage.IV),
+ PLUTONIUM(78, "plutonium", true, Materials.Plutonium, 10, 0x240000, 0x570000, ItemComb.Voltage.IV),
+ NAQUADAH(79, "naquadah", true, Materials.Naquadah, 10, 0x000000, 0x004400, ItemComb.Voltage.IV),
+ NAQUADRIA(80, "naquadria", true, Materials.Naquadria, 5, 0x000000, 0x002400, ItemComb.Voltage.IV),
+ DOB(81, "d-o-b", true, Materials._NULL, 50, 0x007700, 0x002400, ItemComb.Voltage.LV),
+ THORIUM(82, "thorium", true, Materials.Thorium, 75, 0x001E00, 0x005000, ItemComb.Voltage.EV),
+ LUTETIUM(83, "lutetium", true, Materials.Lutetium, 10, 0xE6FFE6, 0xFFFFFF, ItemComb.Voltage.IV),
+ AMERICIUM(84, "americium", true, Materials.Americium, 5, 0xE6E6FF, 0xC8C8C8, ItemComb.Voltage.LuV),
+ NEUTRONIUM(85, "neutronium", true, Materials.Neutronium, 2, 0xFFF0F0, 0xFAFAFA, ItemComb.Voltage.ZPM),
+
+ // Twilight
+ NAGA(86, "naga", true, Materials._NULL, 100, 0x0D5A0D, 0x28874B, ItemComb.Voltage.MV),
+ LICH(87, "lich", true, Materials._NULL, 90, 0x5C605E, 0xC5C5C5, ItemComb.Voltage.HV),
+ HYDRA(88, "hydra", true, Materials._NULL, 80, 0x872836, 0xB8132C, ItemComb.Voltage.HV),
+ URGHAST(89, "urghast", true, Materials._NULL, 70, 0x7C0618, 0xA7041C, ItemComb.Voltage.EV),
+ SNOWQUEEN(90, "snowqueen", true, Materials._NULL, 60, 0x9C0018, 0xD02001, ItemComb.Voltage.EV),
+
+ // Space
+ SPACE(91, "space", true, Materials._NULL, 100, 0x003366, 0xC0C0C0, ItemComb.Voltage.HV),
+ METEORICIRON(92, "meteoriciron", true, Materials.MeteoricIron, 100, 0x321928, 0x643250, ItemComb.Voltage.EV),
+ DESH(93, "desh", true, Materials.Desh, 90, 0x282828, 0x323232, ItemComb.Voltage.IV),
+ LEDOX(94, "ledox", true, Materials.Ledox, 75, 0x0000CD, 0x0074FF, ItemComb.Voltage.IV),
+ CALLISTOICE(95, "callistoice", true, Materials.CallistoIce, 75, 0x0074FF, 0x1EB1FF, ItemComb.Voltage.IV),
+ MYTRYL(96, "mytryl", true, Materials.Mytryl, 65, 0xDAA520, 0xF26404, ItemComb.Voltage.IV),
+ QUANTIUM(97, "quantium", true, Materials.Quantium, 50, 0x00FF00, 0x00D10B, ItemComb.Voltage.IV),
+ ORIHARUKON(98, "oriharukon", true, Materials.Oriharukon, 50, 0x228B22, 0x677D68, ItemComb.Voltage.IV),
+ MYSTERIOUSCRYSTAL(99, "mysteriouscrystal", true, Materials.MysteriousCrystal, 45, 0x3CB371, 0x16856C,
+ ItemComb.Voltage.LuV),
+ BLACKPLUTONIUM(100, "blackplutonium", true, Materials.Quantium, 25, 0x000000, 0x323232, ItemComb.Voltage.LuV),
+ TRINIUM(101, "trinium", true, Materials.Trinium, 25, 0xB0E0E6, 0xC8C8D2, ItemComb.Voltage.ZPM),
+
+ // Planet
+ MERCURY(102, "mercury", true, Materials._NULL, 65, 0x4A4033, 0xB5A288, ItemComb.Voltage.EV),
+ VENUS(103, "venus", true, Materials._NULL, 65, 0x120E07, 0x272010, ItemComb.Voltage.EV),
+ MOON(104, "moon", true, Materials._NULL, 90, 0x373735, 0x7E7E78, ItemComb.Voltage.MV),
+ MARS(105, "mars", true, Materials._NULL, 80, 0x220D05, 0x3A1505, ItemComb.Voltage.MV),
+ JUPITER(106, "jupiter", true, Materials._NULL, 75, 0x734B2E, 0xD0CBC4, ItemComb.Voltage.MV),
+ SATURN(107, "saturn", true, Materials._NULL, 55, 0xD2A472, 0xF8C37B, ItemComb.Voltage.IV),
+ URANUS(108, "uranus", true, Materials._NULL, 45, 0x75C0C9, 0x84D8EC, ItemComb.Voltage.IV),
+ NEPTUN(109, "neptun", true, Materials._NULL, 35, 0x334CFF, 0x576DFF, ItemComb.Voltage.IV),
+ PLUTO(110, "pluto", true, Materials._NULL, 25, 0x34271E, 0x69503D, ItemComb.Voltage.LuV),
+ HAUMEA(111, "haumea", true, Materials._NULL, 20, 0x1C1413, 0x392B28, ItemComb.Voltage.LuV),
+ MAKEMAKE(112, "makemake", true, Materials._NULL, 20, 0x301811, 0x120A07, ItemComb.Voltage.LuV),
+ CENTAURI(113, "centauri", true, Materials._NULL, 15, 0x2F2A14, 0xB06B32, ItemComb.Voltage.ZPM),
+ TCETI(114, "tceti", true, Materials._NULL, 10, 0x46241A, 0x7B412F, ItemComb.Voltage.ZPM),
+ BARNARDA(115, "barnarda", true, Materials._NULL, 10, 0x0D5A0D, 0xE6C18D, ItemComb.Voltage.ZPM),
+ VEGA(116, "vega", true, Materials._NULL, 10, 0x1A2036, 0xB5C0DE, ItemComb.Voltage.ZPM),
+
+ // Infinity
+ COSMICNEUTRONIUM(117, "cosmicneutronium", true, Materials.CosmicNeutronium, 5, 0x484848, 0x323232,
+ ItemComb.Voltage.UV),
+ INFINITYCATALYST(118, "infinitycatalyst", true, Materials.InfinityCatalyst, 2, 0xFFFFFF, 0xFFFFFF,
+ ItemComb.Voltage.UHV),
+ INFINITY(119, "infinity", true, Materials.Infinity, 1, 0xFFFFFF, 0xFFFFFF, ItemComb.Voltage.UEV),
+
+ // HEE
+ ENDDUST(120, "enddust", true, Materials._NULL, 50, 0x003A7D, 0xCC00FA, ItemComb.Voltage.HV),
+ ECTOPLASMA(121, "ectoplasma", true, Materials._NULL, 35, 0x381C40, 0xDCB0E5, ItemComb.Voltage.EV),
+ ARCANESHARD(122, "arcaneshard", true, Materials._NULL, 35, 0x333D82, 0x9010AD, ItemComb.Voltage.EV),
+ STARDUST(123, "stardust", true, Materials._NULL, 60, 0xDCBE13, 0xffff00, ItemComb.Voltage.HV),
+ DRAGONESSENCE(124, "dragonessence", true, Materials._NULL, 30, 0x911ECE, 0xFFA12B, ItemComb.Voltage.IV),
+ ENDERMAN(125, "enderman", true, Materials._NULL, 25, 0x6200e7, 0x161616, ItemComb.Voltage.IV),
+ SILVERFISH(126, "silverfish", true, Materials._NULL, 25, 0x0000000, 0xEE053D, ItemComb.Voltage.EV),
+ ENDIUM(127, "endium", true, Materials.HeeEndium, 50, 0x2F5A6C, 0xa0ffff, ItemComb.Voltage.HV),
+ RUNEI(128, "rune1", true, Materials._NULL, 10, 0x0104D9, 0xE31010, ItemComb.Voltage.IV),
+ RUNEII(129, "rune2", true, Materials._NULL, 10, 0xE31010, 0x0104D9, ItemComb.Voltage.IV),
+ FIREESSENSE(130, "fireessence", true, Materials._NULL, 30, 0xFFA157, 0xD41238, ItemComb.Voltage.IV),
+ CRYOLITE(131, "cryolite", true, Materials.Cryolite, 90, 0xBFEFFF, 0x73B9D0, ItemComb.Voltage.LV),
+ // (NOBLE) GAS LINE
+ HELIUM(132, "helium", true, Materials.Helium, 90, 0xFFA9FF, 0xFFFFC3, ItemComb.Voltage.HV),
+ ARGON(133, "argon", true, Materials.Argon, 95, 0x89D9E1, 0x160822, ItemComb.Voltage.MV),
+ // XENON, NEON and KRYPTON Fluid extractor Recipes are located in GT_MachineRecipeLoader.java
+ XENON(134, "xenon", true, Materials._NULL, 85, 0x160822, 0x8A97B0, ItemComb.Voltage.IV),
+ NEON(135, "neon", true, Materials._NULL, 90, 0xFF7200, 0xFFC826, ItemComb.Voltage.IV),
+ KRYPTON(136, "krypton", true, Materials._NULL, 85, 0x160822, 0x8A97B0, ItemComb.Voltage.IV),
+ NITROGEN(137, "nitrogen", true, Materials.Nitrogen, 100, 0xA52A2A, 0xFFC832, ItemComb.Voltage.MV),
+ OXYGEN(138, "oxygen", true, Materials.Oxygen, 100, 0x8F8FFF, 0xFFFFFF, ItemComb.Voltage.MV),
+ HYDROGEN(139, "hydrogen", true, Materials.Hydrogen, 100, 0xFF1493, 0xFFFFFF, ItemComb.Voltage.MV),
+ // Those are supposed to be in the organic branch, but that would require shifting all comb IDs and we don't want to
+ // risk it.
+ PHOSPHORUS(140, "phosphorus", true, Materials.Phosphorus, 100, 0xC1C1F6, 0xFFC826, ItemComb.Voltage.HV),
+ MICA(141, "mica", true, Materials.Mica, 100, 0x8A97B0, 0x2F3641, ItemComb.Voltage.HV),
+ // Seaweed is located in the planet line
+ SEAWEED(142, "seaweed", true, Materials._NULL, 90, 0x83FF83, 0xCBCBCB, ItemComb.Voltage.UV),
+ // just Walrus
+ WALRUS(143, "walrus", true, Materials._NULL, 100, 0xB5CFC9, 0xD6D580, ItemComb.Voltage.LV),
+ // TC infused Air shards line. Recipes in GT_MachineRecipeLoader.java Lines 1500+ + Nether/Endshard
+ INFUSEDAER(144, "infusedair", true, Materials._NULL, 100, 0x60602F, 0xFFFF7E, ItemComb.Voltage.LV),
+ INFUSEDTERRA(145, "infusedterra", true, Materials._NULL, 100, 0x003300, 0x008600, ItemComb.Voltage.LV),
+ INFUSEDIGNIS(146, "infusedignis", true, Materials._NULL, 100, 0x3B0E00, 0xED3801, ItemComb.Voltage.LV),
+ INFUSEDAQUA(147, "infusedaqua", true, Materials._NULL, 100, 0x002542, 0x0090FF, ItemComb.Voltage.LV),
+ INFUSEDORDO(148, "infusedordo", true, Materials._NULL, 100, 0x5C5F62, 0x8A97B0, ItemComb.Voltage.LV),
+ INFUSEDPERDITIO(149, "infusedperditio", true, Materials._NULL, 100, 0x232129, 0x2E2E41, ItemComb.Voltage.LV),
+ FLUORINE(150, "fluorine", true, Materials.Fluorine, 100, 0xFF6D00, 0x86AFF0, ItemComb.Voltage.MV),
+ BEDROCKIUM(151, "bedrockium", true, Materials.Bedrockium, 100, 0xC6C6C6, 0x0C0C0C, ItemComb.Voltage.EV),
+ NETHERSHARD(152, "nethershard", true, Materials.Netherrack, 100, 0x350211, 0xBE0135, ItemComb.Voltage.HV),
+ ENDSHARD(153, "endshard", true, Materials.EnderEye, 100, 0x232129, 0x2E2E41, ItemComb.Voltage.HV),
+ CAELESTISRED(154, "caelestisred", true, Materials._NULL, 100, 0xFF0000, 0xFF00FF, ItemComb.Voltage.LV),
+ CAELESTISGREEN(155, "caelestisgreen", true, Materials._NULL, 100, 0x00FF00, 0xB233FF, ItemComb.Voltage.LV),
+ CAELESTISBLUE(156, "caelestisblue", true, Materials._NULL, 100, 0x0000FF, 0xFF99A5, ItemComb.Voltage.LV),
+ UNKNOWNWATER(157, "unknownwater", true, Materials._NULL, 100, 0x36ABFF, 0x4333A5, ItemComb.Voltage.ZPM),
+ // ESSENTIA gets a use soon. Dont remove.
+ ESSENTIA(158, "essentia", true, Materials._NULL, 100, 0xED3601, 0xFF6D50, ItemComb.Voltage.MV),
+ INDIUM(159, "indium", true, Materials.Indium, 100, 0x8F5D99, 0xFFA9FF, ItemComb.Voltage.ZPM),
+ BLIZZ(160, "blizz", true, Materials.Blizz, 50, 0xFF99A5, 0x5af7ff, ItemComb.Voltage.MV),
+ KEVLAR(161, "kevlar", true, Materials._NULL, 50, 0xa2baa3, 0x2d542f, ItemComb.Voltage.MV),
+ DRACONIC(162, "draconium", true, Materials.Draconium, 50, 0x161616, 0x6200e7, ItemComb.Voltage.MV),
+ AWAKENEDDRACONIUM(163, "awakeneddraconium", true, Materials.DraconiumAwakened, 50, 0xD41238, 0xFFA157,
+ ItemComb.Voltage.MV),
+ PALLADIUM(164, "palladium", true, Materials.Palladium, 50, 0x8B8B8B, 0xF1D9D9, ItemComb.Voltage.MV),
+ INFUSEDGOLD(165, "infusedgold", true, Materials.InfusedGold, 50, 0x80641E, 0xFFC83C, ItemComb.Voltage.IV),
+
+ // ALWAYS KEEP _NULL AT THE BOTTOM
+ _NULL(-1, "INVALIDCOMB", false, Materials._NULL, 0, 0, 0);
+
+ public boolean showInList;
+ public final ItemComb.Voltage voltage;
+ public final Materials material;
+ public final int chance;
+
+ private final int id;
+ private final String localizedName;
+ private final int[] color;
+
+ CombType(int id, String pName, boolean show, Materials material, int chance, int color1, int color2) {
+ this(id, pName, show, material, chance, color1, color2, null);
+ }
+
+ CombType(int id, String pName, boolean show, Materials material, int chance, int color1, int color2,
+ ItemComb.Voltage voltage) {
+ if (id < 0 && !"INVALIDCOMB".equals(pName)) throw new IllegalArgumentException();
+ this.id = id;
+ this.voltage = voltage;
+ this.material = material;
+ this.chance = chance;
+ this.showInList = show;
+ this.color = new int[] { color1, color2 };
+ this.localizedName = GT_LanguageManager.addStringLocalization(
+ "comb." + pName,
+ pName.substring(0, 1)
+ .toUpperCase() + pName.substring(1)
+ + " Comb");
+ }
+
+ public void setHidden() {
+ this.showInList = false;
+ }
+
+ public String getName() {
+
+ return this.localizedName;
+ }
+
+ public int[] getColours() {
+ return color == null || color.length != 2 ? new int[] { 0, 0 } : color;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public static CombType valueOf(int id) {
+ return id < 0 || id >= Companion.VALUES.length ? _NULL : Companion.VALUES[id];
+ }
+
+ private static final class Companion {
+
+ private static final CombType[] VALUES;
+
+ static {
+ int biggestId = Arrays.stream(CombType.values())
+ .mapToInt(CombType::getId)
+ .max()
+ .getAsInt();
+ VALUES = new CombType[biggestId + 1];
+ Arrays.fill(VALUES, _NULL);
+ for (CombType type : CombType.values()) {
+ if (type != _NULL) VALUES[type.getId()] = type;
+ }
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/items/DropType.java b/src/main/java/gregtech/common/items/DropType.java
new file mode 100644
index 0000000000..64d42b2eeb
--- /dev/null
+++ b/src/main/java/gregtech/common/items/DropType.java
@@ -0,0 +1,46 @@
+package gregtech.common.items;
+
+import gregtech.api.enums.Materials;
+import gregtech.api.util.GT_LanguageManager;
+
+public enum DropType {
+
+ OIL("oil", true),
+ MUTAGEN("small mutagen catalyst", true),
+ COOLANT("coolant", true),
+ HOT_COOLANT("hot coolant", true),
+ HYDRA("hydra blood", true),
+ SNOW_QUEEN("snowqueen blood", true),
+ OXYGEN("oxygen", true),
+ LAPIS("lapis coolant", true),
+ ENDERGOO("ender goo", true);
+
+ private static final int[][] colours = new int[][] { { 0x19191B, 0x303032 }, { 0xffc100, 0x00ff11 },
+ { 0x144F5A, 0x2494A2 }, { 0xC11F1F, 0xEBB9B9 }, { 0x872836, 0xB8132C }, { 0xD02001, 0x9C0018 },
+ { 0x003366, 0x0066BB }, { 0x1727b1, 0x008ce3 }, { 0xA005E7, 0x161616 }, };
+ public boolean showInList;
+ public Materials material;
+ public int chance;
+ private final String name;
+
+ DropType(String pName, boolean show) {
+ this.name = pName;
+ this.showInList = show;
+ }
+
+ public void setHidden() {
+ this.showInList = false;
+ }
+
+ public String getName() {
+
+ return GT_LanguageManager.addStringLocalization(
+ "drop." + this.name,
+ this.name.substring(0, 1)
+ .toUpperCase() + this.name.substring(1) + " Drop");
+ }
+
+ public int[] getColours() {
+ return colours[this.ordinal()];
+ }
+}
diff --git a/src/main/java/gregtech/common/items/GT_AdvancedSensorCard_Item.java b/src/main/java/gregtech/common/items/GT_AdvancedSensorCard_Item.java
new file mode 100644
index 0000000000..ae64bea432
--- /dev/null
+++ b/src/main/java/gregtech/common/items/GT_AdvancedSensorCard_Item.java
@@ -0,0 +1,327 @@
+package gregtech.common.items;
+
+import static gregtech.api.enums.Mods.GregTech;
+import static gregtech.common.covers.GT_Cover_Metrics_Transmitter.CARD_STATE_KEY;
+import static gregtech.common.covers.GT_Cover_Metrics_Transmitter.FREQUENCY_LSB_KEY;
+import static gregtech.common.covers.GT_Cover_Metrics_Transmitter.FREQUENCY_MSB_KEY;
+import static gregtech.common.covers.GT_Cover_Metrics_Transmitter.MACHINE_KEY;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
+import java.util.function.Predicate;
+import java.util.stream.IntStream;
+
+import net.minecraft.client.renderer.texture.IIconRegister;
+import net.minecraft.creativetab.CreativeTabs;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IIcon;
+import net.minecraft.util.StatCollector;
+import net.minecraft.world.World;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.google.common.collect.ImmutableList;
+
+import cpw.mods.fml.common.registry.GameRegistry;
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.common.misc.GlobalMetricsCoverDatabase;
+import gregtech.common.misc.GlobalMetricsCoverDatabase.State;
+import shedar.mods.ic2.nuclearcontrol.api.CardState;
+import shedar.mods.ic2.nuclearcontrol.api.ICardWrapper;
+import shedar.mods.ic2.nuclearcontrol.api.IPanelDataSource;
+import shedar.mods.ic2.nuclearcontrol.api.PanelSetting;
+import shedar.mods.ic2.nuclearcontrol.api.PanelString;
+
+@SuppressWarnings("unused")
+public class GT_AdvancedSensorCard_Item extends Item implements IPanelDataSource {
+
+ public static final UUID CARD_TYPE_ID = UUID.fromString("ff952e84-7608-4c4a-85af-dd6e1aa27fc7");
+
+ // This has obfuscated formatting, so no need to localize it.
+ private static final String SELF_DESTRUCTED_OUTPUT = EnumChatFormatting.OBFUSCATED + "critical error"
+ + EnumChatFormatting.RESET;
+
+ private static final ImmutableList<String> DECONSTRUCTED_OUTPUT = ImmutableList.of(
+ StatCollector.translateToLocal("gt.item.adv_sensor_card.error.deconstructed.1"),
+ StatCollector.translateToLocal("gt.item.adv_sensor_card.error.deconstructed.2"));
+
+ private static final String NO_DATA_FOUND = StatCollector.translateToLocal("gt.item.adv_sensor_card.error.no_data");
+
+ private static final String MACHINE_NAME_KEY = "client_machine_name";
+ private static final String OUTPUT_ENTRY_KEY = "client_entry_%d";
+ private static final String OUTPUT_ENTRY_LENGTH_KEY = "client_entry_length";
+
+ private int payloadSize = 0;
+
+ @SideOnly(Side.CLIENT)
+ private IIcon normalIcon;
+ @SideOnly(Side.CLIENT)
+ private IIcon selfDestructedIcon;
+
+ @SuppressWarnings("unused")
+ public GT_AdvancedSensorCard_Item() {
+ super();
+
+ GameRegistry.registerItem(this, "gt.advancedsensorcard", GregTech.ID);
+ setUnlocalizedName("gt.advancedsensorcard");
+ setMaxStackSize(1);
+ setNoRepair();
+ }
+
+ @Override
+ public void addInformation(final ItemStack itemStack, final EntityPlayer player, final List<String> tooltip,
+ final boolean p_77624_4_) {
+ super.addInformation(itemStack, player, tooltip, p_77624_4_);
+
+ final Optional<State> cardState = getCardState(itemStack);
+ if (cardState.isPresent()) {
+ final State state = cardState.get();
+
+ if (state == State.SELF_DESTRUCTED) {
+ tooltip.add(StatCollector.translateToLocal("gt.item.adv_sensor_card.tooltip.fried.1"));
+ tooltip.add(StatCollector.translateToLocal("gt.item.adv_sensor_card.tooltip.fried.2"));
+ tooltip.add(StatCollector.translateToLocal("gt.item.adv_sensor_card.tooltip.fried.3"));
+ } else {
+ getMachineName(itemStack).ifPresent(
+ machineName -> tooltip.add(
+ StatCollector
+ .translateToLocalFormatted("gt.item.adv_sensor_card.tooltip.machine", machineName)));
+ getUUID(itemStack).ifPresent(
+ uuid -> tooltip.add(
+ StatCollector
+ .translateToLocalFormatted("gt.item.adv_sensor_card.tooltip.frequency", uuid.toString())));
+ }
+ } else {
+ tooltip.add(StatCollector.translateToLocal("gt.item.adv_sensor_card.tooltip.recipe_hint"));
+ }
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void getSubItems(Item aItem, CreativeTabs aCreativeTab, List<ItemStack> aOutputSubItems) {}
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void registerIcons(final IIconRegister aIconRegister) {
+ super.registerIcons(aIconRegister);
+ itemIcon = aIconRegister.registerIcon(GregTech.ID + ":gt.advancedsensorcard");
+ normalIcon = itemIcon;
+ selfDestructedIcon = aIconRegister.registerIcon(GregTech.ID + ":gt.advancedsensorcardburned");
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public IIcon getIcon(final ItemStack stack, final int renderPass) {
+ return getIconIndex(stack);
+ }
+
+ @Override
+ public IIcon getIconIndex(final ItemStack itemStack) {
+ return getCardState(itemStack).filter(Predicate.isEqual(State.SELF_DESTRUCTED))
+ .map(ignored -> selfDestructedIcon)
+ .orElse(normalIcon);
+ }
+
+ @Override
+ public CardState update(TileEntity tileEntity, ICardWrapper card, int maxRange) {
+ return update(tileEntity.getWorldObj(), card, maxRange);
+ }
+
+ @Override
+ public CardState update(World world, ICardWrapper card, int maxRange) {
+ final Optional<GlobalMetricsCoverDatabase.Data> optionalData = getDataFromDatabase(card);
+
+ optionalData.ifPresent(data -> {
+ final State machineState = data.getState();
+ reconcileSelfDestructedCard(card.getItemStack(), machineState);
+ card.setInt(CARD_STATE_KEY, machineState.getType());
+
+ getMachineName(card.getItemStack())
+ .ifPresent(name -> card.setString(MACHINE_NAME_KEY, machineState == State.SELF_DESTRUCTED ? "" : name));
+
+ final ImmutableList.Builder<String> builder = ImmutableList.builder();
+ switch (machineState) {
+ case SELF_DESTRUCTED -> builder.add(SELF_DESTRUCTED_OUTPUT);
+ case HOST_DECONSTRUCTED -> builder.addAll(DECONSTRUCTED_OUTPUT);
+ case OPERATIONAL -> {
+ data.getCoordinates()
+ .ifPresent(
+ coordinates -> builder.add(
+ StatCollector.translateToLocalFormatted(
+ "gt.item.adv_sensor_card.dimension",
+ coordinates.getDimension()),
+ StatCollector.translateToLocalFormatted(
+ "gt.item.adv_sensor_card.coords",
+ coordinates.getLocalizedCoordinates())));
+
+ data.getPayload()
+ .ifPresent(builder::addAll);
+ }
+ default -> builder.add(NO_DATA_FOUND);
+ }
+
+ final List<String> payload = builder.build();
+ card.setInt(OUTPUT_ENTRY_LENGTH_KEY, payload.size());
+ for (int i = 0; i < payload.size(); i++) {
+ card.setString(String.format(OUTPUT_ENTRY_KEY, i), payload.get(i));
+ }
+ });
+
+ return CardState.OK;
+ }
+
+ @Override
+ public List<PanelString> getStringData(final int displaySettings, final ICardWrapper card,
+ final boolean showLabels) {
+ final List<PanelString> returned = new ArrayList<>();
+ final String machineName = card.getString(MACHINE_NAME_KEY);
+ final int bitmaskOffset;
+
+ payloadSize = card.getInt(OUTPUT_ENTRY_LENGTH_KEY);
+
+ if (!machineName.isEmpty() && (displaySettings & 1) != 0) {
+ returned.add(panelString(machineName, true));
+ payloadSize += 1;
+ bitmaskOffset = 1;
+ } else {
+ bitmaskOffset = 0;
+ }
+
+ // Not reusing payloadSize here because it can be conditionally mutated.
+ IntStream.range(0, card.getInt(OUTPUT_ENTRY_LENGTH_KEY))
+ .forEach(i -> {
+ if ((displaySettings & 1 << (i + bitmaskOffset)) != 0) {
+ returned.add(panelString(card.getString(String.format(OUTPUT_ENTRY_KEY, i))));
+ }
+ });
+
+ return returned;
+ }
+
+ @Override
+ public List<PanelSetting> getSettingsList() {
+ return payloadSize == 0 ? ImmutableList.of()
+ : ImmutableList.copyOf(
+ IntStream.range(0, Math.min(payloadSize, 31))
+ .mapToObj(i -> new PanelSetting(String.valueOf(i + 1), 1 << i, getCardType()))
+ .iterator());
+ }
+
+ @Override
+ public UUID getCardType() {
+ return CARD_TYPE_ID;
+ }
+
+ @Override
+ public void onUpdate(ItemStack stack, World worldIn, Entity entityIn, int slot, boolean isHeld) {
+ super.onUpdate(stack, worldIn, entityIn, slot, isHeld);
+ // At the time of this comment's writing, there are 52 matches of the regex:
+ // /% \d+0 \)?\s*== 0/ in the code base, indicating an over-reliance on events happening on either the 10th or
+ // 20th tick. Let's tick on something slightly off of that. A prime number will do nicely.
+ if ((worldIn.getWorldTime() % 20) == 13) {
+ getDataFromDatabase(stack).ifPresent(data -> {
+ reconcileSelfDestructedCard(stack, data.getState());
+ if (!stack.hasTagCompound()) {
+ stack.setTagCompound(new NBTTagCompound());
+ }
+
+ stack.getTagCompound()
+ .setInteger(
+ CARD_STATE_KEY,
+ data.getState()
+ .getType());
+ });
+ }
+ }
+
+ private void reconcileSelfDestructedCard(ItemStack stack, State newState) {
+ getUUID(stack).ifPresent(uuid -> getCardState(stack).ifPresent(oldState -> {
+ if (newState == State.SELF_DESTRUCTED && oldState != State.SELF_DESTRUCTED) {
+ GlobalMetricsCoverDatabase.clearSelfDestructedFrequency(uuid);
+ }
+ }));
+
+ }
+
+ @NotNull
+ private Optional<State> getCardState(ICardWrapper card) {
+ return getCardState(card.getItemStack());
+ }
+
+ @NotNull
+ private Optional<State> getCardState(ItemStack itemStack) {
+ if (itemStack.hasTagCompound() && itemStack.getTagCompound()
+ .hasKey(CARD_STATE_KEY)) {
+ return State.find(
+ itemStack.getTagCompound()
+ .getInteger(CARD_STATE_KEY));
+ }
+
+ return Optional.empty();
+ }
+
+ @NotNull
+ private Optional<UUID> getUUID(ItemStack stack) {
+ if (stack.hasTagCompound()) {
+ NBTTagCompound nbt = stack.getTagCompound();
+ if (nbt.hasKey(FREQUENCY_LSB_KEY) && nbt.hasKey(FREQUENCY_MSB_KEY)) {
+ return Optional.of(new UUID(nbt.getLong(FREQUENCY_MSB_KEY), nbt.getLong(FREQUENCY_LSB_KEY)));
+ }
+ }
+
+ return Optional.empty();
+ }
+
+ @NotNull
+ private Optional<String> getMachineName(ItemStack stack) {
+ if (stack.hasTagCompound() && stack.getTagCompound()
+ .hasKey(MACHINE_KEY)) {
+ try {
+ final ItemStack machine = ItemStack.loadItemStackFromNBT(
+ stack.getTagCompound()
+ .getCompoundTag(MACHINE_KEY));
+ if (machine != null) {
+ return Optional.of(machine.getDisplayName());
+ }
+ } catch (Exception ignored) {}
+ }
+
+ return Optional.empty();
+ }
+
+ @NotNull
+ private Optional<GlobalMetricsCoverDatabase.Data> getDataFromDatabase(ICardWrapper card) {
+ return getDataFromDatabase(card.getItemStack());
+ }
+
+ @NotNull
+ private Optional<GlobalMetricsCoverDatabase.Data> getDataFromDatabase(ItemStack stack) {
+ return getUUID(stack).flatMap(GlobalMetricsCoverDatabase::getData);
+ }
+
+ @NotNull
+ private static PanelString panelString(String info) {
+ return panelString(info, false);
+ }
+
+ @NotNull
+ private static PanelString panelString(String info, boolean center) {
+ final PanelString panelString = new PanelString();
+ if (center) {
+ panelString.textCenter = info;
+ } else {
+ panelString.textLeft = info;
+ }
+ return panelString;
+
+ }
+}
diff --git a/src/main/java/gregtech/common/items/GT_DepletetCell_Item.java b/src/main/java/gregtech/common/items/GT_DepletetCell_Item.java
new file mode 100644
index 0000000000..df14adc39b
--- /dev/null
+++ b/src/main/java/gregtech/common/items/GT_DepletetCell_Item.java
@@ -0,0 +1,49 @@
+package gregtech.common.items;
+
+import net.minecraft.item.ItemStack;
+
+import gregtech.api.items.GT_RadioactiveCellIC_Item;
+import ic2.api.reactor.IReactor;
+
+public class GT_DepletetCell_Item extends GT_RadioactiveCellIC_Item {
+
+ public GT_DepletetCell_Item(String aUnlocalized, String aEnglish, int aRadiation) {
+ super(aUnlocalized, aEnglish, 1, 1, 0, aRadiation, 0, null, false);
+ }
+
+ @Override
+ public void processChamber(IReactor paramIReactor, ItemStack paramItemStack, int paramInt1, int paramInt2,
+ boolean paramBoolean) {}
+
+ @Override
+ public boolean acceptUraniumPulse(IReactor paramIReactor, ItemStack paramItemStack1, ItemStack paramItemStack2,
+ int paramInt1, int paramInt2, int paramInt3, int paramInt4, boolean paramBoolean) {
+ return false;
+ }
+
+ @Override
+ public boolean canStoreHeat(IReactor paramIReactor, ItemStack paramItemStack, int paramInt1, int paramInt2) {
+ return false;
+ }
+
+ @Override
+ public int getMaxHeat(IReactor paramIReactor, ItemStack paramItemStack, int paramInt1, int paramInt2) {
+ return 0;
+ }
+
+ @Override
+ public int getCurrentHeat(IReactor paramIReactor, ItemStack paramItemStack, int paramInt1, int paramInt2) {
+ return 0;
+ }
+
+ @Override
+ public int alterHeat(IReactor paramIReactor, ItemStack paramItemStack, int paramInt1, int paramInt2,
+ int paramInt3) {
+ return 0;
+ }
+
+ @Override
+ public float influenceExplosion(IReactor paramIReactor, ItemStack paramItemStack) {
+ return 0.0F;
+ }
+}
diff --git a/src/main/java/gregtech/common/items/GT_FluidDisplayItem.java b/src/main/java/gregtech/common/items/GT_FluidDisplayItem.java
new file mode 100644
index 0000000000..850fe21811
--- /dev/null
+++ b/src/main/java/gregtech/common/items/GT_FluidDisplayItem.java
@@ -0,0 +1,181 @@
+package gregtech.common.items;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Stream;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.texture.IIconRegister;
+import net.minecraft.creativetab.CreativeTabs;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IIcon;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidRegistry;
+import net.minecraftforge.fluids.FluidStack;
+import net.minecraftforge.oredict.OreDictionary;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Materials;
+import gregtech.api.items.GT_Generic_Item;
+import gregtech.api.util.GT_Utility;
+
+public class GT_FluidDisplayItem extends GT_Generic_Item {
+
+ private static final Map<Fluid, String> sFluidTooltips = new HashMap<>();
+
+ public GT_FluidDisplayItem() {
+ super("GregTech_FluidDisplay", "Fluid Display", null);
+ ItemList.Display_Fluid.set(this);
+ }
+
+ @Override
+ protected void addAdditionalToolTips(List<String> aList, ItemStack aStack, EntityPlayer aPlayer) {
+ if (FluidRegistry.getFluid(aStack.getItemDamage()) != null) {
+ String tChemicalFormula = getChemicalFormula(
+ new FluidStack(FluidRegistry.getFluid(aStack.getItemDamage()), 1));
+ if (!tChemicalFormula.isEmpty())
+ aList.add(EnumChatFormatting.YELLOW + tChemicalFormula + EnumChatFormatting.RESET);
+ }
+ NBTTagCompound aNBT = aStack.getTagCompound();
+ if (GT_Values.D1 || Minecraft.getMinecraft().gameSettings.advancedItemTooltips) {
+ Fluid tFluid = FluidRegistry.getFluid(aStack.getItemDamage());
+ if (tFluid != null) {
+ aList.add("Registry: " + tFluid.getName());
+ }
+ }
+ if (aNBT != null) {
+ long tToolTipAmount = aNBT.getLong("mFluidDisplayAmount");
+ if (tToolTipAmount > 0L) {
+ aList.add(
+ EnumChatFormatting.BLUE + "Amount: "
+ + GT_Utility.formatNumbers(tToolTipAmount)
+ + " L"
+ + EnumChatFormatting.GRAY);
+ }
+ aList.add(
+ EnumChatFormatting.RED + "Temperature: "
+ + GT_Utility.formatNumbers(aNBT.getLong("mFluidDisplayHeat"))
+ + " K"
+ + EnumChatFormatting.GRAY);
+ aList.add(
+ EnumChatFormatting.GREEN
+ + String.format(transItem("018", "State: %s"), aNBT.getBoolean("mFluidState") ? "Gas" : "Liquid")
+ + EnumChatFormatting.GRAY);
+ }
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void registerIcons(IIconRegister aIconRegister) {}
+
+ @Override
+ public IIcon getIconFromDamage(int aMetaData) {
+ return Stream.of(FluidRegistry.getFluid(aMetaData), FluidRegistry.WATER)
+ .filter(Objects::nonNull)
+ .map(Fluid::getStillIcon)
+ .filter(Objects::nonNull)
+ .findFirst()
+ .orElseThrow(IllegalStateException::new);
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public int getColorFromItemStack(ItemStack aStack, int aRenderPass) {
+ Fluid tFluid = FluidRegistry.getFluid(aStack.getItemDamage());
+ return tFluid == null ? 16777215 : tFluid.getColor();
+ }
+
+ @Override
+ public int getSpriteNumber() {
+ return 0;
+ }
+
+ @Override
+ public String getUnlocalizedName(ItemStack aStack) {
+ if (aStack != null) {
+ return GT_Utility.getFluidName(FluidRegistry.getFluid(aStack.getItemDamage()), false);
+ }
+ return "";
+ }
+
+ @Override
+ public String getItemStackDisplayName(ItemStack aStack) {
+ if (aStack != null) {
+ return GT_Utility.getFluidName(FluidRegistry.getFluid(aStack.getItemDamage()), true);
+ }
+ return "";
+ }
+
+ @SideOnly(Side.CLIENT)
+ public static String getChemicalFormula(FluidStack aRealFluid) {
+ return sFluidTooltips.computeIfAbsent(aRealFluid.getFluid(), fluid -> {
+ for (ItemStack tContainer : GT_Utility.getContainersFromFluid(aRealFluid)) {
+ if (isCell(tContainer)) {
+ Materials tMaterial = getMaterialFromCell(tContainer);
+ if (!tMaterial.equals(Materials._NULL)) {
+ if (tMaterial.mChemicalFormula.equals("?")) {
+ return "";
+ } else {
+ return tMaterial.mChemicalFormula;
+ }
+ } else {
+ // For GT++ Fluid Display
+ // GT++ didn't register a Material in GT, so I have too find the Chemical Formula in its cell's
+ // tooltip
+ List<String> tTooltip = tContainer.getTooltip(null, true);
+ for (String tInfo : tTooltip) {
+ if (!tInfo.contains(" ") && !tInfo.contains(":") && tTooltip.indexOf(tInfo) != 0) {
+ return tInfo;
+ }
+ }
+ }
+ }
+ }
+ return "";
+ });
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void getSubItems(Item aItem, CreativeTabs aTab, List<ItemStack> aList) {
+ if (GT_Values.D1) {
+ int i = 0;
+ for (int j = FluidRegistry.getMaxID(); i < j; i++) {
+ ItemStack tStack = GT_Utility.getFluidDisplayStack(FluidRegistry.getFluid(i));
+ if (tStack != null) {
+ aList.add(tStack);
+ }
+ }
+ }
+ }
+
+ public static boolean isCell(ItemStack tItemStack) {
+ for (int tOreDict : OreDictionary.getOreIDs(tItemStack)) {
+ String tOreDictName = OreDictionary.getOreName(tOreDict);
+ if (tOreDictName.startsWith("cell")) return true;
+ }
+ return false;
+ }
+
+ public static Materials getMaterialFromCell(ItemStack tItemStack) {
+ for (int tOreDict : OreDictionary.getOreIDs(tItemStack)) {
+ String tOreDictName = OreDictionary.getOreName(tOreDict);
+ if (tOreDictName.startsWith("cell")) {
+ return Materials.getRealMaterial(
+ tOreDictName.replace("cell", "")
+ .replace("Molten", "")
+ .replace("Plasma", ""));
+ }
+ }
+ return Materials._NULL;
+ }
+}
diff --git a/src/main/java/gregtech/common/items/GT_IntegratedCircuit_Item.java b/src/main/java/gregtech/common/items/GT_IntegratedCircuit_Item.java
new file mode 100644
index 0000000000..0dc5000e7a
--- /dev/null
+++ b/src/main/java/gregtech/common/items/GT_IntegratedCircuit_Item.java
@@ -0,0 +1,328 @@
+package gregtech.common.items;
+
+import static gregtech.GT_Mod.GT_FML_LOGGER;
+import static gregtech.api.enums.Mods.GregTech;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.function.BiFunction;
+import java.util.function.Predicate;
+
+import net.minecraft.client.renderer.texture.IIconRegister;
+import net.minecraft.creativetab.CreativeTabs;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.ChatComponentTranslation;
+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.FakePlayer;
+
+import org.apache.commons.lang3.tuple.Pair;
+
+import com.gtnewhorizons.modularui.api.UIInfos;
+
+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.ItemList;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.interfaces.INetworkUpdatableItem;
+import gregtech.api.items.GT_Generic_Item;
+import gregtech.api.net.GT_Packet_UpdateItem;
+import gregtech.api.objects.XSTR;
+import gregtech.api.util.GT_Config;
+import gregtech.api.util.GT_LanguageManager;
+import gregtech.api.util.GT_Log;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.gui.modularui.uifactory.SelectItemUIFactory;
+
+public class GT_IntegratedCircuit_Item extends GT_Generic_Item implements INetworkUpdatableItem {
+
+ private static final String aTextEmptyRow = " ";
+ private static final List<ItemStack> ALL_VARIANTS = new ArrayList<>();
+ protected final IIcon[] mIconDamage = new IIcon[25];
+
+ public GT_IntegratedCircuit_Item() {
+ super("integrated_circuit", "Programmed Circuit", "");
+ setHasSubtypes(true);
+ setMaxDamage(0);
+
+ ItemList.Circuit_Integrated.set(this);
+
+ ALL_VARIANTS.add(new ItemStack(this, 0, 0));
+ for (int i = 1; i <= 24; i++) {
+ ItemStack aStack = new ItemStack(this, 0, i);
+ GregTech_API.registerConfigurationCircuit(aStack, 1);
+ ALL_VARIANTS.add(aStack);
+ }
+
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Circuit_Integrated.getWithDamage(1L, 0L),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { OrePrefixes.circuit.get(Materials.Basic) });
+ long bits = GT_ModHandler.RecipeBits.BUFFERED | GT_ModHandler.RecipeBits.NOT_REMOVABLE;
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Circuit_Integrated.getWithDamage(1L, 1L),
+ bits,
+ new Object[] { "d ", " P ", aTextEmptyRow, 'P', ItemList.Circuit_Integrated.getWildcard(1L) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Circuit_Integrated.getWithDamage(1L, 2L),
+ bits,
+ new Object[] { " d ", " P ", aTextEmptyRow, 'P', ItemList.Circuit_Integrated.getWildcard(1L) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Circuit_Integrated.getWithDamage(1L, 3L),
+ bits,
+ new Object[] { " d", " P ", aTextEmptyRow, 'P', ItemList.Circuit_Integrated.getWildcard(1L) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Circuit_Integrated.getWithDamage(1L, 4L),
+ bits,
+ new Object[] { aTextEmptyRow, " Pd", aTextEmptyRow, 'P', ItemList.Circuit_Integrated.getWildcard(1L) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Circuit_Integrated.getWithDamage(1L, 5L),
+ bits,
+ new Object[] { aTextEmptyRow, " P ", " d", 'P', ItemList.Circuit_Integrated.getWildcard(1L) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Circuit_Integrated.getWithDamage(1L, 6L),
+ bits,
+ new Object[] { aTextEmptyRow, " P ", " d ", 'P', ItemList.Circuit_Integrated.getWildcard(1L) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Circuit_Integrated.getWithDamage(1L, 7L),
+ bits,
+ new Object[] { aTextEmptyRow, " P ", "d ", 'P', ItemList.Circuit_Integrated.getWildcard(1L) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Circuit_Integrated.getWithDamage(1L, 8L),
+ bits,
+ new Object[] { aTextEmptyRow, "dP ", aTextEmptyRow, 'P', ItemList.Circuit_Integrated.getWildcard(1L) });
+
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Circuit_Integrated.getWithDamage(1L, 9L),
+ bits,
+ new Object[] { "P d", aTextEmptyRow, aTextEmptyRow, 'P', ItemList.Circuit_Integrated.getWildcard(1L) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Circuit_Integrated.getWithDamage(1L, 10L),
+ bits,
+ new Object[] { "P ", " d", aTextEmptyRow, 'P', ItemList.Circuit_Integrated.getWildcard(1L) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Circuit_Integrated.getWithDamage(1L, 11L),
+ bits,
+ new Object[] { "P ", aTextEmptyRow, " d", 'P', ItemList.Circuit_Integrated.getWildcard(1L) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Circuit_Integrated.getWithDamage(1L, 12L),
+ bits,
+ new Object[] { "P ", aTextEmptyRow, " d ", 'P', ItemList.Circuit_Integrated.getWildcard(1L) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Circuit_Integrated.getWithDamage(1L, 13L),
+ bits,
+ new Object[] { " P", aTextEmptyRow, " d", 'P', ItemList.Circuit_Integrated.getWildcard(1L) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Circuit_Integrated.getWithDamage(1L, 14L),
+ bits,
+ new Object[] { " P", aTextEmptyRow, " d ", 'P', ItemList.Circuit_Integrated.getWildcard(1L) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Circuit_Integrated.getWithDamage(1L, 15L),
+ bits,
+ new Object[] { " P", aTextEmptyRow, "d ", 'P', ItemList.Circuit_Integrated.getWildcard(1L) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Circuit_Integrated.getWithDamage(1L, 16L),
+ bits,
+ new Object[] { " P", "d ", aTextEmptyRow, 'P', ItemList.Circuit_Integrated.getWildcard(1L) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Circuit_Integrated.getWithDamage(1L, 17L),
+ bits,
+ new Object[] { aTextEmptyRow, aTextEmptyRow, "d P", 'P', ItemList.Circuit_Integrated.getWildcard(1L) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Circuit_Integrated.getWithDamage(1L, 18L),
+ bits,
+ new Object[] { aTextEmptyRow, "d ", " P", 'P', ItemList.Circuit_Integrated.getWildcard(1L) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Circuit_Integrated.getWithDamage(1L, 19L),
+ bits,
+ new Object[] { "d ", aTextEmptyRow, " P", 'P', ItemList.Circuit_Integrated.getWildcard(1L) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Circuit_Integrated.getWithDamage(1L, 20L),
+ bits,
+ new Object[] { " d ", aTextEmptyRow, " P", 'P', ItemList.Circuit_Integrated.getWildcard(1L) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Circuit_Integrated.getWithDamage(1L, 21L),
+ bits,
+ new Object[] { "d ", aTextEmptyRow, "P ", 'P', ItemList.Circuit_Integrated.getWildcard(1L) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Circuit_Integrated.getWithDamage(1L, 22L),
+ bits,
+ new Object[] { " d ", aTextEmptyRow, "P ", 'P', ItemList.Circuit_Integrated.getWildcard(1L) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Circuit_Integrated.getWithDamage(1L, 23L),
+ bits,
+ new Object[] { " d", aTextEmptyRow, "P ", 'P', ItemList.Circuit_Integrated.getWildcard(1L) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Circuit_Integrated.getWithDamage(1L, 24L),
+ bits,
+ new Object[] { aTextEmptyRow, " d", "P ", 'P', ItemList.Circuit_Integrated.getWildcard(1L) });
+ }
+
+ private static String getModeString(int aMetaData) {
+ return switch ((byte) (aMetaData >>> 8)) {
+ case 0 -> "==";
+ case 1 -> "<=";
+ case 2 -> ">=";
+ case 3 -> "<";
+ case 4 -> ">";
+ default -> "";
+ };
+ }
+
+ private static String getConfigurationString(int aMetaData) {
+ return getModeString(aMetaData) + " " + (byte) (aMetaData & 0xFF);
+ }
+
+ @Override
+ public void addAdditionalToolTips(List<String> aList, ItemStack aStack, EntityPlayer aPlayer) {
+ super.addAdditionalToolTips(aList, aStack, aPlayer);
+ aList.add(
+ GT_LanguageManager.addStringLocalization(getUnlocalizedName() + ".configuration", "Configuration: ")
+ + getConfigurationString(getDamage(aStack)));
+ aList.add(
+ GT_LanguageManager
+ .addStringLocalization(getUnlocalizedName() + ".tooltip.0", "Right click to reconfigure"));
+ aList.add(
+ GT_LanguageManager.addStringLocalization(
+ getUnlocalizedName() + ".tooltip.1",
+ "Needs a screwdriver or circuit programming tool"));
+ }
+
+ @Override
+ public String getUnlocalizedName(ItemStack aStack) {
+ return getUnlocalizedName();
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public final void getSubItems(Item aItem, CreativeTabs aCreativeTab, List<ItemStack> aList) {
+ aList.add(new ItemStack(this, 1, 0));
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void registerIcons(IIconRegister aIconRegister) {
+ super.registerIcons(aIconRegister);
+ for (int i = 0; i < mIconDamage.length; i++) {
+ mIconDamage[i] = aIconRegister
+ .registerIcon(GregTech.getResourcePath(GT_Config.troll ? "troll" : getUnlocalizedName() + "/" + i));
+ }
+ if (GregTech_API.sPostloadFinished) {
+ GT_Log.out.println("GT_Mod: Starting Item Icon Load Phase");
+ GT_FML_LOGGER.info("GT_Mod: Starting Item Icon Load Phase");
+ GregTech_API.sItemIcons = aIconRegister;
+ try {
+ for (Runnable tRunnable : GregTech_API.sGTItemIconload) {
+ tRunnable.run();
+ }
+ } catch (Throwable e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ GT_Log.out.println("GT_Mod: Finished Item Icon Load Phase");
+ GT_FML_LOGGER.info("GT_Mod: Finished Item Icon Load Phase");
+ }
+ }
+
+ @Override
+ public IIcon getIconFromDamage(int aMetaData) {
+ byte circuitMode = ((byte) (aMetaData & 0xFF)); // Mask out the MSB Comparison Mode Bits. See: getModeString
+ return mIconDamage[circuitMode < mIconDamage.length ? circuitMode : 0];
+ }
+
+ @Override
+ public boolean receive(ItemStack stack, EntityPlayerMP player, NBTTagCompound tag) {
+ int meta = tag.hasKey("meta", Constants.NBT.TAG_BYTE) ? tag.getByte("meta") : -1;
+ if (meta < 0 || meta > 24) return true;
+
+ if (!player.capabilities.isCreativeMode) {
+ Pair<Integer, BiFunction<ItemStack, EntityPlayerMP, ItemStack>> toolIndex = findConfiguratorInInv(player);
+ if (toolIndex == null) return true;
+
+ ItemStack[] mainInventory = player.inventory.mainInventory;
+ mainInventory[toolIndex.getKey()] = toolIndex.getValue()
+ .apply(mainInventory[toolIndex.getKey()], player);
+ }
+ stack.setItemDamage(meta);
+
+ return true;
+ }
+
+ @Override
+ public ItemStack onItemRightClick(ItemStack stack, World world, EntityPlayer player) {
+ // nothing on server side or fake player
+ if (player instanceof FakePlayer || !world.isRemote) return stack;
+ // check if any screwdriver
+ ItemStack configuratorStack;
+ if (player.capabilities.isCreativeMode) {
+ configuratorStack = null;
+ } else {
+ Pair<Integer, ?> configurator = findConfiguratorInInv(player);
+ if (configurator == null) {
+ int count;
+ try {
+ count = Integer
+ .parseInt(StatCollector.translateToLocal("GT5U.item.programmed_circuit.no_screwdriver.count"));
+ } catch (NumberFormatException e) {
+ player.addChatComponentMessage(
+ new ChatComponentText(
+ "Error in translation GT5U.item.programmed_circuit.no_screwdriver.count: "
+ + e.getMessage()));
+ count = 1;
+ }
+ player.addChatComponentMessage(
+ new ChatComponentTranslation(
+ "GT5U.item.programmed_circuit.no_screwdriver." + XSTR.XSTR_INSTANCE.nextInt(count)));
+ return stack;
+ }
+ configuratorStack = player.inventory.mainInventory[configurator.getKey()];
+ }
+ openSelectorGui(configuratorStack, stack.getItemDamage(), player);
+ return stack;
+ }
+
+ private void openSelectorGui(ItemStack configurator, int meta, EntityPlayer player) {
+ UIInfos.openClientUI(
+ player,
+ buildContext -> new SelectItemUIFactory(
+ StatCollector.translateToLocal("GT5U.item.programmed_circuit.select.header"),
+ configurator,
+ GT_IntegratedCircuit_Item::onConfigured,
+ ALL_VARIANTS,
+ meta,
+ true).createWindow(buildContext));
+ }
+
+ private static void onConfigured(ItemStack stack) {
+ NBTTagCompound tag = new NBTTagCompound();
+ tag.setByte("meta", (byte) stack.getItemDamage());
+ GT_Values.NW.sendToServer(new GT_Packet_UpdateItem(tag));
+ }
+
+ private static Pair<Integer, BiFunction<ItemStack, EntityPlayerMP, ItemStack>> findConfiguratorInInv(
+ EntityPlayer player) {
+ ItemStack[] mainInventory = player.inventory.mainInventory;
+ for (int j = 0, mainInventoryLength = mainInventory.length; j < mainInventoryLength; j++) {
+ ItemStack toolStack = mainInventory[j];
+
+ if (!GT_Utility.isStackValid(toolStack)) continue;
+
+ for (Map.Entry<Predicate<ItemStack>, BiFunction<ItemStack, EntityPlayerMP, ItemStack>> p : GregTech_API.sCircuitProgrammerList
+ .entrySet())
+ if (p.getKey()
+ .test(toolStack)) return Pair.of(j, p.getValue());
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/gregtech/common/items/GT_MetaGenerated_Item_01.java b/src/main/java/gregtech/common/items/GT_MetaGenerated_Item_01.java
new file mode 100644
index 0000000000..ae1d2568f7
--- /dev/null
+++ b/src/main/java/gregtech/common/items/GT_MetaGenerated_Item_01.java
@@ -0,0 +1,4627 @@
+package gregtech.common.items;
+
+import static gregtech.api.enums.Mods.GalacticraftMars;
+import static gregtech.api.enums.Textures.BlockIcons.COVER_WOOD_PLATE;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASINGS;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_ACTIVITYDETECTOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_ACTIVITYDETECTOR_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_ARM;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_CONTROLLER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_CONVEYOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_CRAFTING;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_DRAIN;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_ENERGYDETECTOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FLUIDDETECTOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FLUID_STORAGE_MONITOR0;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_ITEMDETECTOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_MAINTENANCE_DETECTOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_PUMP;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_REDSTONE_RECEIVER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_REDSTONE_TRANSMITTER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SCREEN;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SCREEN_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SHUTTER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_VALVE;
+import static gregtech.api.enums.Textures.BlockIcons.SOLARPANEL;
+import static gregtech.api.enums.Textures.BlockIcons.SOLARPANEL_8V;
+import static gregtech.api.enums.Textures.BlockIcons.SOLARPANEL_EV;
+import static gregtech.api.enums.Textures.BlockIcons.SOLARPANEL_HV;
+import static gregtech.api.enums.Textures.BlockIcons.SOLARPANEL_IV;
+import static gregtech.api.enums.Textures.BlockIcons.SOLARPANEL_LV;
+import static gregtech.api.enums.Textures.BlockIcons.SOLARPANEL_LuV;
+import static gregtech.api.enums.Textures.BlockIcons.SOLARPANEL_MV;
+import static gregtech.api.enums.Textures.BlockIcons.SOLARPANEL_UV;
+import static gregtech.api.enums.Textures.BlockIcons.SOLARPANEL_ZPM;
+import static gregtech.api.recipe.RecipeMaps.assemblerRecipes;
+import static gregtech.api.recipe.RecipeMaps.cannerRecipes;
+import static gregtech.api.recipe.RecipeMaps.compressorRecipes;
+import static gregtech.api.recipe.RecipeMaps.packagerRecipes;
+import static gregtech.api.util.GT_RecipeBuilder.MINUTES;
+import static gregtech.api.util.GT_RecipeBuilder.SECONDS;
+import static gregtech.api.util.GT_RecipeBuilder.TICKS;
+import static gregtech.client.GT_TooltipHandler.Tier.ERV;
+import static gregtech.client.GT_TooltipHandler.Tier.EV;
+import static gregtech.client.GT_TooltipHandler.Tier.HV;
+import static gregtech.client.GT_TooltipHandler.Tier.IV;
+import static gregtech.client.GT_TooltipHandler.Tier.LV;
+import static gregtech.client.GT_TooltipHandler.Tier.LuV;
+import static gregtech.client.GT_TooltipHandler.Tier.MAX;
+import static gregtech.client.GT_TooltipHandler.Tier.MV;
+import static gregtech.client.GT_TooltipHandler.Tier.ULV;
+import static gregtech.client.GT_TooltipHandler.Tier.UMV;
+import static gregtech.client.GT_TooltipHandler.Tier.UV;
+import static gregtech.client.GT_TooltipHandler.Tier.UXV;
+import static gregtech.client.GT_TooltipHandler.Tier.ZPM;
+import static gregtech.client.GT_TooltipHandler.registerTieredTooltip;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.minecraft.block.Block;
+import net.minecraft.enchantment.Enchantment;
+import net.minecraft.entity.item.EntityItem;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraft.init.Items;
+import net.minecraft.item.EnumAction;
+import net.minecraft.item.ItemStack;
+import net.minecraft.potion.Potion;
+import net.minecraft.util.MathHelper;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.Dyes;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.OreDictNames;
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.enums.SubTag;
+import gregtech.api.enums.TC_Aspects;
+import gregtech.api.enums.TierEU;
+import gregtech.api.interfaces.IItemBehaviour;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.items.GT_MetaBase_Item;
+import gregtech.api.items.GT_MetaGenerated_Item_X32;
+import gregtech.api.objects.ItemData;
+import gregtech.api.objects.MaterialStack;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_FoodStat;
+import gregtech.api.util.GT_LanguageManager;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_OreDictUnificator;
+import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.covers.GT_Cover_Arm;
+import gregtech.common.covers.GT_Cover_ControlsWork;
+import gregtech.common.covers.GT_Cover_Conveyor;
+import gregtech.common.covers.GT_Cover_Crafting;
+import gregtech.common.covers.GT_Cover_DoesWork;
+import gregtech.common.covers.GT_Cover_Drain;
+import gregtech.common.covers.GT_Cover_EUMeter;
+import gregtech.common.covers.GT_Cover_FluidLimiter;
+import gregtech.common.covers.GT_Cover_FluidRegulator;
+import gregtech.common.covers.GT_Cover_FluidStorageMonitor;
+import gregtech.common.covers.GT_Cover_Fluidfilter;
+import gregtech.common.covers.GT_Cover_ItemFilter;
+import gregtech.common.covers.GT_Cover_ItemMeter;
+import gregtech.common.covers.GT_Cover_LiquidMeter;
+import gregtech.common.covers.GT_Cover_NeedMaintainance;
+import gregtech.common.covers.GT_Cover_PlayerDetector;
+import gregtech.common.covers.GT_Cover_Pump;
+import gregtech.common.covers.GT_Cover_RedstoneReceiverExternal;
+import gregtech.common.covers.GT_Cover_RedstoneReceiverInternal;
+import gregtech.common.covers.GT_Cover_RedstoneTransmitterExternal;
+import gregtech.common.covers.GT_Cover_RedstoneTransmitterInternal;
+import gregtech.common.covers.GT_Cover_Screen;
+import gregtech.common.covers.GT_Cover_Shutter;
+import gregtech.common.covers.GT_Cover_SolarPanel;
+import gregtech.common.covers.GT_Cover_SteamRegulator;
+import gregtech.common.covers.GT_Cover_SteamValve;
+import gregtech.common.items.behaviors.Behaviour_Arrow_Potion;
+import gregtech.common.items.behaviors.Behaviour_Cover_Tool;
+import gregtech.common.items.behaviors.Behaviour_DataOrb;
+import gregtech.common.items.behaviors.Behaviour_DataStick;
+import gregtech.common.items.behaviors.Behaviour_Lighter;
+import gregtech.common.items.behaviors.Behaviour_PrintedPages;
+import gregtech.common.items.behaviors.Behaviour_Scanner;
+import gregtech.common.items.behaviors.Behaviour_SensorKit;
+import gregtech.common.items.behaviors.Behaviour_Sonictron;
+import gregtech.common.items.behaviors.Behaviour_Spray_Color;
+import gregtech.common.items.behaviors.Behaviour_Spray_Color_Remover;
+import gregtech.common.items.behaviors.Behaviour_WrittenBook;
+
+public class GT_MetaGenerated_Item_01 extends GT_MetaGenerated_Item_X32 {
+
+ public static GT_MetaGenerated_Item_01 INSTANCE;
+ private final String mToolTipPurify = GT_LanguageManager
+ .addStringLocalization("metaitem.01.tooltip.purify", "Throw into Cauldron to get clean Dust");
+ private static final String aTextArrow = " A";
+ private static final String aTextStick = " S ";
+ private static final String aTextFeather = "F ";
+ private static final String aTextEmptyRow = " ";
+ private static final String aTextShape = " P ";
+ private static final String PartCoverText = " L/t (";
+ private static final String PartCoverText2 = " L/s) as Cover";
+ private static final String PartNotCoverText = "Cannot be used as a Cover";
+ private static final String RAText = "Grabs from and inserts into specific slots";
+ private static final String FRText1 = "Configurable up to ";
+ private static final String FRText2 = " L/sec (as Cover)/n Rightclick/Screwdriver-rightclick/Shift-screwdriver-rightclick/n to adjust the pump speed by 1/16/256 L/sec per click";
+
+ public GT_MetaGenerated_Item_01() {
+ super(
+ "metaitem.01",
+ OrePrefixes.dustTiny,
+ OrePrefixes.dustSmall,
+ OrePrefixes.dust,
+ OrePrefixes.dustImpure,
+ OrePrefixes.dustPure,
+ OrePrefixes.crushed,
+ OrePrefixes.crushedPurified,
+ OrePrefixes.crushedCentrifuged,
+ OrePrefixes.gem,
+ OrePrefixes.nugget,
+ null,
+ OrePrefixes.ingot,
+ OrePrefixes.ingotHot,
+ OrePrefixes.ingotDouble,
+ OrePrefixes.ingotTriple,
+ OrePrefixes.ingotQuadruple,
+ OrePrefixes.ingotQuintuple,
+ OrePrefixes.plate,
+ OrePrefixes.plateDouble,
+ OrePrefixes.plateTriple,
+ OrePrefixes.plateQuadruple,
+ OrePrefixes.plateQuintuple,
+ OrePrefixes.plateDense,
+ OrePrefixes.stick,
+ OrePrefixes.lens,
+ OrePrefixes.round,
+ OrePrefixes.bolt,
+ OrePrefixes.screw,
+ OrePrefixes.ring,
+ OrePrefixes.foil,
+ OrePrefixes.cell,
+ OrePrefixes.cellPlasma);
+ INSTANCE = this;
+
+ int tLastID = 0;
+
+ setBurnValue(17000 + Materials.Wood.mMetaItemSubID, 1600);
+ GT_OreDictUnificator.addToBlacklist(new ItemStack(this, 1, 17000 + Materials.Wood.mMetaItemSubID));
+
+ // Compressor recipe
+ {
+ GT_Values.RA.stdBuilder()
+ .itemInputs(GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Wood, 8L))
+ .itemOutputs(new ItemStack(this, 1, 17000 + Materials.Wood.mMetaItemSubID))
+ .duration(15 * SECONDS)
+ .eut(2)
+ .addTo(compressorRecipes);
+ }
+
+ GregTech_API.registerCover(
+ new ItemStack(this, 1, 17000 + Materials.Wood.mMetaItemSubID),
+ TextureFactory.of(COVER_WOOD_PLATE),
+ null);
+
+ ItemStack tStack = new ItemStack(this, 1, 17000 + Materials.Wood.mMetaItemSubID);
+ tStack.setStackDisplayName("The holy Planks of Sengir");
+ GT_Utility.ItemNBT.addEnchantment(tStack, Enchantment.smite, 10);
+ GT_ModHandler.addCraftingRecipe(
+ tStack,
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { "XXX", "XDX", "XXX", 'X', OrePrefixes.gem.get(Materials.NetherStar), 'D',
+ new ItemStack(Blocks.dragon_egg, 1, 32767) });
+
+ ItemList.Credit_Greg_Copper.set(addItem(tLastID = 0, "Copper GT Credit", "0.125 Credits"));
+ ItemList.Credit_Greg_Cupronickel.set(
+ addItem(tLastID = 1, "Cupronickel GT Credit", "1 Credit", new ItemData(Materials.Cupronickel, 907200L)));
+ ItemList.Credit_Greg_Silver.set(
+ addItem(
+ tLastID = 2,
+ "Silver GT Credit",
+ "8 Credits",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.LUCRUM, 1L)));
+ ItemList.Credit_Greg_Gold.set(addItem(tLastID = 3, "Gold GT Credit", "64 Credits"));
+ ItemList.Credit_Greg_Platinum.set(addItem(tLastID = 4, "Platinum GT Credit", "512 Credits"));
+ ItemList.Credit_Greg_Osmium.set(addItem(tLastID = 5, "Osmium GT Credit", "4,096 Credits"));
+ ItemList.Credit_Greg_Naquadah.set(addItem(tLastID = 6, "Naquadah GT Credit", "32,768 Credits"));
+ ItemList.Credit_Greg_Neutronium.set(addItem(tLastID = 7, "Neutronium GT Credit", "262,144 Credits"));
+ ItemList.Coin_Gold_Ancient.set(
+ addItem(
+ tLastID = 8,
+ "Ancient Gold Coin",
+ "Found in ancient Ruins",
+ new ItemData(Materials.Gold, 907200L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.LUCRUM, 8L)));
+ ItemList.Coin_Doge.set(
+ addItem(
+ tLastID = 9,
+ "Doge Coin",
+ "wow much coin how money so crypto plz mine v rich very currency wow",
+ new ItemData(Materials.Brass, 907200L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.LUCRUM, 1L)));
+ ItemList.Coin_Chocolate.set(
+ addItem(
+ tLastID = 10,
+ "Chocolate Coin",
+ "Wrapped in Gold",
+ new ItemData(Materials.Gold, OrePrefixes.foil.mMaterialAmount),
+ new GT_FoodStat(
+ 1,
+ 0.1F,
+ EnumAction.eat,
+ GT_OreDictUnificator.get(OrePrefixes.foil, Materials.Gold, 1L),
+ true,
+ false,
+ false,
+ Potion.moveSpeed.id,
+ 200,
+ 1,
+ 100)));
+ ItemList.Credit_Copper.set(addItem(tLastID = 11, "Industrial Copper Credit", "0.125 Credits"));
+
+ ItemList.Credit_Silver.set(
+ addItem(
+ tLastID = 13,
+ "Industrial Silver Credit",
+ "8 Credits",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.LUCRUM, 1L)));
+ ItemList.Credit_Gold.set(addItem(tLastID = 14, "Industrial Gold Credit", "64 Credits"));
+ ItemList.Credit_Platinum.set(addItem(tLastID = 15, "Industrial Platinum Credit", "512 Credits"));
+ ItemList.Credit_Osmium.set(addItem(tLastID = 16, "Industrial Osmium Credit", "4096 Credits"));
+
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Coin_Chocolate.get(1L),
+ new Object[] { OrePrefixes.dust.get(Materials.Cocoa), OrePrefixes.dust.get(Materials.Milk),
+ OrePrefixes.dust.get(Materials.Sugar), OrePrefixes.foil.get(Materials.Gold) });
+
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Credit_Copper.get(8L),
+ GT_ModHandler.RecipeBits.KEEPNBT | GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { ItemList.Credit_Iron });
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Credit_Iron.get(8L),
+ GT_ModHandler.RecipeBits.KEEPNBT | GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { ItemList.Credit_Silver });
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Credit_Silver.get(8L),
+ GT_ModHandler.RecipeBits.KEEPNBT | GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { ItemList.Credit_Gold });
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Credit_Gold.get(8L),
+ GT_ModHandler.RecipeBits.KEEPNBT | GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { ItemList.Credit_Platinum });
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Credit_Platinum.get(8L),
+ GT_ModHandler.RecipeBits.KEEPNBT | GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { ItemList.Credit_Osmium });
+
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Credit_Iron.get(1L),
+ GT_ModHandler.RecipeBits.KEEPNBT | GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { ItemList.Credit_Copper, ItemList.Credit_Copper, ItemList.Credit_Copper,
+ ItemList.Credit_Copper, ItemList.Credit_Copper, ItemList.Credit_Copper, ItemList.Credit_Copper,
+ ItemList.Credit_Copper });
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Credit_Silver.get(1L),
+ GT_ModHandler.RecipeBits.KEEPNBT | GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { ItemList.Credit_Iron, ItemList.Credit_Iron, ItemList.Credit_Iron, ItemList.Credit_Iron,
+ ItemList.Credit_Iron, ItemList.Credit_Iron, ItemList.Credit_Iron, ItemList.Credit_Iron });
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Credit_Gold.get(1L),
+ GT_ModHandler.RecipeBits.KEEPNBT | GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { ItemList.Credit_Silver, ItemList.Credit_Silver, ItemList.Credit_Silver,
+ ItemList.Credit_Silver, ItemList.Credit_Silver, ItemList.Credit_Silver, ItemList.Credit_Silver,
+ ItemList.Credit_Silver });
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Credit_Platinum.get(1L),
+ GT_ModHandler.RecipeBits.KEEPNBT | GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { ItemList.Credit_Gold, ItemList.Credit_Gold, ItemList.Credit_Gold, ItemList.Credit_Gold,
+ ItemList.Credit_Gold, ItemList.Credit_Gold, ItemList.Credit_Gold, ItemList.Credit_Gold });
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Credit_Osmium.get(1L),
+ GT_ModHandler.RecipeBits.KEEPNBT | GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { ItemList.Credit_Platinum, ItemList.Credit_Platinum, ItemList.Credit_Platinum,
+ ItemList.Credit_Platinum, ItemList.Credit_Platinum, ItemList.Credit_Platinum, ItemList.Credit_Platinum,
+ ItemList.Credit_Platinum });
+
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Credit_Greg_Copper.get(8L),
+ GT_ModHandler.RecipeBits.KEEPNBT | GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { ItemList.Credit_Greg_Cupronickel });
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Credit_Greg_Cupronickel.get(8L),
+ GT_ModHandler.RecipeBits.KEEPNBT | GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { ItemList.Credit_Greg_Silver });
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Credit_Greg_Silver.get(8L),
+ GT_ModHandler.RecipeBits.KEEPNBT | GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { ItemList.Credit_Greg_Gold });
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Credit_Greg_Gold.get(8L),
+ GT_ModHandler.RecipeBits.KEEPNBT | GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { ItemList.Credit_Greg_Platinum });
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Credit_Greg_Platinum.get(8L),
+ GT_ModHandler.RecipeBits.KEEPNBT | GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { ItemList.Credit_Greg_Osmium });
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Credit_Greg_Osmium.get(8L),
+ GT_ModHandler.RecipeBits.KEEPNBT | GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { ItemList.Credit_Greg_Naquadah });
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Credit_Greg_Naquadah.get(8L),
+ GT_ModHandler.RecipeBits.KEEPNBT | GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { ItemList.Credit_Greg_Neutronium });
+
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Credit_Greg_Cupronickel.get(1L),
+ GT_ModHandler.RecipeBits.KEEPNBT | GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { ItemList.Credit_Greg_Copper, ItemList.Credit_Greg_Copper, ItemList.Credit_Greg_Copper,
+ ItemList.Credit_Greg_Copper, ItemList.Credit_Greg_Copper, ItemList.Credit_Greg_Copper,
+ ItemList.Credit_Greg_Copper, ItemList.Credit_Greg_Copper });
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Credit_Greg_Silver.get(1L),
+ GT_ModHandler.RecipeBits.KEEPNBT | GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { ItemList.Credit_Greg_Cupronickel, ItemList.Credit_Greg_Cupronickel,
+ ItemList.Credit_Greg_Cupronickel, ItemList.Credit_Greg_Cupronickel, ItemList.Credit_Greg_Cupronickel,
+ ItemList.Credit_Greg_Cupronickel, ItemList.Credit_Greg_Cupronickel, ItemList.Credit_Greg_Cupronickel });
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Credit_Greg_Gold.get(1L),
+ GT_ModHandler.RecipeBits.KEEPNBT | GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { ItemList.Credit_Greg_Silver, ItemList.Credit_Greg_Silver, ItemList.Credit_Greg_Silver,
+ ItemList.Credit_Greg_Silver, ItemList.Credit_Greg_Silver, ItemList.Credit_Greg_Silver,
+ ItemList.Credit_Greg_Silver, ItemList.Credit_Greg_Silver });
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Credit_Greg_Platinum.get(1L),
+ GT_ModHandler.RecipeBits.KEEPNBT | GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { ItemList.Credit_Greg_Gold, ItemList.Credit_Greg_Gold, ItemList.Credit_Greg_Gold,
+ ItemList.Credit_Greg_Gold, ItemList.Credit_Greg_Gold, ItemList.Credit_Greg_Gold,
+ ItemList.Credit_Greg_Gold, ItemList.Credit_Greg_Gold });
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Credit_Greg_Osmium.get(1L),
+ GT_ModHandler.RecipeBits.KEEPNBT | GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { ItemList.Credit_Greg_Platinum, ItemList.Credit_Greg_Platinum, ItemList.Credit_Greg_Platinum,
+ ItemList.Credit_Greg_Platinum, ItemList.Credit_Greg_Platinum, ItemList.Credit_Greg_Platinum,
+ ItemList.Credit_Greg_Platinum, ItemList.Credit_Greg_Platinum });
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Credit_Greg_Naquadah.get(1L),
+ GT_ModHandler.RecipeBits.KEEPNBT | GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { ItemList.Credit_Greg_Osmium, ItemList.Credit_Greg_Osmium, ItemList.Credit_Greg_Osmium,
+ ItemList.Credit_Greg_Osmium, ItemList.Credit_Greg_Osmium, ItemList.Credit_Greg_Osmium,
+ ItemList.Credit_Greg_Osmium, ItemList.Credit_Greg_Osmium });
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Credit_Greg_Neutronium.get(1L),
+ GT_ModHandler.RecipeBits.KEEPNBT | GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { ItemList.Credit_Greg_Naquadah, ItemList.Credit_Greg_Naquadah, ItemList.Credit_Greg_Naquadah,
+ ItemList.Credit_Greg_Naquadah, ItemList.Credit_Greg_Naquadah, ItemList.Credit_Greg_Naquadah,
+ ItemList.Credit_Greg_Naquadah, ItemList.Credit_Greg_Naquadah });
+
+ ItemList.Component_Minecart_Wheels_Iron.set(
+ addItem(
+ tLastID = 100,
+ "Iron Minecart Wheels",
+ "To get things rolling",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METALLUM, 2L)));
+ ItemList.Component_Minecart_Wheels_Steel.set(
+ addItem(
+ tLastID = 101,
+ "Steel Minecart Wheels",
+ "To get things rolling",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METALLUM, 2L)));
+
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Component_Minecart_Wheels_Iron.get(1L),
+ GT_ModHandler.RecipeBits.BUFFERED | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { " h ", "RSR", " w ", 'R', OrePrefixes.ring.get(Materials.AnyIron), 'S',
+ OrePrefixes.stick.get(Materials.AnyIron) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Component_Minecart_Wheels_Steel.get(1L),
+ GT_ModHandler.RecipeBits.BUFFERED | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { " h ", "RSR", " w ", 'R', OrePrefixes.ring.get(Materials.Steel), 'S',
+ OrePrefixes.stick.get(Materials.Steel) });
+
+ ItemList.CompressedFireclay.set(addItem(tLastID = 110, "Compressed Fireclay", "Brick-shaped"));
+ ItemList.Firebrick.set(addItem(tLastID = 111, "Firebrick", "Heat resistant"));
+
+ ItemList.Arrow_Head_Glass_Emtpy.set(
+ addItem(
+ tLastID = 200,
+ "Empty Glass Arrow Head",
+ "Fill with Potions before use",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VACUOS, 1L)));
+ ItemList.Arrow_Head_Glass_Poison.set(
+ addItem(
+ tLastID = 201,
+ "Poison Glass Arrow Head",
+ "Glass Arrow filled with Poison",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 1L)));
+ ItemList.Arrow_Head_Glass_Poison_Long.set(
+ addItem(
+ tLastID = 202,
+ "Poison Glass Arrow Head",
+ "Glass Arrow filled with stretched Poison",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 1L)));
+ ItemList.Arrow_Head_Glass_Poison_Strong.set(
+ addItem(
+ tLastID = 203,
+ "Poison Glass Arrow Head",
+ "Glass Arrow filled with strong Poison",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 1L)));
+ ItemList.Arrow_Head_Glass_Slowness.set(
+ addItem(
+ tLastID = 204,
+ "Slowness Glass Arrow Head",
+ "Glass Arrow filled with Laming Brew",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 1L)));
+ ItemList.Arrow_Head_Glass_Slowness_Long.set(
+ addItem(
+ tLastID = 205,
+ "Slowness Glass Arrow Head",
+ "Glass Arrow filled with stretched Laming Brew",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 1L)));
+ ItemList.Arrow_Head_Glass_Weakness.set(
+ addItem(
+ tLastID = 206,
+ "Weakness Glass Arrow Head",
+ "Glass Arrow filled with Weakening Brew",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 1L)));
+ ItemList.Arrow_Head_Glass_Weakness_Long.set(
+ addItem(
+ tLastID = 207,
+ "Weakness Glass Arrow Head",
+ "Glass Arrow filled with stretched Weakening Brew",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 1L)));
+ ItemList.Arrow_Head_Glass_Holy_Water.set(
+ addItem(
+ tLastID = 208,
+ "Holy Water Glass Arrow Head",
+ "Glass Arrow filled with Holy Water",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AURAM, 1L)));
+
+ ItemList.Arrow_Wooden_Glass_Emtpy.set(
+ addItem(
+ tLastID = 225,
+ "Regular Glass Vial Arrow",
+ "Empty Glass Arrow",
+ new Behaviour_Arrow_Potion(1.0F, 6.0F),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VACUOS, 1L)));
+ ItemList.Arrow_Wooden_Glass_Poison.set(
+ addItem(
+ tLastID = 226,
+ "Regular Poison Arrow",
+ "Glass Arrow filled with Poison",
+ new Behaviour_Arrow_Potion(1.0F, 6.0F, Potion.poison.id, 450, 0, 100),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 1L)));
+ ItemList.Arrow_Wooden_Glass_Poison_Long.set(
+ addItem(
+ tLastID = 227,
+ "Regular Poison Arrow",
+ "Glass Arrow filled with stretched Poison",
+ new Behaviour_Arrow_Potion(1.0F, 6.0F, Potion.poison.id, 900, 0, 100),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 1L)));
+ ItemList.Arrow_Wooden_Glass_Poison_Strong.set(
+ addItem(
+ tLastID = 228,
+ "Regular Poison Arrow",
+ "Glass Arrow filled with strong Poison",
+ new Behaviour_Arrow_Potion(1.0F, 6.0F, Potion.poison.id, 450, 1, 100),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 1L)));
+ ItemList.Arrow_Wooden_Glass_Slowness.set(
+ addItem(
+ tLastID = 229,
+ "Regular Slowness Arrow",
+ "Glass Arrow filled with Laming Brew",
+ new Behaviour_Arrow_Potion(1.0F, 6.0F, Potion.moveSlowdown.id, 900, 0, 100),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 1L)));
+ ItemList.Arrow_Wooden_Glass_Slowness_Long.set(
+ addItem(
+ tLastID = 230,
+ "Regular Slowness Arrow",
+ "Glass Arrow filled with stretched Laming Brew",
+ new Behaviour_Arrow_Potion(1.0F, 6.0F, Potion.moveSlowdown.id, 1800, 0, 100),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 1L)));
+ ItemList.Arrow_Wooden_Glass_Weakness.set(
+ addItem(
+ tLastID = 231,
+ "Regular Weakness Arrow",
+ "Glass Arrow filled with Weakening Brew",
+ new Behaviour_Arrow_Potion(1.0F, 6.0F, Potion.weakness.id, 900, 0, 100),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 1L)));
+ ItemList.Arrow_Wooden_Glass_Weakness_Long.set(
+ addItem(
+ tLastID = 232,
+ "Regular Weakness Arrow",
+ "Glass Arrow filled with stretched Weakening Brew",
+ new Behaviour_Arrow_Potion(1.0F, 6.0F, Potion.weakness.id, 1800, 0, 100),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 1L)));
+ ItemList.Arrow_Wooden_Glass_Holy_Water.set(
+ addItem(
+ tLastID = 233,
+ "Regular Holy Water Arrow",
+ "Glass Arrow filled with Holy Water",
+ new Behaviour_Arrow_Potion(1.0F, 6.0F, Enchantment.smite, 10),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AURAM, 1L)));
+
+ ItemList.Arrow_Plastic_Glass_Emtpy.set(
+ addItem(
+ tLastID = 250,
+ "Light Glass Vial Arrow",
+ "Empty Glass Arrow",
+ new Behaviour_Arrow_Potion(1.5F, 6.0F),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VACUOS, 1L)));
+ ItemList.Arrow_Plastic_Glass_Poison.set(
+ addItem(
+ tLastID = 251,
+ "Light Poison Arrow",
+ "Glass Arrow filled with Poison",
+ new Behaviour_Arrow_Potion(1.5F, 6.0F, Potion.poison.id, 450, 0, 100),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 1L)));
+ ItemList.Arrow_Plastic_Glass_Poison_Long.set(
+ addItem(
+ tLastID = 252,
+ "Light Poison Arrow",
+ "Glass Arrow filled with stretched Poison",
+ new Behaviour_Arrow_Potion(1.5F, 6.0F, Potion.poison.id, 900, 0, 100),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 1L)));
+ ItemList.Arrow_Plastic_Glass_Poison_Strong.set(
+ addItem(
+ tLastID = 253,
+ "Light Poison Arrow",
+ "Glass Arrow filled with strong Poison",
+ new Behaviour_Arrow_Potion(1.5F, 6.0F, Potion.poison.id, 450, 1, 100),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 1L)));
+ ItemList.Arrow_Plastic_Glass_Slowness.set(
+ addItem(
+ tLastID = 254,
+ "Light Slowness Arrow",
+ "Glass Arrow filled with Laming Brew",
+ new Behaviour_Arrow_Potion(1.5F, 6.0F, Potion.moveSlowdown.id, 900, 0, 100),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 1L)));
+ ItemList.Arrow_Plastic_Glass_Slowness_Long.set(
+ addItem(
+ tLastID = 255,
+ "Light Slowness Arrow",
+ "Glass Arrow filled with stretched Laming Brew",
+ new Behaviour_Arrow_Potion(1.5F, 6.0F, Potion.moveSlowdown.id, 1800, 0, 100),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 1L)));
+ ItemList.Arrow_Plastic_Glass_Weakness.set(
+ addItem(
+ tLastID = 256,
+ "Light Weakness Arrow",
+ "Glass Arrow filled with Weakening Brew",
+ new Behaviour_Arrow_Potion(1.5F, 6.0F, Potion.weakness.id, 900, 0, 100),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 1L)));
+ ItemList.Arrow_Plastic_Glass_Weakness_Long.set(
+ addItem(
+ tLastID = 257,
+ "Light Weakness Arrow",
+ "Glass Arrow filled with stretched Weakening Brew",
+ new Behaviour_Arrow_Potion(1.5F, 6.0F, Potion.weakness.id, 1800, 0, 100),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 1L)));
+ ItemList.Arrow_Plastic_Glass_Holy_Water.set(
+ addItem(
+ tLastID = 258,
+ "Light Holy Water Arrow",
+ "Glass Arrow filled with Holy Water",
+ new Behaviour_Arrow_Potion(1.5F, 6.0F, Enchantment.smite, 10),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AURAM, 1L)));
+
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Arrow_Wooden_Glass_Emtpy.get(1L),
+ GT_ModHandler.RecipeBits.BUFFERED | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { aTextArrow, aTextStick, aTextFeather, 'A', ItemList.Arrow_Head_Glass_Emtpy, 'F',
+ OreDictNames.craftingFeather, 'S', OrePrefixes.stick.get(Materials.Wood) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Arrow_Wooden_Glass_Poison.get(1L),
+ GT_ModHandler.RecipeBits.BUFFERED | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { aTextArrow, aTextStick, aTextFeather, 'A', ItemList.Arrow_Head_Glass_Poison, 'F',
+ OreDictNames.craftingFeather, 'S', OrePrefixes.stick.get(Materials.Wood) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Arrow_Wooden_Glass_Poison_Long.get(1L),
+ GT_ModHandler.RecipeBits.BUFFERED | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { aTextArrow, aTextStick, aTextFeather, 'A', ItemList.Arrow_Head_Glass_Poison_Long, 'F',
+ OreDictNames.craftingFeather, 'S', OrePrefixes.stick.get(Materials.Wood) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Arrow_Wooden_Glass_Poison_Strong.get(1L),
+ GT_ModHandler.RecipeBits.BUFFERED | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { aTextArrow, aTextStick, aTextFeather, 'A', ItemList.Arrow_Head_Glass_Poison_Strong, 'F',
+ OreDictNames.craftingFeather, 'S', OrePrefixes.stick.get(Materials.Wood) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Arrow_Wooden_Glass_Slowness.get(1L),
+ GT_ModHandler.RecipeBits.BUFFERED | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { aTextArrow, aTextStick, aTextFeather, 'A', ItemList.Arrow_Head_Glass_Slowness, 'F',
+ OreDictNames.craftingFeather, 'S', OrePrefixes.stick.get(Materials.Wood) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Arrow_Wooden_Glass_Slowness_Long.get(1L),
+ GT_ModHandler.RecipeBits.BUFFERED | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { aTextArrow, aTextStick, aTextFeather, 'A', ItemList.Arrow_Head_Glass_Slowness_Long, 'F',
+ OreDictNames.craftingFeather, 'S', OrePrefixes.stick.get(Materials.Wood) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Arrow_Wooden_Glass_Weakness.get(1L),
+ GT_ModHandler.RecipeBits.BUFFERED | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { aTextArrow, aTextStick, aTextFeather, 'A', ItemList.Arrow_Head_Glass_Weakness, 'F',
+ OreDictNames.craftingFeather, 'S', OrePrefixes.stick.get(Materials.Wood) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Arrow_Wooden_Glass_Weakness_Long.get(1L),
+ GT_ModHandler.RecipeBits.BUFFERED | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { aTextArrow, aTextStick, aTextFeather, 'A', ItemList.Arrow_Head_Glass_Weakness_Long, 'F',
+ OreDictNames.craftingFeather, 'S', OrePrefixes.stick.get(Materials.Wood) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Arrow_Wooden_Glass_Holy_Water.get(1L),
+ GT_ModHandler.RecipeBits.BUFFERED | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { aTextArrow, aTextStick, aTextFeather, 'A', ItemList.Arrow_Head_Glass_Holy_Water, 'F',
+ OreDictNames.craftingFeather, 'S', OrePrefixes.stick.get(Materials.Wood) });
+
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Arrow_Plastic_Glass_Emtpy.get(1L),
+ GT_ModHandler.RecipeBits.BUFFERED | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { aTextArrow, aTextStick, aTextFeather, 'A', ItemList.Arrow_Head_Glass_Emtpy, 'F',
+ OreDictNames.craftingFeather, 'S', OrePrefixes.stick.get(Materials.Plastic) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Arrow_Plastic_Glass_Poison.get(1L),
+ GT_ModHandler.RecipeBits.BUFFERED | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { aTextArrow, aTextStick, aTextFeather, 'A', ItemList.Arrow_Head_Glass_Poison, 'F',
+ OreDictNames.craftingFeather, 'S', OrePrefixes.stick.get(Materials.Plastic) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Arrow_Plastic_Glass_Poison_Long.get(1L),
+ GT_ModHandler.RecipeBits.BUFFERED | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { aTextArrow, aTextStick, aTextFeather, 'A', ItemList.Arrow_Head_Glass_Poison_Long, 'F',
+ OreDictNames.craftingFeather, 'S', OrePrefixes.stick.get(Materials.Plastic) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Arrow_Plastic_Glass_Poison_Strong.get(1L),
+ GT_ModHandler.RecipeBits.BUFFERED | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { aTextArrow, aTextStick, aTextFeather, 'A', ItemList.Arrow_Head_Glass_Poison_Strong, 'F',
+ OreDictNames.craftingFeather, 'S', OrePrefixes.stick.get(Materials.Plastic) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Arrow_Plastic_Glass_Slowness.get(1L),
+ GT_ModHandler.RecipeBits.BUFFERED | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { aTextArrow, aTextStick, aTextFeather, 'A', ItemList.Arrow_Head_Glass_Slowness, 'F',
+ OreDictNames.craftingFeather, 'S', OrePrefixes.stick.get(Materials.Plastic) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Arrow_Plastic_Glass_Slowness_Long.get(1L),
+ GT_ModHandler.RecipeBits.BUFFERED | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { aTextArrow, aTextStick, aTextFeather, 'A', ItemList.Arrow_Head_Glass_Slowness_Long, 'F',
+ OreDictNames.craftingFeather, 'S', OrePrefixes.stick.get(Materials.Plastic) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Arrow_Plastic_Glass_Weakness.get(1L),
+ GT_ModHandler.RecipeBits.BUFFERED | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { aTextArrow, aTextStick, aTextFeather, 'A', ItemList.Arrow_Head_Glass_Weakness, 'F',
+ OreDictNames.craftingFeather, 'S', OrePrefixes.stick.get(Materials.Plastic) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Arrow_Plastic_Glass_Weakness_Long.get(1L),
+ GT_ModHandler.RecipeBits.BUFFERED | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { aTextArrow, aTextStick, aTextFeather, 'A', ItemList.Arrow_Head_Glass_Weakness_Long, 'F',
+ OreDictNames.craftingFeather, 'S', OrePrefixes.stick.get(Materials.Plastic) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Arrow_Plastic_Glass_Holy_Water.get(1L),
+ GT_ModHandler.RecipeBits.BUFFERED | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { aTextArrow, aTextStick, aTextFeather, 'A', ItemList.Arrow_Head_Glass_Holy_Water, 'F',
+ OreDictNames.craftingFeather, 'S', OrePrefixes.stick.get(Materials.Plastic) });
+
+ ItemList.Shape_Empty.set(
+ addItem(
+ tLastID = 300,
+ "Empty Shape Plate",
+ "Raw Plate to make Molds and Extruder Shapes",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FABRICO, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METALLUM, 4L)));
+
+ ItemList.Shape_Mold_Plate.set(addItem(tLastID = 301, "Mold (Plate)", "Mold for making Plates"));
+ ItemList.Shape_Mold_Casing.set(addItem(tLastID = 302, "Mold (Casing)", "Mold for making Item Casings"));
+ ItemList.Shape_Mold_Gear.set(addItem(tLastID = 303, "Mold (Gear)", "Mold for making Gears"));
+ ItemList.Shape_Mold_Credit
+ .set(addItem(tLastID = 304, "Mold (Coinage)", "Secure Mold for making Coins (Don't lose it!)"));
+ ItemList.Shape_Mold_Bottle.set(addItem(tLastID = 305, "Mold (Bottle)", "Mold for making Bottles"));
+ ItemList.Shape_Mold_Ingot.set(addItem(tLastID = 306, "Mold (Ingot)", "Mold for making Ingots"));
+ ItemList.Shape_Mold_Ball.set(addItem(tLastID = 307, "Mold (Ball)", "Mold for making Balls"));
+ ItemList.Shape_Mold_Block.set(addItem(tLastID = 308, "Mold (Block)", "Mold for making Blocks"));
+ ItemList.Shape_Mold_Nugget.set(addItem(tLastID = 309, "Mold (Nuggets)", "Mold for making Nuggets"));
+ ItemList.Shape_Mold_Bun.set(addItem(tLastID = 310, "Mold (Buns)", "Mold for shaping Buns"));
+ ItemList.Shape_Mold_Bread.set(addItem(tLastID = 311, "Mold (Bread)", "Mold for shaping Breads"));
+ ItemList.Shape_Mold_Baguette.set(addItem(tLastID = 312, "Mold (Baguette)", "Mold for shaping Baguettes"));
+ ItemList.Shape_Mold_Cylinder.set(addItem(tLastID = 313, "Mold (Cylinder)", "Mold for shaping Cylinders"));
+ ItemList.Shape_Mold_Anvil.set(addItem(tLastID = 314, "Mold (Anvil)", "Mold for shaping Anvils"));
+ ItemList.Shape_Mold_Name
+ .set(addItem(tLastID = 315, "Mold (Name)", "Mold for naming Items (rename Mold with Anvil)"));
+ ItemList.Shape_Mold_Arrow.set(addItem(tLastID = 316, "Mold (Arrow Head)", "Mold for making Arrow Heads"));
+ ItemList.Shape_Mold_Gear_Small.set(addItem(tLastID = 317, "Mold (Small Gear)", "Mold for making small Gears"));
+ ItemList.Shape_Mold_Rod.set(addItem(tLastID = 318, "Mold (Rod)", "Mold for making Rods"));
+ ItemList.Shape_Mold_Bolt.set(addItem(tLastID = 319, "Mold (Bolt)", "Mold for making Bolts"));
+ ItemList.Shape_Mold_Round.set(addItem(tLastID = 320, "Mold (Round)", "Mold for making Rounds"));
+ ItemList.Shape_Mold_Screw.set(addItem(tLastID = 321, "Mold (Screw)", "Mold for making Screws"));
+ ItemList.Shape_Mold_Ring.set(addItem(tLastID = 322, "Mold (Ring)", "Mold for making Rings"));
+ ItemList.Shape_Mold_Rod_Long.set(addItem(tLastID = 323, "Mold (Long Rod)", "Mold for making Long Rods"));
+ ItemList.Shape_Mold_Rotor.set(addItem(tLastID = 324, "Mold (Rotor)", "Mold for making a Rotor"));
+ ItemList.Shape_Mold_Turbine_Blade
+ .set(addItem(tLastID = 325, "Mold (Turbine Blade)", "Mold for making a Turbine Blade"));
+ ItemList.Shape_Mold_Pipe_Tiny.set(addItem(tLastID = 326, "Mold (Tiny Pipe)", "Mold for making tiny Pipes"));
+ ItemList.Shape_Mold_Pipe_Small.set(addItem(tLastID = 327, "Mold (Small Pipe)", "Mold for making small Pipes"));
+ ItemList.Shape_Mold_Pipe_Medium.set(addItem(tLastID = 328, "Mold (Normal Pipe)", "Mold for making Pipes"));
+ ItemList.Shape_Mold_Pipe_Large.set(addItem(tLastID = 329, "Mold (Large Pipe)", "Mold for making large Pipes"));
+ ItemList.Shape_Mold_Pipe_Huge
+ .set(addItem(tLastID = 330, "Mold (Huge Pipe)", "Mold for making full Block Pipes"));
+ ItemList.Shape_Mold_ToolHeadDrill
+ .set(addItem(tLastID = 331, "Mold (Drill Head)", "Mold for making Drill Heads"));
+ GT_ModHandler.removeRecipe(
+ new ItemStack(Blocks.glass),
+ null,
+ new ItemStack(Blocks.glass),
+ null,
+ new ItemStack(Blocks.glass));
+
+ ItemList.Shape_Extruder_Plate
+ .set(addItem(tLastID = 350, "Extruder Shape (Plate)", "Extruder Shape for making Plates"));
+ ItemList.Shape_Extruder_Rod
+ .set(addItem(tLastID = 351, "Extruder Shape (Rod)", "Extruder Shape for making Rods"));
+ ItemList.Shape_Extruder_Bolt
+ .set(addItem(tLastID = 352, "Extruder Shape (Bolt)", "Extruder Shape for making Bolts"));
+ ItemList.Shape_Extruder_Ring
+ .set(addItem(tLastID = 353, "Extruder Shape (Ring)", "Extruder Shape for making Rings"));
+ ItemList.Shape_Extruder_Cell
+ .set(addItem(tLastID = 354, "Extruder Shape (Cell)", "Extruder Shape for making Cells"));
+ ItemList.Shape_Extruder_Ingot.set(
+ addItem(tLastID = 355, "Extruder Shape (Ingot)", "Extruder Shape for, wait, can't we just use a Furnace?"));
+ ItemList.Shape_Extruder_Wire
+ .set(addItem(tLastID = 356, "Extruder Shape (Wire)", "Extruder Shape for making Wires"));
+ ItemList.Shape_Extruder_Casing
+ .set(addItem(tLastID = 357, "Extruder Shape (Casing)", "Extruder Shape for making Item Casings"));
+ ItemList.Shape_Extruder_Pipe_Tiny
+ .set(addItem(tLastID = 358, "Extruder Shape (Tiny Pipe)", "Extruder Shape for making tiny Pipes"));
+ ItemList.Shape_Extruder_Pipe_Small
+ .set(addItem(tLastID = 359, "Extruder Shape (Small Pipe)", "Extruder Shape for making small Pipes"));
+ ItemList.Shape_Extruder_Pipe_Medium
+ .set(addItem(tLastID = 360, "Extruder Shape (Normal Pipe)", "Extruder Shape for making Pipes"));
+ ItemList.Shape_Extruder_Pipe_Large
+ .set(addItem(tLastID = 361, "Extruder Shape (Large Pipe)", "Extruder Shape for making large Pipes"));
+ ItemList.Shape_Extruder_Pipe_Huge
+ .set(addItem(tLastID = 362, "Extruder Shape (Huge Pipe)", "Extruder Shape for making full Block Pipes"));
+ ItemList.Shape_Extruder_Block
+ .set(addItem(tLastID = 363, "Extruder Shape (Block)", "Extruder Shape for making Blocks"));
+ ItemList.Shape_Extruder_Sword
+ .set(addItem(tLastID = 364, "Extruder Shape (Sword Blade)", "Extruder Shape for making Swords"));
+ ItemList.Shape_Extruder_Pickaxe
+ .set(addItem(tLastID = 365, "Extruder Shape (Pickaxe Head)", "Extruder Shape for making Pickaxes"));
+ ItemList.Shape_Extruder_Shovel
+ .set(addItem(tLastID = 366, "Extruder Shape (Shovel Head)", "Extruder Shape for making Shovels"));
+ ItemList.Shape_Extruder_Axe
+ .set(addItem(tLastID = 367, "Extruder Shape (Axe Head)", "Extruder Shape for making Axes"));
+ ItemList.Shape_Extruder_Hoe
+ .set(addItem(tLastID = 368, "Extruder Shape (Hoe Head)", "Extruder Shape for making Hoes"));
+ ItemList.Shape_Extruder_Hammer
+ .set(addItem(tLastID = 369, "Extruder Shape (Hammer Head)", "Extruder Shape for making Hammers"));
+ ItemList.Shape_Extruder_File
+ .set(addItem(tLastID = 370, "Extruder Shape (File Head)", "Extruder Shape for making Files"));
+ ItemList.Shape_Extruder_Saw
+ .set(addItem(tLastID = 371, "Extruder Shape (Saw Blade)", "Extruder Shape for making Saws"));
+ ItemList.Shape_Extruder_Gear
+ .set(addItem(tLastID = 372, "Extruder Shape (Gear)", "Extruder Shape for making Gears"));
+ ItemList.Shape_Extruder_Bottle
+ .set(addItem(tLastID = 373, "Extruder Shape (Bottle)", "Extruder Shape for making Bottles"));
+ ItemList.Shape_Extruder_Rotor
+ .set(addItem(tLastID = 374, "Extruder Shape (Rotor)", "Extruder Shape for a Rotor"));
+ ItemList.Shape_Extruder_Small_Gear
+ .set(addItem(tLastID = 375, "Extruder Shape (Small Gear)", "Extruder Shape for a Small Gear"));
+ ItemList.Shape_Extruder_Turbine_Blade
+ .set(addItem(tLastID = 376, "Extruder Shape (Turbine Blade)", "Extruder Shape for a Turbine Blade"));
+ ItemList.Shape_Extruder_ToolHeadDrill
+ .set(addItem(tLastID = 377, "Extruder Shape (Drill Head)", "Extruder Shape for a Drill Head"));
+
+ ItemList.Shape_Slicer_Flat.set(addItem(tLastID = 398, "Slicer Blade (Flat)", "Slicer Blade for cutting Flat"));
+ ItemList.Shape_Slicer_Stripes
+ .set(addItem(tLastID = 399, "Slicer Blade (Stripes)", "Slicer Blade for cutting Stripes"));
+
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Shape_Slicer_Flat.get(1L),
+ GT_ModHandler.RecipeBits.BUFFERED | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "hXS", aTextShape, "fXd", 'P', ItemList.Shape_Extruder_Block, 'X',
+ OrePrefixes.plate.get(Materials.StainlessSteel), 'S',
+ OrePrefixes.screw.get(Materials.StainlessSteel) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Shape_Slicer_Stripes.get(1L),
+ GT_ModHandler.RecipeBits.BUFFERED | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "hXS", "XPX", "fXd", 'P', ItemList.Shape_Extruder_Block, 'X',
+ OrePrefixes.plate.get(Materials.StainlessSteel), 'S',
+ OrePrefixes.screw.get(Materials.StainlessSteel) });
+
+ ItemList.Fuel_Can_Plastic_Empty.set(
+ addItem(
+ tLastID = 400,
+ "Empty Plastic Fuel Can",
+ "Used to store Fuels",
+ new ItemData(Materials.Plastic, OrePrefixes.plate.mMaterialAmount * 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VACUOS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 1L)));
+ ItemList.Fuel_Can_Plastic_Filled.set(
+ addItem(
+ tLastID = 401,
+ "Plastic Fuel Can",
+ "Burns well in Diesel Generators",
+ new ItemData(Materials.Plastic, OrePrefixes.plate.mMaterialAmount * 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VACUOS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 1L)));
+
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Fuel_Can_Plastic_Empty.get(7L),
+ GT_ModHandler.RecipeBits.BUFFERED | GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { " PP", "P P", "PPP", 'P', OrePrefixes.plate.get(Materials.Plastic) });
+
+ ItemList.Spray_Empty.set(
+ addItem(
+ tLastID = 402,
+ "Empty Spray Can",
+ "Used for making Sprays",
+ new ItemData(
+ Materials.Tin,
+ OrePrefixes.plate.mMaterialAmount * 2L,
+ Materials.Redstone,
+ OrePrefixes.dust.mMaterialAmount),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VACUOS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 1L)));
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Redstone, 1L),
+ GT_OreDictUnificator.get(OrePrefixes.cell, Materials.Empty, 1L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Spray_Empty.get(1L))
+ .duration(40 * SECONDS)
+ .eut(1)
+ .addTo(assemblerRecipes);
+
+ ItemList.Crate_Empty.set(
+ addItem(
+ tLastID = 403,
+ "Empty Crate",
+ "To Package lots of Material",
+ new ItemData(Materials.Wood, 3628800L, Materials.Iron, OrePrefixes.screw.mMaterialAmount),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VACUOS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 2L)));
+
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Crate_Empty.get(4L),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { "SWS", "WdW", "SWS", 'W', OrePrefixes.plank.get(Materials.Wood), 'S',
+ OrePrefixes.screw.get(Materials.AnyIron) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Crate_Empty.get(4L),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { "SWS", "WdW", "SWS", 'W', OrePrefixes.plank.get(Materials.Wood), 'S',
+ OrePrefixes.screw.get(Materials.Steel) });
+
+ ItemList.ThermosCan_Empty.set(
+ addItem(
+ tLastID = 404,
+ "Empty Thermos Can",
+ "Keeping hot things hot and cold things cold",
+ new ItemData(
+ Materials.Aluminium,
+ OrePrefixes.plateDouble.mMaterialAmount * 1L + 2L * OrePrefixes.ring.mMaterialAmount),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VACUOS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.GELUM, 1L)));
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.plateDouble, Materials.Aluminium, 1L),
+ GT_OreDictUnificator.get(OrePrefixes.ring, Materials.Aluminium, 2L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.ThermosCan_Empty.get(1L))
+ .duration(40 * SECONDS)
+ .eut(1)
+ .addTo(assemblerRecipes);
+
+ ItemList.Large_Fluid_Cell_Steel.set(
+ addItem(
+ tLastID = 405,
+ "Large Steel Fluid Cell",
+ "",
+ new ItemData(
+ Materials.Steel,
+ OrePrefixes.plateDouble.mMaterialAmount * 4L,
+ new MaterialStack(Materials.Bronze, OrePrefixes.ring.mMaterialAmount * 4L)),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VACUOS, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 2L)));
+ setFluidContainerStats(32000 + tLastID, 8000L, 64L);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.plateDouble, Materials.Steel, 4L),
+ GT_OreDictUnificator.get(OrePrefixes.ring, Materials.AnyBronze, 4L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Large_Fluid_Cell_Steel.get(1L))
+ .duration(10 * SECONDS)
+ .eut(TierEU.RECIPE_LV)
+ .addTo(assemblerRecipes);
+
+ ItemList.Large_Fluid_Cell_TungstenSteel.set(
+ addItem(
+ tLastID = 406,
+ "Large Tungstensteel Fluid Cell",
+ "",
+ new ItemData(
+ Materials.TungstenSteel,
+ OrePrefixes.plateDouble.mMaterialAmount * 4L,
+ new MaterialStack(Materials.Platinum, OrePrefixes.ring.mMaterialAmount * 4L)),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VACUOS, 9L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 7L)));
+ setFluidContainerStats(32000 + tLastID, 512000L, 32L);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.plateDouble, Materials.TungstenSteel, 4L),
+ GT_OreDictUnificator.get(OrePrefixes.ring, Materials.Platinum, 4L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Large_Fluid_Cell_TungstenSteel.get(1L))
+ .duration(10 * SECONDS)
+ .eut(TierEU.RECIPE_HV)
+ .addTo(assemblerRecipes);
+
+ ItemList.Large_Fluid_Cell_Aluminium.set(
+ addItem(
+ tLastID = 407,
+ "Large Aluminium Fluid Cell",
+ "",
+ new ItemData(
+ Materials.Aluminium,
+ OrePrefixes.plateDouble.mMaterialAmount * 4L,
+ new MaterialStack(Materials.Silver, OrePrefixes.ring.mMaterialAmount * 4L)),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VACUOS, 5L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 3L)));
+ setFluidContainerStats(32000 + tLastID, 32000L, 64L);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.plateDouble, Materials.Aluminium, 4L),
+ GT_OreDictUnificator.get(OrePrefixes.ring, Materials.Silver, 4L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Large_Fluid_Cell_Aluminium.get(1L))
+ .duration(10 * SECONDS)
+ .eut(64)
+ .addTo(assemblerRecipes);
+
+ ItemList.Large_Fluid_Cell_StainlessSteel.set(
+ addItem(
+ tLastID = 408,
+ "Large Stainless Steel Fluid Cell",
+ "",
+ new ItemData(
+ Materials.StainlessSteel,
+ OrePrefixes.plateDouble.mMaterialAmount * 4L,
+ new MaterialStack(Materials.Electrum, OrePrefixes.ring.mMaterialAmount * 4L)),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VACUOS, 6L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 4L)));
+ setFluidContainerStats(32000 + tLastID, 64000L, 64L);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.plateDouble, Materials.StainlessSteel, 4L),
+ GT_OreDictUnificator.get(OrePrefixes.ring, Materials.Electrum, 4L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Large_Fluid_Cell_StainlessSteel.get(1L))
+ .duration(10 * SECONDS)
+ .eut(TierEU.RECIPE_MV)
+ .addTo(assemblerRecipes);
+
+ ItemList.Large_Fluid_Cell_Titanium.set(
+ addItem(
+ tLastID = 409,
+ "Large Titanium Fluid Cell",
+ "",
+ new ItemData(
+ Materials.Titanium,
+ OrePrefixes.plateDouble.mMaterialAmount * 4L,
+ new MaterialStack(Materials.RoseGold, OrePrefixes.ring.mMaterialAmount * 4L)),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VACUOS, 7L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 5L)));
+ setFluidContainerStats(32000 + tLastID, 128000L, 64L);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.plateDouble, Materials.Titanium, 4L),
+ GT_OreDictUnificator.get(OrePrefixes.ring, Materials.RoseGold, 4L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Large_Fluid_Cell_Titanium.get(1L))
+ .duration(10 * SECONDS)
+ .eut(256)
+ .addTo(assemblerRecipes);
+
+ ItemList.Large_Fluid_Cell_Chrome.set(
+ addItem(
+ tLastID = 410,
+ "Large Chrome Fluid Cell",
+ "",
+ new ItemData(
+ Materials.Chrome,
+ OrePrefixes.plateDouble.mMaterialAmount * 4L,
+ new MaterialStack(Materials.Palladium, OrePrefixes.ring.mMaterialAmount * 4L)),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VACUOS, 8L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 6L)));
+ setFluidContainerStats(32000 + tLastID, 2048000L, 8L);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.plateDouble, Materials.Chrome, 4L),
+ GT_OreDictUnificator.get(OrePrefixes.ring, Materials.Palladium, 4L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Large_Fluid_Cell_Chrome.get(1L))
+ .duration(10 * SECONDS)
+ .eut(1024)
+ .addTo(assemblerRecipes);
+
+ ItemList.Large_Fluid_Cell_Iridium.set(
+ addItem(
+ tLastID = 411,
+ "Large Iridium Fluid Cell",
+ "",
+ new ItemData(
+ Materials.Iridium,
+ OrePrefixes.plateDouble.mMaterialAmount * 4L,
+ new MaterialStack(Materials.Naquadah, OrePrefixes.ring.mMaterialAmount * 4L)),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VACUOS, 10L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 8L)));
+ setFluidContainerStats(32000 + tLastID, 8192000L, 2L);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.plateDouble, Materials.Iridium, 4L),
+ GT_OreDictUnificator.get(OrePrefixes.ring, Materials.Naquadah, 4L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Large_Fluid_Cell_Iridium.get(1L))
+ .duration(10 * SECONDS)
+ .eut(TierEU.RECIPE_EV)
+ .addTo(assemblerRecipes);
+
+ ItemList.Large_Fluid_Cell_Osmium.set(
+ addItem(
+ tLastID = 412,
+ "Large Osmium Fluid Cell",
+ "",
+ new ItemData(
+ Materials.Osmium,
+ OrePrefixes.plateDouble.mMaterialAmount * 4L,
+ new MaterialStack(Materials.ElectrumFlux, OrePrefixes.ring.mMaterialAmount * 4L)),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VACUOS, 11L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 9L)));
+ setFluidContainerStats(32000 + tLastID, 32768000L, 1L);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.plateDouble, Materials.Osmium, 4L),
+ GT_OreDictUnificator.get(OrePrefixes.ring, Materials.ElectrumFlux, 4L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Large_Fluid_Cell_Osmium.get(1L))
+ .duration(10 * SECONDS)
+ .eut(4096)
+ .addTo(assemblerRecipes);
+
+ ItemList.Large_Fluid_Cell_Neutronium.set(
+ addItem(
+ tLastID = 413,
+ "Large Neutronium Fluid Cell",
+ "",
+ new ItemData(
+ Materials.Neutronium,
+ OrePrefixes.plateDouble.mMaterialAmount * 4L,
+ new MaterialStack(Materials.Draconium, OrePrefixes.ring.mMaterialAmount * 4L)),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VACUOS, 12L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 10L)));
+ setFluidContainerStats(32000 + tLastID, 131072000L, 1L);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.plateDouble, Materials.Neutronium, 4L),
+ GT_OreDictUnificator.get(OrePrefixes.ring, Materials.Draconium, 4L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Large_Fluid_Cell_Neutronium.get(1L))
+ .duration(10 * SECONDS)
+ .eut(TierEU.RECIPE_IV)
+ .addTo(assemblerRecipes);
+ for (byte i = 0; i < 16; i = (byte) (i + 1)) {
+ ItemList.SPRAY_CAN_DYES[i].set(
+ addItem(
+ tLastID = 430 + 2 * i,
+ "Spray Can (" + Dyes.get(i).mName + ")",
+ "Full",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SENSUS, 4L)));
+ ItemList.SPRAY_CAN_DYES_USED[i].set(
+ addItem(
+ tLastID + 1,
+ "Spray Can (" + Dyes.get(i).mName + ")",
+ "Used",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SENSUS, 3L),
+ SubTag.INVISIBLE));
+ IItemBehaviour<GT_MetaBase_Item> tBehaviour = new Behaviour_Spray_Color(
+ ItemList.Spray_Empty.get(1L),
+ ItemList.SPRAY_CAN_DYES_USED[i].get(1L),
+ ItemList.SPRAY_CAN_DYES[i].get(1L),
+ 512L,
+ i);
+ addItemBehavior(32000 + tLastID, tBehaviour);
+ addItemBehavior(32001 + tLastID, tBehaviour);
+ }
+
+ ItemList.Spray_Color_Remover.set(
+ addItem(
+ tLastID = 465,
+ "Spray Can Solvent",
+ "Full",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SENSUS, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.PERDITIO, 8L)));
+ ItemList.Spray_Color_Used_Remover.set(
+ addItem(
+ tLastID = 466,
+ "Spray Can Solvent",
+ "Used",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SENSUS, 3L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.PERDITIO, 6L),
+ SubTag.INVISIBLE));
+ IItemBehaviour<GT_MetaBase_Item> tBehaviour = new Behaviour_Spray_Color_Remover(
+ ItemList.Spray_Empty.get(1L),
+ ItemList.Spray_Color_Used_Remover.get(1L),
+ ItemList.Spray_Color_Remover.get(1L),
+ 1024L);
+ addItemBehavior(32000 + 465, tBehaviour);
+ addItemBehavior(32000 + 466, tBehaviour);
+
+ ItemList.Spray_Color_Remover_Empty.set(
+ addItem(
+ tLastID = 467,
+ "Empty Spray Can Solvent Cannister",
+ "Used for making Spray Can Solvent",
+ new ItemData(
+ Materials.Aluminium,
+ OrePrefixes.plateDouble.mMaterialAmount * 4L,
+ Materials.Redstone,
+ OrePrefixes.dust.mMaterialAmount),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VACUOS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 1L)));
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Redstone, 1L),
+ ItemList.Large_Fluid_Cell_Aluminium.get(1),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Spray_Color_Remover_Empty.get(1L))
+ .duration(40 * SECONDS)
+ .eut(1)
+ .addTo(assemblerRecipes);
+
+ ItemList.Tool_Matches.set(
+ addItem(
+ tLastID = 471,
+ "Match",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VACUOS, 1L)));
+ ItemList.Tool_MatchBox_Used.set(
+ addItem(
+ tLastID = 472,
+ "Match Box",
+ "This is not a Car",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 1L),
+ SubTag.INVISIBLE));
+ ItemList.Tool_MatchBox_Full.set(
+ addItem(
+ tLastID = 473,
+ "Match Box (Full)",
+ "This is not a Car",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 2L)));
+
+ tBehaviour = new Behaviour_Lighter(null, ItemList.Tool_Matches.get(1L), ItemList.Tool_Matches.get(1L), 1L);
+ addItemBehavior(32471, tBehaviour);
+ tBehaviour = new Behaviour_Lighter(
+ null,
+ ItemList.Tool_MatchBox_Used.get(1L),
+ ItemList.Tool_MatchBox_Full.get(1L),
+ 16L);
+ addItemBehavior(32472, tBehaviour);
+ addItemBehavior(32473, tBehaviour);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.bolt, Materials.Wood, 1L),
+ GT_OreDictUnificator.get(OrePrefixes.dustSmall, Materials.Phosphorus, 1L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Tool_Matches.get(1L))
+ .duration(16 * TICKS)
+ .eut(16)
+ .addTo(assemblerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.bolt, Materials.Wood, 1L),
+ GT_OreDictUnificator.get(OrePrefixes.dustSmall, Materials.TricalciumPhosphate, 1L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Tool_Matches.get(1L))
+ .duration(16 * TICKS)
+ .eut(16)
+ .addTo(assemblerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.bolt, Materials.Wood, 4L),
+ GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Phosphorus, 1L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Tool_Matches.get(4L))
+ .duration(3 * SECONDS + 4 * TICKS)
+ .eut(16)
+ .addTo(assemblerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.bolt, Materials.Wood, 4L),
+ GT_OreDictUnificator.get(OrePrefixes.dust, Materials.TricalciumPhosphate, 1L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Tool_Matches.get(4L))
+ .duration(3 * SECONDS + 4 * TICKS)
+ .eut(16)
+ .addTo(assemblerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ ItemList.Tool_Matches.get(16L),
+ GT_OreDictUnificator.get(OrePrefixes.plateDouble, Materials.Paper, 1L))
+ .itemOutputs(ItemList.Tool_MatchBox_Full.get(1L))
+ .duration(3 * SECONDS + 4 * TICKS)
+ .eut(16)
+ .addTo(packagerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(ItemList.Tool_MatchBox_Full.get(1L))
+ .itemOutputs(ItemList.Tool_Matches.get(16L))
+ .duration(1 * SECONDS + 12 * TICKS)
+ .eut(16)
+ .addTo(packagerRecipes);
+
+ ItemList.Tool_Lighter_Invar_Empty.set(
+ addItem(
+ tLastID = 474,
+ "Lighter (Empty)",
+ "",
+ new ItemData(Materials.Invar, OrePrefixes.plate.mMaterialAmount * 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VACUOS, 1L)));
+ ItemList.Tool_Lighter_Invar_Used.set(
+ addItem(
+ tLastID = 475,
+ "Lighter",
+ "",
+ new ItemData(Materials.Invar, OrePrefixes.plate.mMaterialAmount * 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 1L),
+ SubTag.INVISIBLE));
+ ItemList.Tool_Lighter_Invar_Full.set(
+ addItem(
+ tLastID = 476,
+ "Lighter (Full)",
+ "",
+ new ItemData(Materials.Invar, OrePrefixes.plate.mMaterialAmount * 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 2L)));
+
+ tBehaviour = new Behaviour_Lighter(
+ ItemList.Tool_Lighter_Invar_Empty.get(1L),
+ ItemList.Tool_Lighter_Invar_Used.get(1L),
+ ItemList.Tool_Lighter_Invar_Full.get(1L),
+ 100L);
+ addItemBehavior(32475, tBehaviour);
+ addItemBehavior(32476, tBehaviour);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.plate, Materials.Invar, 2L),
+ new ItemStack(Items.flint, 1),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Tool_Lighter_Invar_Empty.get(1L))
+ .duration(12 * SECONDS + 16 * TICKS)
+ .eut(16)
+ .addTo(assemblerRecipes);
+
+ ItemList.Tool_Lighter_Platinum_Empty.set(
+ addItem(
+ tLastID = 477,
+ "Platinum Lighter (Empty)",
+ "A known Prank Master is engraved on it",
+ new ItemData(Materials.Platinum, OrePrefixes.plate.mMaterialAmount * 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.NEBRISUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VACUOS, 1L)));
+ ItemList.Tool_Lighter_Platinum_Used.set(
+ addItem(
+ tLastID = 478,
+ "Platinum Lighter",
+ "A known Prank Master is engraved on it",
+ new ItemData(Materials.Platinum, OrePrefixes.plate.mMaterialAmount * 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.NEBRISUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 1L),
+ SubTag.INVISIBLE));
+ ItemList.Tool_Lighter_Platinum_Full.set(
+ addItem(
+ tLastID = 479,
+ "Platinum Lighter (Full)",
+ "A known Prank Master is engraved on it",
+ new ItemData(Materials.Platinum, OrePrefixes.plate.mMaterialAmount * 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.NEBRISUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 2L)));
+
+ tBehaviour = new Behaviour_Lighter(
+ ItemList.Tool_Lighter_Platinum_Empty.get(1L),
+ ItemList.Tool_Lighter_Platinum_Used.get(1L),
+ ItemList.Tool_Lighter_Platinum_Full.get(1L),
+ 1000L);
+ addItemBehavior(32478, tBehaviour);
+ addItemBehavior(32479, tBehaviour);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.plate, Materials.Platinum, 2L),
+ new ItemStack(Items.flint, 1),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Tool_Lighter_Platinum_Empty.get(1L))
+ .duration(12 * SECONDS + 16 * TICKS)
+ .eut(256)
+ .addTo(assemblerRecipes);
+
+ if (GalacticraftMars.isModLoaded()) {
+ ItemList.Ingot_Heavy1
+ .set(addItem(tLastID = 462, "Heavy Duty Alloy Ingot T1", "Used to make Heavy Duty Plates T1"));
+ ItemList.Ingot_Heavy2
+ .set(addItem(tLastID = 463, "Heavy Duty Alloy Ingot T2", "Used to make Heavy Duty Plates T2"));
+ ItemList.Ingot_Heavy3
+ .set(addItem(tLastID = 464, "Heavy Duty Alloy Ingot T3", "Used to make Heavy Duty Plates T3"));
+
+ }
+ ItemList.Ingot_IridiumAlloy.set(
+ addItem(
+ tLastID = 480,
+ "Iridium Alloy Ingot",
+ "Used to make Iridium Plates",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TUTAMEN, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METALLUM, 4L)));
+
+ ItemList.Paper_Printed_Pages.set(
+ addItem(
+ tLastID = 481,
+ "Printed Pages",
+ "Used to make written Books",
+ new ItemData(Materials.Paper, 10886400L),
+ new Behaviour_PrintedPages(),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.COGNITIO, 2L)));
+ ItemList.Paper_Magic_Empty.set(
+ addItem(
+ tLastID = 482,
+ "Magic Paper",
+ "",
+ SubTag.INVISIBLE,
+ new ItemData(Materials.Paper, 3628800L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.COGNITIO, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.PRAECANTATIO, 1L)));
+ ItemList.Paper_Magic_Page.set(
+ addItem(
+ tLastID = 483,
+ "Enchanted Page",
+ "",
+ SubTag.INVISIBLE,
+ new ItemData(Materials.Paper, 3628800L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.COGNITIO, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.PRAECANTATIO, 2L)));
+ ItemList.Paper_Magic_Pages.set(
+ addItem(
+ tLastID = 484,
+ "Enchanted Pages",
+ "",
+ SubTag.INVISIBLE,
+ new ItemData(Materials.Paper, 10886400L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.COGNITIO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.PRAECANTATIO, 4L)));
+ ItemList.Paper_Punch_Card_Empty.set(
+ addItem(
+ tLastID = 485,
+ "Punch Card",
+ "",
+ SubTag.INVISIBLE,
+ new ItemData(Materials.Paper, 7257600L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.COGNITIO, 1L)));
+ ItemList.Paper_Punch_Card_Encoded.set(
+ addItem(
+ tLastID = 486,
+ "Punched Card",
+ "",
+ SubTag.INVISIBLE,
+ new ItemData(Materials.Paper, 7257600L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.COGNITIO, 2L)));
+ ItemList.Book_Written_01.set(
+ addItem(
+ tLastID = 487,
+ "Book",
+ "",
+ new ItemData(Materials.Paper, 10886400L),
+ "bookWritten",
+ OreDictNames.craftingBook,
+ new Behaviour_WrittenBook(),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.COGNITIO, 2L)));
+ ItemList.Book_Written_02.set(
+ addItem(
+ tLastID = 488,
+ "Book",
+ "",
+ new ItemData(Materials.Paper, 10886400L),
+ "bookWritten",
+ OreDictNames.craftingBook,
+ new Behaviour_WrittenBook(),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.COGNITIO, 2L)));
+ ItemList.Book_Written_03.set(
+ addItem(
+ tLastID = 489,
+ "Book",
+ "",
+ new ItemData(Materials.Paper, 10886400L),
+ "bookWritten",
+ OreDictNames.craftingBook,
+ new Behaviour_WrittenBook(),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.COGNITIO, 2L)));
+
+ ItemList.Schematic.set(
+ addItem(
+ tLastID = 490,
+ "Schematic",
+ "EMPTY",
+ new ItemData(Materials.Steel, 7257600L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.STRONTIO, 1L)));
+ ItemList.Schematic_Crafting.set(
+ addItem(
+ tLastID = 491,
+ "Schematic (Crafting)",
+ "Crafts the Programmed Recipe",
+ new ItemData(Materials.Steel, 7257600L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.COGNITIO, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FABRICO, 1L)));
+ ItemList.Schematic_1by1.set(
+ addItem(
+ tLastID = 495,
+ "Schematic (1x1)",
+ "Crafts 1 Items as 1x1 (use in Packager)",
+ new ItemData(Materials.Steel, 7257600L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.COGNITIO, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FABRICO, 1L)));
+ ItemList.Schematic_2by2.set(
+ addItem(
+ tLastID = 496,
+ "Schematic (2x2)",
+ "Crafts 4 Items as 2x2 (use in Packager)",
+ new ItemData(Materials.Steel, 7257600L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.COGNITIO, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FABRICO, 1L)));
+ ItemList.Schematic_3by3.set(
+ addItem(
+ tLastID = 497,
+ "Schematic (3x3)",
+ "Crafts 9 Items as 3x3 (use in Packager)",
+ new ItemData(Materials.Steel, 7257600L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.COGNITIO, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FABRICO, 1L)));
+ ItemList.Schematic_Dust.set(
+ addItem(
+ tLastID = 498,
+ "Schematic (Dusts)",
+ "Combines Dusts (use in Packager)",
+ new ItemData(Materials.Steel, 7257600L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.COGNITIO, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FABRICO, 1L)));
+
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Schematic_1by1.get(1L),
+ GT_ModHandler.RecipeBits.BUFFERED | GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { "d ", aTextShape, aTextEmptyRow, 'P', ItemList.Schematic });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Schematic_2by2.get(1L),
+ GT_ModHandler.RecipeBits.BUFFERED | GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { " d ", aTextShape, aTextEmptyRow, 'P', ItemList.Schematic });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Schematic_3by3.get(1L),
+ GT_ModHandler.RecipeBits.BUFFERED | GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { " d", aTextShape, aTextEmptyRow, 'P', ItemList.Schematic });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Schematic_Dust.get(1L),
+ GT_ModHandler.RecipeBits.BUFFERED | GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { aTextEmptyRow, aTextShape, " d", 'P', ItemList.Schematic });
+
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Schematic.get(1L),
+ GT_ModHandler.RecipeBits.BUFFERED | GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { ItemList.Schematic_Crafting });
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Schematic.get(1L),
+ GT_ModHandler.RecipeBits.BUFFERED | GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { ItemList.Schematic_1by1 });
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Schematic.get(1L),
+ GT_ModHandler.RecipeBits.BUFFERED | GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { ItemList.Schematic_2by2 });
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Schematic.get(1L),
+ GT_ModHandler.RecipeBits.BUFFERED | GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { ItemList.Schematic_3by3 });
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Schematic.get(1L),
+ GT_ModHandler.RecipeBits.BUFFERED | GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { ItemList.Schematic_Dust });
+
+ ItemList.Battery_Hull_LV.set(
+ addItem(
+ 500,
+ "Small Battery Hull",
+ "An empty LV Battery Hull",
+ new ItemData(Materials.BatteryAlloy, OrePrefixes.plate.mMaterialAmount * 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METALLUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VACUOS, 1L)));
+ ItemList.Battery_Hull_MV.set(
+ addItem(
+ 501,
+ "Medium Battery Hull",
+ "An empty MV Battery Hull",
+ new ItemData(Materials.BatteryAlloy, OrePrefixes.plate.mMaterialAmount * 3L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METALLUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VACUOS, 1L)));
+ ItemList.Battery_Hull_HV.set(
+ addItem(
+ 502,
+ "Large Battery Hull",
+ "An empty HV Battery Hull",
+ new ItemData(Materials.BatteryAlloy, OrePrefixes.plate.mMaterialAmount * 9L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METALLUM, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VACUOS, 1L)));
+
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Battery_Hull_LV.get(1L),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { "Cf ", "Ph ", "Ps ", 'P', OrePrefixes.plate.get(Materials.BatteryAlloy), 'C',
+ OreDictNames.craftingWireTin });
+ // GT_ModHandler.addCraftingRecipe(ItemList.Battery_Hull_MV.get(1L), GT_ModHandler.RecipeBits.NOT_REMOVABLE, new
+ // Object[]{"C C", "PPP", "PPP", 'P', OrePrefixes.plate.get(Materials.BatteryAlloy), 'C',
+ // OreDictNames.craftingWireCopper});
+
+ // ULV Batteries
+ ItemList.Battery_RE_ULV_Tantalum.set(
+ addItem(
+ tLastID = 499,
+ "Tantalum Capacitor",
+ "Reusable",
+ "batteryULV",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METALLUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 1L)));
+ setElectricStats(32000 + tLastID, 1000L, GT_Values.V[0], 0L, -3L, false);
+ registerTieredTooltip(ItemList.Battery_RE_ULV_Tantalum.get(1), ULV);
+
+ // LV Batteries
+ ItemList.Battery_SU_LV_SulfuricAcid.set(
+ addItem(
+ tLastID = 510,
+ "Small Acid Battery",
+ "Single Use",
+ "batteryLV",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METALLUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 2L)));
+ setElectricStats(32000 + tLastID, 18000L, GT_Values.V[1], 1L, -2L, true);
+ registerTieredTooltip(ItemList.Battery_SU_LV_SulfuricAcid.get(1), LV);
+
+ ItemList.Battery_SU_LV_Mercury.set(
+ addItem(
+ tLastID = 511,
+ "Small Mercury Battery",
+ "Single Use",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METALLUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 2L)));
+ setElectricStats(32000 + tLastID, 32000L, GT_Values.V[1], 1L, -2L, true);
+ registerTieredTooltip(ItemList.Battery_SU_LV_Mercury.get(1), LV);
+
+ ItemList.Battery_RE_LV_Cadmium.set(
+ addItem(
+ tLastID = 517,
+ "Small Cadmium Battery",
+ "Reusable",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METALLUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 1L),
+ "batteryLV"));
+ setElectricStats(32000 + tLastID, 75000L, GT_Values.V[1], 1L, -3L, true);
+ registerTieredTooltip(ItemList.Battery_RE_LV_Cadmium.get(1), LV);
+
+ ItemList.Battery_RE_LV_Lithium.set(
+ addItem(
+ tLastID = 518,
+ "Small Lithium Battery",
+ "Reusable",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METALLUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 1L),
+ "batteryLV"));
+ setElectricStats(32000 + tLastID, 100000L, GT_Values.V[1], 1L, -3L, true);
+ registerTieredTooltip(ItemList.Battery_RE_LV_Lithium.get(1), LV);
+
+ ItemList.Battery_RE_LV_Sodium.set(
+ addItem(
+ tLastID = 519,
+ "Small Sodium Battery",
+ "Reusable",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METALLUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 1L),
+ "batteryLV"));
+ setElectricStats(32000 + tLastID, 50000L, GT_Values.V[1], 1L, -3L, true);
+ registerTieredTooltip(ItemList.Battery_RE_LV_Sodium.get(1), LV);
+
+ // MV Batteries
+ ItemList.Battery_SU_MV_SulfuricAcid.set(
+ addItem(
+ tLastID = 520,
+ "Medium Acid Battery",
+ "Single Use",
+ "batteryMV",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METALLUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 4L)));
+ setElectricStats(32000 + tLastID, 72000L, GT_Values.V[2], 2L, -2L, true);
+ registerTieredTooltip(ItemList.Battery_SU_MV_SulfuricAcid.get(1), MV);
+
+ ItemList.Battery_SU_MV_Mercury.set(
+ addItem(
+ tLastID = 521,
+ "Medium Mercury Battery",
+ "Single Use",
+ "batteryMV",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METALLUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 4L)));
+ setElectricStats(32000 + tLastID, 128000L, GT_Values.V[2], 2L, -2L, true);
+ registerTieredTooltip(ItemList.Battery_SU_MV_Mercury.get(1), MV);
+
+ ItemList.Battery_RE_MV_Cadmium.set(
+ addItem(
+ tLastID = 527,
+ "Medium Cadmium Battery",
+ "Reusable",
+ "batteryMV",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METALLUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 2L)));
+ setElectricStats(32000 + tLastID, 300000L, GT_Values.V[2], 2L, -3L, true);
+ registerTieredTooltip(ItemList.Battery_RE_MV_Cadmium.get(1), MV);
+
+ ItemList.Battery_RE_MV_Lithium.set(
+ addItem(
+ tLastID = 528,
+ "Medium Lithium Battery",
+ "Reusable",
+ "batteryMV",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METALLUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 2L)));
+ setElectricStats(32000 + tLastID, 400000L, GT_Values.V[2], 2L, -3L, true);
+ registerTieredTooltip(ItemList.Battery_RE_MV_Lithium.get(1), MV);
+
+ ItemList.Battery_RE_MV_Sodium.set(
+ addItem(
+ tLastID = 529,
+ "Medium Sodium Battery",
+ "Reusable",
+ "batteryMV",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METALLUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 2L)));
+ setElectricStats(32000 + tLastID, 200000L, GT_Values.V[2], 2L, -3L, true);
+ registerTieredTooltip(ItemList.Battery_RE_MV_Sodium.get(1), MV);
+
+ // HV Batteries
+ ItemList.Battery_SU_HV_SulfuricAcid.set(
+ addItem(
+ tLastID = 530,
+ "Large Acid Battery",
+ "Single Use",
+ "batteryHV",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METALLUM, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 8L)));
+ setElectricStats(32000 + tLastID, 288000L, GT_Values.V[3], 3L, -2L, true);
+ registerTieredTooltip(ItemList.Battery_SU_HV_SulfuricAcid.get(1), HV);
+
+ ItemList.Battery_SU_HV_Mercury.set(
+ addItem(
+ tLastID = 531,
+ "Large Mercury Battery",
+ "Single Use",
+ "batteryHV",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METALLUM, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 8L)));
+ setElectricStats(32000 + tLastID, 512000L, GT_Values.V[3], 3L, -2L, true);
+ registerTieredTooltip(ItemList.Battery_SU_HV_Mercury.get(1), HV);
+
+ ItemList.Battery_RE_HV_Cadmium.set(
+ addItem(
+ tLastID = 537,
+ "Large Cadmium Battery",
+ "Reusable",
+ "batteryHV",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METALLUM, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 4L)));
+ setElectricStats(32000 + tLastID, 1200000L, GT_Values.V[3], 3L, -3L, true);
+ registerTieredTooltip(ItemList.Battery_RE_HV_Cadmium.get(1), HV);
+
+ ItemList.Battery_RE_HV_Lithium.set(
+ addItem(
+ tLastID = 538,
+ "Large Lithium Battery",
+ "Reusable",
+ "batteryHV",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METALLUM, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 4L)));
+ setElectricStats(32000 + tLastID, 1600000L, GT_Values.V[3], 3L, -3L, true);
+ registerTieredTooltip(ItemList.Battery_RE_HV_Lithium.get(1), HV);
+
+ ItemList.Battery_RE_HV_Sodium.set(
+ addItem(
+ tLastID = 539,
+ "Large Sodium Battery",
+ "Reusable",
+ "batteryHV",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METALLUM, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 4L)));
+ setElectricStats(32000 + tLastID, 800000L, GT_Values.V[3], 3L, -3L, true);
+ registerTieredTooltip(ItemList.Battery_RE_HV_Sodium.get(1), HV);
+
+ GT_ModHandler
+ .addExtractionRecipe(ItemList.Battery_SU_LV_SulfuricAcid.get(1L), ItemList.Battery_Hull_LV.get(1L));
+ GT_ModHandler.addExtractionRecipe(ItemList.Battery_SU_LV_Mercury.get(1L), ItemList.Battery_Hull_LV.get(1L));
+ GT_ModHandler
+ .addExtractionRecipe(ItemList.Battery_SU_MV_SulfuricAcid.get(1L), ItemList.Battery_Hull_MV.get(1L));
+ GT_ModHandler.addExtractionRecipe(ItemList.Battery_SU_MV_Mercury.get(1L), ItemList.Battery_Hull_MV.get(1L));
+ GT_ModHandler
+ .addExtractionRecipe(ItemList.Battery_SU_HV_SulfuricAcid.get(1L), ItemList.Battery_Hull_HV.get(1L));
+ GT_ModHandler.addExtractionRecipe(ItemList.Battery_SU_HV_Mercury.get(1L), ItemList.Battery_Hull_HV.get(1L));
+ GT_ModHandler.addExtractionRecipe(ItemList.Battery_RE_LV_Cadmium.get(1L), ItemList.Battery_Hull_LV.get(1L));
+ GT_ModHandler.addExtractionRecipe(ItemList.Battery_RE_LV_Lithium.get(1L), ItemList.Battery_Hull_LV.get(1L));
+ GT_ModHandler.addExtractionRecipe(ItemList.Battery_RE_LV_Sodium.get(1L), ItemList.Battery_Hull_LV.get(1L));
+ GT_ModHandler.addExtractionRecipe(ItemList.Battery_RE_MV_Cadmium.get(1L), ItemList.Battery_Hull_MV.get(1L));
+ GT_ModHandler.addExtractionRecipe(ItemList.Battery_RE_MV_Lithium.get(1L), ItemList.Battery_Hull_MV.get(1L));
+ GT_ModHandler.addExtractionRecipe(ItemList.Battery_RE_MV_Sodium.get(1L), ItemList.Battery_Hull_MV.get(1L));
+ GT_ModHandler.addExtractionRecipe(ItemList.Battery_RE_HV_Cadmium.get(1L), ItemList.Battery_Hull_HV.get(1L));
+ GT_ModHandler.addExtractionRecipe(ItemList.Battery_RE_HV_Lithium.get(1L), ItemList.Battery_Hull_HV.get(1L));
+ GT_ModHandler.addExtractionRecipe(ItemList.Battery_RE_HV_Sodium.get(1L), ItemList.Battery_Hull_HV.get(1L));
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Cadmium, 2L),
+ ItemList.Battery_Hull_LV.get(1L))
+ .itemOutputs(ItemList.Battery_RE_LV_Cadmium.get(1L))
+ .duration(5 * SECONDS)
+ .eut(2)
+ .addTo(cannerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Lithium, 2L),
+ ItemList.Battery_Hull_LV.get(1L))
+ .itemOutputs(ItemList.Battery_RE_LV_Lithium.get(1L))
+ .duration(5 * SECONDS)
+ .eut(2)
+ .addTo(cannerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Sodium, 2L),
+ ItemList.Battery_Hull_LV.get(1L))
+ .itemOutputs(ItemList.Battery_RE_LV_Sodium.get(1L))
+ .duration(5 * SECONDS)
+ .eut(2)
+ .addTo(cannerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Cadmium, 8L),
+ ItemList.Battery_Hull_MV.get(1L))
+ .itemOutputs(ItemList.Battery_RE_MV_Cadmium.get(1L))
+ .duration(20 * SECONDS)
+ .eut(2)
+ .addTo(cannerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Lithium, 8L),
+ ItemList.Battery_Hull_MV.get(1L))
+ .itemOutputs(ItemList.Battery_RE_MV_Lithium.get(1L))
+ .duration(20 * SECONDS)
+ .eut(2)
+ .addTo(cannerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Sodium, 8L),
+ ItemList.Battery_Hull_MV.get(1L))
+ .itemOutputs(ItemList.Battery_RE_MV_Sodium.get(1L))
+ .duration(20 * SECONDS)
+ .eut(2)
+ .addTo(cannerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Cadmium, 32L),
+ ItemList.Battery_Hull_HV.get(1L))
+ .itemOutputs(ItemList.Battery_RE_HV_Cadmium.get(1L))
+ .duration(1 * MINUTES + 20 * SECONDS)
+ .eut(2)
+ .addTo(cannerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Lithium, 32L),
+ ItemList.Battery_Hull_HV.get(1L))
+ .itemOutputs(ItemList.Battery_RE_HV_Lithium.get(1L))
+ .duration(1 * MINUTES + 20 * SECONDS)
+ .eut(2)
+ .addTo(cannerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Sodium, 32L),
+ ItemList.Battery_Hull_HV.get(1L))
+ .itemOutputs(ItemList.Battery_RE_HV_Sodium.get(1L))
+ .duration(1 * MINUTES + 20 * SECONDS)
+ .eut(2)
+ .addTo(cannerRecipes);
+
+ // IV Battery
+ ItemList.Energy_LapotronicOrb.set(
+ addItem(
+ tLastID = 597,
+ "Lapotronic Energy Orb",
+ "Reusable battery",
+ "batteryIV",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 16L),
+ OrePrefixes.battery.get(Materials.Ultimate)));
+ setElectricStats(32000 + tLastID, 100000000L, GT_Values.V[5], 5L, -3L, true);
+ registerTieredTooltip(ItemList.Energy_LapotronicOrb.get(1), IV);
+
+ // ZPM Module
+ ItemList.ZPM.set(
+ addItem(
+ tLastID = 598,
+ "Zero Point Module",
+ "Single use battery",
+ "batteryZPM",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 64L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 64L)));
+ setElectricStats(32000 + tLastID, 2000000000000L, GT_Values.V[7], 7L, -2L, true);
+ registerTieredTooltip(ItemList.ZPM.get(1), ZPM);
+
+ // LuV Lapotron orb cluster battery
+ ItemList.Energy_LapotronicOrb2.set(
+ addItem(
+ tLastID = 599,
+ "Lapotronic Energy Orb Cluster",
+ "Reusable battery",
+ "batteryLuV",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 16L),
+ OrePrefixes.battery.get(Materials.Ultimate)));
+ setElectricStats(32000 + tLastID, 1000000000L, GT_Values.V[6], 6L, -3L, true);
+ registerTieredTooltip(ItemList.Energy_LapotronicOrb2.get(1), LuV);
+
+ // UV Battery
+ ItemList.ZPM2.set(
+ addItem(
+ tLastID = 605,
+ "Ultimate Battery",
+ "Fill this to win minecraft",
+ "batteryUV",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 64L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 64L)));
+ setElectricStats(32000 + tLastID, Long.MAX_VALUE, GT_Values.V[8], 8L, -3L, true);
+ registerTieredTooltip(ItemList.ZPM2.get(1), UV);
+
+ // UMV Battery
+ ItemList.ZPM3.set(
+ addItem(
+ tLastID = 609,
+ "Really Ultimate Battery",
+ "Fill this to be way older",
+ "batteryUMV",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 64L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 64L)));
+ setElectricStats(32000 + tLastID, Long.MAX_VALUE, GT_Values.V[12], 12L, -3L, true);
+ registerTieredTooltip(ItemList.ZPM3.get(1), UMV);
+
+ // UXV Battery
+ ItemList.ZPM4.set(
+ addItem(
+ tLastID = 594,
+ "Extremely Ultimate Battery",
+ "Fill this to be older",
+ "batteryUXV",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 64L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 64L)));
+ setElectricStats(32000 + tLastID, Long.MAX_VALUE, GT_Values.V[13], 13L, -3L, true);
+ registerTieredTooltip(ItemList.ZPM4.get(1), UXV);
+
+ // MAX Battery
+ ItemList.ZPM5.set(
+ addItem(
+ tLastID = 145,
+ "Insanely Ultimate Battery",
+ "Fill this for fun",
+ "batteryMAX",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 64L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 64L)));
+ setElectricStats(32000 + tLastID, Long.MAX_VALUE, GT_Values.V[14], 14L, -3L, true);
+ registerTieredTooltip(ItemList.ZPM5.get(1), MAX);
+
+ // ERROR Battery
+ ItemList.ZPM6.set(
+ addItem(
+ tLastID = 146,
+ "Mega Ultimate Battery",
+ "Fill the capacitor to reach enlightenment",
+ "batteryERV",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 64L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 64L)));
+ setElectricStats(32000 + tLastID, Long.MAX_VALUE, GT_Values.V[15], 15L, -3L, true);
+ registerTieredTooltip(ItemList.ZPM6.get(1), ERV);
+
+ // ZPM Cluster
+ ItemList.Energy_Module.set(
+ addItem(
+ tLastID = 736,
+ "Energy Module",
+ "Reusable battery",
+ "batteryZPM",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 16L),
+ OrePrefixes.battery.get(Materials.Ultimate)));
+ setElectricStats(32000 + tLastID, 10000000000L, GT_Values.V[7], 7L, -3L, true);
+ registerTieredTooltip(ItemList.Energy_Module.get(1), ZPM);
+
+ // UV Cluster
+ ItemList.Energy_Cluster.set(
+ addItem(
+ tLastID = 737,
+ "Energy Cluster",
+ "Reusable battery",
+ "batteryUV",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 64L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 64L)));
+ setElectricStats(32000 + tLastID, 100000000000L, GT_Values.V[8], 8L, -3L, true);
+ registerTieredTooltip(ItemList.Energy_Cluster.get(1), UV);
+
+ // UIV, UMV, UXV and MAX component textures backported from gregicality.
+ ItemList.Electric_Motor_LV.set(
+ addItem(
+ 600,
+ "Electric Motor (LV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 1L)));
+ ItemList.Electric_Motor_MV.set(
+ addItem(
+ 601,
+ "Electric Motor (MV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 2L)));
+ ItemList.Electric_Motor_HV.set(
+ addItem(
+ 602,
+ "Electric Motor (HV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 4L)));
+ ItemList.Electric_Motor_EV.set(
+ addItem(
+ 603,
+ "Electric Motor (EV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 8L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 8L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 8L)));
+ ItemList.Electric_Motor_IV.set(
+ addItem(
+ 604,
+ "Electric Motor (IV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 16L)));
+ ItemList.Electric_Motor_LuV.set(
+ addItem(
+ 606,
+ "Electric Motor (LuV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 32L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 32L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 32L)));
+ ItemList.Electric_Motor_ZPM.set(
+ addItem(
+ 607,
+ "Electric Motor (ZPM)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 64L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 64L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 64L)));
+ ItemList.Electric_Motor_UV.set(
+ addItem(
+ 608,
+ "Electric Motor (UV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 128L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 128L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 128L)));
+ ItemList.Electric_Motor_UHV.set(
+ addItem(
+ 596,
+ "Electric Motor (UHV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 256L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 256L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 256L)));
+ ItemList.Electric_Motor_UEV.set(
+ addItem(
+ 595,
+ "Electric Motor (UEV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 512L)));
+ ItemList.Electric_Motor_UIV.set(
+ addItem(
+ 17,
+ "Electric Motor (UIV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 512L)));
+ ItemList.Electric_Motor_UMV.set(
+ addItem(
+ 18,
+ "Electric Motor (UMV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 512L)));
+ ItemList.Electric_Motor_UXV.set(
+ addItem(
+ 19,
+ "Electric Motor (UXV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 512L)));
+ ItemList.Electric_Motor_MAX.set(
+ addItem(
+ 20,
+ "Electric Motor (MAX)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 512L)));
+
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Electric_Motor_LV.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "CWR", "WIW", "RWC", 'I', OrePrefixes.stick.get(Materials.IronMagnetic), 'R',
+ OrePrefixes.stick.get(Materials.AnyIron), 'W', OrePrefixes.wireGt01.get(Materials.AnyCopper), 'C',
+ OrePrefixes.cableGt01.get(Materials.Tin) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Electric_Motor_LV.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "CWR", "WIW", "RWC", 'I', OrePrefixes.stick.get(Materials.SteelMagnetic), 'R',
+ OrePrefixes.stick.get(Materials.Steel), 'W', OrePrefixes.wireGt01.get(Materials.AnyCopper), 'C',
+ OrePrefixes.cableGt01.get(Materials.Tin) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Electric_Motor_MV.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "CWR", "WIW", "RWC", 'I', OrePrefixes.stick.get(Materials.SteelMagnetic), 'R',
+ OrePrefixes.stick.get(Materials.Aluminium), 'W', OrePrefixes.wireGt02.get(Materials.Cupronickel), 'C',
+ OrePrefixes.cableGt01.get(Materials.AnyCopper) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Electric_Motor_HV.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "CWR", "WIW", "RWC", 'I', OrePrefixes.stick.get(Materials.SteelMagnetic), 'R',
+ OrePrefixes.stick.get(Materials.StainlessSteel), 'W', OrePrefixes.wireGt04.get(Materials.Electrum), 'C',
+ OrePrefixes.cableGt02.get(Materials.Silver) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Electric_Motor_EV.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "CWR", "WIW", "RWC", 'I', OrePrefixes.stick.get(Materials.NeodymiumMagnetic), 'R',
+ OrePrefixes.stick.get(Materials.Titanium), 'W', OrePrefixes.wireGt04.get(Materials.BlackSteel), 'C',
+ OrePrefixes.cableGt02.get(Materials.Aluminium) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Electric_Motor_IV.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "CWR", "WIW", "RWC", 'I', OrePrefixes.stick.get(Materials.NeodymiumMagnetic), 'R',
+ OrePrefixes.stick.get(Materials.TungstenSteel), 'W', OrePrefixes.wireGt04.get(Materials.Graphene), 'C',
+ OrePrefixes.cableGt02.get(Materials.Tungsten) });
+
+ ItemList.Tesseract.set(
+ addItem(
+ 415,
+ "Raw Tesseract",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 1L)));
+ ItemList.GigaChad.set(
+ addItem(
+ 416,
+ "Giga Chad Token",
+ "You are worthy",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.COGNITIO, 1000L)));
+ ItemList.EnergisedTesseract.set(
+ addItem(
+ 417,
+ "Energised Tesseract",
+ "Higher dimensional engineering",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 10L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 1L)));
+
+ ItemList.Electric_Piston_LV.set(
+ addItem(
+ 640,
+ "Electric Piston (LV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 1L)));
+ ItemList.Electric_Piston_MV.set(
+ addItem(
+ 641,
+ "Electric Piston (MV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 2L)));
+ ItemList.Electric_Piston_HV.set(
+ addItem(
+ 642,
+ "Electric Piston (HV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 8L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 4L)));
+ ItemList.Electric_Piston_EV.set(
+ addItem(
+ 643,
+ "Electric Piston (EV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 8L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 8L)));
+ ItemList.Electric_Piston_IV.set(
+ addItem(
+ 644,
+ "Electric Piston (IV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 32L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 16L)));
+ ItemList.Electric_Piston_LuV.set(
+ addItem(
+ 645,
+ "Electric Piston (LuV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 32L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 64L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 32L)));
+ ItemList.Electric_Piston_ZPM.set(
+ addItem(
+ 646,
+ "Electric Piston (ZPM)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 64L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 64L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 64L)));
+ ItemList.Electric_Piston_UV.set(
+ addItem(
+ 647,
+ "Electric Piston (UV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 128L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 128L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 128L)));
+ ItemList.Electric_Piston_UHV.set(
+ addItem(
+ 648,
+ "Electric Piston (UHV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 256L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 256L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 256L)));
+ ItemList.Electric_Piston_UEV.set(
+ addItem(
+ 649,
+ "Electric Piston (UEV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 512L)));
+ ItemList.Electric_Piston_UIV.set(
+ addItem(
+ 21,
+ "Electric Piston (UIV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 512L)));
+ ItemList.Electric_Piston_UMV.set(
+ addItem(
+ 22,
+ "Electric Piston (UMV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 512L)));
+ ItemList.Electric_Piston_UXV.set(
+ addItem(
+ 23,
+ "Electric Piston (UXV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 512L)));
+ ItemList.Electric_Piston_MAX.set(
+ addItem(
+ 24,
+ "Electric Piston (MAX)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 512L)));
+
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Electric_Piston_LV.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "PPP", "CSS", "CMG", 'P', OrePrefixes.plate.get(Materials.Steel), 'S',
+ OrePrefixes.stick.get(Materials.Steel), 'G', OrePrefixes.gearGtSmall.get(Materials.Steel), 'M',
+ ItemList.Electric_Motor_LV, 'C', OrePrefixes.cableGt01.get(Materials.Tin) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Electric_Piston_MV.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "PPP", "CSS", "CMG", 'P', OrePrefixes.plate.get(Materials.Aluminium), 'S',
+ OrePrefixes.stick.get(Materials.Aluminium), 'G', OrePrefixes.gearGtSmall.get(Materials.Aluminium), 'M',
+ ItemList.Electric_Motor_MV, 'C', OrePrefixes.cableGt01.get(Materials.AnyCopper) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Electric_Piston_HV.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "PPP", "CSS", "CMG", 'P', OrePrefixes.plate.get(Materials.StainlessSteel), 'S',
+ OrePrefixes.stick.get(Materials.StainlessSteel), 'G',
+ OrePrefixes.gearGtSmall.get(Materials.StainlessSteel), 'M', ItemList.Electric_Motor_HV, 'C',
+ OrePrefixes.cableGt01.get(Materials.Gold) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Electric_Piston_EV.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "PPP", "CSS", "CMG", 'P', OrePrefixes.plate.get(Materials.Titanium), 'S',
+ OrePrefixes.stick.get(Materials.Titanium), 'G', OrePrefixes.gearGtSmall.get(Materials.Titanium), 'M',
+ ItemList.Electric_Motor_EV, 'C', OrePrefixes.cableGt01.get(Materials.Aluminium) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Electric_Piston_IV.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "PPP", "CSS", "CMG", 'P', OrePrefixes.plate.get(Materials.TungstenSteel), 'S',
+ OrePrefixes.stick.get(Materials.TungstenSteel), 'G',
+ OrePrefixes.gearGtSmall.get(Materials.TungstenSteel), 'M', ItemList.Electric_Motor_IV, 'C',
+ OrePrefixes.cableGt01.get(Materials.Tungsten) });
+
+ ItemList.Electric_Pump_LV.set(
+ addItem(
+ 610,
+ "Electric Pump (LV)",
+ GT_Utility.formatNumbers(32) + PartCoverText + GT_Utility.formatNumbers(32 * 20) + PartCoverText2,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 1L)));
+ ItemList.Electric_Pump_MV.set(
+ addItem(
+ 611,
+ "Electric Pump (MV)",
+ GT_Utility.formatNumbers(128) + PartCoverText + GT_Utility.formatNumbers(128 * 20) + PartCoverText2,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 2L)));
+ ItemList.Electric_Pump_HV.set(
+ addItem(
+ 612,
+ "Electric Pump (HV)",
+ GT_Utility.formatNumbers(512) + PartCoverText + GT_Utility.formatNumbers(512 * 20) + PartCoverText2,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 4L)));
+ ItemList.Electric_Pump_EV.set(
+ addItem(
+ 613,
+ "Electric Pump (EV)",
+ GT_Utility.formatNumbers(2048) + PartCoverText + GT_Utility.formatNumbers(2048 * 20) + PartCoverText2,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 8L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 8L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 8L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 8L)));
+ ItemList.Electric_Pump_IV.set(
+ addItem(
+ 614,
+ "Electric Pump (IV)",
+ GT_Utility.formatNumbers(8192) + PartCoverText + GT_Utility.formatNumbers(8192 * 20) + PartCoverText2,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 16L)));
+ ItemList.Electric_Pump_LuV.set(
+ addItem(
+ 615,
+ "Electric Pump (LuV)",
+ GT_Utility.formatNumbers(32768) + PartCoverText + GT_Utility.formatNumbers(32768 * 20) + PartCoverText2,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 32L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 32L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 32L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 32L)));
+ ItemList.Electric_Pump_ZPM.set(
+ addItem(
+ 616,
+ "Electric Pump (ZPM)",
+ GT_Utility.formatNumbers(131072) + PartCoverText
+ + GT_Utility.formatNumbers(131072 * 20)
+ + PartCoverText2,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 64L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 64L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 64L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 64L)));
+ ItemList.Electric_Pump_UV.set(
+ addItem(
+ 617,
+ "Electric Pump (UV)",
+ GT_Utility.formatNumbers(524288) + PartCoverText
+ + GT_Utility.formatNumbers(524288 * 20)
+ + PartCoverText2,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 128L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 128L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 128L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 128L)));
+ ItemList.Electric_Pump_UHV.set(
+ addItem(
+ 618,
+ "Electric Pump (UHV)",
+ GT_Utility.formatNumbers(1048576) + PartCoverText
+ + GT_Utility.formatNumbers(1048576 * 20)
+ + PartCoverText2,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 256L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 256L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 256L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 256L)));
+ ItemList.Electric_Pump_UEV.set(
+ addItem(
+ 619,
+ "Electric Pump (UEV)",
+ GT_Utility.formatNumbers(2097152) + PartCoverText
+ + GT_Utility.formatNumbers(2097152 * 20)
+ + PartCoverText2,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 512L)));
+ ItemList.Electric_Pump_UIV.set(
+ addItem(
+ 25,
+ "Electric Pump (UIV)",
+ PartNotCoverText,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 512L)));
+ ItemList.Electric_Pump_UMV.set(
+ addItem(
+ 26,
+ "Electric Pump (UMV)",
+ PartNotCoverText,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 512L)));
+ ItemList.Electric_Pump_UXV.set(
+ addItem(
+ 27,
+ "Electric Pump (UXV)",
+ PartNotCoverText,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 512L)));
+ ItemList.Electric_Pump_MAX.set(
+ addItem(
+ 28,
+ "Electric Pump (MAX)",
+ PartNotCoverText,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 512L)));
+
+ GregTech_API.registerCover(
+ ItemList.Electric_Pump_LV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[1][0], TextureFactory.of(OVERLAY_PUMP)),
+ new GT_Cover_Pump(32, TextureFactory.of(OVERLAY_PUMP)));
+ GregTech_API.registerCover(
+ ItemList.Electric_Pump_MV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[2][0], TextureFactory.of(OVERLAY_PUMP)),
+ new GT_Cover_Pump(128, TextureFactory.of(OVERLAY_PUMP)));
+ GregTech_API.registerCover(
+ ItemList.Electric_Pump_HV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[3][0], TextureFactory.of(OVERLAY_PUMP)),
+ new GT_Cover_Pump(512, TextureFactory.of(OVERLAY_PUMP)));
+ GregTech_API.registerCover(
+ ItemList.Electric_Pump_EV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[4][0], TextureFactory.of(OVERLAY_PUMP)),
+ new GT_Cover_Pump(2048, TextureFactory.of(OVERLAY_PUMP)));
+ GregTech_API.registerCover(
+ ItemList.Electric_Pump_IV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[5][0], TextureFactory.of(OVERLAY_PUMP)),
+ new GT_Cover_Pump(8192, TextureFactory.of(OVERLAY_PUMP)));
+ GregTech_API.registerCover(
+ ItemList.Electric_Pump_LuV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[6][0], TextureFactory.of(OVERLAY_PUMP)),
+ new GT_Cover_Pump(32768, TextureFactory.of(OVERLAY_PUMP)));
+ GregTech_API.registerCover(
+ ItemList.Electric_Pump_ZPM.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[7][0], TextureFactory.of(OVERLAY_PUMP)),
+ new GT_Cover_Pump(131072, TextureFactory.of(OVERLAY_PUMP)));
+ GregTech_API.registerCover(
+ ItemList.Electric_Pump_UV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[8][0], TextureFactory.of(OVERLAY_PUMP)),
+ new GT_Cover_Pump(524288, TextureFactory.of(OVERLAY_PUMP)));
+ GregTech_API.registerCover(
+ ItemList.Electric_Pump_UHV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[9][0], TextureFactory.of(OVERLAY_PUMP)),
+ new GT_Cover_Pump(1048576, TextureFactory.of(OVERLAY_PUMP)));
+ GregTech_API.registerCover(
+ ItemList.Electric_Pump_UEV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[10][0], TextureFactory.of(OVERLAY_PUMP)),
+ new GT_Cover_Pump(2097152, TextureFactory.of(OVERLAY_PUMP)));
+
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Electric_Pump_LV.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "SXO", "dPw", "OMW", 'M', ItemList.Electric_Motor_LV, 'O',
+ OrePrefixes.ring.get(Materials.AnyRubber), 'X', OrePrefixes.rotor.get(Materials.Tin), 'S',
+ OrePrefixes.screw.get(Materials.Tin), 'W', OrePrefixes.cableGt01.get(Materials.Tin), 'P',
+ OrePrefixes.pipeMedium.get(Materials.Bronze) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Electric_Pump_MV.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "SXO", "dPw", "OMW", 'M', ItemList.Electric_Motor_MV, 'O',
+ OrePrefixes.ring.get(Materials.AnyRubber), 'X', OrePrefixes.rotor.get(Materials.Bronze), 'S',
+ OrePrefixes.screw.get(Materials.Bronze), 'W', OrePrefixes.cableGt01.get(Materials.AnyCopper), 'P',
+ OrePrefixes.pipeMedium.get(Materials.Steel) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Electric_Pump_HV.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "SXO", "dPw", "OMW", 'M', ItemList.Electric_Motor_HV, 'O',
+ OrePrefixes.ring.get(Materials.AnyRubber), 'X', OrePrefixes.rotor.get(Materials.Steel), 'S',
+ OrePrefixes.screw.get(Materials.Steel), 'W', OrePrefixes.cableGt01.get(Materials.Gold), 'P',
+ OrePrefixes.pipeMedium.get(Materials.StainlessSteel) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Electric_Pump_EV.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "SXO", "dPw", "OMW", 'M', ItemList.Electric_Motor_EV, 'O',
+ OrePrefixes.ring.get(Materials.AnyRubber), 'X', OrePrefixes.rotor.get(Materials.StainlessSteel), 'S',
+ OrePrefixes.screw.get(Materials.StainlessSteel), 'W', OrePrefixes.cableGt01.get(Materials.Aluminium),
+ 'P', OrePrefixes.pipeMedium.get(Materials.Titanium) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Electric_Pump_IV.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "SXO", "dPw", "OMW", 'M', ItemList.Electric_Motor_IV, 'O',
+ OrePrefixes.ring.get(Materials.AnySyntheticRubber), 'X', OrePrefixes.rotor.get(Materials.TungstenSteel),
+ 'S', OrePrefixes.screw.get(Materials.TungstenSteel), 'W', OrePrefixes.cableGt01.get(Materials.Tungsten),
+ 'P', OrePrefixes.pipeMedium.get(Materials.TungstenSteel) });
+
+ ItemList.Steam_Valve_LV.set(
+ addItem(
+ 620,
+ "Steam Valve (LV)",
+ GT_Utility.formatNumbers(1024) + PartCoverText + GT_Utility.formatNumbers(1024 * 20) + PartCoverText2,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 1L)));
+ ItemList.Steam_Valve_MV.set(
+ addItem(
+ 621,
+ "Steam Valve (MV)",
+ GT_Utility.formatNumbers(2048) + PartCoverText + GT_Utility.formatNumbers(2048 * 20) + PartCoverText2,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 2L)));
+ ItemList.Steam_Valve_HV.set(
+ addItem(
+ 622,
+ "Steam Valve (HV)",
+ GT_Utility.formatNumbers(4096) + PartCoverText + GT_Utility.formatNumbers(4096 * 20) + PartCoverText2,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 4L)));
+ ItemList.Steam_Valve_EV.set(
+ addItem(
+ 623,
+ "Steam Valve (EV)",
+ GT_Utility.formatNumbers(8192) + PartCoverText + GT_Utility.formatNumbers(8192 * 20) + PartCoverText2,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 8L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 8L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 8L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 8L)));
+ ItemList.Steam_Valve_IV.set(
+ addItem(
+ 624,
+ "Steam Valve (IV)",
+ GT_Utility.formatNumbers(16384) + PartCoverText + GT_Utility.formatNumbers(16384 * 20) + PartCoverText2,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 16L)));
+
+ GregTech_API.registerCover(
+ ItemList.Steam_Valve_LV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[1][0], TextureFactory.of(OVERLAY_VALVE)),
+ new GT_Cover_SteamValve(1024, TextureFactory.of(OVERLAY_VALVE)));
+ GregTech_API.registerCover(
+ ItemList.Steam_Valve_MV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[2][0], TextureFactory.of(OVERLAY_VALVE)),
+ new GT_Cover_SteamValve(2048, TextureFactory.of(OVERLAY_VALVE)));
+ GregTech_API.registerCover(
+ ItemList.Steam_Valve_HV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[3][0], TextureFactory.of(OVERLAY_VALVE)),
+ new GT_Cover_SteamValve(4096, TextureFactory.of(OVERLAY_VALVE)));
+ GregTech_API.registerCover(
+ ItemList.Steam_Valve_EV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[4][0], TextureFactory.of(OVERLAY_VALVE)),
+ new GT_Cover_SteamValve(8192, TextureFactory.of(OVERLAY_VALVE)));
+ GregTech_API.registerCover(
+ ItemList.Steam_Valve_IV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[5][0], TextureFactory.of(OVERLAY_VALVE)),
+ new GT_Cover_SteamValve(16384, TextureFactory.of(OVERLAY_VALVE)));
+
+ ItemList.FluidRegulator_LV
+ .set(addItem(tLastID = 660, "Fluid Regulator (LV)", FRText1 + GT_Utility.formatNumbers(640) + FRText2));
+ ItemList.FluidRegulator_MV
+ .set(addItem(tLastID = 661, "Fluid Regulator (MV)", FRText1 + GT_Utility.formatNumbers(2560) + FRText2));
+ ItemList.FluidRegulator_HV
+ .set(addItem(tLastID = 662, "Fluid Regulator (HV)", FRText1 + GT_Utility.formatNumbers(10240) + FRText2));
+ ItemList.FluidRegulator_EV
+ .set(addItem(tLastID = 663, "Fluid Regulator (EV)", FRText1 + GT_Utility.formatNumbers(40960) + FRText2));
+ ItemList.FluidRegulator_IV
+ .set(addItem(tLastID = 664, "Fluid Regulator (IV)", FRText1 + GT_Utility.formatNumbers(163840) + FRText2));
+ ItemList.FluidRegulator_LuV
+ .set(addItem(tLastID = 665, "Fluid Regulator (LuV)", FRText1 + GT_Utility.formatNumbers(655360) + FRText2));
+ ItemList.FluidRegulator_ZPM.set(
+ addItem(tLastID = 666, "Fluid Regulator (ZPM)", FRText1 + GT_Utility.formatNumbers(2621440) + FRText2));
+ ItemList.FluidRegulator_UV.set(
+ addItem(tLastID = 667, "Fluid Regulator (UV)", FRText1 + GT_Utility.formatNumbers(10485760) + FRText2));
+
+ GregTech_API.registerCover(
+ ItemList.FluidRegulator_LV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[1][0], TextureFactory.of(OVERLAY_PUMP)),
+ new GT_Cover_FluidRegulator(32, TextureFactory.of(OVERLAY_PUMP)));
+ GregTech_API.registerCover(
+ ItemList.FluidRegulator_MV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[2][0], TextureFactory.of(OVERLAY_PUMP)),
+ new GT_Cover_FluidRegulator(128, TextureFactory.of(OVERLAY_PUMP)));
+ GregTech_API.registerCover(
+ ItemList.FluidRegulator_HV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[3][0], TextureFactory.of(OVERLAY_PUMP)),
+ new GT_Cover_FluidRegulator(512, TextureFactory.of(OVERLAY_PUMP)));
+ GregTech_API.registerCover(
+ ItemList.FluidRegulator_EV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[4][0], TextureFactory.of(OVERLAY_PUMP)),
+ new GT_Cover_FluidRegulator(2048, TextureFactory.of(OVERLAY_PUMP)));
+ GregTech_API.registerCover(
+ ItemList.FluidRegulator_IV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[5][0], TextureFactory.of(OVERLAY_PUMP)),
+ new GT_Cover_FluidRegulator(8192, TextureFactory.of(OVERLAY_PUMP)));
+ GregTech_API.registerCover(
+ ItemList.FluidRegulator_LuV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[6][0], TextureFactory.of(OVERLAY_PUMP)),
+ new GT_Cover_FluidRegulator(32768, TextureFactory.of(OVERLAY_PUMP)));
+ GregTech_API.registerCover(
+ ItemList.FluidRegulator_ZPM.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[7][0], TextureFactory.of(OVERLAY_PUMP)),
+ new GT_Cover_FluidRegulator(131072, TextureFactory.of(OVERLAY_PUMP)));
+ GregTech_API.registerCover(
+ ItemList.FluidRegulator_UV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[8][0], TextureFactory.of(OVERLAY_PUMP)),
+ new GT_Cover_FluidRegulator(524288, TextureFactory.of(OVERLAY_PUMP)));
+
+ ItemList.FluidFilter
+ .set(addItem(669, "Fluid Filter Cover", "Set with Fluid Container to only accept one Fluid Type"));
+ GregTech_API.registerCover(
+ ItemList.FluidFilter.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[1][0], TextureFactory.of(OVERLAY_SHUTTER)),
+ new GT_Cover_Fluidfilter(TextureFactory.of(OVERLAY_SHUTTER)));
+ ItemList.ItemFilter_Export.set(
+ addItem(
+ 270,
+ "Item Filter Cover (Export)",
+ "Right click with an item to set filter (Only supports Export Mode)"));
+ GregTech_API.registerCover(
+ ItemList.ItemFilter_Export.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[5][0], TextureFactory.of(OVERLAY_CONVEYOR)),
+ new GT_Cover_ItemFilter(true, TextureFactory.of(OVERLAY_CONVEYOR)));
+ ItemList.ItemFilter_Import.set(
+ addItem(
+ 271,
+ "Item Filter Cover (Import)",
+ "Right click with an item to set filter (Only supports Import Mode)"));
+ GregTech_API.registerCover(
+ ItemList.ItemFilter_Import.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[5][0], TextureFactory.of(OVERLAY_CONVEYOR)),
+ new GT_Cover_ItemFilter(false, TextureFactory.of(OVERLAY_CONVEYOR)));
+ ItemList.Cover_FluidLimiter
+ .set(addItem(272, "Fluid Limiter Cover", "Limits fluid input depending on fill level"));
+ GregTech_API.registerCover(
+ ItemList.Cover_FluidLimiter.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[1][0], TextureFactory.of(OVERLAY_SHUTTER)),
+ new GT_Cover_FluidLimiter(TextureFactory.of(OVERLAY_SHUTTER)));
+
+ ItemList.Conveyor_Module_LV.set(
+ addItem(
+ 630,
+ "Conveyor Module (LV)",
+ "1 stack every 20 secs (as Cover)",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 1L)));
+ ItemList.Conveyor_Module_MV.set(
+ addItem(
+ 631,
+ "Conveyor Module (MV)",
+ "1 stack every 5 secs (as Cover)",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 2L)));
+ ItemList.Conveyor_Module_HV.set(
+ addItem(
+ 632,
+ "Conveyor Module (HV)",
+ "1 stack every 1 sec (as Cover)",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 4L)));
+ ItemList.Conveyor_Module_EV.set(
+ addItem(
+ 633,
+ "Conveyor Module (EV)",
+ "1 stack every 1/5 sec (as Cover)",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 8L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 8L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 8L)));
+ ItemList.Conveyor_Module_IV.set(
+ addItem(
+ 634,
+ "Conveyor Module (IV)",
+ "1 stack every 1/20 sec (as Cover)",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 16L)));
+ ItemList.Conveyor_Module_LuV.set(
+ addItem(
+ 635,
+ "Conveyor Module (LuV)",
+ "2 stacks every 1/20 sec (as Cover)",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 32L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 32L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 32L)));
+ ItemList.Conveyor_Module_ZPM.set(
+ addItem(
+ 636,
+ "Conveyor Module (ZPM)",
+ "4 stacks every 1/20 sec (as Cover)",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 64L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 64L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 64L)));
+ ItemList.Conveyor_Module_UV.set(
+ addItem(
+ 637,
+ "Conveyor Module (UV)",
+ "8 stacks every 1/20 sec (as Cover)",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 128L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 128L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 128L)));
+ ItemList.Conveyor_Module_UHV.set(
+ addItem(
+ 638,
+ "Conveyor Module (UHV)",
+ "16 stacks every 1/20 sec (as Cover)",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 256L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 256L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 256L)));
+ ItemList.Conveyor_Module_UEV.set(
+ addItem(
+ 639,
+ "Conveyor Module (UEV)",
+ "32 stacks every 1/20 sec (as Cover)",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 512L)));
+ ItemList.Conveyor_Module_UIV.set(
+ addItem(
+ 29,
+ "Conveyor Module (UIV)",
+ PartNotCoverText,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 512L)));
+ ItemList.Conveyor_Module_UMV.set(
+ addItem(
+ 30,
+ "Conveyor Module (UMV)",
+ PartNotCoverText,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 512L)));
+ ItemList.Conveyor_Module_UXV.set(
+ addItem(
+ 31,
+ "Conveyor Module (UXV)",
+ PartNotCoverText,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 512L)));
+ ItemList.Conveyor_Module_MAX.set(
+ addItem(
+ 32,
+ "Conveyor Module (MAX)",
+ PartNotCoverText,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 512L)));
+
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Conveyor_Module_LV.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "RRR", "MCM", "RRR", 'M', ItemList.Electric_Motor_LV, 'C',
+ OrePrefixes.cableGt01.get(Materials.Tin), 'R', OrePrefixes.plate.get(Materials.AnyRubber) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Conveyor_Module_MV.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "RRR", "MCM", "RRR", 'M', ItemList.Electric_Motor_MV, 'C',
+ OrePrefixes.cableGt01.get(Materials.AnyCopper), 'R', OrePrefixes.plate.get(Materials.AnyRubber) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Conveyor_Module_HV.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "RRR", "MCM", "RRR", 'M', ItemList.Electric_Motor_HV, 'C',
+ OrePrefixes.cableGt01.get(Materials.Gold), 'R', OrePrefixes.plate.get(Materials.AnyRubber) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Conveyor_Module_EV.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "RRR", "MCM", "RRR", 'M', ItemList.Electric_Motor_EV, 'C',
+ OrePrefixes.cableGt01.get(Materials.Aluminium), 'R', OrePrefixes.plate.get(Materials.AnyRubber) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Conveyor_Module_IV.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "RRR", "MCM", "RRR", 'M', ItemList.Electric_Motor_IV, 'C',
+ OrePrefixes.cableGt01.get(Materials.Tungsten), 'R',
+ OrePrefixes.plate.get(Materials.AnySyntheticRubber) });
+
+ GregTech_API.registerCover(
+ ItemList.Conveyor_Module_LV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[1][0], TextureFactory.of(OVERLAY_CONVEYOR)),
+ new GT_Cover_Conveyor(400, 1, TextureFactory.of(OVERLAY_CONVEYOR)));
+ GregTech_API.registerCover(
+ ItemList.Conveyor_Module_MV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[2][0], TextureFactory.of(OVERLAY_CONVEYOR)),
+ new GT_Cover_Conveyor(100, 1, TextureFactory.of(OVERLAY_CONVEYOR)));
+ GregTech_API.registerCover(
+ ItemList.Conveyor_Module_HV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[3][0], TextureFactory.of(OVERLAY_CONVEYOR)),
+ new GT_Cover_Conveyor(20, 1, TextureFactory.of(OVERLAY_CONVEYOR)));
+ GregTech_API.registerCover(
+ ItemList.Conveyor_Module_EV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[4][0], TextureFactory.of(OVERLAY_CONVEYOR)),
+ new GT_Cover_Conveyor(4, 1, TextureFactory.of(OVERLAY_CONVEYOR)));
+ GregTech_API.registerCover(
+ ItemList.Conveyor_Module_IV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[5][0], TextureFactory.of(OVERLAY_CONVEYOR)),
+ new GT_Cover_Conveyor(1, 1, TextureFactory.of(OVERLAY_CONVEYOR)));
+ GregTech_API.registerCover(
+ ItemList.Conveyor_Module_LuV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[6][0], TextureFactory.of(OVERLAY_CONVEYOR)),
+ new GT_Cover_Conveyor(1, 2, TextureFactory.of(OVERLAY_CONVEYOR)));
+ GregTech_API.registerCover(
+ ItemList.Conveyor_Module_ZPM.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[7][0], TextureFactory.of(OVERLAY_CONVEYOR)),
+ new GT_Cover_Conveyor(1, 4, TextureFactory.of(OVERLAY_CONVEYOR)));
+ GregTech_API.registerCover(
+ ItemList.Conveyor_Module_UV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[8][0], TextureFactory.of(OVERLAY_CONVEYOR)),
+ new GT_Cover_Conveyor(1, 8, TextureFactory.of(OVERLAY_CONVEYOR)));
+ GregTech_API.registerCover(
+ ItemList.Conveyor_Module_UHV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[9][0], TextureFactory.of(OVERLAY_CONVEYOR)),
+ new GT_Cover_Conveyor(1, 16, TextureFactory.of(OVERLAY_CONVEYOR)));
+ GregTech_API.registerCover(
+ ItemList.Conveyor_Module_UEV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[10][0], TextureFactory.of(OVERLAY_CONVEYOR)),
+ new GT_Cover_Conveyor(1, 32, TextureFactory.of(OVERLAY_CONVEYOR)));
+
+ ItemList.Robot_Arm_LV.set(
+ addItem(
+ 650,
+ "Robot Arm (LV)",
+ "1 stack every 20 secs (as Cover)/n " + RAText,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.COGNITIO, 1L)));
+ ItemList.Robot_Arm_MV.set(
+ addItem(
+ 651,
+ "Robot Arm (MV)",
+ "1 stack every 5 secs (as Cover)/n " + RAText,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.COGNITIO, 2L)));
+ ItemList.Robot_Arm_HV.set(
+ addItem(
+ 652,
+ "Robot Arm (HV)",
+ "1 stack every 1 sec (as Cover)/n " + RAText,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 8L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.COGNITIO, 4L)));
+ ItemList.Robot_Arm_EV.set(
+ addItem(
+ 653,
+ "Robot Arm (EV)",
+ "1 stack every 1/5 sec (as Cover)/n " + RAText,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 8L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 8L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.COGNITIO, 8L)));
+ ItemList.Robot_Arm_IV.set(
+ addItem(
+ 654,
+ "Robot Arm (IV)",
+ "1 stack every 1/20 sec (as Cover)/n " + RAText,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 32L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.COGNITIO, 16L)));
+ ItemList.Robot_Arm_LuV.set(
+ addItem(
+ 655,
+ "Robot Arm (LuV)",
+ PartNotCoverText,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 32L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 64L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 32L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.COGNITIO, 32L)));
+ ItemList.Robot_Arm_ZPM.set(
+ addItem(
+ 656,
+ "Robot Arm (ZPM)",
+ PartNotCoverText,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 64L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 128L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 64L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.COGNITIO, 64L)));
+ ItemList.Robot_Arm_UV.set(
+ addItem(
+ 657,
+ "Robot Arm (UV)",
+ PartNotCoverText,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 128L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 256L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 128L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.COGNITIO, 128L)));
+ ItemList.Robot_Arm_UHV.set(
+ addItem(
+ 658,
+ "Robot Arm (UHV)",
+ PartNotCoverText,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 256L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 256L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.COGNITIO, 256L)));
+ ItemList.Robot_Arm_UEV.set(
+ addItem(
+ 659,
+ "Robot Arm (UEV)",
+ PartNotCoverText,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 1024L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.COGNITIO, 512L)));
+ ItemList.Robot_Arm_UIV.set(
+ addItem(
+ 33,
+ "Robot Arm (UIV)",
+ PartNotCoverText,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 1024L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.COGNITIO, 512L)));
+ ItemList.Robot_Arm_UMV.set(
+ addItem(
+ 34,
+ "Robot Arm (UMV)",
+ PartNotCoverText,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 1024L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.COGNITIO, 512L)));
+ ItemList.Robot_Arm_UXV.set(
+ addItem(
+ 35,
+ "Robot Arm (UXV)",
+ PartNotCoverText,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 1024L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.COGNITIO, 512L)));
+ ItemList.Robot_Arm_MAX.set(
+ addItem(
+ 36,
+ "Robot Arm (MAX)",
+ PartNotCoverText,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 1024L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.COGNITIO, 512L)));
+
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Robot_Arm_LV.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "CCC", "MSM", "PES", 'S', OrePrefixes.stick.get(Materials.Steel), 'M',
+ ItemList.Electric_Motor_LV, 'P', ItemList.Electric_Piston_LV, 'E',
+ OrePrefixes.circuit.get(Materials.Basic), 'C', OrePrefixes.cableGt01.get(Materials.Tin) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Robot_Arm_MV.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "CCC", "MSM", "PES", 'S', OrePrefixes.stick.get(Materials.Aluminium), 'M',
+ ItemList.Electric_Motor_MV, 'P', ItemList.Electric_Piston_MV, 'E',
+ OrePrefixes.circuit.get(Materials.Good), 'C', OrePrefixes.cableGt01.get(Materials.AnyCopper) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Robot_Arm_HV.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "CCC", "MSM", "PES", 'S', OrePrefixes.stick.get(Materials.StainlessSteel), 'M',
+ ItemList.Electric_Motor_HV, 'P', ItemList.Electric_Piston_HV, 'E',
+ OrePrefixes.circuit.get(Materials.Advanced), 'C', OrePrefixes.cableGt01.get(Materials.Gold) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Robot_Arm_EV.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "CCC", "MSM", "PES", 'S', OrePrefixes.stick.get(Materials.Titanium), 'M',
+ ItemList.Electric_Motor_EV, 'P', ItemList.Electric_Piston_EV, 'E',
+ OrePrefixes.circuit.get(Materials.Data), 'C', OrePrefixes.cableGt01.get(Materials.Aluminium) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Robot_Arm_IV.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "CCC", "MSM", "PES", 'S', OrePrefixes.stick.get(Materials.TungstenSteel), 'M',
+ ItemList.Electric_Motor_IV, 'P', ItemList.Electric_Piston_IV, 'E',
+ OrePrefixes.circuit.get(Materials.Elite), 'C', OrePrefixes.cableGt01.get(Materials.Tungsten) });
+
+ GregTech_API.registerCover(
+ ItemList.Robot_Arm_LV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[1][0], TextureFactory.of(OVERLAY_ARM)),
+ new GT_Cover_Arm(400, TextureFactory.of(OVERLAY_ARM)));
+ GregTech_API.registerCover(
+ ItemList.Robot_Arm_MV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[2][0], TextureFactory.of(OVERLAY_ARM)),
+ new GT_Cover_Arm(100, TextureFactory.of(OVERLAY_ARM)));
+ GregTech_API.registerCover(
+ ItemList.Robot_Arm_HV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[3][0], TextureFactory.of(OVERLAY_ARM)),
+ new GT_Cover_Arm(20, TextureFactory.of(OVERLAY_ARM)));
+ GregTech_API.registerCover(
+ ItemList.Robot_Arm_EV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[4][0], TextureFactory.of(OVERLAY_ARM)),
+ new GT_Cover_Arm(4, TextureFactory.of(OVERLAY_ARM)));
+ GregTech_API.registerCover(
+ ItemList.Robot_Arm_IV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[5][0], TextureFactory.of(OVERLAY_ARM)),
+ new GT_Cover_Arm(1, TextureFactory.of(OVERLAY_ARM)));
+
+ ItemList.QuantumEye.set(addItem(tLastID = 724, "Quantum Eye", "Improved Ender Eye"));
+ ItemList.QuantumStar.set(addItem(tLastID = 725, "Quantum Star", "Improved Nether Star"));
+ ItemList.Gravistar.set(addItem(tLastID = 726, "Gravi Star", "Ultimate Nether Star"));
+
+ ItemList.Emitter_LV.set(
+ addItem(
+ 680,
+ "Emitter (LV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.LUX, 1L)));
+ ItemList.Emitter_MV.set(
+ addItem(
+ 681,
+ "Emitter (MV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.LUX, 2L)));
+ ItemList.Emitter_HV.set(
+ addItem(
+ 682,
+ "Emitter (HV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.LUX, 4L)));
+ ItemList.Emitter_EV.set(
+ addItem(
+ 683,
+ "Emitter (EV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 8L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 8L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.LUX, 8L)));
+ ItemList.Emitter_IV.set(
+ addItem(
+ 684,
+ "Emitter (IV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.LUX, 16L)));
+ ItemList.Emitter_LuV.set(
+ addItem(
+ 685,
+ "Emitter (LuV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 32L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 32L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.LUX, 32L)));
+ ItemList.Emitter_ZPM.set(
+ addItem(
+ 686,
+ "Emitter (ZPM)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 64L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 64L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.LUX, 64L)));
+ ItemList.Emitter_UV.set(
+ addItem(
+ 687,
+ "Emitter (UV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 128L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 128L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.LUX, 128L)));
+ ItemList.Emitter_UHV.set(
+ addItem(
+ 688,
+ "Emitter (UHV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 256L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 256L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.LUX, 256L)));
+ ItemList.Emitter_UEV.set(
+ addItem(
+ 689,
+ "Emitter (UEV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.LUX, 512L)));
+ ItemList.Emitter_UIV.set(
+ addItem(
+ 37,
+ "Emitter (UIV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.LUX, 512L)));
+ ItemList.Emitter_UMV.set(
+ addItem(
+ 38,
+ "Emitter (UMV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.LUX, 512L)));
+ ItemList.Emitter_UXV.set(
+ addItem(
+ 39,
+ "Emitter (UXV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.LUX, 512L)));
+ ItemList.Emitter_MAX.set(
+ addItem(
+ 40,
+ "Emitter (MAX)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.LUX, 512L)));
+
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Emitter_LV.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "SSC", "WQS", "CWS", 'Q', OrePrefixes.gem.get(Materials.CertusQuartz), 'S',
+ OrePrefixes.stick.get(Materials.Brass), 'C', OrePrefixes.circuit.get(Materials.Basic), 'W',
+ OrePrefixes.cableGt01.get(Materials.Tin) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Emitter_MV.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "SSC", "WQS", "CWS", 'Q', OrePrefixes.gem.get(Materials.EnderPearl), 'S',
+ OrePrefixes.stick.get(Materials.Electrum), 'C', OrePrefixes.circuit.get(Materials.Good), 'W',
+ OrePrefixes.cableGt01.get(Materials.AnyCopper) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Emitter_HV.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "SSC", "WQS", "CWS", 'Q', OrePrefixes.gem.get(Materials.EnderEye), 'S',
+ OrePrefixes.stick.get(Materials.Chrome), 'C', OrePrefixes.circuit.get(Materials.Advanced), 'W',
+ OrePrefixes.cableGt01.get(Materials.Gold) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Emitter_EV.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "SSC", "WQS", "CWS", 'Q', ItemList.QuantumEye, 'S',
+ OrePrefixes.stick.get(Materials.Platinum), 'C', OrePrefixes.circuit.get(Materials.Data), 'W',
+ OrePrefixes.cableGt01.get(Materials.Aluminium) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Emitter_IV.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "SSC", "WQS", "CWS", 'Q', ItemList.QuantumStar, 'S',
+ OrePrefixes.stick.get(Materials.Iridium), 'C', OrePrefixes.circuit.get(Materials.Elite), 'W',
+ OrePrefixes.cableGt01.get(Materials.Tungsten) });
+
+ ItemList.Sensor_LV.set(
+ addItem(
+ 690,
+ "Sensor (LV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SENSUS, 1L)));
+ ItemList.Sensor_MV.set(
+ addItem(
+ 691,
+ "Sensor (MV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SENSUS, 2L)));
+ ItemList.Sensor_HV.set(
+ addItem(
+ 692,
+ "Sensor (HV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SENSUS, 4L)));
+ ItemList.Sensor_EV.set(
+ addItem(
+ 693,
+ "Sensor (EV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 8L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 8L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SENSUS, 8L)));
+ ItemList.Sensor_IV.set(
+ addItem(
+ 694,
+ "Sensor (IV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SENSUS, 16L)));
+ ItemList.Sensor_LuV.set(
+ addItem(
+ 695,
+ "Sensor (LuV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 32L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 32L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SENSUS, 32L)));
+ ItemList.Sensor_ZPM.set(
+ addItem(
+ 696,
+ "Sensor (ZPM)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 64L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 64L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SENSUS, 64L)));
+ ItemList.Sensor_UV.set(
+ addItem(
+ 697,
+ "Sensor (UV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 128L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 128L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SENSUS, 128L)));
+ ItemList.Sensor_UHV.set(
+ addItem(
+ 698,
+ "Sensor (UHV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 256L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 256L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SENSUS, 256L)));
+ ItemList.Sensor_UEV.set(
+ addItem(
+ 699,
+ "Sensor (UEV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SENSUS, 512L)));
+ ItemList.Sensor_UIV.set(
+ addItem(
+ 41,
+ "Sensor (UIV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SENSUS, 512L)));
+ ItemList.Sensor_UMV.set(
+ addItem(
+ 42,
+ "Sensor (UMV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SENSUS, 512L)));
+ ItemList.Sensor_UXV.set(
+ addItem(
+ 43,
+ "Sensor (UXV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SENSUS, 512L)));
+ ItemList.Sensor_MAX.set(
+ addItem(
+ 44,
+ "Sensor (MAX)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SENSUS, 512L)));
+
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Sensor_LV.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "P Q", "PS ", "CPP", 'Q', OrePrefixes.gem.get(Materials.CertusQuartz), 'S',
+ OrePrefixes.stick.get(Materials.Brass), 'P', OrePrefixes.plate.get(Materials.Steel), 'C',
+ OrePrefixes.circuit.get(Materials.Basic) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Sensor_MV.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "P Q", "PS ", "CPP", 'Q', OrePrefixes.gemFlawless.get(Materials.Emerald), 'S',
+ OrePrefixes.stick.get(Materials.Electrum), 'P', OrePrefixes.plate.get(Materials.Aluminium), 'C',
+ OrePrefixes.circuit.get(Materials.Good) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Sensor_HV.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "P Q", "PS ", "CPP", 'Q', OrePrefixes.gem.get(Materials.EnderEye), 'S',
+ OrePrefixes.stick.get(Materials.Chrome), 'P', OrePrefixes.plate.get(Materials.StainlessSteel), 'C',
+ OrePrefixes.circuit.get(Materials.Advanced) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Sensor_EV.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "P Q", "PS ", "CPP", 'Q', ItemList.QuantumEye, 'S',
+ OrePrefixes.stick.get(Materials.Platinum), 'P', OrePrefixes.plate.get(Materials.Titanium), 'C',
+ OrePrefixes.circuit.get(Materials.Data) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Sensor_IV.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "P Q", "PS ", "CPP", 'Q', ItemList.QuantumStar, 'S',
+ OrePrefixes.stick.get(Materials.Iridium), 'P', OrePrefixes.plate.get(Materials.TungstenSteel), 'C',
+ OrePrefixes.circuit.get(Materials.Elite) });
+
+ ItemList.Field_Generator_LV.set(
+ addItem(
+ 670,
+ "Field Generator (LV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TUTAMEN, 1L)));
+ ItemList.Field_Generator_MV.set(
+ addItem(
+ 671,
+ "Field Generator (MV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TUTAMEN, 2L)));
+ ItemList.Field_Generator_HV.set(
+ addItem(
+ 672,
+ "Field Generator (HV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 8L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TUTAMEN, 4L)));
+ ItemList.Field_Generator_EV.set(
+ addItem(
+ 673,
+ "Field Generator (EV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 8L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TUTAMEN, 8L)));
+ ItemList.Field_Generator_IV.set(
+ addItem(
+ 674,
+ "Field Generator (IV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 32L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TUTAMEN, 16L)));
+ ItemList.Field_Generator_LuV.set(
+ addItem(
+ 675,
+ "Field Generator (LuV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 64L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 32L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TUTAMEN, 32L)));
+ ItemList.Field_Generator_ZPM.set(
+ addItem(
+ 676,
+ "Field Generator (ZPM)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 128L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 64L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TUTAMEN, 64L)));
+ ItemList.Field_Generator_UV.set(
+ addItem(
+ 677,
+ "Field Generator (UV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 256L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 128L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TUTAMEN, 128L)));
+ ItemList.Field_Generator_UHV.set(
+ addItem(
+ 678,
+ "Field Generator (UHV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 256L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TUTAMEN, 256L)));
+ ItemList.Field_Generator_UEV.set(
+ addItem(
+ 679,
+ "Field Generator (UEV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 1024L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TUTAMEN, 512L)));
+ ItemList.Field_Generator_UIV.set(
+ addItem(
+ 45,
+ "Field Generator (UIV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 1024L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TUTAMEN, 512L)));
+ ItemList.Field_Generator_UMV.set(
+ addItem(
+ 46,
+ "Field Generator (UMV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 1024L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TUTAMEN, 512L)));
+ ItemList.Field_Generator_UXV.set(
+ addItem(
+ 47,
+ "Field Generator (UXV)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 1024L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TUTAMEN, 512L)));
+ ItemList.Field_Generator_MAX.set(
+ addItem(
+ 48,
+ "Field Generator (MAX)",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 1024L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TUTAMEN, 512L)));
+
+ ItemList.StableAdhesive.set(
+ addItem(
+ 427,
+ "Hyper-Stable Self-Healing Adhesive",
+ "Complete and selective adhesion, even when torn or damaged",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 30L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SANO, 20L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.LIMUS, 10L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VINCULUM, 5L)));
+ ItemList.SuperconductorComposite.set(
+ addItem(
+ 428,
+ "Superconductor Rare-Earth Composite",
+ "Zero resistance to electrical and quantum flow, regardless of temperature",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 50L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 25L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TERRA, 15L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METALLUM, 10L)));
+ ItemList.NaquadriaSupersolid.set(
+ addItem(
+ 429,
+ "Black Body Naquadria Supersolid",
+ "Flows like a fluid and reflects nothing, perfect absorption and transfer",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TENEBRAE, 100L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 60L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.PERMUTATIO, 40L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.RADIO, 20L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ALIENIS, 10L)));
+
+ // Circuits ULV - LuV.
+ ItemList.Circuit_Primitive.set(
+ addItem(
+ tLastID = 700,
+ "Vacuum Tube",
+ "A very simple Circuit",
+ OrePrefixes.circuit.get(Materials.Primitive),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_Primitive.get(1), ULV);
+ ItemList.Circuit_Basic.set(
+ addItem(
+ tLastID = 701,
+ "Integrated Logic Circuit",
+ "A Basic Circuit",
+ OrePrefixes.circuit.get(Materials.Basic),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_Basic.get(1), LV);
+ ItemList.Circuit_Good.set(
+ addItem(
+ tLastID = 702,
+ "Good Electronic Circuit",
+ "A Good Circuit",
+ OrePrefixes.circuit.get(Materials.Good),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_Good.get(1), MV);
+ ItemList.Circuit_Advanced.set(
+ addItem(
+ tLastID = 703,
+ "Processor Assembly",
+ "An Advanced Circuit",
+ OrePrefixes.circuit.get(Materials.Advanced),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_Advanced.get(1), HV);
+ ItemList.Circuit_Data.set(
+ addItem(
+ tLastID = 704,
+ "Workstation",
+ "An Extreme Circuit",
+ OrePrefixes.circuit.get(Materials.Data),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_Data.get(1), EV);
+ ItemList.Circuit_Elite.set(
+ addItem(
+ tLastID = 705,
+ "Mainframe",
+ "An Elite Circuit",
+ OrePrefixes.circuit.get(Materials.Elite),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_Elite.get(1), IV);
+ ItemList.Circuit_Master.set(
+ addItem(
+ tLastID = 706,
+ "Nanoprocessor Mainframe",
+ "A Master Circuit",
+ OrePrefixes.circuit.get(Materials.Master),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_Master.get(1), LuV);
+
+ // Backwards compatibility.
+ ItemList.Circuit_Parts_Vacuum_Tube.set(ItemList.Circuit_Primitive.get(1));
+ ItemList.Circuit_Computer.set(ItemList.Circuit_Advanced.get(1));
+
+ ItemList.Tool_DataOrb.set(
+ addItem(
+ tLastID = 707,
+ "Data Orb",
+ "A High Capacity Data Storage",
+ SubTag.NO_UNIFICATION,
+ new Behaviour_DataOrb()));
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Tool_DataOrb.get(1L),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { ItemList.Tool_DataOrb.get(1L) });
+ ItemList.Tool_DataStick.set(
+ addItem(
+ tLastID = 708,
+ "Data Stick",
+ "A Low Capacity Data Storage",
+ SubTag.NO_UNIFICATION,
+ new Behaviour_DataStick()));
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Tool_DataStick.get(1L),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { ItemList.Tool_DataStick.get(1L) });
+ ItemList.Tool_Cover_Copy_Paste.set(
+ addItem(
+ tLastID = 709,
+ "Cover Copy/Paste tool",
+ "Set Cover Massively.",
+ Behaviour_Cover_Tool.INSTANCE,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 6L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SENSUS, 6L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 6L)));
+ setElectricStats(32000 + tLastID, 400000L, GT_Values.V[2], 2L, -1L, false);
+
+ ItemList.Circuit_Board_Basic.set(addItem(tLastID = 710, "Coated Circuit Board", "A Basic Board"));
+ ItemList.Circuit_Board_Coated.set(ItemList.Circuit_Board_Basic.get(1));
+ ItemList.Circuit_Board_Advanced.set(addItem(tLastID = 711, "Epoxy Circuit Board", "An Advanced Board"));
+ ItemList.Circuit_Board_Epoxy.set(ItemList.Circuit_Board_Advanced.get(1));
+ ItemList.Circuit_Board_Elite
+ .set(addItem(tLastID = 712, "Multilayer Fiber-Reinforced Circuit Board", "An Elite Board"));
+ ItemList.Circuit_Board_Multifiberglass.set(ItemList.Circuit_Board_Elite.get(1));
+ ItemList.Circuit_Parts_Crystal_Chip_Elite
+ .set(addItem(tLastID = 713, "Engraved Crystal Chip", "Needed for Circuits"));
+ ItemList.Circuit_Parts_Crystal_Chip_Master
+ .set(addItem(tLastID = 714, "Engraved Lapotron Chip", "Needed for Circuits"));
+ ItemList.Circuit_Parts_Crystal_Chip_Wetware
+ .set(addItem(tLastID = 668, "Living Crystal Chip", "Needed for Circuits"));
+ ItemList.Circuit_Parts_Advanced.set(addItem(tLastID = 715, "Diode", "Basic Electronic Component"));
+ ItemList.Circuit_Parts_Diode.set(ItemList.Circuit_Parts_Advanced.get(1));
+ ItemList.Circuit_Parts_Wiring_Basic.set(addItem(tLastID = 716, "Resistor", "Basic Electronic Component"));
+ ItemList.Circuit_Parts_Resistor.set(ItemList.Circuit_Parts_Wiring_Basic.get(1));
+ ItemList.Circuit_Parts_Wiring_Advanced.set(addItem(tLastID = 717, "Transistor", "Basic Electronic Component"));
+ ItemList.Circuit_Parts_Transistor.set(ItemList.Circuit_Parts_Wiring_Advanced.get(1));
+ ItemList.Circuit_Parts_Wiring_Elite.set(addItem(tLastID = 718, "Capacitor", "Electronic Component"));
+ ItemList.Circuit_Parts_Capacitor.set(ItemList.Circuit_Parts_Wiring_Elite.get(1));
+ ItemList.Empty_Board_Basic.set(addItem(tLastID = 719, "Phenolic Circuit Board", "A Good Board"));
+ ItemList.Circuit_Board_Phenolic.set(ItemList.Empty_Board_Basic.get(1));
+ ItemList.Empty_Board_Elite.set(addItem(tLastID = 720, "Fiber-Reinforced Circuit Board", "An Extreme Board"));
+ ItemList.Circuit_Board_Fiberglass.set(ItemList.Empty_Board_Elite.get(1));
+
+ ItemList.Component_Sawblade_Diamond.set(
+ addItem(
+ tLastID = 721,
+ "Diamond Sawblade",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.INSTRUMENTUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.PERDITIO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 4L),
+ OreDictNames.craftingDiamondBlade));
+ ItemList.Component_Grinder_Diamond.set(
+ addItem(
+ tLastID = 722,
+ "Diamond Grinding Head",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.INSTRUMENTUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.PERDITIO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 6L),
+ OreDictNames.craftingGrinder));
+ ItemList.Component_Grinder_Tungsten.set(
+ addItem(
+ tLastID = 723,
+ "Tungsten Grinding Head",
+ "",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.INSTRUMENTUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.PERDITIO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METALLUM, 6L),
+ OreDictNames.craftingGrinder));
+
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Component_Sawblade_Diamond.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { " D ", "DGD", " D ", 'D', OrePrefixes.dustSmall.get(Materials.Diamond), 'G',
+ OrePrefixes.gearGt.get(Materials.CobaltBrass) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Component_Grinder_Diamond.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "DSD", "SIS", "DSD", 'I', OrePrefixes.gem.get(Materials.Diamond), 'D',
+ OrePrefixes.dust.get(Materials.Diamond), 'S', OrePrefixes.plateDouble.get(Materials.Steel) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Component_Grinder_Tungsten.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "TST", "SIS", "TST", 'I', OreDictNames.craftingIndustrialDiamond, 'T',
+ OrePrefixes.plate.get(Materials.Tungsten), 'S', OrePrefixes.plateDouble.get(Materials.Steel) });
+
+ ItemList.Upgrade_Muffler.set(
+ addItem(
+ tLastID = 727,
+ "Muffler Upgrade",
+ "Makes Machines silent",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SENSUS, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VACUOS, 2L)));
+ ItemList.Upgrade_Lock.set(
+ addItem(
+ tLastID = 728,
+ "Lock Upgrade",
+ "Protects your Machines",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TUTAMEN, 4L)));
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.plate, Materials.Aluminium, 1L),
+ GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Plastic, 2L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Upgrade_Muffler.get(1L))
+ .duration(1 * MINUTES + 20 * SECONDS)
+ .eut(2)
+ .addTo(assemblerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.plate, Materials.Aluminium, 1L),
+ GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Wood, 2L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Upgrade_Muffler.get(1L))
+ .duration(1 * MINUTES + 20 * SECONDS)
+ .eut(2)
+ .addTo(assemblerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.plate, Materials.Iron, 1L),
+ GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Plastic, 2L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Upgrade_Muffler.get(1L))
+ .duration(1 * MINUTES + 20 * SECONDS)
+ .eut(2)
+ .addTo(assemblerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.plate, Materials.Iron, 1L),
+ GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Wood, 2L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Upgrade_Muffler.get(1L))
+ .duration(1 * MINUTES + 20 * SECONDS)
+ .eut(2)
+ .addTo(assemblerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.plate, Materials.WroughtIron, 1L),
+ GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Plastic, 2L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Upgrade_Muffler.get(1L))
+ .duration(1 * MINUTES + 20 * SECONDS)
+ .eut(2)
+ .addTo(assemblerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.plate, Materials.WroughtIron, 1L),
+ GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Wood, 2L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Upgrade_Muffler.get(1L))
+ .duration(1 * MINUTES + 20 * SECONDS)
+ .eut(2)
+ .addTo(assemblerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.plate, Materials.Aluminium, 1L),
+ GT_OreDictUnificator.get(OrePrefixes.plate, Materials.Iridium, 1L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Upgrade_Lock.get(1L))
+ .duration(5 * MINUTES + 20 * SECONDS)
+ .eut(16)
+ .addTo(assemblerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.plate, Materials.Iron, 1L),
+ GT_OreDictUnificator.get(OrePrefixes.plate, Materials.Iridium, 1L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Upgrade_Lock.get(1L))
+ .duration(5 * MINUTES + 20 * SECONDS)
+ .eut(16)
+ .addTo(assemblerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.plate, Materials.WroughtIron, 1L),
+ GT_OreDictUnificator.get(OrePrefixes.plate, Materials.Iridium, 1L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Upgrade_Lock.get(1L))
+ .duration(5 * MINUTES + 20 * SECONDS)
+ .eut(16)
+ .addTo(assemblerRecipes);
+
+ ItemList.Component_Filter.set(
+ addItem(
+ tLastID = 729,
+ "Item Filter",
+ "",
+ new ItemData(Materials.Zinc, OrePrefixes.foil.mMaterialAmount * 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.COGNITIO, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SENSUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 1L),
+ OreDictNames.craftingFilter));
+
+ ItemList.Cover_Controller.set(
+ addItem(
+ tLastID = 730,
+ "Machine Controller Cover",
+ "Turns Machines ON/OFF",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 1L)));
+ ItemList.Cover_ActivityDetector.set(
+ addItem(
+ tLastID = 731,
+ "Activity Detector Cover",
+ "Gives out Activity as Redstone",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SENSUS, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 1L)));
+ ItemList.Cover_FluidDetector.set(
+ addItem(
+ tLastID = 732,
+ "Fluid Detector Cover",
+ "Gives out Fluid Amount as Redstone",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SENSUS, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 1L)));
+ ItemList.Cover_ItemDetector.set(
+ addItem(
+ tLastID = 733,
+ "Item Detector Cover",
+ "Gives out Item Amount as Redstone",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SENSUS, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TERRA, 1L)));
+ ItemList.Cover_EnergyDetector.set(
+ addItem(
+ tLastID = 734,
+ "Energy Detector Cover",
+ "Gives out Energy Amount as Redstone",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SENSUS, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 1L)));
+ ItemList.Cover_PlayerDetector.set(
+ addItem(
+ tLastID = 735,
+ "Player Detector Cover",
+ "Gives out close Players as Redstone",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SENSUS, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 1L)));
+ ItemList.Cover_FluidStorageMonitor.set(
+ addItem(
+ tLastID = 577,
+ "Fluid Storage Monitor Cover",
+ "Displays the fluid stored in the Tank",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SENSUS, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 1L)));
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ ItemList.Sensor_EV.get(1L),
+ GT_OreDictUnificator.get(OrePrefixes.plate, Materials.Titanium, 1L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Cover_PlayerDetector.get(1L))
+ .duration(2 * MINUTES + 40 * SECONDS)
+ .eut(TierEU.RECIPE_MV)
+ .addTo(assemblerRecipes);
+
+ GregTech_API.registerCover(
+ ItemList.Cover_Controller.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[2][0], TextureFactory.of(OVERLAY_CONTROLLER)),
+ new GT_Cover_ControlsWork(TextureFactory.of(OVERLAY_CONTROLLER)));
+
+ final ITexture doesWorkCoverTexture = TextureFactory.of(
+ TextureFactory.of(OVERLAY_ACTIVITYDETECTOR),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_ACTIVITYDETECTOR_GLOW)
+ .glow()
+ .build());
+ GregTech_API.registerCover(
+ ItemList.Cover_ActivityDetector.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[2][0], doesWorkCoverTexture),
+ new GT_Cover_DoesWork(doesWorkCoverTexture));
+ GregTech_API.registerCover(
+ ItemList.Cover_FluidDetector.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[2][0], TextureFactory.of(OVERLAY_FLUIDDETECTOR)),
+ new GT_Cover_LiquidMeter(TextureFactory.of(OVERLAY_FLUIDDETECTOR)));
+ GregTech_API.registerCover(
+ ItemList.Cover_ItemDetector.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[2][0], TextureFactory.of(OVERLAY_ITEMDETECTOR)),
+ new GT_Cover_ItemMeter(TextureFactory.of(OVERLAY_ITEMDETECTOR)));
+ GregTech_API.registerCover(
+ ItemList.Cover_EnergyDetector.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[2][0], TextureFactory.of(OVERLAY_ENERGYDETECTOR)),
+ new GT_Cover_EUMeter(TextureFactory.of(OVERLAY_ENERGYDETECTOR)));
+
+ final ITexture playerDectectorCoverTexture = TextureFactory.of(
+ TextureFactory.of(OVERLAY_ACTIVITYDETECTOR),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_ACTIVITYDETECTOR_GLOW)
+ .glow()
+ .build());
+ GregTech_API.registerCover(
+ ItemList.Cover_PlayerDetector.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[2][0], playerDectectorCoverTexture),
+ new GT_Cover_PlayerDetector(playerDectectorCoverTexture));
+ GregTech_API.registerCover(
+ ItemList.Cover_FluidStorageMonitor.get(1L),
+ TextureFactory.of(OVERLAY_FLUID_STORAGE_MONITOR0),
+ new GT_Cover_FluidStorageMonitor());
+
+ ItemList.Cover_Screen.set(
+ addItem(
+ tLastID = 740,
+ "Computer Monitor Cover",
+ "Displays Data and GUI",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.COGNITIO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.LUX, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L)));
+ ItemList.Cover_Crafting.set(
+ addItem(
+ tLastID = 744,
+ "Crafting Table Cover",
+ "Better than a wooden Workbench",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FABRICO, 4L)));
+ ItemList.Cover_Drain.set(
+ addItem(
+ tLastID = 745,
+ "Drain Module Cover",
+ "Absorbs Fluids and collects Rain",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VACUOS, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 2L)));
+
+ ItemList.Cover_Shutter.set(
+ addItem(
+ tLastID = 749,
+ "Shutter Module Cover",
+ "Blocks Inventory/Tank Side. Use together with Machine Controller.",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 1L)));
+
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Cover_Screen.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "AGA", "RPB", "ALA", 'A', OrePrefixes.plate.get(Materials.Aluminium), 'L',
+ OrePrefixes.dust.get(Materials.Glowstone), 'R', Dyes.dyeRed, 'G', Dyes.dyeLime, 'B', Dyes.dyeBlue, 'P',
+ OrePrefixes.plate.get(Materials.Glass) });
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.plate, Materials.Aluminium, 1L),
+ ItemList.Cover_Drain.get(1L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Cover_Shutter.get(1L))
+ .duration(40 * SECONDS)
+ .eut(16)
+ .addTo(assemblerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.plate, Materials.Iron, 1L),
+ ItemList.Cover_Drain.get(1L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Cover_Shutter.get(1L))
+ .duration(40 * SECONDS)
+ .eut(16)
+ .addTo(assemblerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.plate, Materials.WroughtIron, 1L),
+ ItemList.Cover_Drain.get(1L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Cover_Shutter.get(1L))
+ .duration(40 * SECONDS)
+ .eut(16)
+ .addTo(assemblerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.plate, Materials.Aluminium, 2L),
+ new ItemStack(Blocks.iron_bars, 2),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Cover_Drain.get(1L))
+ .duration(40 * SECONDS)
+ .eut(16)
+ .addTo(assemblerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.plate, Materials.Iron, 2L),
+ new ItemStack(Blocks.iron_bars, 2),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Cover_Drain.get(1L))
+ .duration(40 * SECONDS)
+ .eut(16)
+ .addTo(assemblerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.plate, Materials.WroughtIron, 2L),
+ new ItemStack(Blocks.iron_bars, 2),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Cover_Drain.get(1L))
+ .duration(40 * SECONDS)
+ .eut(16)
+ .addTo(assemblerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.plate, Materials.Aluminium, 1L),
+ new ItemStack(Blocks.crafting_table, 1),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Cover_Crafting.get(1L))
+ .duration(40 * SECONDS)
+ .eut(16)
+ .addTo(assemblerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.plate, Materials.Iron, 1L),
+ new ItemStack(Blocks.crafting_table, 1),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Cover_Crafting.get(1L))
+ .duration(40 * SECONDS)
+ .eut(16)
+ .addTo(assemblerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.plate, Materials.WroughtIron, 1L),
+ new ItemStack(Blocks.crafting_table, 1),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Cover_Crafting.get(1L))
+ .duration(40 * SECONDS)
+ .eut(16)
+ .addTo(assemblerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ ItemList.Cover_Shutter.get(1L),
+ GT_OreDictUnificator.get(OrePrefixes.circuit, Materials.Basic, 1),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.FluidFilter.get(1L))
+ .duration(40 * SECONDS)
+ .eut(4)
+ .addTo(assemblerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ ItemList.Cover_Screen.get(1L),
+ ItemList.Cover_FluidDetector.get(1L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Cover_FluidStorageMonitor.get(1L))
+ .duration(40 * SECONDS)
+ .eut(4)
+ .addTo(assemblerRecipes);
+
+ final ITexture screenCoverTexture = TextureFactory.of(
+ TextureFactory.of(OVERLAY_SCREEN),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_SCREEN_GLOW)
+ .glow()
+ .build());
+ GregTech_API.registerCover(
+ ItemList.Cover_Screen.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[2][0], screenCoverTexture),
+ new GT_Cover_Screen(screenCoverTexture));
+ GregTech_API.registerCover(
+ ItemList.Cover_Crafting.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[1][0], TextureFactory.of(OVERLAY_CRAFTING)),
+ new GT_Cover_Crafting(TextureFactory.of(OVERLAY_CRAFTING)));
+ GregTech_API.registerCover(
+ ItemList.Cover_Drain.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[0][0], TextureFactory.of(OVERLAY_DRAIN)),
+ new GT_Cover_Drain(TextureFactory.of(OVERLAY_DRAIN)));
+ GregTech_API.registerCover(
+ ItemList.Cover_Shutter.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[1][0], TextureFactory.of(OVERLAY_SHUTTER)),
+ new GT_Cover_Shutter(TextureFactory.of(OVERLAY_SHUTTER)));
+
+ ItemList.Cover_SolarPanel.set(
+ addItem(
+ tLastID = 750,
+ "Solar Panel",
+ "May the Sun be with you (Needs cleaning with right click)",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TENEBRAE, 1L)));
+ ItemList.Cover_SolarPanel_8V.set(
+ addItem(
+ tLastID = 751,
+ "Solar Panel (8V)",
+ "8 Volt Solar Panel (Needs cleaning with right click)",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TENEBRAE, 2L)));
+ ItemList.Cover_SolarPanel_LV.set(
+ addItem(
+ tLastID = 752,
+ "Solar Panel (LV)",
+ "Low Voltage Solar Panel (Needs cleaning with right click)",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TENEBRAE, 4L)));
+ ItemList.Cover_SolarPanel_MV.set(
+ addItem(
+ tLastID = 753,
+ "Solar Panel (MV)",
+ "Medium Voltage Solar Panel (Needs cleaning with right click)",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 8L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 8L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TENEBRAE, 8L)));
+ ItemList.Cover_SolarPanel_HV.set(
+ addItem(
+ tLastID = 754,
+ "Solar Panel (HV)",
+ "High Voltage Solar Panel (Needs cleaning with right click)",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TENEBRAE, 16L)));
+ ItemList.Cover_SolarPanel_EV.set(
+ addItem(
+ tLastID = 755,
+ "Solar Panel (EV)",
+ "Extreme Solar Panel (Needs cleaning with right click)",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 32L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 32L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TENEBRAE, 32L)));
+ ItemList.Cover_SolarPanel_IV.set(
+ addItem(
+ tLastID = 756,
+ "Solar Panel (IV)",
+ "Insane Solar Panel (Needs cleaning with right click)",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 64L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 64L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TENEBRAE, 64L)));
+ ItemList.Cover_SolarPanel_LuV.set(
+ addItem(
+ tLastID = 757,
+ "Solar Panel (LuV)",
+ "Ludicrous Solar Panel (Needs cleaning with right click)",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 64L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 64L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TENEBRAE, 64L)));
+ ItemList.Cover_SolarPanel_ZPM.set(
+ addItem(
+ tLastID = 758,
+ "Solar Panel (ZPM)",
+ "ZPM Voltage Solar Panel (Needs cleaning with right click)",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 64L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 64L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TENEBRAE, 64L)));
+ ItemList.Cover_SolarPanel_UV.set(
+ addItem(
+ tLastID = 759,
+ "Solar Panel (UV)",
+ "Ultimate Solar Panel (Needs cleaning with right click)",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 64L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 64L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TENEBRAE, 64L)));
+
+ GregTech_API.registerCover(
+ ItemList.Cover_SolarPanel.get(1L),
+ TextureFactory.of(SOLARPANEL),
+ new GT_Cover_SolarPanel(1));
+ GregTech_API.registerCover(
+ ItemList.Cover_SolarPanel_8V.get(1L),
+ TextureFactory.of(SOLARPANEL_8V),
+ new GT_Cover_SolarPanel(8));
+ GregTech_API.registerCover(
+ ItemList.Cover_SolarPanel_LV.get(1L),
+ TextureFactory.of(SOLARPANEL_LV),
+ new GT_Cover_SolarPanel(32));
+ GregTech_API.registerCover(
+ ItemList.Cover_SolarPanel_MV.get(1L),
+ TextureFactory.of(SOLARPANEL_MV),
+ new GT_Cover_SolarPanel(128));
+ GregTech_API.registerCover(
+ ItemList.Cover_SolarPanel_HV.get(1L),
+ TextureFactory.of(SOLARPANEL_HV),
+ new GT_Cover_SolarPanel(512));
+ GregTech_API.registerCover(
+ ItemList.Cover_SolarPanel_EV.get(1L),
+ TextureFactory.of(SOLARPANEL_EV),
+ new GT_Cover_SolarPanel(2048));
+ GregTech_API.registerCover(
+ ItemList.Cover_SolarPanel_IV.get(1L),
+ TextureFactory.of(SOLARPANEL_IV),
+ new GT_Cover_SolarPanel(8192));
+ GregTech_API.registerCover(
+ ItemList.Cover_SolarPanel_LuV.get(1L),
+ TextureFactory.of(SOLARPANEL_LuV),
+ new GT_Cover_SolarPanel(32768));
+ GregTech_API.registerCover(
+ ItemList.Cover_SolarPanel_ZPM.get(1L),
+ TextureFactory.of(SOLARPANEL_ZPM),
+ new GT_Cover_SolarPanel(131072));
+ GregTech_API.registerCover(
+ ItemList.Cover_SolarPanel_UV.get(1L),
+ TextureFactory.of(SOLARPANEL_UV),
+ new GT_Cover_SolarPanel(524288));
+
+ ItemList.Tool_Sonictron.set(
+ addItem(
+ tLastID = 760,
+ "Sonictron",
+ "Bring your Music with you",
+ Behaviour_Sonictron.INSTANCE,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SENSUS, 4L)));
+ ItemList.Tool_Cheat.set(
+ addItem(
+ tLastID = 761,
+ "Debug Scanner",
+ "Also an Infinite Energy Source",
+ Behaviour_Scanner.INSTANCE,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.NEBRISUM, 64L)));
+ setElectricStats(32000 + tLastID, -2000000000L, 1000000000L, -1L, -3L, false);
+ ItemList.Tool_Scanner.set(
+ addItem(
+ tLastID = 762,
+ "Portable Scanner",
+ "Tricorder",
+ Behaviour_Scanner.INSTANCE,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 6L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SENSUS, 6L)));
+ setElectricStats(32000 + tLastID, 400000L, GT_Values.V[2], 2L, -1L, false);
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Tool_Scanner.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.NOT_REMOVABLE
+ | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "EPR", "CSC", "PBP", 'C', OrePrefixes.circuit.get(Materials.Advanced), 'P',
+ OrePrefixes.plate.get(Materials.Aluminium), 'E', ItemList.Emitter_MV, 'R', ItemList.Sensor_MV, 'S',
+ ItemList.Cover_Screen, 'B', ItemList.Battery_RE_MV_Lithium });
+ ItemList.NC_SensorKit.set(addItem(tLastID = 763, "GregTech Sensor Kit", "", new Behaviour_SensorKit()));
+ ItemList.Duct_Tape.set(
+ addItem(
+ tLastID = 764,
+ "BrainTech Aerospace Advanced Reinforced Duct Tape FAL-84",
+ "If you can't fix it with this, use more of it!",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.INSTRUMENTUM, 2L),
+ OreDictNames.craftingDuctTape));
+ ItemList.McGuffium_239.set(
+ addItem(
+ tLastID = 765,
+ "Mc Guffium 239",
+ "42% better than Phlebotnium",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ALIENIS, 8L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.PERMUTATIO, 8L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SPIRITUS, 8L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AURAM, 8L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITIUM, 8L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.RADIO, 8L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MAGNETO, 8L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 8L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.NEBRISUM, 8L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.STRONTIO, 8L)));
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(ItemList.Sensor_LV.get(1L), ItemList.Emitter_LV.get(1L), GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.NC_SensorKit.get(1L))
+ .duration(1 * MINUTES + 20 * SECONDS)
+ .eut(2)
+ .addTo(assemblerRecipes);
+
+ ItemList.Cover_RedstoneTransmitterExternal.set(
+ addItem(
+ tLastID = 741,
+ "Redstone Transmitter (External)",
+ "Transfers Redstone signals wireless",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 1L)));
+ ItemList.Cover_RedstoneTransmitterInternal.set(
+ addItem(
+ tLastID = 742,
+ "Redstone Transmitter (Internal)",
+ "Transfers Redstone signals wireless",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 1L)));
+ ItemList.Cover_RedstoneReceiverExternal.set(
+ addItem(
+ tLastID = 746,
+ "Redstone Receiver (External)",
+ "Transfers Redstone signals wireless",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 1L)));
+ ItemList.Cover_RedstoneReceiverInternal.set(
+ addItem(
+ tLastID = 747,
+ "Redstone Receiver (Internal)",
+ "Transfers Redstone signals wireless",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 1L)));
+
+ GregTech_API.registerCover(
+ ItemList.Cover_RedstoneTransmitterExternal.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[2][0], TextureFactory.of(OVERLAY_REDSTONE_TRANSMITTER)),
+ new GT_Cover_RedstoneTransmitterExternal(TextureFactory.of(OVERLAY_REDSTONE_TRANSMITTER)));
+ GregTech_API.registerCover(
+ ItemList.Cover_RedstoneTransmitterInternal.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[2][0], TextureFactory.of(OVERLAY_REDSTONE_TRANSMITTER)),
+ new GT_Cover_RedstoneTransmitterInternal(TextureFactory.of(OVERLAY_REDSTONE_TRANSMITTER)));
+ GregTech_API.registerCover(
+ ItemList.Cover_RedstoneReceiverExternal.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[2][0], TextureFactory.of(OVERLAY_REDSTONE_RECEIVER)),
+ new GT_Cover_RedstoneReceiverExternal(TextureFactory.of(OVERLAY_REDSTONE_RECEIVER)));
+ GregTech_API.registerCover(
+ ItemList.Cover_RedstoneReceiverInternal.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[2][0], TextureFactory.of(OVERLAY_REDSTONE_RECEIVER)),
+ new GT_Cover_RedstoneReceiverInternal(TextureFactory.of(OVERLAY_REDSTONE_RECEIVER)));
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ ItemList.Emitter_EV.get(1L),
+ GT_OreDictUnificator.get(OrePrefixes.plate, Materials.StainlessSteel, 1L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Cover_RedstoneTransmitterExternal.get(1L))
+ .duration(2 * MINUTES + 40 * SECONDS)
+ .eut(TierEU.RECIPE_MV)
+ .addTo(assemblerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ ItemList.Sensor_EV.get(1L),
+ GT_OreDictUnificator.get(OrePrefixes.plate, Materials.StainlessSteel, 1L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Cover_RedstoneReceiverExternal.get(1L))
+ .duration(2 * MINUTES + 40 * SECONDS)
+ .eut(TierEU.RECIPE_MV)
+ .addTo(assemblerRecipes);
+
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Cover_RedstoneTransmitterInternal.get(1L),
+ new Object[] { ItemList.Cover_RedstoneTransmitterExternal.get(1L) });
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Cover_RedstoneReceiverInternal.get(1L),
+ new Object[] { ItemList.Cover_RedstoneReceiverExternal.get(1L) });
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Cover_RedstoneTransmitterExternal.get(1L),
+ new Object[] { ItemList.Cover_RedstoneTransmitterInternal.get(1L) });
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Cover_RedstoneReceiverExternal.get(1L),
+ new Object[] { ItemList.Cover_RedstoneReceiverInternal.get(1L) });
+
+ ItemList.Cover_NeedsMaintainance.set(
+ addItem(
+ tLastID = 748,
+ "Needs Maintenance Cover",
+ "Attach to Multiblock Controller. Emits Redstone Signal if needs Maintenance",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 1L)));
+ GregTech_API.registerCover(
+ ItemList.Cover_NeedsMaintainance.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[2][0], TextureFactory.of(OVERLAY_MAINTENANCE_DETECTOR)),
+ new GT_Cover_NeedMaintainance(TextureFactory.of(OVERLAY_MAINTENANCE_DETECTOR)));
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ ItemList.Emitter_MV.get(1L),
+ GT_OreDictUnificator.get(OrePrefixes.plate, Materials.Aluminium, 1L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Cover_NeedsMaintainance.get(1L))
+ .duration(30 * SECONDS)
+ .eut(TierEU.RECIPE_LV)
+ .addTo(assemblerRecipes);
+
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.ItemFilter_Export.get(1L),
+ new Object[] { "SPS", "dIC", "SPS", 'P', OrePrefixes.plate.get(Materials.Tin), 'S',
+ OrePrefixes.screw.get(Materials.Iron), 'I', ItemList.Component_Filter, 'C',
+ ItemList.Conveyor_Module_LV });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.ItemFilter_Import.get(1L),
+ new Object[] { "SPS", "CId", "SPS", 'P', OrePrefixes.plate.get(Materials.Tin), 'S',
+ OrePrefixes.screw.get(Materials.Iron), 'I', ItemList.Component_Filter, 'C',
+ ItemList.Conveyor_Module_LV });
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.ItemFilter_Export.get(1L),
+ new Object[] { ItemList.ItemFilter_Import.get(1L) });
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.ItemFilter_Import.get(1L),
+ new Object[] { ItemList.ItemFilter_Export.get(1L) });
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.plate, Materials.Tin, 2L),
+ ItemList.Component_Filter.get(1L),
+ ItemList.Conveyor_Module_LV.get(1L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.ItemFilter_Export.get(1L))
+ .duration(5 * SECONDS)
+ .eut(TierEU.RECIPE_LV)
+ .addTo(assemblerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ GT_OreDictUnificator.get(OrePrefixes.plate, Materials.Tin, 2L),
+ ItemList.Component_Filter.get(1L),
+ ItemList.Conveyor_Module_LV.get(1L),
+ GT_Utility.getIntegratedCircuit(2))
+ .itemOutputs(ItemList.ItemFilter_Import.get(1L))
+ .duration(5 * SECONDS)
+ .eut(TierEU.RECIPE_LV)
+ .addTo(assemblerRecipes);
+
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Tool_Cover_Copy_Paste.get(1L),
+ GT_ModHandler.RecipeBits.DISMANTLEABLE | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "PSP", "PCP", "PBP", 'P', OrePrefixes.plate.get(Materials.Aluminium), 'S',
+ ItemList.Tool_DataStick.get(1L), 'C', ItemList.Cover_Screen.get(1L), 'B',
+ ItemList.Battery_RE_MV_Lithium.get(1L) });
+
+ ItemList.Steam_Regulator_LV.set(
+ addItem(
+ tLastID = 332,
+ "Steam Regulator (LV)",
+ GT_Utility.formatNumbers(1024) + PartCoverText + GT_Utility.formatNumbers(1024 * 20) + PartCoverText2,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 1L)));
+ ItemList.Steam_Regulator_MV.set(
+ addItem(
+ tLastID = 333,
+ "Steam Regulator (MV)",
+ GT_Utility.formatNumbers(2048) + PartCoverText + GT_Utility.formatNumbers(2048 * 20) + PartCoverText2,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 2L)));
+ ItemList.Steam_Regulator_HV.set(
+ addItem(
+ tLastID = 334,
+ "Steam Regulator (HV)",
+ GT_Utility.formatNumbers(4096) + PartCoverText + GT_Utility.formatNumbers(4096 * 20) + PartCoverText2,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 4L)));
+ ItemList.Steam_Regulator_EV.set(
+ addItem(
+ tLastID = 335,
+ "Steam Regulator (EV)",
+ GT_Utility.formatNumbers(8192) + PartCoverText + GT_Utility.formatNumbers(8192 * 20) + PartCoverText2,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 8L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 8L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 8L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 8L)));
+ ItemList.Steam_Regulator_IV.set(
+ addItem(
+ tLastID = 336,
+ "Steam Regulator (IV)",
+ GT_Utility.formatNumbers(16384) + PartCoverText + GT_Utility.formatNumbers(16384 * 20) + PartCoverText2,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 16L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 16L)));
+
+ GregTech_API.registerCover(
+ ItemList.Steam_Regulator_LV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[1][0], TextureFactory.of(OVERLAY_VALVE)),
+ new GT_Cover_SteamRegulator(1024, TextureFactory.of(OVERLAY_VALVE)));
+ GregTech_API.registerCover(
+ ItemList.Steam_Regulator_MV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[2][0], TextureFactory.of(OVERLAY_VALVE)),
+ new GT_Cover_SteamRegulator(2048, TextureFactory.of(OVERLAY_VALVE)));
+ GregTech_API.registerCover(
+ ItemList.Steam_Regulator_HV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[3][0], TextureFactory.of(OVERLAY_VALVE)),
+ new GT_Cover_SteamRegulator(4096, TextureFactory.of(OVERLAY_VALVE)));
+ GregTech_API.registerCover(
+ ItemList.Steam_Regulator_EV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[4][0], TextureFactory.of(OVERLAY_VALVE)),
+ new GT_Cover_SteamRegulator(8192, TextureFactory.of(OVERLAY_VALVE)));
+ GregTech_API.registerCover(
+ ItemList.Steam_Regulator_IV.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[5][0], TextureFactory.of(OVERLAY_VALVE)),
+ new GT_Cover_SteamRegulator(16384, TextureFactory.of(OVERLAY_VALVE)));
+
+ }
+
+ private static final Map<Materials, Materials> cauldronRemap = new HashMap<>();
+
+ public static void registerCauldronCleaningFor(Materials in, Materials out) {
+ cauldronRemap.put(in, out);
+ }
+
+ @Override
+ public boolean onEntityItemUpdate(EntityItem aItemEntity) {
+ int aDamage = aItemEntity.getEntityItem()
+ .getItemDamage();
+ if ((aDamage < 32000) && (aDamage >= 0) && (!aItemEntity.worldObj.isRemote)) {
+ Materials aMaterial = GregTech_API.sGeneratedMaterials[(aDamage % 1000)];
+ if ((aMaterial != null) && (aMaterial != Materials.Empty) && (aMaterial != Materials._NULL)) {
+ int tX = MathHelper.floor_double(aItemEntity.posX);
+ int tY = MathHelper.floor_double(aItemEntity.posY);
+ int tZ = MathHelper.floor_double(aItemEntity.posZ);
+ OrePrefixes aPrefix = this.mGeneratedPrefixList[(aDamage / 1000)];
+ if ((aPrefix == OrePrefixes.dustImpure) || (aPrefix == OrePrefixes.dustPure)) {
+ Block tBlock = aItemEntity.worldObj.getBlock(tX, tY, tZ);
+ byte tMetaData = (byte) aItemEntity.worldObj.getBlockMetadata(tX, tY, tZ);
+ if ((tBlock == Blocks.cauldron) && (tMetaData > 0)) {
+
+ aMaterial = cauldronRemap.getOrDefault(aMaterial, aMaterial);
+
+ aItemEntity.setEntityItemStack(
+ GT_OreDictUnificator
+ .get(OrePrefixes.dust, aMaterial, aItemEntity.getEntityItem().stackSize));
+ aItemEntity.worldObj.setBlockMetadataWithNotify(tX, tY, tZ, tMetaData - 1, 3);
+ return true;
+ }
+ } else if (aPrefix == OrePrefixes.crushed) {
+ Block tBlock = aItemEntity.worldObj.getBlock(tX, tY, tZ);
+ byte tMetaData = (byte) aItemEntity.worldObj.getBlockMetadata(tX, tY, tZ);
+ if ((tBlock == Blocks.cauldron) && (tMetaData > 0)) {
+ aItemEntity.setEntityItemStack(
+ GT_OreDictUnificator
+ .get(OrePrefixes.crushedPurified, aMaterial, aItemEntity.getEntityItem().stackSize));
+ aItemEntity.worldObj.setBlockMetadataWithNotify(tX, tY, tZ, tMetaData - 1, 3);
+ return true;
+ }
+ } else if (aPrefix == OrePrefixes.dust && aMaterial == Materials.Wheat) {
+ Block tBlock = aItemEntity.worldObj.getBlock(tX, tY, tZ);
+ byte tMetaData = (byte) aItemEntity.worldObj.getBlockMetadata(tX, tY, tZ);
+ if ((tBlock == Blocks.cauldron) && (tMetaData > 0)) {
+ aItemEntity.setEntityItemStack(ItemList.Food_Dough.get(aItemEntity.getEntityItem().stackSize));
+ aItemEntity.worldObj.setBlockMetadataWithNotify(tX, tY, tZ, tMetaData - 1, 3);
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ protected void addAdditionalToolTips(List<String> aList, ItemStack aStack, EntityPlayer aPlayer) {
+ super.addAdditionalToolTips(aList, aStack, aPlayer);
+ int aDamage = aStack.getItemDamage();
+ if ((aDamage < 32000) && (aDamage >= 0)) {
+ Materials aMaterial = GregTech_API.sGeneratedMaterials[(aDamage % 1000)];
+ if ((aMaterial != null) && (aMaterial != Materials.Empty) && (aMaterial != Materials._NULL)) {
+ OrePrefixes aPrefix = this.mGeneratedPrefixList[(aDamage / 1000)];
+ if ((aPrefix == OrePrefixes.dustImpure) || (aPrefix == OrePrefixes.dustPure)) {
+ aList.add(this.mToolTipPurify);
+ }
+ }
+ }
+ }
+
+ public boolean isPlasmaCellUsed(OrePrefixes aPrefix, Materials aMaterial) {
+ Collection<GT_Recipe> fusionRecipes = RecipeMaps.fusionRecipes.getAllRecipes();
+ if (aPrefix == OrePrefixes.cellPlasma && aMaterial.getPlasma(1L) != null) { // Materials has a plasma fluid
+ for (GT_Recipe recipe : fusionRecipes) { // Loop through fusion recipes
+ if (recipe.getFluidOutput(0) != null) { // Make sure fluid output can't be null (not sure if possible)
+ if (recipe.getFluidOutput(0)
+ .isFluidEqual(aMaterial.getPlasma(1L))) return true; // Fusion recipe
+ // output matches
+ // current plasma
+ // cell fluid
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean doesShowInCreative(OrePrefixes aPrefix, Materials aMaterial, boolean aDoShowAllItems) {
+ return (aDoShowAllItems) || (((aPrefix != OrePrefixes.gem) || (!aMaterial.mName.startsWith("Infused")))
+ && (aPrefix != OrePrefixes.dustTiny)
+ && (aPrefix != OrePrefixes.dustSmall)
+ && (aPrefix != OrePrefixes.dustImpure)
+ && (aPrefix != OrePrefixes.dustPure)
+ && (aPrefix != OrePrefixes.crushed)
+ && (aPrefix != OrePrefixes.crushedPurified)
+ && (aPrefix != OrePrefixes.crushedCentrifuged)
+ && (aPrefix != OrePrefixes.ingotHot)
+ && !(aPrefix == OrePrefixes.cellPlasma && !isPlasmaCellUsed(aPrefix, aMaterial)));
+ }
+
+ @Override
+ public ItemStack getContainerItem(ItemStack aStack) {
+ int aDamage = aStack.getItemDamage();
+ if (((aDamage >= 32430) && (aDamage <= 32461)) || (aDamage == 32465 || aDamage == 32466)) {
+ return ItemList.Spray_Empty.get(1L);
+ }
+ if ((aDamage == 32479) || (aDamage == 32476)) {
+ return new ItemStack(this, 1, aDamage - 2);
+ }
+ if (aDamage == 32401) {
+ return new ItemStack(this, 1, aDamage - 1);
+ }
+ return super.getContainerItem(aStack);
+ }
+
+ @Override
+ public boolean doesMaterialAllowGeneration(OrePrefixes aPrefix, Materials aMaterial) {
+ return (super.doesMaterialAllowGeneration(aPrefix, aMaterial));
+ }
+}
diff --git a/src/main/java/gregtech/common/items/GT_MetaGenerated_Item_02.java b/src/main/java/gregtech/common/items/GT_MetaGenerated_Item_02.java
new file mode 100644
index 0000000000..875c4e9861
--- /dev/null
+++ b/src/main/java/gregtech/common/items/GT_MetaGenerated_Item_02.java
@@ -0,0 +1,2831 @@
+package gregtech.common.items;
+
+import static gregtech.api.enums.Mods.Forestry;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASINGS;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_ADVANCED_REDSTONE_RECEIVER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_ADVANCED_REDSTONE_TRANSMITTER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_WIRELESS_ACTIVITYDETECTOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_WIRELESS_FLUID_DETECTOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_WIRELESS_ITEM_DETECTOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_WIRELESS_MAINTENANCE_DETECTOR;
+import static gregtech.api.recipe.RecipeMaps.assemblerRecipes;
+import static gregtech.api.recipe.RecipeMaps.compressorRecipes;
+import static gregtech.api.recipe.RecipeMaps.maceratorRecipes;
+import static gregtech.api.util.GT_RecipeBuilder.MINUTES;
+import static gregtech.api.util.GT_RecipeBuilder.SECONDS;
+import static gregtech.api.util.GT_RecipeBuilder.WILDCARD;
+
+import net.minecraft.dispenser.IBlockSource;
+import net.minecraft.enchantment.Enchantment;
+import net.minecraft.enchantment.EnumEnchantmentType;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.projectile.EntityArrow;
+import net.minecraft.init.Blocks;
+import net.minecraft.init.Items;
+import net.minecraft.item.EnumAction;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.potion.Potion;
+import net.minecraft.world.World;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.Dyes;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.MaterialsUEVplus;
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.enums.SubTag;
+import gregtech.api.enums.TC_Aspects;
+import gregtech.api.enums.TierEU;
+import gregtech.api.items.GT_MetaGenerated_Item_X32;
+import gregtech.api.objects.ItemData;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_FoodStat;
+import gregtech.api.util.GT_Log;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_OreDictUnificator;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.covers.redstone.GT_Cover_AdvancedRedstoneReceiverExternal;
+import gregtech.common.covers.redstone.GT_Cover_AdvancedRedstoneReceiverInternal;
+import gregtech.common.covers.redstone.GT_Cover_AdvancedRedstoneTransmitterExternal;
+import gregtech.common.covers.redstone.GT_Cover_AdvancedRedstoneTransmitterInternal;
+import gregtech.common.covers.redstone.GT_Cover_WirelessDoesWorkDetector;
+import gregtech.common.covers.redstone.GT_Cover_WirelessFluidDetector;
+import gregtech.common.covers.redstone.GT_Cover_WirelessItemDetector;
+import gregtech.common.covers.redstone.GT_Cover_WirelessMaintenanceDetector;
+import gregtech.common.items.behaviors.Behaviour_Arrow;
+import ic2.api.crops.CropCard;
+import ic2.api.crops.Crops;
+
+public class GT_MetaGenerated_Item_02 extends GT_MetaGenerated_Item_X32 {
+
+ public static GT_MetaGenerated_Item_02 INSTANCE;
+ private static final String aTextCover = "Usable as Cover";
+
+ public GT_MetaGenerated_Item_02() {
+ super(
+ "metaitem.02",
+ OrePrefixes.toolHeadSword,
+ OrePrefixes.toolHeadPickaxe,
+ OrePrefixes.toolHeadShovel,
+ OrePrefixes.toolHeadAxe,
+ OrePrefixes.toolHeadHoe,
+ OrePrefixes.toolHeadHammer,
+ OrePrefixes.toolHeadFile,
+ OrePrefixes.toolHeadSaw,
+ OrePrefixes.toolHeadDrill,
+ OrePrefixes.toolHeadChainsaw,
+ OrePrefixes.toolHeadWrench,
+ OrePrefixes.toolHeadUniversalSpade,
+ OrePrefixes.toolHeadSense,
+ OrePrefixes.toolHeadPlow,
+ OrePrefixes.toolHeadArrow,
+ OrePrefixes.toolHeadBuzzSaw,
+ OrePrefixes.turbineBlade,
+ null,
+ OrePrefixes.itemCasing,
+ OrePrefixes.wireFine,
+ OrePrefixes.gearGtSmall,
+ OrePrefixes.rotor,
+ OrePrefixes.stickLong,
+ OrePrefixes.springSmall,
+ OrePrefixes.spring,
+ OrePrefixes.arrowGtWood,
+ OrePrefixes.arrowGtPlastic,
+ OrePrefixes.gemChipped,
+ OrePrefixes.gemFlawed,
+ OrePrefixes.gemFlawless,
+ OrePrefixes.gemExquisite,
+ OrePrefixes.gearGt);
+ INSTANCE = this;
+
+ int tLastID = 0;
+
+ ItemList.ThermosCan_Dark_Coffee.set(
+ addItem(
+ tLastID = 0,
+ "Dark Coffee",
+ "Coffee, dark, without anything else",
+ new GT_FoodStat(
+ 2,
+ 0.2F,
+ EnumAction.drink,
+ ItemList.ThermosCan_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.moveSpeed.id,
+ 400,
+ 1,
+ 70,
+ Potion.digSpeed.id,
+ 400,
+ 1,
+ 70),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.GELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 2L)));
+ ItemList.ThermosCan_Dark_Cafe_au_lait.set(
+ addItem(
+ tLastID = 1,
+ "Dark Coffee au lait",
+ "Keeping you awake the whole night",
+ new GT_FoodStat(
+ 2,
+ 0.2F,
+ EnumAction.drink,
+ ItemList.ThermosCan_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.moveSpeed.id,
+ 400,
+ 2,
+ 90,
+ Potion.digSpeed.id,
+ 400,
+ 2,
+ 90),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.GELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 3L)));
+ ItemList.ThermosCan_Coffee.set(
+ addItem(
+ tLastID = 2,
+ "Coffee",
+ "Just the regular morning Coffee",
+ new GT_FoodStat(
+ 3,
+ 0.4F,
+ EnumAction.drink,
+ ItemList.ThermosCan_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.moveSpeed.id,
+ 400,
+ 0,
+ 50,
+ Potion.digSpeed.id,
+ 400,
+ 0,
+ 50),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.GELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 1L)));
+ ItemList.ThermosCan_Cafe_au_lait.set(
+ addItem(
+ tLastID = 3,
+ "Cafe au lait",
+ "Sweet Coffee",
+ new GT_FoodStat(
+ 3,
+ 0.4F,
+ EnumAction.drink,
+ ItemList.ThermosCan_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.moveSpeed.id,
+ 400,
+ 1,
+ 70,
+ Potion.digSpeed.id,
+ 400,
+ 1,
+ 70),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.GELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 2L)));
+ ItemList.ThermosCan_Lait_au_cafe.set(
+ addItem(
+ tLastID = 4,
+ "Lait au cafe",
+ "You want Coffee to your Sugar?",
+ new GT_FoodStat(
+ 3,
+ 0.4F,
+ EnumAction.drink,
+ ItemList.ThermosCan_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.moveSpeed.id,
+ 400,
+ 2,
+ 90,
+ Potion.digSpeed.id,
+ 400,
+ 2,
+ 90),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.GELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MOTUS, 3L)));
+ ItemList.ThermosCan_Dark_Chocolate_Milk.set(
+ addItem(
+ tLastID = 5,
+ "Dark Chocolate Milk",
+ "A bit bitter, better add a bit Sugar",
+ new GT_FoodStat(
+ 3,
+ 0.4F,
+ EnumAction.drink,
+ ItemList.ThermosCan_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.regeneration.id,
+ 50,
+ 1,
+ 60),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.GELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SANO, 1L)));
+ ItemList.ThermosCan_Chocolate_Milk.set(
+ addItem(
+ tLastID = 6,
+ "Chocolate Milk",
+ "Sweet Goodness",
+ new GT_FoodStat(
+ 3,
+ 0.4F,
+ EnumAction.drink,
+ ItemList.ThermosCan_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.regeneration.id,
+ 50,
+ 1,
+ 90),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.GELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SANO, 2L)));
+ ItemList.ThermosCan_Tea.set(
+ addItem(
+ tLastID = 7,
+ "Tea",
+ "Keep calm and carry on",
+ new GT_FoodStat(
+ 2,
+ 0.2F,
+ EnumAction.drink,
+ ItemList.ThermosCan_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.moveSlowdown.id,
+ 300,
+ 0,
+ 50),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.GELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 2L)));
+ ItemList.ThermosCan_Sweet_Tea.set(
+ addItem(
+ tLastID = 8,
+ "Sweet Tea",
+ "How about a Tea Party? In Boston?",
+ new GT_FoodStat(
+ 2,
+ 0.2F,
+ EnumAction.drink,
+ ItemList.ThermosCan_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.GELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 2L)));
+ ItemList.ThermosCan_Ice_Tea.set(
+ addItem(
+ tLastID = 9,
+ "Ice Tea",
+ "Better than this purple Junk Drink from failed Potions",
+ new GT_FoodStat(
+ 2,
+ 0.2F,
+ EnumAction.drink,
+ ItemList.ThermosCan_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.moveSlowdown.id,
+ 300,
+ 0,
+ 50),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.GELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 2L)));
+
+ ItemList.GelledToluene.set(addItem(tLastID = 10, "Gelled Toluene", "Raw Explosive"));
+
+ ItemList.Bottle_Purple_Drink.set(
+ addItem(
+ tLastID = 100,
+ "Purple Drink",
+ "How about Lemonade. Or some Ice Tea? I got Purple Drink!",
+ new GT_FoodStat(
+ 8,
+ 0.2F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.moveSlowdown.id,
+ 400,
+ 1,
+ 90),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VINCULUM, 1L)));
+ ItemList.Bottle_Grape_Juice.set(
+ addItem(
+ tLastID = 101,
+ "Grape Juice",
+ "This has a cleaning effect on your internals.",
+ new GT_FoodStat(
+ 4,
+ 0.2F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.hunger.id,
+ 400,
+ 1,
+ 60),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SANO, 1L)));
+ ItemList.Bottle_Wine.set(
+ addItem(
+ tLastID = 102,
+ "Wine",
+ "Ordinary",
+ new GT_FoodStat(
+ 2,
+ 0.2F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.confusion.id,
+ 400,
+ 1,
+ 60,
+ Potion.heal.id,
+ 0,
+ 0,
+ 60,
+ Potion.poison.id,
+ 200,
+ 1,
+ 5),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SANO, 1L)));
+ ItemList.Bottle_Vinegar.set(
+ addItem(
+ tLastID = 103,
+ "Vinegar",
+ "Exquisite",
+ new GT_FoodStat(
+ 2,
+ 0.2F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.confusion.id,
+ 400,
+ 1,
+ 90,
+ Potion.heal.id,
+ 0,
+ 1,
+ 90,
+ Potion.poison.id,
+ 200,
+ 2,
+ 10,
+ Potion.harm.id,
+ 0,
+ 2,
+ 5),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SANO, 1L)));
+ ItemList.Bottle_Potato_Juice.set(
+ addItem(
+ tLastID = 104,
+ "Potato Juice",
+ "Ever seen Potato Juice in stores? No? That has a reason.",
+ new GT_FoodStat(
+ 3,
+ 0.3F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 1L)));
+ ItemList.Bottle_Vodka.set(
+ addItem(
+ tLastID = 105,
+ "Vodka",
+ "Not to confuse with Water",
+ new GT_FoodStat(
+ 2,
+ 0.2F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.confusion.id,
+ 500,
+ 0,
+ 60,
+ Potion.damageBoost.id,
+ 500,
+ 1,
+ 60,
+ Potion.poison.id,
+ 200,
+ 1,
+ 5),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TELUM, 1L)));
+ ItemList.Bottle_Leninade.set(
+ addItem(
+ tLastID = 106,
+ "Leninade",
+ "Let the Communism flow through you!",
+ new GT_FoodStat(
+ 2,
+ 0.2F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.confusion.id,
+ 500,
+ 1,
+ 90,
+ Potion.damageBoost.id,
+ 500,
+ 2,
+ 90,
+ Potion.poison.id,
+ 200,
+ 2,
+ 10,
+ Potion.harm.id,
+ 0,
+ 2,
+ 5),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TELUM, 2L)));
+ ItemList.Bottle_Mineral_Water.set(
+ addItem(
+ tLastID = 107,
+ "Mineral Water",
+ "The best Stuff you can drink to stay healthy",
+ new GT_FoodStat(
+ 1,
+ 0.1F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.regeneration.id,
+ 100,
+ 1,
+ 10),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SANO, 1L)));
+ ItemList.Bottle_Salty_Water.set(
+ addItem(
+ tLastID = 108,
+ "Salty Water",
+ "Like Sea Water but less dirty",
+ SubTag.INVISIBLE,
+ new GT_FoodStat(
+ 1,
+ 0.0F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.hunger.id,
+ 400,
+ 2,
+ 95),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TEMPESTAS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L)));
+ ItemList.Bottle_Reed_Water.set(
+ addItem(
+ tLastID = 109,
+ "Reed Water",
+ "I guess this tastes better when fermented",
+ new GT_FoodStat(
+ 1,
+ 0.1F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L)));
+ ItemList.Bottle_Rum.set(
+ addItem(
+ tLastID = 110,
+ "Rum",
+ "A buddle o' rum",
+ new GT_FoodStat(
+ 4,
+ 0.4F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.confusion.id,
+ 300,
+ 0,
+ 60,
+ Potion.damageBoost.id,
+ 300,
+ 1,
+ 60,
+ Potion.poison.id,
+ 200,
+ 1,
+ 5),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.LUCRUM, 1L)));
+ ItemList.Bottle_Pirate_Brew.set(
+ addItem(
+ tLastID = 111,
+ "Pirate Brew",
+ "Set the Sails, we are going to Torrentuga!",
+ new GT_FoodStat(
+ 4,
+ 0.4F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.confusion.id,
+ 300,
+ 1,
+ 90,
+ Potion.damageBoost.id,
+ 300,
+ 2,
+ 90,
+ Potion.poison.id,
+ 200,
+ 2,
+ 10,
+ Potion.harm.id,
+ 0,
+ 2,
+ 5),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.LUCRUM, 2L)));
+ ItemList.Bottle_Hops_Juice.set(
+ addItem(
+ tLastID = 112,
+ "Hops Juice",
+ "Every Beer has a start",
+ new GT_FoodStat(
+ 1,
+ 0.1F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 1L)));
+ ItemList.Bottle_Dark_Beer.set(
+ addItem(
+ tLastID = 113,
+ "Dark Beer",
+ "Dark Beer, for the real Men",
+ new GT_FoodStat(
+ 4,
+ 0.4F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.confusion.id,
+ 300,
+ 1,
+ 60,
+ Potion.damageBoost.id,
+ 300,
+ 1,
+ 60,
+ Potion.poison.id,
+ 200,
+ 1,
+ 5),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 1L)));
+ ItemList.Bottle_Dragon_Blood.set(
+ addItem(
+ tLastID = 114,
+ "Dragon Blood",
+ "FUS RO DAH!",
+ new GT_FoodStat(
+ 4,
+ 0.4F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.confusion.id,
+ 300,
+ 2,
+ 90,
+ Potion.damageBoost.id,
+ 300,
+ 2,
+ 90,
+ Potion.poison.id,
+ 200,
+ 2,
+ 10,
+ Potion.harm.id,
+ 0,
+ 2,
+ 5),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 2L)));
+ ItemList.Bottle_Wheaty_Juice.set(
+ addItem(
+ tLastID = 115,
+ "Wheaty Juice",
+ "Is this liquefied Bread or what?",
+ new GT_FoodStat(
+ 2,
+ 0.1F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 1L)));
+ ItemList.Bottle_Scotch.set(
+ addItem(
+ tLastID = 116,
+ "Scotch",
+ "Technically this is just a Whisky",
+ new GT_FoodStat(
+ 2,
+ 0.1F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.confusion.id,
+ 400,
+ 0,
+ 60,
+ Potion.resistance.id,
+ 400,
+ 1,
+ 60,
+ Potion.poison.id,
+ 200,
+ 1,
+ 5),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TUTAMEN, 1L)));
+ ItemList.Bottle_Glen_McKenner.set(
+ addItem(
+ tLastID = 117,
+ "Glen McKenner",
+ "Don't hand to easily surprised people, they will shatter it.",
+ new GT_FoodStat(
+ 2,
+ 0.1F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.confusion.id,
+ 400,
+ 1,
+ 90,
+ Potion.resistance.id,
+ 400,
+ 2,
+ 90,
+ Potion.poison.id,
+ 200,
+ 2,
+ 10,
+ Potion.harm.id,
+ 0,
+ 2,
+ 5),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TUTAMEN, 2L)));
+ ItemList.Bottle_Wheaty_Hops_Juice.set(
+ addItem(
+ tLastID = 118,
+ "Wheaty Hops Juice",
+ "Also known as 'Duff-Lite'",
+ new GT_FoodStat(
+ 1,
+ 0.1F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 2L)));
+ ItemList.Bottle_Beer.set(
+ addItem(
+ tLastID = 119,
+ "Beer",
+ "Good old Beer",
+ new GT_FoodStat(
+ 6,
+ 0.4F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.confusion.id,
+ 400,
+ 0,
+ 60,
+ Potion.digSpeed.id,
+ 400,
+ 2,
+ 60,
+ Potion.poison.id,
+ 100,
+ 0,
+ 5),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.PERFODIO, 1L)));
+ ItemList.Bottle_Chilly_Sauce.set(
+ addItem(
+ tLastID = 120,
+ "Chilly Sauce",
+ "Spicy",
+ new GT_FoodStat(
+ 2,
+ 0.1F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.confusion.id,
+ 1000,
+ 0,
+ 10,
+ Potion.fireResistance.id,
+ 1000,
+ 0,
+ 60),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L)));
+ ItemList.Bottle_Hot_Sauce.set(
+ addItem(
+ tLastID = 121,
+ "Hot Sauce",
+ "Very Spicy, I guess?",
+ new GT_FoodStat(
+ 2,
+ 0.1F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.confusion.id,
+ 2000,
+ 0,
+ 30,
+ Potion.fireResistance.id,
+ 2000,
+ 0,
+ 70),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 2L)));
+ ItemList.Bottle_Diabolo_Sauce.set(
+ addItem(
+ tLastID = 122,
+ "Diabolo Sauce",
+ "As if the Devil made this Sauce",
+ new GT_FoodStat(
+ 2,
+ 0.1F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.confusion.id,
+ 3000,
+ 1,
+ 50,
+ Potion.fireResistance.id,
+ 3000,
+ 0,
+ 80),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 3L)));
+ ItemList.Bottle_Diablo_Sauce.set(
+ addItem(
+ tLastID = 123,
+ "Diablo Sauce",
+ "Diablo always comes back!",
+ new GT_FoodStat(
+ 2,
+ 0.1F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.confusion.id,
+ 4000,
+ 1,
+ 70,
+ Potion.fireResistance.id,
+ 4000,
+ 0,
+ 90),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 4L)));
+ ItemList.Bottle_Snitches_Glitch_Sauce.set(
+ addItem(
+ tLastID = 124,
+ "Old Man Snitches glitched Diablo Sauce",
+ "[Missing No]",
+ SubTag.INVISIBLE,
+ new GT_FoodStat(
+ 2,
+ 0.1F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.confusion.id,
+ 9999,
+ 2,
+ 999,
+ Potion.fireResistance.id,
+ 9999,
+ 9,
+ 999),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 3L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 5L)));
+ ItemList.Bottle_Apple_Juice.set(
+ addItem(
+ tLastID = 125,
+ "Apple Juice",
+ "Made of the Apples from our best Oak Farms",
+ new GT_FoodStat(
+ 4,
+ 0.2F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.hunger.id,
+ 400,
+ 0,
+ 20),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L)));
+ ItemList.Bottle_Cider.set(
+ addItem(
+ tLastID = 126,
+ "Cider",
+ "If you have nothing better to do with your Apples",
+ new GT_FoodStat(
+ 4,
+ 0.2F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.confusion.id,
+ 400,
+ 0,
+ 60,
+ Potion.resistance.id,
+ 400,
+ 1,
+ 60,
+ Potion.poison.id,
+ 200,
+ 1,
+ 5),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TUTAMEN, 1L)));
+ ItemList.Bottle_Golden_Apple_Juice.set(
+ addItem(
+ tLastID = 127,
+ "Golden Apple Juice",
+ "A golden Apple in liquid form",
+ new GT_FoodStat(
+ 4,
+ 0.2F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.hunger.id,
+ 400,
+ 0,
+ 20,
+ Potion.field_76444_x.id,
+ 2400,
+ 0,
+ 100,
+ Potion.regeneration.id,
+ 100,
+ 1,
+ 100),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SANO, 1L)));
+ ItemList.Bottle_Golden_Cider.set(
+ addItem(
+ tLastID = 128,
+ "Golden Cider",
+ "More Resistance, less Regeneration",
+ new GT_FoodStat(
+ 4,
+ 0.2F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.confusion.id,
+ 400,
+ 0,
+ 60,
+ Potion.field_76444_x.id,
+ 2400,
+ 1,
+ 95,
+ Potion.poison.id,
+ 200,
+ 1,
+ 5),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TUTAMEN, 1L)));
+ ItemList.Bottle_Iduns_Apple_Juice.set(
+ addItem(
+ tLastID = 129,
+ "Idun's Apple Juice",
+ "So you got the Idea of using Notch Apples for a drink?",
+ new GT_FoodStat(
+ 4,
+ 0.2F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.regeneration.id,
+ 600,
+ 4,
+ 100,
+ Potion.field_76444_x.id,
+ 2400,
+ 0,
+ 100,
+ Potion.resistance.id,
+ 6000,
+ 0,
+ 100,
+ Potion.fireResistance.id,
+ 6000,
+ 0,
+ 100),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.NEBRISUM, 9L)));
+ ItemList.Bottle_Notches_Brew.set(
+ addItem(
+ tLastID = 130,
+ "Notches Brew",
+ "This is just overpowered",
+ new GT_FoodStat(
+ 4,
+ 0.2F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.regeneration.id,
+ 700,
+ 4,
+ 95,
+ Potion.field_76444_x.id,
+ 3000,
+ 1,
+ 95,
+ Potion.resistance.id,
+ 7000,
+ 1,
+ 95,
+ Potion.fireResistance.id,
+ 7000,
+ 0,
+ 95,
+ Potion.harm.id,
+ 0,
+ 2,
+ 20),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.NEBRISUM, 9L)));
+ ItemList.Bottle_Lemon_Juice.set(
+ addItem(
+ tLastID = 131,
+ "Lemon Juice",
+ "Maybe adding Sugar will make it less sour",
+ new GT_FoodStat(
+ 2,
+ 0.4F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.digSpeed.id,
+ 1200,
+ 0,
+ 60),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.PERFODIO, 1L)));
+ ItemList.Bottle_Limoncello.set(
+ addItem(
+ tLastID = 132,
+ "Limoncello",
+ "An alcoholic Drink which tastes like Lemons",
+ new GT_FoodStat(
+ 2,
+ 0.4F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.digSpeed.id,
+ 1200,
+ 0,
+ 90,
+ Potion.poison.id,
+ 200,
+ 1,
+ 5),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.PERFODIO, 1L)));
+ ItemList.Bottle_Lemonade.set(
+ addItem(
+ tLastID = 133,
+ "Lemonade",
+ "Cold and refreshing Lemonade",
+ new GT_FoodStat(
+ 4,
+ 0.3F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.digSpeed.id,
+ 900,
+ 1,
+ 90),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.PERFODIO, 1L)));
+ ItemList.Bottle_Alcopops.set(
+ addItem(
+ tLastID = 134,
+ "Alcopops",
+ "Don't let your Children drink this junk!",
+ new GT_FoodStat(
+ 2,
+ 0.2F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.digSpeed.id,
+ 900,
+ 1,
+ 90,
+ Potion.poison.id,
+ 300,
+ 2,
+ 20),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VENENUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VINCULUM, 1L)));
+ ItemList.Bottle_Cave_Johnsons_Grenade_Juice.set(
+ addItem(
+ tLastID = 135,
+ "Cave Johnson's Grenade Juice",
+ "When life gives you Lemons, make Life take them Lemons back!",
+ new GT_FoodStat(
+ 0,
+ 0.0F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false).setExplosive(),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MORTUUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.PERDITIO, 1L)));
+ ItemList.Bottle_Milk.set(
+ addItem(
+ tLastID = 136,
+ "Milk",
+ "Got Milk?",
+ OrePrefixes.bottle.get(Materials.Milk),
+ new GT_FoodStat(
+ 0,
+ 0.0F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false).setMilk(),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SANO, 1L)));
+ ItemList.Bottle_Holy_Water.set(
+ addItem(
+ tLastID = 137,
+ "Holy Water",
+ "May the holy Planks be with you",
+ OrePrefixes.bottle.get(Materials.HolyWater),
+ new GT_FoodStat(
+ 0,
+ 0.0F,
+ EnumAction.drink,
+ ItemList.Bottle_Empty.get(1L),
+ GregTech_API.sDrinksAlwaysDrinkable,
+ false,
+ false,
+ Potion.poison.id,
+ 100,
+ 1,
+ 100).setMilk(),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AURAM, 1L)));
+
+ ItemList.Food_Potato_On_Stick.set(
+ addItem(
+ tLastID = 200,
+ "Potato on a Stick",
+ "Totally looks like a Crab Claw",
+ new GT_FoodStat(1, 0.3F, EnumAction.eat, new ItemStack(Items.stick, 1), false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 1L)));
+ ItemList.Food_Potato_On_Stick_Roasted.set(
+ addItem(
+ tLastID = 201,
+ "Roasted Potato on a Stick",
+ "Still looks like a Crab Claw",
+ new GT_FoodStat(6, 0.6F, EnumAction.eat, new ItemStack(Items.stick, 1), false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L)));
+ ItemList.Food_Raw_Fries.set(
+ addItem(
+ tLastID = 202,
+ "Potato Strips",
+ "It's Potato in Stripe Form",
+ new GT_FoodStat(1, 0.3F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L)));
+ setFluidContainerStats(32000 + tLastID, 0L, 16L);
+ ItemList.Food_Fries.set(
+ addItem(
+ tLastID = 203,
+ "Fries",
+ "Not to confuse with Fry the Delivery Boy",
+ new GT_FoodStat(7, 0.5F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L)));
+ setFluidContainerStats(32000 + tLastID, 0L, 16L);
+ ItemList.Food_Packaged_Fries.set(
+ addItem(
+ tLastID = 204,
+ "Fries",
+ "Ketchup not included",
+ new GT_FoodStat(
+ 7,
+ 0.5F,
+ EnumAction.eat,
+ GT_OreDictUnificator.get(OrePrefixes.plate, Materials.Paper, 1L),
+ false,
+ true,
+ false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L)));
+ ItemList.Food_Raw_PotatoChips.set(
+ addItem(
+ tLastID = 205,
+ "Potato Chips (Raw)",
+ "Just like a Potato",
+ new GT_FoodStat(1, 0.3F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L)));
+ setFluidContainerStats(32000 + tLastID, 0L, 16L);
+ ItemList.Food_PotatoChips.set(
+ addItem(
+ tLastID = 206,
+ "Potato Chips",
+ "Crunchy",
+ new GT_FoodStat(7, 0.5F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L)));
+ setFluidContainerStats(32000 + tLastID, 0L, 16L);
+ ItemList.Food_ChiliChips.set(
+ addItem(
+ tLastID = 207,
+ "Chili Chips",
+ "Spicy",
+ new GT_FoodStat(7, 0.6F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L)));
+ setFluidContainerStats(32000 + tLastID, 0L, 16L);
+ ItemList.Food_Packaged_PotatoChips.set(
+ addItem(
+ tLastID = 208,
+ "Bag of Potato Chips",
+ "Full of delicious Air",
+ new GT_FoodStat(
+ 7,
+ 0.5F,
+ EnumAction.eat,
+ GT_OreDictUnificator.get(OrePrefixes.foil, Materials.Aluminium, 1L),
+ false,
+ true,
+ false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L)));
+ ItemList.Food_Packaged_ChiliChips.set(
+ addItem(
+ tLastID = 209,
+ "Bag of Chili Chips",
+ "Stop making noises Baj!",
+ new GT_FoodStat(
+ 7,
+ 0.6F,
+ EnumAction.eat,
+ GT_OreDictUnificator.get(OrePrefixes.foil, Materials.Aluminium, 1L),
+ false,
+ true,
+ false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L)));
+ ItemList.Food_Chum.set(
+ addItem(
+ tLastID = 210,
+ "Chum",
+ "Chum is Fum!",
+ new GT_FoodStat(
+ 5,
+ 0.2F,
+ EnumAction.eat,
+ null,
+ true,
+ false,
+ true,
+ Potion.hunger.id,
+ 1000,
+ 4,
+ 100,
+ Potion.confusion.id,
+ 300,
+ 1,
+ 80),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L)));
+ ItemList.Food_Chum_On_Stick.set(
+ addItem(
+ tLastID = 211,
+ "Chum on a Stick",
+ "Don't forget to try our Chum-balaya",
+ new GT_FoodStat(
+ 5,
+ 0.2F,
+ EnumAction.eat,
+ new ItemStack(Items.stick, 1),
+ true,
+ false,
+ true,
+ Potion.hunger.id,
+ 1000,
+ 4,
+ 100,
+ Potion.confusion.id,
+ 300,
+ 1,
+ 80),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L)));
+ ItemList.Food_Dough_Sugar.set(
+ addItem(
+ tLastID = 212,
+ "Sugary Dough",
+ "Don't eat the Dough before it is baken",
+ new GT_FoodStat(1, 0.1F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L)));
+ ItemList.Food_Dough_Chocolate.set(
+ addItem(
+ tLastID = 213,
+ "Chocolate Dough",
+ "I said don't eat the Dough!",
+ new GT_FoodStat(1, 0.1F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L)));
+ ItemList.Food_Raw_Cookie.set(
+ addItem(
+ tLastID = 214,
+ "Cookie shaped Dough",
+ "For baking Cookies",
+ new GT_FoodStat(1, 0.1F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L)));
+
+ ItemList.Food_Sliced_Buns.set(
+ addItem(
+ tLastID = 220,
+ "Buns",
+ "Pre Sliced",
+ new GT_FoodStat(3, 0.5F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L)));
+ ItemList.Food_Burger_Veggie.set(
+ addItem(
+ tLastID = 221,
+ "Veggieburger",
+ "No matter how you call this, this is NOT a Burger!",
+ new GT_FoodStat(3, 0.5F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L)));
+ ItemList.Food_Burger_Cheese.set(
+ addItem(
+ tLastID = 222,
+ "Cheeseburger",
+ "Cheesy!",
+ new GT_FoodStat(3, 0.5F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L),
+ new ItemData(Materials.Cheese, 907200L)));
+ ItemList.Food_Burger_Meat.set(
+ addItem(
+ tLastID = 223,
+ "Hamburger",
+ "The Mc Burger Queen Burger",
+ new GT_FoodStat(3, 0.5F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.CORPUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L)));
+ ItemList.Food_Burger_Chum.set(
+ addItem(
+ tLastID = 224,
+ "Chumburger",
+ "Fum is Chum!",
+ new GT_FoodStat(
+ 5,
+ 0.2F,
+ EnumAction.eat,
+ null,
+ true,
+ false,
+ true,
+ Potion.hunger.id,
+ 1000,
+ 4,
+ 100,
+ Potion.confusion.id,
+ 300,
+ 1,
+ 80),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L)));
+
+ ItemList.Food_Sliced_Breads.set(
+ addItem(
+ tLastID = 230,
+ "Breads",
+ "Pre Sliced",
+ new GT_FoodStat(5, 0.6F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L)));
+ ItemList.Food_Sandwich_Veggie.set(
+ addItem(
+ tLastID = 231,
+ "Veggie Sandwich",
+ "Meatless",
+ new GT_FoodStat(7, 0.6F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L)));
+ setFluidContainerStats(32000 + tLastID, 0L, 32L);
+ ItemList.Food_Sandwich_Cheese.set(
+ addItem(
+ tLastID = 232,
+ "Cheese Sandwich",
+ "Say Cheese!",
+ new GT_FoodStat(7, 0.6F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L)));
+ setFluidContainerStats(32000 + tLastID, 0L, 32L);
+ ItemList.Food_Sandwich_Bacon.set(
+ addItem(
+ tLastID = 233,
+ "Bacon Sandwich",
+ "The best Sandwich ever!",
+ new GT_FoodStat(10, 0.8F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.CORPUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L)));
+ setFluidContainerStats(32000 + tLastID, 0L, 32L);
+ ItemList.Food_Sandwich_Steak.set(
+ addItem(
+ tLastID = 234,
+ "Steak Sandwich",
+ "Not a 'Steam Sandwich'",
+ new GT_FoodStat(10, 0.8F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.CORPUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L)));
+ setFluidContainerStats(32000 + tLastID, 0L, 32L);
+
+ ItemList.Food_Sliced_Baguettes.set(
+ addItem(
+ tLastID = 240,
+ "Baguettes",
+ "Pre Sliced",
+ new GT_FoodStat(8, 0.5F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L)));
+ ItemList.Food_Large_Sandwich_Veggie.set(
+ addItem(
+ tLastID = 241,
+ "Large Veggie Sandwich",
+ "Just not worth it",
+ new GT_FoodStat(15, 0.8F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 3L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L)));
+ setFluidContainerStats(32000 + tLastID, 0L, 16L);
+ ItemList.Food_Large_Sandwich_Cheese.set(
+ addItem(
+ tLastID = 242,
+ "Large Cheese Sandwich",
+ "I need another cheesy tooltip for this",
+ new GT_FoodStat(15, 0.8F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 3L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L)));
+ setFluidContainerStats(32000 + tLastID, 0L, 16L);
+ ItemList.Food_Large_Sandwich_Bacon.set(
+ addItem(
+ tLastID = 243,
+ "Large Bacon Sandwich",
+ "For Men! (and manly Women)",
+ new GT_FoodStat(20, 1.0F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.CORPUS, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L)));
+ setFluidContainerStats(32000 + tLastID, 0L, 16L);
+ ItemList.Food_Large_Sandwich_Steak.set(
+ addItem(
+ tLastID = 244,
+ "Large Steak Sandwich",
+ "Yes, I once accidentially called it 'Steam Sandwich'",
+ new GT_FoodStat(20, 1.0F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.CORPUS, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L)));
+ setFluidContainerStats(32000 + tLastID, 0L, 16L);
+
+ ItemList.Food_Raw_Pizza_Veggie.set(
+ addItem(
+ tLastID = 250,
+ "Raw Veggie Pizza",
+ "Into the Oven with it!",
+ new GT_FoodStat(1, 0.2F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L)));
+ ItemList.Food_Raw_Pizza_Cheese.set(
+ addItem(
+ tLastID = 251,
+ "Raw Cheese Pizza",
+ "Into the Oven with it!",
+ new GT_FoodStat(2, 0.2F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L)));
+ ItemList.Food_Raw_Pizza_Meat.set(
+ addItem(
+ tLastID = 252,
+ "Raw Mince Meat Pizza",
+ "Into the Oven with it!",
+ new GT_FoodStat(2, 0.2F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.CORPUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L)));
+
+ ItemList.Food_Baked_Pizza_Veggie.set(
+ addItem(
+ tLastID = 260,
+ "Veggie Pizza",
+ "The next they want is Gluten Free Pizzas...",
+ new GT_FoodStat(3, 0.3F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L)));
+ ItemList.Food_Baked_Pizza_Cheese.set(
+ addItem(
+ tLastID = 261,
+ "Cheese Pizza",
+ "Pizza Magarita",
+ new GT_FoodStat(4, 0.4F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L)));
+ ItemList.Food_Baked_Pizza_Meat.set(
+ addItem(
+ tLastID = 262,
+ "Mince Meat Pizza",
+ "Emo Pizza, it cuts itself!",
+ new GT_FoodStat(5, 0.5F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.CORPUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L)));
+
+ ItemList.Dye_Indigo.set(
+ addItem(
+ tLastID = 410,
+ "Indigo Dye",
+ "Blue Dye",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SENSUS, 1L),
+ Dyes.dyeBlue));
+ for (byte i = 0; i < 16; i = (byte) (i + 1)) {
+ ItemList.DYE_ONLY_ITEMS[i].set(
+ addItem(
+ tLastID = 414 + i,
+ Dyes.get(i).mName + " Dye",
+ "",
+ Dyes.get(i)
+ .name(),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SENSUS, 1L)));
+ }
+ ItemList.Plank_Oak
+ .set(addItem(tLastID = 470, "Oak Plank", aTextCover, new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 1L)));
+ setBurnValue(32000 + tLastID, 75);
+ ItemList.Plank_Spruce.set(
+ addItem(tLastID = 471, "Spruce Plank", aTextCover, new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 1L)));
+ setBurnValue(32000 + tLastID, 75);
+ ItemList.Plank_Birch.set(
+ addItem(tLastID = 472, "Birch Plank", aTextCover, new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 1L)));
+ setBurnValue(32000 + tLastID, 75);
+ ItemList.Plank_Jungle.set(
+ addItem(tLastID = 473, "Jungle Plank", aTextCover, new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 1L)));
+ setBurnValue(32000 + tLastID, 75);
+ ItemList.Plank_Acacia.set(
+ addItem(tLastID = 474, "Acacia Plank", aTextCover, new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 1L)));
+ setBurnValue(32000 + tLastID, 75);
+ ItemList.Plank_DarkOak.set(
+ addItem(tLastID = 475, "Dark Oak Plank", aTextCover, new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 1L)));
+ setBurnValue(32000 + tLastID, 75);
+ ItemList.Plank_Larch.set(
+ addItem(tLastID = 476, "Larch Plank", aTextCover, new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 1L)));
+ setBurnValue(32000 + tLastID, 75);
+ ItemList.Plank_Teak
+ .set(addItem(tLastID = 477, "Teak Plank", aTextCover, new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 1L)));
+ setBurnValue(32000 + tLastID, 75);
+ ItemList.Plank_Acacia_Green.set(
+ addItem(
+ tLastID = 478,
+ "Green Acacia Plank",
+ aTextCover,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 1L)));
+ setBurnValue(32000 + tLastID, 75);
+ ItemList.Plank_Lime
+ .set(addItem(tLastID = 479, "Lime Plank", aTextCover, new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 1L)));
+ setBurnValue(32000 + tLastID, 75);
+ ItemList.Plank_Chestnut.set(
+ addItem(tLastID = 480, "Chestnut Plank", aTextCover, new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 1L)));
+ setBurnValue(32000 + tLastID, 75);
+ ItemList.Plank_Wenge.set(
+ addItem(tLastID = 481, "Wenge Plank", aTextCover, new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 1L)));
+ setBurnValue(32000 + tLastID, 75);
+ ItemList.Plank_Baobab.set(
+ addItem(tLastID = 482, "Baobab Plank", aTextCover, new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 1L)));
+ setBurnValue(32000 + tLastID, 75);
+ ItemList.Plank_Sequoia.set(
+ addItem(tLastID = 483, "Sequoia Plank", aTextCover, new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 1L)));
+ setBurnValue(32000 + tLastID, 75);
+ ItemList.Plank_Kapok.set(
+ addItem(tLastID = 484, "Kapok Plank", aTextCover, new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 1L)));
+ setBurnValue(32000 + tLastID, 75);
+ ItemList.Plank_Ebony.set(
+ addItem(tLastID = 485, "Ebony Plank", aTextCover, new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 1L)));
+ setBurnValue(32000 + tLastID, 75);
+ ItemList.Plank_Mahagony.set(
+ addItem(tLastID = 486, "Mahagony Plank", aTextCover, new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 1L)));
+ setBurnValue(32000 + tLastID, 75);
+ ItemList.Plank_Balsa.set(
+ addItem(tLastID = 487, "Balsa Plank", aTextCover, new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 1L)));
+ setBurnValue(32000 + tLastID, 75);
+ ItemList.Plank_Willow.set(
+ addItem(tLastID = 488, "Willow Plank", aTextCover, new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 1L)));
+ setBurnValue(32000 + tLastID, 75);
+ ItemList.Plank_Walnut.set(
+ addItem(tLastID = 489, "Walnut Plank", aTextCover, new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 1L)));
+ setBurnValue(32000 + tLastID, 75);
+ ItemList.Plank_Greenheart.set(
+ addItem(
+ tLastID = 490,
+ "Greenheart Plank",
+ aTextCover,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 1L)));
+ setBurnValue(32000 + tLastID, 75);
+ ItemList.Plank_Cherry.set(
+ addItem(tLastID = 491, "Cherry Plank", aTextCover, new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 1L)));
+ setBurnValue(32000 + tLastID, 75);
+ ItemList.Plank_Mahoe.set(
+ addItem(tLastID = 492, "Mahoe Plank", aTextCover, new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 1L)));
+ setBurnValue(32000 + tLastID, 75);
+ ItemList.Plank_Poplar.set(
+ addItem(tLastID = 493, "Poplar Plank", aTextCover, new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 1L)));
+ setBurnValue(32000 + tLastID, 75);
+ ItemList.Plank_Palm
+ .set(addItem(tLastID = 494, "Palm Plank", aTextCover, new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 1L)));
+ setBurnValue(32000 + tLastID, 75);
+ ItemList.Plank_Papaya.set(
+ addItem(tLastID = 495, "Papaya Plank", aTextCover, new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 1L)));
+ setBurnValue(32000 + tLastID, 75);
+ ItemList.Plank_Pine
+ .set(addItem(tLastID = 496, "Pine Plank", aTextCover, new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 1L)));
+ setBurnValue(32000 + tLastID, 75);
+ ItemList.Plank_Plum
+ .set(addItem(tLastID = 497, "Plum Plank", aTextCover, new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 1L)));
+ setBurnValue(32000 + tLastID, 75);
+ ItemList.Plank_Maple.set(
+ addItem(tLastID = 498, "Maple Plank", aTextCover, new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 1L)));
+ setBurnValue(32000 + tLastID, 75);
+ ItemList.Plank_Citrus.set(
+ addItem(tLastID = 499, "Citrus Plank", aTextCover, new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 1L)));
+ setBurnValue(32000 + tLastID, 75);
+
+ ItemList.SFMixture.set(addItem(tLastID = 270, "Super Fuel Binder", "Raw Material"));
+ ItemList.MSFMixture.set(addItem(tLastID = 271, "Magic Super Fuel Binder", "Raw Material"));
+
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Plank_Oak.get(2L),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "s ", " P", 'P', new ItemStack(Blocks.wooden_slab, 1, 0) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Plank_Spruce.get(2L),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "s ", " P", 'P', new ItemStack(Blocks.wooden_slab, 1, 1) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Plank_Birch.get(2L),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "s ", " P", 'P', new ItemStack(Blocks.wooden_slab, 1, 2) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Plank_Jungle.get(2L),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "s ", " P", 'P', new ItemStack(Blocks.wooden_slab, 1, 3) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Plank_Acacia.get(2L),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "s ", " P", 'P', new ItemStack(Blocks.wooden_slab, 1, 4) });
+ GT_ModHandler.addCraftingRecipe(
+ ItemList.Plank_DarkOak.get(2L),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE | GT_ModHandler.RecipeBits.REVERSIBLE,
+ new Object[] { "s ", " P", 'P', new ItemStack(Blocks.wooden_slab, 1, 5) });
+
+ GregTech_API.registerCover(ItemList.Plank_Oak.get(1L), TextureFactory.of(Blocks.planks, 0), null);
+ GregTech_API.registerCover(ItemList.Plank_Spruce.get(1L), TextureFactory.of(Blocks.planks, 1), null);
+ GregTech_API.registerCover(ItemList.Plank_Birch.get(1L), TextureFactory.of(Blocks.planks, 2), null);
+ GregTech_API.registerCover(ItemList.Plank_Jungle.get(1L), TextureFactory.of(Blocks.planks, 3), null);
+ GregTech_API.registerCover(ItemList.Plank_Acacia.get(1L), TextureFactory.of(Blocks.planks, 4), null);
+ GregTech_API.registerCover(ItemList.Plank_DarkOak.get(1L), TextureFactory.of(Blocks.planks, 5), null);
+ GregTech_API.registerCover(
+ ItemList.Plank_Larch.get(1L),
+ TextureFactory.of(
+ GT_Utility.getBlockFromStack(
+ GT_ModHandler.getModItem(Forestry.ID, "planks", 1L, 0, new ItemStack(Blocks.planks, 1, 0))),
+ 0),
+ null);
+ GregTech_API.registerCover(
+ ItemList.Plank_Teak.get(1L),
+ TextureFactory.of(
+ GT_Utility.getBlockFromStack(
+ GT_ModHandler.getModItem(Forestry.ID, "planks", 1L, 1, new ItemStack(Blocks.planks, 1, 0))),
+ 1),
+ null);
+ GregTech_API.registerCover(
+ ItemList.Plank_Acacia_Green.get(1L),
+ TextureFactory.of(
+ GT_Utility.getBlockFromStack(
+ GT_ModHandler.getModItem(Forestry.ID, "planks", 1L, 2, new ItemStack(Blocks.planks, 1, 0))),
+ 2),
+ null);
+ GregTech_API.registerCover(
+ ItemList.Plank_Lime.get(1L),
+ TextureFactory.of(
+ GT_Utility.getBlockFromStack(
+ GT_ModHandler.getModItem(Forestry.ID, "planks", 1L, 3, new ItemStack(Blocks.planks, 1, 0))),
+ 3),
+ null);
+ GregTech_API.registerCover(
+ ItemList.Plank_Chestnut.get(1L),
+ TextureFactory.of(
+ GT_Utility.getBlockFromStack(
+ GT_ModHandler.getModItem(Forestry.ID, "planks", 1L, 4, new ItemStack(Blocks.planks, 1, 0))),
+ 4),
+ null);
+ GregTech_API.registerCover(
+ ItemList.Plank_Wenge.get(1L),
+ TextureFactory.of(
+ GT_Utility.getBlockFromStack(
+ GT_ModHandler.getModItem(Forestry.ID, "planks", 1L, 5, new ItemStack(Blocks.planks, 1, 0))),
+ 5),
+ null);
+ GregTech_API.registerCover(
+ ItemList.Plank_Baobab.get(1L),
+ TextureFactory.of(
+ GT_Utility.getBlockFromStack(
+ GT_ModHandler.getModItem(Forestry.ID, "planks", 1L, 6, new ItemStack(Blocks.planks, 1, 0))),
+ 6),
+ null);
+ GregTech_API.registerCover(
+ ItemList.Plank_Sequoia.get(1L),
+ TextureFactory.of(
+ GT_Utility.getBlockFromStack(
+ GT_ModHandler.getModItem(Forestry.ID, "planks", 1L, 7, new ItemStack(Blocks.planks, 1, 0))),
+ 7),
+ null);
+ GregTech_API.registerCover(
+ ItemList.Plank_Kapok.get(1L),
+ TextureFactory.of(
+ GT_Utility.getBlockFromStack(
+ GT_ModHandler.getModItem(Forestry.ID, "planks", 1L, 8, new ItemStack(Blocks.planks, 1, 0))),
+ 8),
+ null);
+ GregTech_API.registerCover(
+ ItemList.Plank_Ebony.get(1L),
+ TextureFactory.of(
+ GT_Utility.getBlockFromStack(
+ GT_ModHandler.getModItem(Forestry.ID, "planks", 1L, 9, new ItemStack(Blocks.planks, 1, 0))),
+ 9),
+ null);
+ GregTech_API.registerCover(
+ ItemList.Plank_Mahagony.get(1L),
+ TextureFactory.of(
+ GT_Utility.getBlockFromStack(
+ GT_ModHandler.getModItem(Forestry.ID, "planks", 1L, 10, new ItemStack(Blocks.planks, 1, 0))),
+ 10),
+ null);
+ GregTech_API.registerCover(
+ ItemList.Plank_Balsa.get(1L),
+ TextureFactory.of(
+ GT_Utility.getBlockFromStack(
+ GT_ModHandler.getModItem(Forestry.ID, "planks", 1L, 11, new ItemStack(Blocks.planks, 1, 0))),
+ 11),
+ null);
+ GregTech_API.registerCover(
+ ItemList.Plank_Willow.get(1L),
+ TextureFactory.of(
+ GT_Utility.getBlockFromStack(
+ GT_ModHandler.getModItem(Forestry.ID, "planks", 1L, 12, new ItemStack(Blocks.planks, 1, 0))),
+ 12),
+ null);
+ GregTech_API.registerCover(
+ ItemList.Plank_Walnut.get(1L),
+ TextureFactory.of(
+ GT_Utility.getBlockFromStack(
+ GT_ModHandler.getModItem(Forestry.ID, "planks", 1L, 13, new ItemStack(Blocks.planks, 1, 0))),
+ 13),
+ null);
+ GregTech_API.registerCover(
+ ItemList.Plank_Greenheart.get(1L),
+ TextureFactory.of(
+ GT_Utility.getBlockFromStack(
+ GT_ModHandler.getModItem(Forestry.ID, "planks", 1L, 14, new ItemStack(Blocks.planks, 1, 0))),
+ 14),
+ null);
+ GregTech_API.registerCover(
+ ItemList.Plank_Cherry.get(1L),
+ TextureFactory.of(
+ GT_Utility.getBlockFromStack(
+ GT_ModHandler.getModItem(Forestry.ID, "planks", 1L, 15, new ItemStack(Blocks.planks, 1, 0))),
+ 15),
+ null);
+ GregTech_API.registerCover(
+ ItemList.Plank_Mahoe.get(1L),
+ TextureFactory.of(
+ GT_Utility.getBlockFromStack(
+ GT_ModHandler.getModItem(Forestry.ID, "planks", 1L, 16, new ItemStack(Blocks.planks, 1, 0))),
+ 0),
+ null);
+ GregTech_API.registerCover(
+ ItemList.Plank_Poplar.get(1L),
+ TextureFactory.of(
+ GT_Utility.getBlockFromStack(
+ GT_ModHandler.getModItem(Forestry.ID, "planks", 1L, 17, new ItemStack(Blocks.planks, 1, 0))),
+ 1),
+ null);
+ GregTech_API.registerCover(
+ ItemList.Plank_Palm.get(1L),
+ TextureFactory.of(
+ GT_Utility.getBlockFromStack(
+ GT_ModHandler.getModItem(Forestry.ID, "planks", 1L, 18, new ItemStack(Blocks.planks, 1, 0))),
+ 2),
+ null);
+ GregTech_API.registerCover(
+ ItemList.Plank_Papaya.get(1L),
+ TextureFactory.of(
+ GT_Utility.getBlockFromStack(
+ GT_ModHandler.getModItem(Forestry.ID, "planks", 1L, 19, new ItemStack(Blocks.planks, 1, 0))),
+ 3),
+ null);
+ GregTech_API.registerCover(
+ ItemList.Plank_Pine.get(1L),
+ TextureFactory.of(
+ GT_Utility.getBlockFromStack(
+ GT_ModHandler.getModItem(Forestry.ID, "planks", 1L, 20, new ItemStack(Blocks.planks, 1, 0))),
+ 4),
+ null);
+ GregTech_API.registerCover(
+ ItemList.Plank_Plum.get(1L),
+ TextureFactory.of(
+ GT_Utility.getBlockFromStack(
+ GT_ModHandler.getModItem(Forestry.ID, "planks", 1L, 21, new ItemStack(Blocks.planks, 1, 0))),
+ 5),
+ null);
+ GregTech_API.registerCover(
+ ItemList.Plank_Maple.get(1L),
+ TextureFactory.of(
+ GT_Utility.getBlockFromStack(
+ GT_ModHandler.getModItem(Forestry.ID, "planks", 1L, 22, new ItemStack(Blocks.planks, 1, 0))),
+ 6),
+ null);
+ GregTech_API.registerCover(
+ ItemList.Plank_Citrus.get(1L),
+ TextureFactory.of(
+ GT_Utility.getBlockFromStack(
+ GT_ModHandler.getModItem(Forestry.ID, "planks", 1L, 23, new ItemStack(Blocks.planks, 1, 0))),
+ 7),
+ null);
+
+ ItemList.Crop_Drop_Plumbilia.set(
+ addItem(
+ tLastID = 500,
+ "Plumbilia Leaf",
+ "Source of Lead",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METALLUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 1L)));
+ ItemList.Crop_Drop_Argentia.set(
+ addItem(
+ tLastID = 501,
+ "Argentia Leaf",
+ "Source of Silver",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METALLUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.LUCRUM, 1L)));
+ ItemList.Crop_Drop_Indigo.set(
+ addItem(
+ tLastID = 502,
+ "Indigo Blossom",
+ "Used for making Blue Dye",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SENSUS, 1L)));
+ ItemList.Crop_Drop_Ferru.set(
+ addItem(
+ tLastID = 503,
+ "Ferru Leaf",
+ "Source of Iron",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METALLUM, 2L)));
+ ItemList.Crop_Drop_Aurelia.set(
+ addItem(
+ tLastID = 504,
+ "Aurelia Leaf",
+ "Source of Gold",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METALLUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.LUCRUM, 1L)));
+ ItemList.Crop_Drop_TeaLeaf.set(
+ addItem(
+ tLastID = 505,
+ "Tea Leaf",
+ "Source of Tea",
+ "cropTea",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SANO, 1L)));
+
+ ItemList.Crop_Drop_OilBerry.set(
+ addItem(
+ tLastID = 510,
+ "Oil Berry",
+ "Oil in Berry form",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 1L)));
+ ItemList.Crop_Drop_BobsYerUncleRanks.set(
+ addItem(
+ tLastID = 511,
+ "Bobs-Yer-Uncle-Berry",
+ "Source of Emeralds",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VITREUS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.LUCRUM, 1L)));
+ ItemList.Crop_Drop_UUMBerry.set(
+ addItem(
+ tLastID = 512,
+ "UUM Berry",
+ "UUM in Berry form",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 1L)));
+ ItemList.Crop_Drop_UUABerry.set(
+ addItem(
+ tLastID = 513,
+ "UUA Berry",
+ "UUA in Berry form",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 1L)));
+
+ ItemList.Crop_Drop_MilkWart.set(
+ addItem(
+ tLastID = 520,
+ "Milk Wart",
+ "Source of Milk",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SANO, 1L)));
+
+ ItemList.Crop_Drop_Coppon.set(
+ addItem(
+ tLastID = 530,
+ "Coppon Fiber",
+ "ORANGE WOOOOOOOL!!!",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METALLUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.PERMUTATIO, 1L)));
+
+ ItemList.Crop_Drop_Tine.set(
+ addItem(
+ tLastID = 540,
+ "Tine Twig",
+ "Source of Tin",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METALLUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 1L)));
+ setBurnValue(32000 + tLastID, 100);
+
+ ItemList.Crop_Drop_Mica.set(
+ addItem(
+ tLastID = 538,
+ "Micadia Twig",
+ "Source of Mica",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TUTAMEN, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 1L)));
+ setBurnValue(32000 + tLastID, 240);
+
+ ItemList.Crop_Drop_Bauxite.set(addItem(tLastID = 521, "Bauxia Leaf", "Source of Aluminium"));
+ ItemList.Crop_Drop_Ilmenite.set(addItem(tLastID = 522, "Titania Leaf", "Source of Titanium"));
+ ItemList.Crop_Drop_Pitchblende.set(addItem(tLastID = 523, "Reactoria Leaf", "Source of Uranium"));
+ ItemList.Crop_Drop_Uraninite.set(addItem(tLastID = 524, "Uranium Leaf", "Source of Uranite"));
+ ItemList.Crop_Drop_Thorium.set(addItem(tLastID = 526, "Thunder Leaf", "Source of Thorium"));
+ ItemList.Crop_Drop_Nickel.set(addItem(tLastID = 527, "Nickelback Leaf", "Source of Nickel"));
+ ItemList.Crop_Drop_Zinc.set(addItem(tLastID = 528, "Galvania Leaf", "Source of Zinc"));
+ ItemList.Crop_Drop_Manganese.set(addItem(tLastID = 529, "Pyrolusium Leaf", "Source of Manganese"));
+ ItemList.Crop_Drop_Scheelite.set(addItem(tLastID = 531, "Scheelinium Leaf", "Source of Tungsten"));
+ ItemList.Crop_Drop_Platinum.set(addItem(tLastID = 532, "Platina Leaf", "Source of Platinum"));
+ ItemList.Crop_Drop_Iridium.set(addItem(tLastID = 533, "Quantaria Leaf", "Source of Iridium"));
+ ItemList.Crop_Drop_Osmium.set(addItem(tLastID = 534, "Quantaria Leaf", "Source of Osmium"));
+ ItemList.Crop_Drop_Naquadah.set(addItem(tLastID = 535, "Stargatium Leaf", "Source of Naquadah"));
+
+ ItemList.Crop_Drop_Chilly.set(
+ addItem(
+ tLastID = 550,
+ "Chilly Pepper",
+ "It is red and hot",
+ "cropChilipepper",
+ new GT_FoodStat(1, 0.3F, EnumAction.eat, null, false, true, false, Potion.confusion.id, 200, 1, 40),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L)));
+ ItemList.Crop_Drop_Lemon.set(
+ addItem(
+ tLastID = 551,
+ "Lemon",
+ "Don't make Lemonade",
+ "cropLemon",
+ new GT_FoodStat(1, 0.3F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L)));
+ ItemList.Crop_Drop_Tomato.set(
+ addItem(
+ tLastID = 552,
+ "Tomato",
+ "Solid Ketchup",
+ "cropTomato",
+ new GT_FoodStat(1, 0.2F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L)));
+ ItemList.Crop_Drop_MTomato.set(
+ addItem(
+ tLastID = 553,
+ "Max Tomato",
+ "Full Health in one Tomato",
+ "cropTomato",
+ new GT_FoodStat(
+ 9,
+ 1.0F,
+ EnumAction.eat,
+ null,
+ false,
+ true,
+ false,
+ Potion.regeneration.id,
+ 100,
+ 100,
+ 100),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SANO, 3L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L)));
+ ItemList.Crop_Drop_Grapes.set(
+ addItem(
+ tLastID = 554,
+ "Grapes",
+ "Source of Wine",
+ "cropGrape",
+ new GT_FoodStat(2, 0.3F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L)));
+ ItemList.Crop_Drop_Onion.set(
+ addItem(
+ tLastID = 555,
+ "Onion",
+ "Taking over the whole Taste",
+ "cropOnion",
+ new GT_FoodStat(2, 0.2F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L)));
+ ItemList.Crop_Drop_Cucumber.set(
+ addItem(
+ tLastID = 556,
+ "Cucumber",
+ "Not a Sea Cucumber!",
+ "cropCucumber",
+ new GT_FoodStat(1, 0.2F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L)));
+ ItemList.Crop_Drop_Rape.set(
+ addItem(
+ tLastID = 557,
+ "Rape",
+ "Time to oil up!",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 1L)));
+
+ ItemList.Food_Cheese.set(
+ addItem(
+ tLastID = 558,
+ "Cheese",
+ "Click the Cheese",
+ "foodCheese",
+ new GT_FoodStat(3, 0.6F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 2L)));
+ ItemList.Food_Dough.set(
+ addItem(
+ tLastID = 559,
+ "Dough",
+ "For making Breads",
+ "foodDough",
+ new GT_FoodStat(1, 0.1F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L)));
+ ItemList.Food_Flat_Dough.set(
+ addItem(
+ tLastID = 560,
+ "Flattened Dough",
+ "For making Pizza",
+ new GT_FoodStat(1, 0.1F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L)));
+ ItemList.Food_Raw_Bread.set(
+ addItem(
+ tLastID = 561,
+ "Dough",
+ "In Bread Shape",
+ new GT_FoodStat(1, 0.2F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L)));
+ ItemList.Food_Raw_Bun.set(
+ addItem(
+ tLastID = 562,
+ "Dough",
+ "In Bun Shape",
+ new GT_FoodStat(1, 0.1F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L)));
+ ItemList.Food_Raw_Baguette.set(
+ addItem(
+ tLastID = 563,
+ "Dough",
+ "In Baguette Shape",
+ new GT_FoodStat(1, 0.3F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L)));
+ ItemList.Food_Baked_Bun.set(
+ addItem(
+ tLastID = 564,
+ "Bun",
+ "Do not teleport Bread!",
+ new GT_FoodStat(3, 0.5F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L)));
+ ItemList.Food_Baked_Baguette.set(
+ addItem(
+ tLastID = 565,
+ "Baguette",
+ "I teleported nothing BUT Bread!!!",
+ new GT_FoodStat(8, 0.5F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L)));
+ ItemList.Food_Sliced_Bread.set(
+ addItem(
+ tLastID = 566,
+ "Sliced Bread",
+ "Just half a Bread",
+ new GT_FoodStat(2, 0.3F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L)));
+ ItemList.Food_Sliced_Bun.set(
+ addItem(
+ tLastID = 567,
+ "Sliced Bun",
+ "Just half a Bun",
+ new GT_FoodStat(1, 0.3F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L)));
+ ItemList.Food_Sliced_Baguette.set(
+ addItem(
+ tLastID = 568,
+ "Sliced Baguette",
+ "Just half a Baguette",
+ new GT_FoodStat(4, 0.3F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.IGNIS, 1L)));
+ ItemList.Food_Raw_Cake.set(
+ addItem(
+ tLastID = 569,
+ "Cake Bottom",
+ "For making Cake",
+ new GT_FoodStat(2, 0.2F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L)));
+ ItemList.Food_Baked_Cake.set(
+ addItem(
+ tLastID = 570,
+ "Baked Cake Bottom",
+ "I know I promised you an actual Cake, but well...",
+ new GT_FoodStat(3, 0.3F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L)));
+ ItemList.Food_Sliced_Lemon.set(
+ addItem(
+ tLastID = 571,
+ "Lemon Slice",
+ "Ideal to put on your Drink",
+ new GT_FoodStat(1, 0.075F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L)));
+ ItemList.Food_Sliced_Tomato.set(
+ addItem(
+ tLastID = 572,
+ "Tomato Slice",
+ "Solid Ketchup",
+ new GT_FoodStat(1, 0.05F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L)));
+ ItemList.Food_Sliced_Onion.set(
+ addItem(
+ tLastID = 573,
+ "Onion Slice",
+ "ONIONS, UNITE!",
+ new GT_FoodStat(1, 0.05F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L)));
+ ItemList.Food_Sliced_Cucumber.set(
+ addItem(
+ tLastID = 574,
+ "Cucumber Slice",
+ "QUEWWW-CUMMM-BERRR!!!",
+ new GT_FoodStat(1, 0.05F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 1L)));
+
+ ItemList.Food_Sliced_Cheese.set(
+ addItem(
+ tLastID = 576,
+ "Cheese Slice",
+ "ALIEN ATTACK!!!, throw the CHEEEEESE!!!",
+ new GT_FoodStat(1, 0.1F, EnumAction.eat, null, false, true, false),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FAMES, 1L)));
+
+ ItemList.Cover_AdvancedRedstoneTransmitterExternal.set(
+ addItem(
+ tLastID = 577,
+ "Advanced Redstone Transmitter (External)",
+ "Transfers Redstone signals wirelessly/n Can only connect with advanced wireless covers",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 2L)));
+ ItemList.Cover_AdvancedRedstoneTransmitterInternal.set(
+ addItem(
+ tLastID = 578,
+ "Advanced Redstone Transmitter (Internal)",
+ "Transfers Redstone signals wirelessly/n Can only connect with advanced wireless covers",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 2L)));
+ ItemList.Cover_AdvancedRedstoneReceiverExternal.set(
+ addItem(
+ tLastID = 579,
+ "Advanced Redstone Receiver (External)",
+ "Transfers Redstone signals wirelessly/n Can only connect with advanced wireless covers",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 2L)));
+ ItemList.Cover_AdvancedRedstoneReceiverInternal.set(
+ addItem(
+ tLastID = 580,
+ "Advanced Redstone Receiver (Internal)",
+ "Transfers Redstone signals wirelessly/n Can only connect with advanced wireless covers",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 2L)));
+
+ ItemList.Cover_WirelessFluidDetector.set(
+ addItem(
+ tLastID = 581,
+ "Wireless Fluid Detector Cover",
+ "Transfers Fluid Amount as Redstone wirelessly/n Can only connect with advanced wireless covers",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SENSUS, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.AQUA, 1L)));
+ ItemList.Cover_WirelessItemDetector.set(
+ addItem(
+ tLastID = 582,
+ "Wireless Item Detector Cover",
+ "Transfers Item Amount as Redstone wirelessly/n Can only connect with advanced wireless covers",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SENSUS, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TERRA, 1L)));
+
+ ItemList.Cover_WirelessNeedsMaintainance.set(
+ addItem(
+ tLastID = 583,
+ "Wireless Needs Maintenance Cover",
+ "Transfers Maintenance Issues as Redstone wirelessly/n Can only connect with advanced wireless covers",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 3L)));
+
+ ItemList.Cover_WirelessActivityDetector.set(
+ addItem(
+ tLastID = 584,
+ "Wireless Activity Detector Cover",
+ "Transfers Activity as Redstone wirelessly/n Can only connect with advanced wireless covers",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.SENSUS, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TERRA, 1L)));
+
+ GregTech_API.registerCover(
+ ItemList.Cover_AdvancedRedstoneTransmitterExternal.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[2][0], TextureFactory.of(OVERLAY_ADVANCED_REDSTONE_TRANSMITTER)),
+ new GT_Cover_AdvancedRedstoneTransmitterExternal(TextureFactory.of(OVERLAY_ADVANCED_REDSTONE_TRANSMITTER)));
+
+ GregTech_API.registerCover(
+ ItemList.Cover_AdvancedRedstoneTransmitterInternal.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[2][0], TextureFactory.of(OVERLAY_ADVANCED_REDSTONE_TRANSMITTER)),
+ new GT_Cover_AdvancedRedstoneTransmitterInternal(TextureFactory.of(OVERLAY_ADVANCED_REDSTONE_TRANSMITTER)));
+
+ GregTech_API.registerCover(
+ ItemList.Cover_AdvancedRedstoneReceiverExternal.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[2][0], TextureFactory.of(OVERLAY_ADVANCED_REDSTONE_RECEIVER)),
+ new GT_Cover_AdvancedRedstoneReceiverExternal(TextureFactory.of(OVERLAY_ADVANCED_REDSTONE_RECEIVER)));
+
+ GregTech_API.registerCover(
+ ItemList.Cover_AdvancedRedstoneReceiverInternal.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[2][0], TextureFactory.of(OVERLAY_ADVANCED_REDSTONE_RECEIVER)),
+ new GT_Cover_AdvancedRedstoneReceiverInternal(TextureFactory.of(OVERLAY_ADVANCED_REDSTONE_RECEIVER)));
+
+ GregTech_API.registerCover(
+ ItemList.Cover_WirelessFluidDetector.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[2][0], TextureFactory.of(OVERLAY_WIRELESS_FLUID_DETECTOR)),
+ new GT_Cover_WirelessFluidDetector(TextureFactory.of(OVERLAY_WIRELESS_FLUID_DETECTOR)));
+
+ GregTech_API.registerCover(
+ ItemList.Cover_WirelessItemDetector.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[2][0], TextureFactory.of(OVERLAY_WIRELESS_ITEM_DETECTOR)),
+ new GT_Cover_WirelessItemDetector(TextureFactory.of(OVERLAY_WIRELESS_ITEM_DETECTOR)));
+
+ GregTech_API.registerCover(
+ ItemList.Cover_WirelessActivityDetector.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[2][0], TextureFactory.of(OVERLAY_WIRELESS_ACTIVITYDETECTOR)),
+ new GT_Cover_WirelessDoesWorkDetector(TextureFactory.of(OVERLAY_WIRELESS_ACTIVITYDETECTOR)));
+
+ GregTech_API.registerCover(
+ ItemList.Cover_WirelessNeedsMaintainance.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[2][0], TextureFactory.of(OVERLAY_WIRELESS_MAINTENANCE_DETECTOR)),
+ new GT_Cover_WirelessMaintenanceDetector(TextureFactory.of(OVERLAY_WIRELESS_MAINTENANCE_DETECTOR)));
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ ItemList.Cover_RedstoneTransmitterExternal.get(1L),
+ GT_OreDictUnificator.get(OrePrefixes.circuit, Materials.Data, 1L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Cover_AdvancedRedstoneTransmitterExternal.get(1L))
+ .duration(2 * MINUTES + 40 * SECONDS)
+ .eut(TierEU.RECIPE_MV)
+ .addTo(assemblerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ ItemList.Cover_RedstoneReceiverExternal.get(1L),
+ GT_OreDictUnificator.get(OrePrefixes.circuit, Materials.Data, 1L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Cover_AdvancedRedstoneReceiverExternal.get(1L))
+ .duration(2 * MINUTES + 40 * SECONDS)
+ .eut(TierEU.RECIPE_MV)
+ .addTo(assemblerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ ItemList.Cover_FluidDetector.get(1L),
+ ItemList.Emitter_EV.get(1L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Cover_WirelessFluidDetector.get(1L))
+ .duration(2 * MINUTES + 40 * SECONDS)
+ .eut(TierEU.RECIPE_MV)
+ .addTo(assemblerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ ItemList.Cover_ItemDetector.get(1L),
+ ItemList.Emitter_EV.get(1L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Cover_WirelessItemDetector.get(1L))
+ .duration(2 * MINUTES + 40 * SECONDS)
+ .eut(TierEU.RECIPE_MV)
+ .addTo(assemblerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ ItemList.Cover_NeedsMaintainance.get(1L),
+ ItemList.Emitter_EV.get(1L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Cover_WirelessNeedsMaintainance.get(1L))
+ .duration(2 * MINUTES + 40 * SECONDS)
+ .eut(TierEU.RECIPE_MV)
+ .addTo(assemblerRecipes);
+ GT_Values.RA.stdBuilder()
+ .itemInputs(
+ ItemList.Cover_ActivityDetector.get(1L),
+ ItemList.Emitter_EV.get(1L),
+ GT_Utility.getIntegratedCircuit(1))
+ .itemOutputs(ItemList.Cover_WirelessActivityDetector.get(1L))
+ .duration(2 * MINUTES + 40 * SECONDS)
+ .eut(TierEU.RECIPE_MV)
+ .addTo(assemblerRecipes);
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Cover_AdvancedRedstoneReceiverExternal.get(1L),
+ new Object[] { ItemList.Cover_AdvancedRedstoneReceiverInternal.get(1L) });
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Cover_AdvancedRedstoneReceiverInternal.get(1L),
+ new Object[] { ItemList.Cover_AdvancedRedstoneReceiverExternal.get(1L) });
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Cover_AdvancedRedstoneTransmitterExternal.get(1L),
+ new Object[] { ItemList.Cover_AdvancedRedstoneTransmitterInternal.get(1L) });
+ GT_ModHandler.addShapelessCraftingRecipe(
+ ItemList.Cover_AdvancedRedstoneTransmitterInternal.get(1L),
+ new Object[] { ItemList.Cover_AdvancedRedstoneTransmitterExternal.get(1L) });
+
+ GT_ModHandler.addExtractionRecipe(new ItemStack(Blocks.red_flower, 1, 0), new ItemStack(Items.dye, 2, 1));
+ GT_ModHandler.addExtractionRecipe(new ItemStack(Blocks.red_flower, 1, 1), new ItemStack(Items.dye, 2, 12));
+ GT_ModHandler.addExtractionRecipe(new ItemStack(Blocks.red_flower, 1, 2), new ItemStack(Items.dye, 2, 13));
+ GT_ModHandler.addExtractionRecipe(new ItemStack(Blocks.red_flower, 1, 3), new ItemStack(Items.dye, 2, 7));
+ GT_ModHandler.addExtractionRecipe(new ItemStack(Blocks.red_flower, 1, 4), new ItemStack(Items.dye, 2, 1));
+ GT_ModHandler.addExtractionRecipe(new ItemStack(Blocks.red_flower, 1, 5), new ItemStack(Items.dye, 2, 14));
+ GT_ModHandler.addExtractionRecipe(new ItemStack(Blocks.red_flower, 1, 6), new ItemStack(Items.dye, 2, 7));
+ GT_ModHandler.addExtractionRecipe(new ItemStack(Blocks.red_flower, 1, 7), new ItemStack(Items.dye, 2, 9));
+ GT_ModHandler.addExtractionRecipe(new ItemStack(Blocks.red_flower, 1, 8), new ItemStack(Items.dye, 2, 7));
+ GT_ModHandler.addExtractionRecipe(new ItemStack(Blocks.yellow_flower, 1, 0), new ItemStack(Items.dye, 2, 11));
+ GT_ModHandler.addExtractionRecipe(new ItemStack(Blocks.double_plant, 1, 0), new ItemStack(Items.dye, 3, 11));
+ GT_ModHandler.addExtractionRecipe(new ItemStack(Blocks.double_plant, 1, 1), new ItemStack(Items.dye, 3, 13));
+ GT_ModHandler.addExtractionRecipe(new ItemStack(Blocks.double_plant, 1, 4), new ItemStack(Items.dye, 3, 1));
+ GT_ModHandler.addExtractionRecipe(new ItemStack(Blocks.double_plant, 1, 5), new ItemStack(Items.dye, 3, 9));
+ GT_ModHandler.addExtractionRecipe(
+ ItemList.Crop_Drop_Plumbilia.get(1L),
+ GT_OreDictUnificator.get(OrePrefixes.dustTiny, Materials.Lead, 1L));
+ GT_ModHandler.addExtractionRecipe(
+ ItemList.Crop_Drop_Argentia.get(1L),
+ GT_OreDictUnificator.get(OrePrefixes.dustTiny, Materials.Silver, 1L));
+ GT_ModHandler.addExtractionRecipe(ItemList.Crop_Drop_Indigo.get(1L), ItemList.Dye_Indigo.get(1L));
+ GT_ModHandler.addExtractionRecipe(
+ ItemList.Crop_Drop_MilkWart.get(1L),
+ GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Milk, 1L));
+ GT_ModHandler.addExtractionRecipe(
+ ItemList.Crop_Drop_Coppon.get(1L),
+ GT_OreDictUnificator.get(OrePrefixes.dustTiny, Materials.Copper, 1L));
+ GT_ModHandler.addExtractionRecipe(
+ ItemList.Crop_Drop_Tine.get(1L),
+ GT_OreDictUnificator.get(OrePrefixes.dustTiny, Materials.Tin, 1L));
+
+ // Compression recipes
+ {
+ GT_Values.RA.stdBuilder()
+ .itemInputs(ItemList.Crop_Drop_Coppon.get(4L))
+ .itemOutputs(new ItemStack(Blocks.wool, 1, 1))
+ .duration(15 * SECONDS)
+ .eut(2)
+ .addTo(compressorRecipes);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(ItemList.Crop_Drop_Plumbilia.get(4L))
+ .itemOutputs(ItemList.IC2_PlantballCompressed.get(1L))
+ .duration(15 * SECONDS)
+ .eut(2)
+ .addTo(compressorRecipes);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(ItemList.Crop_Drop_Argentia.get(4L))
+ .itemOutputs(ItemList.IC2_PlantballCompressed.get(1L))
+ .duration(15 * SECONDS)
+ .eut(2)
+ .addTo(compressorRecipes);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(ItemList.Crop_Drop_Indigo.get(4L))
+ .itemOutputs(ItemList.IC2_PlantballCompressed.get(1L))
+ .duration(15 * SECONDS)
+ .eut(2)
+ .addTo(compressorRecipes);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(ItemList.Crop_Drop_Ferru.get(4L))
+ .itemOutputs(ItemList.IC2_PlantballCompressed.get(1L))
+ .duration(15 * SECONDS)
+ .eut(2)
+ .addTo(compressorRecipes);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(ItemList.Crop_Drop_Aurelia.get(4L))
+ .itemOutputs(ItemList.IC2_PlantballCompressed.get(1L))
+ .duration(15 * SECONDS)
+ .eut(2)
+ .addTo(compressorRecipes);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(ItemList.Crop_Drop_OilBerry.get(4L))
+ .itemOutputs(ItemList.IC2_PlantballCompressed.get(1L))
+ .duration(15 * SECONDS)
+ .eut(2)
+ .addTo(compressorRecipes);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(ItemList.Crop_Drop_BobsYerUncleRanks.get(4L))
+ .itemOutputs(ItemList.IC2_PlantballCompressed.get(1L))
+ .duration(15 * SECONDS)
+ .eut(2)
+ .addTo(compressorRecipes);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(ItemList.Crop_Drop_Tine.get(4L))
+ .itemOutputs(ItemList.IC2_PlantballCompressed.get(1L))
+ .duration(15 * SECONDS)
+ .eut(2)
+ .addTo(compressorRecipes);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(ItemList.Crop_Drop_Rape.get(4L))
+ .itemOutputs(ItemList.IC2_PlantballCompressed.get(1L))
+ .duration(15 * SECONDS)
+ .eut(2)
+ .addTo(compressorRecipes);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(new ItemStack(Blocks.red_flower, 8, 32767))
+ .itemOutputs(ItemList.IC2_PlantballCompressed.get(1L))
+ .duration(15 * SECONDS)
+ .eut(2)
+ .addTo(compressorRecipes);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(new ItemStack(Blocks.yellow_flower, 8, 32767))
+ .itemOutputs(ItemList.IC2_PlantballCompressed.get(1L))
+ .duration(15 * SECONDS)
+ .eut(2)
+ .addTo(compressorRecipes);
+ }
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(ItemList.Food_Sliced_Cheese.get(1L))
+ .itemOutputs(GT_OreDictUnificator.get(OrePrefixes.dustSmall, Materials.Cheese, 1L))
+ .duration(20 * SECONDS)
+ .eut(2)
+ .addTo(maceratorRecipes);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(ItemList.Dye_Cocoa.get(1L))
+ .itemOutputs(GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Cocoa, 1L))
+ .duration(20 * SECONDS)
+ .eut(2)
+ .addTo(maceratorRecipes);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(ItemList.Crop_Drop_Tine.get(1L))
+ .itemOutputs(GT_OreDictUnificator.get(OrePrefixes.dustSmall, Materials.Wood, 2L))
+ .duration(20 * SECONDS)
+ .eut(2)
+ .addTo(maceratorRecipes);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(new ItemStack(Blocks.pumpkin, 1, 0))
+ .itemOutputs(new ItemStack(Items.pumpkin_seeds, 4, 0))
+ .duration(20 * SECONDS)
+ .eut(2)
+ .addTo(maceratorRecipes);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(new ItemStack(Items.melon, 1, 0))
+ .itemOutputs(new ItemStack(Items.melon_seeds, 1, 0))
+ .duration(20 * SECONDS)
+ .eut(2)
+ .addTo(maceratorRecipes);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(GT_ModHandler.getIC2Item("crop", 1L))
+ .itemOutputs(GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Wood, 1L))
+ .duration(20 * SECONDS)
+ .eut(2)
+ .addTo(maceratorRecipes);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(new ItemStack(Items.stick, 1))
+ .itemOutputs(GT_OreDictUnificator.get(OrePrefixes.dustSmall, Materials.Wood, 2L))
+ .duration(20 * SECONDS)
+ .eut(2)
+ .addTo(maceratorRecipes);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(new ItemStack(Blocks.wool, 1, WILDCARD))
+ .itemOutputs(new ItemStack(Items.string, 2), new ItemStack(Items.string, 1))
+ .outputChances(10000, 5000)
+ .duration(20 * SECONDS)
+ .eut(2)
+ .addTo(maceratorRecipes);
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(ItemList.Tesseract.get(1))
+ .itemOutputs(GT_OreDictUnificator.get(OrePrefixes.dust, MaterialsUEVplus.TranscendentMetal, 8L))
+ .duration(5 * SECONDS)
+ .eut(32_000_000)
+ .addTo(maceratorRecipes);
+ try {
+ CropCard tCrop;
+ GT_Utility.getField(tCrop = Crops.instance.getCropList()[13], "mDrop")
+ .set(tCrop, ItemList.Crop_Drop_Ferru.get(1L));
+ GT_Utility.getField(tCrop = Crops.instance.getCropList()[14], "mDrop")
+ .set(tCrop, ItemList.Crop_Drop_Aurelia.get(1L));
+ } catch (Throwable e) {
+ if (GT_Values.D1) {
+ e.printStackTrace(GT_Log.err);
+ }
+ }
+ ItemList.Display_ITS_FREE.set(
+ addItem(
+ tLastID = 765,
+ "ITS FREE",
+ "(or at least almost free)",
+ SubTag.INVISIBLE,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.LUCRUM, 1L)));
+ }
+
+ @Override
+ public boolean onLeftClickEntity(ItemStack aStack, EntityPlayer aPlayer, Entity aEntity) {
+ super.onLeftClickEntity(aStack, aPlayer, aEntity);
+ int aDamage = aStack.getItemDamage();
+ if ((aDamage >= 25000) && (aDamage < 27000)) {
+ if (aDamage >= 26000) {
+ return Behaviour_Arrow.DEFAULT_PLASTIC.onLeftClickEntity(this, aStack, aPlayer, aEntity);
+ }
+ return Behaviour_Arrow.DEFAULT_WOODEN.onLeftClickEntity(this, aStack, aPlayer, aEntity);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean hasProjectile(SubTag aProjectileType, ItemStack aStack) {
+ int aDamage = aStack.getItemDamage();
+ return ((aDamage >= 25000) && (aDamage < 27000)) || (super.hasProjectile(aProjectileType, aStack));
+ }
+
+ @Override
+ public EntityArrow getProjectile(SubTag aProjectileType, ItemStack aStack, World aWorld, double aX, double aY,
+ double aZ) {
+ int aDamage = aStack.getItemDamage();
+ if ((aDamage >= 25000) && (aDamage < 27000)) {
+ if (aDamage >= 26000) {
+ return Behaviour_Arrow.DEFAULT_PLASTIC.getProjectile(this, aProjectileType, aStack, aWorld, aX, aY, aZ);
+ }
+ return Behaviour_Arrow.DEFAULT_WOODEN.getProjectile(this, aProjectileType, aStack, aWorld, aX, aY, aZ);
+ }
+ return super.getProjectile(aProjectileType, aStack, aWorld, aX, aY, aZ);
+ }
+
+ @Override
+ public EntityArrow getProjectile(SubTag aProjectileType, ItemStack aStack, World aWorld, EntityLivingBase aEntity,
+ float aSpeed) {
+ int aDamage = aStack.getItemDamage();
+ if ((aDamage >= 25000) && (aDamage < 27000)) {
+ if (aDamage >= 26000) {
+ return Behaviour_Arrow.DEFAULT_PLASTIC
+ .getProjectile(this, aProjectileType, aStack, aWorld, aEntity, aSpeed);
+ }
+ return Behaviour_Arrow.DEFAULT_WOODEN.getProjectile(this, aProjectileType, aStack, aWorld, aEntity, aSpeed);
+ }
+ return super.getProjectile(aProjectileType, aStack, aWorld, aEntity, aSpeed);
+ }
+
+ @Override
+ public boolean isItemStackUsable(ItemStack aStack) {
+ int aDamage = aStack.getItemDamage();
+ Materials aMaterial = GregTech_API.sGeneratedMaterials[(aDamage % 1000)];
+ if ((aDamage >= 25000) && (aDamage < 27000) && (aMaterial != null) && (aMaterial.mEnchantmentTools != null)) {
+ Enchantment tEnchant = aMaterial.mEnchantmentTools == Enchantment.fortune ? Enchantment.looting
+ : aMaterial.mEnchantmentTools;
+ if (tEnchant.type == EnumEnchantmentType.weapon) {
+ NBTTagCompound tNBT = GT_Utility.ItemNBT.getNBT(aStack);
+ if (!tNBT.getBoolean("GT.HasBeenUpdated")) {
+ tNBT.setBoolean("GT.HasBeenUpdated", true);
+ GT_Utility.ItemNBT.setNBT(aStack, tNBT);
+ GT_Utility.ItemNBT.addEnchantment(aStack, tEnchant, aMaterial.mEnchantmentToolsLevel);
+ }
+ }
+ }
+ return super.isItemStackUsable(aStack);
+ }
+
+ @Override
+ public boolean doesShowInCreative(OrePrefixes aPrefix, Materials aMaterial, boolean aDoShowAllItems) {
+ return (aDoShowAllItems) || (!aPrefix.name()
+ .startsWith("toolHead"));
+ }
+
+ @Override
+ public ItemStack onDispense(IBlockSource aSource, ItemStack aStack) {
+ int aDamage = aStack.getItemDamage();
+ if ((aDamage >= 25000) && (aDamage < 27000)) {
+ if (aDamage >= 26000) {
+ return Behaviour_Arrow.DEFAULT_PLASTIC.onDispense(this, aSource, aStack);
+ }
+ return Behaviour_Arrow.DEFAULT_WOODEN.onDispense(this, aSource, aStack);
+ }
+ return super.onDispense(aSource, aStack);
+ }
+
+ @Override
+ public final ItemStack getContainerItem(ItemStack aStack) {
+ int aDamage = aStack.getItemDamage();
+ if (aDamage < 32000) {
+ return null;
+ }
+ if (aDamage < 32100) {
+ return ItemList.ThermosCan_Empty.get(1L);
+ }
+ if (aDamage < 32200) {
+ return ItemList.Bottle_Empty.get(1L);
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/gregtech/common/items/GT_MetaGenerated_Item_03.java b/src/main/java/gregtech/common/items/GT_MetaGenerated_Item_03.java
new file mode 100644
index 0000000000..3a0c4a95d8
--- /dev/null
+++ b/src/main/java/gregtech/common/items/GT_MetaGenerated_Item_03.java
@@ -0,0 +1,1087 @@
+package gregtech.common.items;
+
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASINGS;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_METRICS_TRANSMITTER;
+import static gregtech.api.enums.Textures.BlockIcons.SOLARPANEL_UEV;
+import static gregtech.api.enums.Textures.BlockIcons.SOLARPANEL_UHV;
+import static gregtech.api.enums.Textures.BlockIcons.SOLARPANEL_UIV;
+import static gregtech.client.GT_TooltipHandler.Tier.EV;
+import static gregtech.client.GT_TooltipHandler.Tier.HV;
+import static gregtech.client.GT_TooltipHandler.Tier.IV;
+import static gregtech.client.GT_TooltipHandler.Tier.LV;
+import static gregtech.client.GT_TooltipHandler.Tier.LuV;
+import static gregtech.client.GT_TooltipHandler.Tier.MAX;
+import static gregtech.client.GT_TooltipHandler.Tier.MV;
+import static gregtech.client.GT_TooltipHandler.Tier.UEV;
+import static gregtech.client.GT_TooltipHandler.Tier.UHV;
+import static gregtech.client.GT_TooltipHandler.Tier.UIV;
+import static gregtech.client.GT_TooltipHandler.Tier.ULV;
+import static gregtech.client.GT_TooltipHandler.Tier.UMV;
+import static gregtech.client.GT_TooltipHandler.Tier.UV;
+import static gregtech.client.GT_TooltipHandler.Tier.UXV;
+import static gregtech.client.GT_TooltipHandler.Tier.ZPM;
+import static gregtech.client.GT_TooltipHandler.registerTieredTooltip;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.enums.SubTag;
+import gregtech.api.enums.TC_Aspects;
+import gregtech.api.items.GT_MetaGenerated_Item_X32;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_OreDictUnificator;
+import gregtech.common.covers.GT_Cover_Metrics_Transmitter;
+import gregtech.common.covers.GT_Cover_SolarPanel;
+
+public class GT_MetaGenerated_Item_03 extends GT_MetaGenerated_Item_X32 {
+
+ public static GT_MetaGenerated_Item_03 INSTANCE;
+
+ public GT_MetaGenerated_Item_03() {
+ super(
+ "metaitem.03",
+ OrePrefixes.crateGtDust,
+ OrePrefixes.crateGtIngot,
+ OrePrefixes.crateGtGem,
+ OrePrefixes.crateGtPlate,
+ OrePrefixes.nanite,
+ OrePrefixes.rawOre);
+ INSTANCE = this;
+ Object[] o = new Object[0];
+
+ /*
+ * circuit boards tier 1-7: coated circuit board / wood plate + resin Plastic Circuit Board / Plastic + Copper
+ * Foil + Sulfuric Acid phenolic circuit board /carton+glue+chemical bath epoxy circuit board /epoxy plate +
+ * copper foil + sulfuric acid fiberglass circuit board (simple + multilayer) / glass + plastic + electrum foil
+ * + sulfuric acid wetware lifesupport board / fiberglass CB + teflon +
+ */
+ ItemList.Circuit_Board_Wetware
+ .set(addItem(6, "Wetware Lifesupport Circuit Board", "The Board that keeps life", o));
+ ItemList.Circuit_Board_Plastic.set(addItem(7, "Plastic Circuit Board", "A Good Board", o));
+ ItemList.Circuit_Board_Bio.set(addItem(8, "Bio Circuit Board", "Bio genetic mutated Board", o));
+
+ /*
+ * electronic components: vacuum tube (glass tube + red alloy cables) basic electronic circuits normal+smd coils
+ * diodes normal+smd transistors normal+smd capacitors normal+smd Glass Fibers
+ */
+ ItemList.Circuit_Parts_ResistorSMD.set(
+ addItem(
+ 11,
+ "SMD Resistor",
+ "Electronic Component",
+ OrePrefixes.componentCircuit.get(Materials.Resistor),
+ SubTag.NO_UNIFICATION));
+ ItemList.Circuit_Parts_Glass_Tube.set(addItem(12, "Glass Tube", "", o));
+ ItemList.Circuit_Parts_Coil.set(addItem(14, "Small Coil", "Basic Electronic Component", o));
+ ItemList.Circuit_Parts_DiodeSMD.set(
+ addItem(
+ 16,
+ "SMD Diode",
+ "Electronic Component",
+ OrePrefixes.componentCircuit.get(Materials.Diode),
+ SubTag.NO_UNIFICATION));
+ ItemList.Circuit_Parts_TransistorSMD.set(
+ addItem(
+ 18,
+ "SMD Transistor",
+ "Electronic Component",
+ OrePrefixes.componentCircuit.get(Materials.Transistor),
+ SubTag.NO_UNIFICATION));
+ ItemList.Circuit_Parts_CapacitorSMD.set(
+ addItem(
+ 20,
+ "SMD Capacitor",
+ "Electronic Component",
+ OrePrefixes.componentCircuit.get(Materials.Capacitor),
+ SubTag.NO_UNIFICATION));
+ ItemList.Circuit_Parts_GlassFiber
+ .set(addItem(21, "Glass Fiber", Materials.BorosilicateGlass.mChemicalFormula, o));
+ ItemList.Circuit_Parts_PetriDish.set(addItem(22, "Petri Dish", "For cultivating cells", o));
+ ItemList.Circuit_Parts_Reinforced_Glass_Tube.set(addItem(23, "Reinforced Glass Tube", "", o));
+
+ ItemList.Circuit_Parts_ResistorASMD
+ .set(addItem(24, "Advanced SMD Resistor", "Advanced Electronic Component", o));
+ ItemList.Circuit_Parts_DiodeASMD.set(addItem(25, "Advanced SMD Diode", "Advanced Electronic Component", o));
+ ItemList.Circuit_Parts_TransistorASMD
+ .set(addItem(26, "Advanced SMD Transistor", "Advanced Electronic Component", o));
+ ItemList.Circuit_Parts_CapacitorASMD
+ .set(addItem(27, "Advanced SMD Capacitor", "Advanced Electronic Component", o));
+
+ ItemList.Circuit_Parts_ResistorXSMD
+ .set(addItem(178, "Optical SMD Resistor", "Highly Advanced Electronic Component", o));
+ ItemList.Circuit_Parts_DiodeXSMD
+ .set(addItem(179, "Optical SMD Diode", "Highly Advanced Electronic Component", o));
+ ItemList.Circuit_Parts_TransistorXSMD
+ .set(addItem(180, "Optical SMD Transistor", "Highly Advanced Electronic Component", o));
+ ItemList.Circuit_Parts_CapacitorXSMD
+ .set(addItem(181, "Optical SMD Capacitor", "Highly Advanced Electronic Component", o));
+
+ ItemList.Circuit_Parts_InductorSMD.set(
+ addItem(
+ 182,
+ "SMD Inductor",
+ "Electronic Component",
+ OrePrefixes.componentCircuit.get(Materials.Inductor),
+ SubTag.NO_UNIFICATION));
+ ItemList.Circuit_Parts_InductorASMD
+ .set(addItem(183, "Advanced SMD Inductor", "Advanced Electronic Component", o));
+ ItemList.Circuit_Parts_InductorXSMD
+ .set(addItem(184, "Optical SMD Inductor", "Highly Advanced Electronic Component", o));
+
+ GT_OreDictUnificator
+ .set(OrePrefixes.componentCircuit, Materials.Resistor, ItemList.Circuit_Parts_Resistor.get(1L));
+ GT_OreDictUnificator.set(OrePrefixes.componentCircuit, Materials.Diode, ItemList.Circuit_Parts_Diode.get(1L));
+ GT_OreDictUnificator
+ .set(OrePrefixes.componentCircuit, Materials.Transistor, ItemList.Circuit_Parts_Transistor.get(1L));
+ GT_OreDictUnificator.set(OrePrefixes.componentCircuit, Materials.Inductor, ItemList.Circuit_Parts_Coil.get(1L));
+ GT_OreDictUnificator
+ .set(OrePrefixes.componentCircuit, Materials.Capacitor, ItemList.Circuit_Parts_Capacitor.get(1L));
+
+ GT_OreDictUnificator.addAssociation(
+ OrePrefixes.componentCircuit,
+ Materials.Resistor,
+ ItemList.Circuit_Parts_ResistorSMD.get(1L),
+ true);
+ GT_OreDictUnificator.addAssociation(
+ OrePrefixes.componentCircuit,
+ Materials.Diode,
+ ItemList.Circuit_Parts_DiodeSMD.get(1L),
+ true);
+ GT_OreDictUnificator.addAssociation(
+ OrePrefixes.componentCircuit,
+ Materials.Transistor,
+ ItemList.Circuit_Parts_TransistorSMD.get(1L),
+ true);
+ GT_OreDictUnificator.addAssociation(
+ OrePrefixes.componentCircuit,
+ Materials.Capacitor,
+ ItemList.Circuit_Parts_CapacitorSMD.get(1L),
+ true);
+ GT_OreDictUnificator.addAssociation(
+ OrePrefixes.componentCircuit,
+ Materials.Inductor,
+ ItemList.Circuit_Parts_InductorSMD.get(1L),
+ true);
+
+ /*
+ * ICs Lenses made from perfect crystals first instead of plates Monocrystalline silicon ingot
+ * (normal+glowstone+naquadah) EBF, normal silicon no EBF need anymore wafer(normal+glowstone+naquadah) cut mono
+ * silicon ingot in cutting machine
+ * Integrated Logic Circuit(8bit DIP) RAM NAND Memory NOR Memory CPU (4 sizes) SoCs(2 sizes, high tier cheap low
+ * tech component) Power IC/High Power IC/Ultra High power
+ * nanotube interconnected circuit (H-IC + nanotubes)
+ * quantum chips
+ */
+ ItemList.Circuit_Silicon_Ingot.set(addItem(30, "Monocrystalline Silicon Boule", "Raw Circuit", o));
+ ItemList.Circuit_Silicon_Ingot2
+ .set(addItem(31, "Phosphorus doped Monocrystalline Silicon Boule", "Raw Circuit", o));
+ ItemList.Circuit_Silicon_Ingot3
+ .set(addItem(32, "Naquadah doped Monocrystalline Silicon Boule", "Raw Circuit", o));
+ ItemList.Circuit_Silicon_Ingot4
+ .set(addItem(150, "Europium doped Monocrystalline Silicon Boule", "Raw Circuit", o));
+ ItemList.Circuit_Silicon_Ingot5
+ .set(addItem(152, "Americium doped Monocrystalline Silicon Boule", "Raw Circuit", o));
+ ItemList.Circuit_Silicon_Ingot6.set(addItem(721, "Optically Enriched Crystalline Boule", "Raw Circuit", o));
+
+ ItemList.Circuit_Silicon_Wafer.set(addItem(33, "Wafer", "Raw Circuit", o));
+ ItemList.Circuit_Silicon_Wafer2.set(addItem(34, "Phosphorus doped Wafer", "Raw Circuit", o));
+ ItemList.Circuit_Silicon_Wafer3.set(addItem(35, "Naquadah doped Wafer", "Raw Circuit", o));
+ ItemList.Circuit_Silicon_Wafer4.set(addItem(151, "Europium doped Wafer", "Raw Circuit", o));
+ ItemList.Circuit_Silicon_Wafer5.set(addItem(153, "Americium doped Wafer", "Raw Circuit", o));
+ ItemList.Circuit_Silicon_Wafer6.set(addItem(722, "Photonically Prepared Wafer", "Raw Circuit", o));
+ ItemList.Circuit_Silicon_Wafer7.set(addItem(723, "Photonically Enhanced Wafer", "Raw Circuit", o));
+
+ ItemList.Circuit_Wafer_ILC.set(addItem(36, "Integrated Logic Circuit (Wafer)", "Raw Circuit", o));
+ ItemList.Circuit_Chip_ILC.set(addItem(37, "Integrated Logic Circuit", "Integrated Circuit", o));
+
+ ItemList.Circuit_Wafer_Ram.set(addItem(38, "Random Access Memory Chip (Wafer)", "Raw Circuit", o));
+ ItemList.Circuit_Chip_Ram.set(addItem(39, "Random Access Memory Chip", "Integrated Circuit", o));
+
+ ItemList.Circuit_Wafer_NAND.set(addItem(40, "NAND Memory Chip (Wafer)", "Raw Circuit", o));
+ ItemList.Circuit_Chip_NAND.set(addItem(41, "NAND Memory Chip", "Integrated Circuit", o));
+
+ ItemList.Circuit_Wafer_NOR.set(addItem(42, "NOR Memory Chip (Wafer)", "Raw Circuit", o));
+ ItemList.Circuit_Chip_NOR.set(addItem(43, "NOR Memory Chip", "Integrated Circuit", o));
+
+ ItemList.Circuit_Wafer_CPU.set(addItem(44, "Central Processing Unit (Wafer)", "Raw Circuit", o));
+ ItemList.Circuit_Chip_CPU.set(addItem(45, "Central Processing Unit", "Integrated Circuit", o));
+
+ ItemList.Circuit_Wafer_SoC.set(addItem(46, "SoC Wafer", "Raw Circuit", o));
+ ItemList.Circuit_Chip_SoC.set(addItem(47, "SoC", "System on a Chip", o));
+
+ ItemList.Circuit_Wafer_SoC2.set(addItem(48, "ASoC Wafer", "Raw Circuit", o));
+ ItemList.Circuit_Chip_SoC2.set(addItem(49, "ASoC", "Advanced System on a Chip", o));
+
+ ItemList.Circuit_Wafer_PIC.set(addItem(50, "PIC Wafer", "Raw Circuit", o));
+ ItemList.Circuit_Chip_PIC.set(addItem(51, "Power IC", "Power Circuit", o));
+
+ ItemList.Circuit_Wafer_HPIC.set(addItem(52, "HPIC Wafer", "Raw Circuit", o));
+ ItemList.Circuit_Chip_HPIC.set(addItem(53, "High Power IC", "High Power Circuit", o));
+
+ ItemList.Circuit_Wafer_NanoCPU.set(addItem(54, "NanoCPU Wafer", "Raw Circuit", o));
+ ItemList.Circuit_Chip_NanoCPU.set(addItem(55, "Nanocomponent Central Processing Unit", "Power Circuit", o));
+
+ ItemList.Circuit_Wafer_QuantumCPU.set(addItem(56, "QBit Wafer", "Raw Circuit", o));
+ ItemList.Circuit_Chip_QuantumCPU.set(addItem(57, "QBit Processing Unit", "Quantum CPU", o));
+
+ ItemList.Circuit_Wafer_UHPIC.set(addItem(58, "UHPIC Wafer", "Raw Circuit", o));
+ ItemList.Circuit_Chip_UHPIC.set(addItem(59, "Ultra High Power IC", "Ultra High Power Circuit", o));
+
+ ItemList.Circuit_Wafer_Simple_SoC.set(addItem(60, "Simple SoC Wafer", "Raw Primitive Circuit", o));
+ ItemList.Circuit_Chip_Simple_SoC.set(addItem(61, "Simple SoC", "Simple System on a Chip", o));
+
+ ItemList.Circuit_Wafer_ULPIC.set(addItem(62, "ULPIC Wafer", "Raw Circuit", o));
+ ItemList.Circuit_Chip_ULPIC.set(addItem(63, "Ultra Low Power IC", "Ultra Low Power Circuit", o));
+
+ ItemList.Circuit_Wafer_LPIC.set(addItem(64, "LPIC Wafer", "Raw Circuit", o));
+ ItemList.Circuit_Chip_LPIC.set(addItem(65, "Low Power IC", "Low Power Circuit", o));
+
+ ItemList.Circuit_Wafer_NPIC.set(addItem(160, "NPIC Wafer", "Raw Circuit", o));
+ ItemList.Circuit_Chip_NPIC.set(addItem(161, "Nano Power IC", "Nano Power Circuit", o));
+
+ ItemList.Circuit_Wafer_PPIC.set(addItem(162, "PPIC Wafer", "Raw Circuit", o));
+ ItemList.Circuit_Chip_PPIC.set(addItem(163, "Piko Power IC", "Piko Power Circuit", o));
+
+ ItemList.Circuit_Wafer_QPIC.set(addItem(164, "QPIC Wafer", "Raw Circuit", o));
+ ItemList.Circuit_Chip_QPIC.set(addItem(165, "Quantum Power IC", "Quantum Power Circuit", o));
+
+ ItemList.Circuit_Wafer_Bioware.set(addItem(188, "Living Bio Wafer", "Raw Circuit", o));
+ ItemList.Circuit_Parts_Chip_Bioware.set(addItem(189, "Living Bio Chip", "Needed for Circuits", o));
+ /*
+ * Engraved Crystal Chip Engraved Lapotron Chip Crystal CPU SoCrystal stem cells (disassemble eggs)
+ */
+ ItemList.Circuit_Chip_CrystalSoC2
+ .set(addItem(68, "Raw Advanced Crystal Chip", "Raw Advanced Crystal Processor", o));
+ ItemList.Circuit_Parts_RawCrystalChip.set(addItem(69, "Raw Crystal Chip", "Raw Crystal Processor", o));
+ ItemList.Circuit_Chip_CrystalCPU.set(addItem(70, "Crystal Processing Unit", "Crystal CPU", o)); // Crystal
+ // chip
+ // elite
+ // part
+ ItemList.Circuit_Chip_CrystalSoC.set(addItem(71, "Crystal SoC", "Crystal System on a Chip", o));
+ ItemList.Circuit_Chip_NeuroCPU.set(addItem(72, "Neuro Processing Unit", "Neuro CPU", o));
+ ItemList.Circuit_Chip_Stemcell.set(addItem(73, "Stemcells", "Raw inteligence", o));
+ ItemList.Circuit_Parts_RawCrystalParts
+ .set(addItem(74, "Raw Crystal Chip Parts", "Raw Crystal Processor Parts", o));
+ ItemList.Circuit_Chip_Biocell.set(addItem(76, "Biocells", "Mutated Raw inteligence", o));
+ ItemList.Circuit_Chip_BioCPU.set(addItem(77, "Bio Processing Unit", "Bio CPU", o));
+ ItemList.Circuit_Chip_Optical.set(addItem(724, "Raw Exposed Optical Chip", "Raw Optical Chip", o));
+
+ // Nand Chip
+ ItemList.NandChip.set(
+ addItem(
+ 75,
+ "NAND Chip",
+ "A very simple Circuit",
+ OrePrefixes.circuit.get(Materials.Primitive),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.NandChip.get(1), ULV);
+ // Vacuum Tube Item01
+ // Basic Circuit IC2
+ // Good Circuit Item01
+
+ // Integrated Logic Circuit Item01
+ ItemList.Circuit_Integrated_Good.set(
+ addItem(
+ 79,
+ "Good Integrated Circuit",
+ "Good Circuit",
+ OrePrefixes.circuit.get(Materials.Good),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_Integrated_Good.get(1), MV);
+ // Good Integrated Circuit Item01
+ // Advanced Circuit IC2
+
+ ItemList.Circuit_Microprocessor.set(
+ addItem(
+ 78,
+ "Microprocessor",
+ "A Basic Circuit",
+ OrePrefixes.circuit.get(Materials.Basic),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_Microprocessor.get(1), LV);
+ ItemList.Circuit_Processor.set(
+ addItem(
+ 80,
+ "Integrated Processor",
+ "A Good Circuit",
+ OrePrefixes.circuit.get(Materials.Good),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_Processor.get(1), MV);
+ // ItemList.Circuit_Computer.set(addItem(tLastID = 81, "Processor Assembly", "Advanced Circuit", new
+ // Object[]{OrePrefixes.circuit.get(Materials.Advanced), SubTag.NO_UNIFICATION}));
+ // Workstation/ Item01 Datacircuit
+ // Mainframe Item01 DataProcessor
+
+ ItemList.Circuit_Nanoprocessor.set(
+ addItem(
+ 82,
+ "Nanoprocessor",
+ "An Advanced Circuit",
+ OrePrefixes.circuit.get(Materials.Advanced),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_Nanoprocessor.get(1), HV);
+ ItemList.Circuit_Nanocomputer.set(
+ addItem(
+ 83,
+ "Nanoprocessor Assembly",
+ "An Extreme Circuit",
+ OrePrefixes.circuit.get(Materials.Data),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_Nanocomputer.get(1), EV);
+ ItemList.Circuit_Elitenanocomputer.set(
+ addItem(
+ 84,
+ "Elite Nanocomputer",
+ "An Elite Circuit",
+ OrePrefixes.circuit.get(Materials.Elite),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_Elitenanocomputer.get(1), IV);
+ // Nanoprocessor Mainframe Item01 Energy Flow Circuit
+
+ // Quantum circuits
+ ItemList.Circuit_Quantumprocessor.set(
+ addItem(
+ 85,
+ "Quantumprocessor",
+ "An Extreme Circuit",
+ OrePrefixes.circuit.get(Materials.Data),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_Quantumprocessor.get(1), EV);
+ ItemList.Circuit_Quantumcomputer.set(
+ addItem(
+ 86,
+ "Quantumprocessor Assembly",
+ "An Elite Circuit",
+ OrePrefixes.circuit.get(Materials.Elite),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_Quantumcomputer.get(1), IV);
+ ItemList.Circuit_Masterquantumcomputer.set(
+ addItem(
+ 87,
+ "Master Quantumcomputer",
+ "A Master Circuit",
+ OrePrefixes.circuit.get(Materials.Master),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_Masterquantumcomputer.get(1), LuV);
+ ItemList.Circuit_Quantummainframe.set(
+ addItem(
+ 88,
+ "Quantumprocessor Mainframe",
+ "An Ultimate Circuit",
+ OrePrefixes.circuit.get(Materials.Ultimate),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_Quantummainframe.get(1), ZPM);
+
+ // Crystal circuits
+ ItemList.Circuit_Crystalprocessor.set(
+ addItem(
+ 89,
+ "Crystalprocessor",
+ "An Elite Circuit",
+ OrePrefixes.circuit.get(Materials.Elite),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_Crystalprocessor.get(1), IV);
+ ItemList.Circuit_Crystalcomputer.set(
+ addItem(
+ 96,
+ "Crystalprocessor Assembly",
+ "A Master Circuit",
+ OrePrefixes.circuit.get(Materials.Master),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_Crystalcomputer.get(1), LuV);
+ ItemList.Circuit_Ultimatecrystalcomputer.set(
+ addItem(
+ 90,
+ "Ultimate Crystalcomputer",
+ "An Ultimate Circuit",
+ OrePrefixes.circuit.get(Materials.Ultimate),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_Ultimatecrystalcomputer.get(1), ZPM);
+ ItemList.Circuit_Crystalmainframe.set(
+ addItem(
+ 91,
+ "Crystalprocessor Mainframe",
+ "A Super Circuit",
+ OrePrefixes.circuit.get(Materials.SuperconductorUHV),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_Crystalmainframe.get(1), UV);
+
+ // ???? Scared to remove.
+ ItemList.Circuit_Ultimate.set(ItemList.Circuit_Ultimatecrystalcomputer.get(1L)); // maybe should be removed
+
+ // Wetware circuits
+ ItemList.Circuit_Neuroprocessor.set(
+ addItem(
+ 92,
+ "Wetwareprocessor",
+ "A Master Circuit",
+ OrePrefixes.circuit.get(Materials.Master),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_Neuroprocessor.get(1), LuV);
+ ItemList.Circuit_Wetwarecomputer.set(
+ addItem(
+ 93,
+ "Wetwareprocessor Assembly",
+ "An Ultimate Circuit",
+ OrePrefixes.circuit.get(Materials.Ultimate),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_Wetwarecomputer.get(1), ZPM);
+ ItemList.Circuit_Wetwaresupercomputer.set(
+ addItem(
+ 94,
+ "Wetware Supercomputer",
+ "A Super Circuit",
+ OrePrefixes.circuit.get(Materials.SuperconductorUHV),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_Wetwaresupercomputer.get(1), UV);
+ ItemList.Circuit_Wetwaremainframe.set(
+ addItem(
+ 95,
+ "Wetware Mainframe",
+ "An Infinite Circuit",
+ OrePrefixes.circuit.get(Materials.Infinite),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_Wetwaremainframe.get(1), UHV);
+
+ // Bioware circuits.
+ ItemList.Circuit_Bioprocessor.set(
+ addItem(
+ 97,
+ "Bioprocessor",
+ "An Ultimate Circuit",
+ OrePrefixes.circuit.get(Materials.Ultimate),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_Bioprocessor.get(1), ZPM);
+ ItemList.Circuit_Biowarecomputer.set(
+ addItem(
+ 98,
+ "Biowareprocessor Assembly",
+ "A Super Circuit",
+ OrePrefixes.circuit.get(Materials.SuperconductorUHV),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_Biowarecomputer.get(1), UV);
+ ItemList.Circuit_Biowaresupercomputer.set(
+ addItem(
+ 99,
+ "Bioware Supercomputer",
+ "An Infinite Circuit",
+ OrePrefixes.circuit.get(Materials.Infinite),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_Biowaresupercomputer.get(1), UHV);
+ ItemList.Circuit_Biomainframe.set(
+ addItem(
+ 120,
+ "Bio Mainframe",
+ "A Bio Circuit",
+ OrePrefixes.circuit.get(Materials.Bio),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_Biomainframe.get(1), UEV);
+
+ ItemList.Circuit_Board_Coated_Basic.set(addItem(100, "Circuit Board", "A basic Circuit Board", o));
+ ItemList.Circuit_Board_Phenolic_Good.set(addItem(101, "Good Circuit Board", "A good Circuit Board", o));
+ ItemList.Circuit_Board_Epoxy_Advanced
+ .set(addItem(102, "Advanced Circuit Board", "A advanced Circuit Board", o));
+ ItemList.Circuit_Board_Fiberglass_Advanced
+ .set(addItem(103, "More Advanced Circuit Board", "A more advanced Circuit Board", o));
+ ItemList.Circuit_Board_Multifiberglass_Elite
+ .set(addItem(104, "Elite Circuit Board", "A elite Circuit Board", o));
+ ItemList.Circuit_Board_Wetware_Extreme
+ .set(addItem(105, "Extreme Wetware Lifesupport Circuit Board", "The Board that keeps life", o));
+ ItemList.Circuit_Board_Plastic_Advanced.set(addItem(106, "Plastic Circuit Board", "A good Board", o));
+ ItemList.Circuit_Board_Bio_Ultra
+ .set(addItem(107, "Ultra Bio Mutated Circuit Board", "Bio genetic mutated Board", o));
+ ItemList.Circuit_Board_Optical.set(addItem(728, "Optical Circuit Board", "Optically Infused Board", o));
+
+ // Optical circuits
+ ItemList.Circuit_OpticalProcessor.set(
+ addItem(
+ 154,
+ "Optical Processor",
+ "An Optical Circuit",
+ OrePrefixes.circuit.get(Materials.SuperconductorUHV),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_OpticalProcessor.get(1), UV);
+ ItemList.Circuit_OpticalAssembly.set(
+ addItem(
+ 155,
+ "Optical Assembly",
+ "An Optical Circuit",
+ OrePrefixes.circuit.get(Materials.Infinite),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_OpticalAssembly.get(1), UHV);
+ ItemList.Circuit_OpticalComputer.set(
+ addItem(
+ 156,
+ "Optical Computer",
+ "An Optical Circuit",
+ OrePrefixes.circuit.get(Materials.Bio),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_OpticalComputer.get(1), UEV);
+ ItemList.Circuit_OpticalMainframe.set(
+ addItem(
+ 157,
+ "Optical Mainframe",
+ "An Optical Circuit",
+ OrePrefixes.circuit.get(Materials.Optical),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_OpticalMainframe.get(1), UIV);
+
+ // Exotic circuits
+ ItemList.Circuit_ExoticProcessor.set(
+ addItem(
+ 166,
+ "Exotic Processor",
+ "An Exotic Circuit",
+ OrePrefixes.circuit.get(Materials.Infinite),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_ExoticProcessor.get(1), UHV);
+ ItemList.Circuit_ExoticAssembly.set(
+ addItem(
+ 167,
+ "Exotic Assembly",
+ "An Exotic Circuit",
+ OrePrefixes.circuit.get(Materials.Bio),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_ExoticAssembly.get(1), UEV);
+ ItemList.Circuit_ExoticComputer.set(
+ addItem(
+ 168,
+ "Exotic Computer",
+ "An Exotic Circuit",
+ OrePrefixes.circuit.get(Materials.Optical),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_ExoticComputer.get(1), UIV);
+ ItemList.Circuit_ExoticMainframe.set(
+ addItem(
+ 169,
+ "Exotic Mainframe",
+ "An Exotic Circuit",
+ OrePrefixes.circuit.get(Materials.Exotic),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_ExoticMainframe.get(1), UMV);
+
+ // Cosmic circuits
+ ItemList.Circuit_CosmicProcessor.set(
+ addItem(
+ 170,
+ "Cosmic Processor",
+ "A Cosmic Circuit",
+ OrePrefixes.circuit.get(Materials.Bio),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_CosmicProcessor.get(1), UEV);
+ ItemList.Circuit_CosmicAssembly.set(
+ addItem(
+ 171,
+ "Cosmic Assembly",
+ "A Cosmic Circuit",
+ OrePrefixes.circuit.get(Materials.Optical),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_CosmicAssembly.get(1), UIV);
+ ItemList.Circuit_CosmicComputer.set(
+ addItem(
+ 172,
+ "Cosmic Computer",
+ "A Cosmic Circuit",
+ OrePrefixes.circuit.get(Materials.Exotic),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_CosmicComputer.get(1), UMV);
+ ItemList.Circuit_CosmicMainframe.set(
+ addItem(
+ 173,
+ "Cosmic Mainframe",
+ "A Cosmic Circuit",
+ OrePrefixes.circuit.get(Materials.Cosmic),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_CosmicMainframe.get(1), UXV);
+
+ // Transcendent circuits
+ ItemList.Circuit_TranscendentProcessor.set(
+ addItem(
+ 174,
+ "Temporally Transcendent Processor",
+ "A circuit operating outside of known spacetime",
+ OrePrefixes.circuit.get(Materials.Optical),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_TranscendentProcessor.get(1), UIV);
+ ItemList.Circuit_TranscendentAssembly.set(
+ addItem(
+ 175,
+ "Temporally Transcendent Assembly",
+ "A circuit operating outside of known spacetime",
+ OrePrefixes.circuit.get(Materials.Exotic),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_TranscendentAssembly.get(1), UMV);
+ ItemList.Circuit_TranscendentComputer.set(
+ addItem(
+ 176,
+ "Temporally Transcendent Computer",
+ "A circuit operating outside of known spacetime",
+ OrePrefixes.circuit.get(Materials.Cosmic),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_TranscendentComputer.get(1), UXV);
+ ItemList.Circuit_TranscendentMainframe.set(
+ addItem(
+ 177,
+ "Temporally Transcendent Mainframe",
+ "A circuit operating outside of known spacetime",
+ OrePrefixes.circuit.get(Materials.Transcendent),
+ SubTag.NO_UNIFICATION));
+ registerTieredTooltip(ItemList.Circuit_TranscendentMainframe.get(1), MAX);
+
+ ItemList.Tube_Wires.set(addItem(110, "Tube Wires", "For the Vacuum Tubes", o));
+
+ ItemList.Cover_SolarPanel_UHV.set(
+ addItem(
+ 130,
+ "Solar Panel (UHV)",
+ "Ultimate High Voltage Solar Panel (Needs cleaning with right click)",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 128L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 128L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TENEBRAE, 128L)));
+ ItemList.Cover_SolarPanel_UEV.set(
+ addItem(
+ 131,
+ "Solar Panel (UEV)",
+ "Ultimate Extreme Voltage Solar Panel (Needs cleaning with right click)",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 256L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 256L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TENEBRAE, 256L)));
+ ItemList.Cover_SolarPanel_UIV.set(
+ addItem(
+ 132,
+ "Solar Panel (UIV)",
+ "Ultimate Insane Voltage Solar Panel (Needs cleaning with right click)",
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ELECTRUM, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.POTENTIA, 512L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TENEBRAE, 512L)));
+
+ GregTech_API.registerCover(
+ ItemList.Cover_SolarPanel_UHV.get(1L),
+ TextureFactory.of(SOLARPANEL_UHV),
+ new GT_Cover_SolarPanel(2097152));
+ GregTech_API.registerCover(
+ ItemList.Cover_SolarPanel_UEV.get(1L),
+ TextureFactory.of(SOLARPANEL_UEV),
+ new GT_Cover_SolarPanel(8388608));
+ GregTech_API.registerCover(
+ ItemList.Cover_SolarPanel_UIV.get(1L),
+ TextureFactory.of(SOLARPANEL_UIV),
+ new GT_Cover_SolarPanel(33554432));
+
+ ItemList.ULV_Coil.set(addItem(140, "Ultra Low Voltage Coil", "Primitive Coil", o));
+ ItemList.LV_Coil.set(addItem(141, "Low Voltage Coil", "Basic Coil", o));
+ ItemList.MV_Coil.set(addItem(142, "Medium Voltage Coil", "Good Coil", o));
+ ItemList.HV_Coil.set(addItem(143, "High Voltage Coil", "Advanced Coil", o));
+ ItemList.EV_Coil.set(addItem(144, "Extreme Voltage Coil", "Extreme Coil", o));
+ ItemList.IV_Coil.set(addItem(145, "Insane Voltage Coil", "Elite Coil", o));
+ ItemList.LuV_Coil.set(addItem(146, "Ludicrous Voltage Coil", "Master Coil", o));
+ ItemList.ZPM_Coil.set(addItem(147, "ZPM Voltage Coil", "Ultimate Coil", o));
+ ItemList.UV_Coil.set(addItem(148, "Ultimate Voltage Coil", "Super Coil", o));
+ ItemList.UHV_Coil.set(addItem(149, "Highly Ultimate Voltage Coil", "Infinite Coil", o));
+
+ ItemList.GalliumArsenideCrystal.set(addItem(190, "Gallium Arsenide Crystal", "For making boules", o));
+ ItemList.GalliumArsenideCrystalSmallPart
+ .set(addItem(191, "Small Gallium Arsenide Crystal", "For making boules", o));
+ ItemList.KevlarFiber.set(addItem(192, "Kevlar Fiber", "For making Kevlar Plates", o));
+ ItemList.WovenKevlar.set(addItem(193, "Woven Kevlar", "For making Kevlar Plates", o));
+ ItemList.Spinneret.set(addItem(194, "Spinneret", "For making Kevlar Fiber", o));
+
+ ItemList.IndustrialApiary_Upgrade_Frame.set(addItem(199, "Upgrade Frame", "Crafting component", o));
+
+ ItemList.IndustrialApiary_Upgrade_Acceleration_1.set(
+ addItem(
+ 200,
+ "Acceleration Upgrade x2",
+ "Acceleration upgrade for Industrial Apiary/n Maximum Installed: 1/n * Unlocks 2x acceleration level/n * Energy Consumption +1 AMP LV",
+ OrePrefixes.apiaryUpgrade.name()));
+ ItemList.IndustrialApiary_Upgrade_Acceleration_2.set(
+ addItem(
+ 201,
+ "Acceleration Upgrade x4",
+ "Acceleration upgrade for Industrial Apiary/n Maximum Installed: 1/n * Unlocks 4x acceleration level/n * Energy Consumption +1 AMP MV",
+ OrePrefixes.apiaryUpgrade.name()));
+ ItemList.IndustrialApiary_Upgrade_Acceleration_3.set(
+ addItem(
+ 202,
+ "Acceleration Upgrade x8",
+ "Acceleration upgrade for Industrial Apiary/n Maximum Installed: 1/n * Unlocks 8x acceleration level/n * Energy Consumption +1 AMP HV",
+ OrePrefixes.apiaryUpgrade.name()));
+ ItemList.IndustrialApiary_Upgrade_Acceleration_4.set(
+ addItem(
+ 203,
+ "Acceleration Upgrade x16",
+ "Acceleration upgrade for Industrial Apiary/n Maximum Installed: 1/n * Unlocks 16x acceleration level/n * Energy Consumption +1 AMP EV",
+ OrePrefixes.apiaryUpgrade.name()));
+ ItemList.IndustrialApiary_Upgrade_Acceleration_5.set(
+ addItem(
+ 204,
+ "Acceleration Upgrade x32",
+ "Acceleration upgrade for Industrial Apiary/n Maximum Installed: 1/n * Unlocks 32x acceleration level/n * Energy Consumption +1 AMP IV",
+ OrePrefixes.apiaryUpgrade.name()));
+ ItemList.IndustrialApiary_Upgrade_Acceleration_6.set(
+ addItem(
+ 205,
+ "Acceleration Upgrade x64",
+ "Acceleration upgrade for Industrial Apiary/n Maximum Installed: 1/n * Unlocks 64x acceleration level/n * Energy Consumption +1 AMP LuV",
+ OrePrefixes.apiaryUpgrade.name()));
+ ItemList.IndustrialApiary_Upgrade_Acceleration_7.set(
+ addItem(
+ 206,
+ "Acceleration Upgrade x128",
+ "Acceleration upgrade for Industrial Apiary/n Maximum Installed: 1/n * Unlocks 128x acceleration level/n * Energy Consumption +1 AMP ZPM",
+ OrePrefixes.apiaryUpgrade.name()));
+ ItemList.IndustrialApiary_Upgrade_Acceleration_8.set(
+ addItem(
+ 207,
+ "Acceleration Upgrade x256",
+ "Acceleration upgrade for Industrial Apiary/n Maximum Installed: 1/n * Unlocks 256x acceleration level/n * Energy Consumption +1 AMP UV",
+ OrePrefixes.apiaryUpgrade.name()));
+ ItemList.IndustrialApiary_Upgrade_Acceleration_8_Upgraded.set(
+ addItem(
+ 208,
+ "Upgraded Acceleration Upgrade x256",
+ "Acceleration upgrade for Industrial Apiary/n Maximum Installed: 1/n * Unlocks 256x acceleration level/n * Will also grant 8x production upgrade/n * Energy Consumption +1 AMP UV",
+ OrePrefixes.apiaryUpgrade.name()));
+ ItemList.IndustrialApiary_Upgrade_PRODUCTION.set(
+ addItem(
+ 209,
+ "Production Upgrade",
+ "Production upgrade for Industrial Apiary/n Maximum Installed: 8/n Increases production modifier by 0.25/n Energy Consumption +40%",
+ OrePrefixes.apiaryUpgrade.name()));
+ ItemList.IndustrialApiary_Upgrade_PLAINS.set(
+ addItem(
+ 210,
+ "Plains Emulation Upgrade",
+ "Plains emulation upgrade for Industrial Apiary/n Maximum Installed: 1/n * Biome Override: Plains/n * Energy Consumption +40%",
+ OrePrefixes.apiaryUpgrade.name()));
+ ItemList.IndustrialApiary_Upgrade_LIGHT.set(
+ addItem(
+ 211,
+ "Light Upgrade",
+ "Light upgrade for Industrial Apiary/n Maximum Installed: 1/n * Internal Lighting/n * Energy Consumption +5%",
+ OrePrefixes.apiaryUpgrade.name()));
+ ItemList.IndustrialApiary_Upgrade_FLOWERING.set(
+ addItem(
+ 212,
+ "Flowering Upgrade",
+ "Flowering upgrade for Industrial Apiary/n Maximum Installed: 8/n * Flowering and Pollination +20%/n * Energy Consumption +10%",
+ OrePrefixes.apiaryUpgrade.name()));
+ ItemList.IndustrialApiary_Upgrade_WINTER.set(
+ addItem(
+ 213,
+ "Winter Emulation Upgrade",
+ "Winter emulation upgrade for Industrial Apiary/n Maximum Installed: 1/n * Biome Override: Taiga/n * Energy Consumption +50%",
+ OrePrefixes.apiaryUpgrade.name()));
+ ItemList.IndustrialApiary_Upgrade_DRYER.set(
+ addItem(
+ 214,
+ "Dryer Upgrade",
+ "Dryer upgrade for Industrial Apiary/n Maximum Installed: 16/n * Humidity -12.5%/n * Energy Consumption +2.5%",
+ OrePrefixes.apiaryUpgrade.name()));
+ ItemList.IndustrialApiary_Upgrade_AUTOMATION.set(
+ addItem(
+ 215,
+ "Automation Upgrade",
+ "Automation upgrade for Industrial Apiary/n Maximum Installed: 1/n * Automation/n * Energy Consumption +10%",
+ OrePrefixes.apiaryUpgrade.name()));
+ ItemList.IndustrialApiary_Upgrade_HUMIDIFIER.set(
+ addItem(
+ 216,
+ "Humidifier Upgrade",
+ "Humidifier upgrade for Industrial Apiary/n Maximum Installed: 16/n * Humidity +12.5%/n * Energy Consumption +2.5%",
+ OrePrefixes.apiaryUpgrade.name()));
+ ItemList.IndustrialApiary_Upgrade_HELL.set(
+ addItem(
+ 217,
+ "HELL Emulation Upgrade",
+ "HELL emulation upgrade for Industrial Apiary/n Maximum Installed: 1/n * Biome Override: HELL/n * Energy Consumption +50%",
+ OrePrefixes.apiaryUpgrade.name()));
+ ItemList.IndustrialApiary_Upgrade_POLLEN.set(
+ addItem(
+ 218,
+ "Pollen Scrubber Upgrade",
+ "Pollen scrubber upgrade for Industrial Apiary/n Maximum Installed: 1/n * Flowering and Pollination -100%/n * Energy Consumption +30%",
+ OrePrefixes.apiaryUpgrade.name()));
+ ItemList.IndustrialApiary_Upgrade_DESERT.set(
+ addItem(
+ 219,
+ "Desert Emulation Upgrade",
+ "Desert emulation upgrade for Industrial Apiary/n Maximum Installed: 1/n * Biome Override: Desert/n * Energy Consumption +20%",
+ OrePrefixes.apiaryUpgrade.name()));
+ ItemList.IndustrialApiary_Upgrade_COOLER.set(
+ addItem(
+ 220,
+ "Cooler Upgrade",
+ "Cooler upgrade for Industrial Apiary/n Maximum Installed: 16/n * Temperature -12.5%/n * Energy Consumption +2.5%",
+ OrePrefixes.apiaryUpgrade.name()));
+ ItemList.IndustrialApiary_Upgrade_LIFESPAN.set(
+ addItem(
+ 221,
+ "Lifespan Upgrade",
+ "Lifespan upgrade for Industrial Apiary/n Maximum Installed: 4/n * Lifespan -33%/n * Energy Consumption +5%",
+ OrePrefixes.apiaryUpgrade.name()));
+ ItemList.IndustrialApiary_Upgrade_SEAL.set(
+ addItem(
+ 222,
+ "Seal Upgrade",
+ "Seal upgrade for Industrial Apiary/n Maximum Installed: 1/n * Rain Protection/n * Energy Consumption +5%",
+ OrePrefixes.apiaryUpgrade.name()));
+ ItemList.IndustrialApiary_Upgrade_STABILIZER.set(
+ addItem(
+ 223,
+ "Genetic Stabilizer Upgrade",
+ "Genetic stabilizer upgrade for Industrial Apiary/n Maximum Installed: 1/n * Genetic Decay -100%/n * Energy Consumption +150%",
+ OrePrefixes.apiaryUpgrade.name()));
+ ItemList.IndustrialApiary_Upgrade_JUNGLE.set(
+ addItem(
+ 224,
+ "Jungle Emulation Upgrade",
+ "Jungle emulation upgrade for Industrial Apiary/n Maximum Installed: 1/n * Biome Override: Jungle/n * Energy Consumption +20%",
+ OrePrefixes.apiaryUpgrade.name()));
+ ItemList.IndustrialApiary_Upgrade_TERRITORY.set(
+ addItem(
+ 225,
+ "Territory Upgrade",
+ "Territory upgrade for Industrial Apiary/n Maximum Installed: 4/n * Territory +50%/n * Energy Consumption +5%",
+ OrePrefixes.apiaryUpgrade.name()));
+ ItemList.IndustrialApiary_Upgrade_OCEAN.set(
+ addItem(
+ 226,
+ "Ocean Emulation Upgrade",
+ "Ocean emulation upgrade for Industrial Apiary/n Maximum Installed: 1/n * Biome Override: Ocean/n * Energy Consumption +20%",
+ OrePrefixes.apiaryUpgrade.name()));
+ ItemList.IndustrialApiary_Upgrade_SKY.set(
+ addItem(
+ 227,
+ "Open Sky Upgrade",
+ "Open sky upgrade for Industrial Apiary/n Maximum Installed: 1/n * Open Sky Simulation/n * Energy Consumption +5%",
+ OrePrefixes.apiaryUpgrade.name()));
+ ItemList.IndustrialApiary_Upgrade_HEATER.set(
+ addItem(
+ 228,
+ "Heater Upgrade",
+ "Heater upgrade for Industrial Apiary/n Maximum Installed: 16/n * Temperature +12.5%/n * Energy Consumption +2.5%",
+ OrePrefixes.apiaryUpgrade.name()));
+ ItemList.IndustrialApiary_Upgrade_SIEVE.set(
+ addItem(
+ 229,
+ "Sieve Upgrade",
+ "Sieve upgrade for Industrial Apiary/n Maximum Installed: 1/n * Pollen Collection/n * Energy Consumption +25%",
+ OrePrefixes.apiaryUpgrade.name()));
+ ItemList.IndustrialApiary_Upgrade_UNLIGHT.set(
+ addItem(
+ 231,
+ "Night Upgrade",
+ "Night upgrade for Industrial Apiary/n Maximum Installed: 1/n * Internal Darkness/n * Energy Consumption +5%",
+ OrePrefixes.apiaryUpgrade.name()));
+
+ OrePrefixes.apiaryUpgrade.add(ItemList.IndustrialApiary_Upgrade_Acceleration_1.get(1L));
+ OrePrefixes.apiaryUpgrade.add(ItemList.IndustrialApiary_Upgrade_Acceleration_2.get(1L));
+ OrePrefixes.apiaryUpgrade.add(ItemList.IndustrialApiary_Upgrade_Acceleration_3.get(1L));
+ OrePrefixes.apiaryUpgrade.add(ItemList.IndustrialApiary_Upgrade_Acceleration_4.get(1L));
+ OrePrefixes.apiaryUpgrade.add(ItemList.IndustrialApiary_Upgrade_Acceleration_5.get(1L));
+ OrePrefixes.apiaryUpgrade.add(ItemList.IndustrialApiary_Upgrade_Acceleration_6.get(1L));
+ OrePrefixes.apiaryUpgrade.add(ItemList.IndustrialApiary_Upgrade_Acceleration_7.get(1L));
+ OrePrefixes.apiaryUpgrade.add(ItemList.IndustrialApiary_Upgrade_Acceleration_8.get(1L));
+ OrePrefixes.apiaryUpgrade.add(ItemList.IndustrialApiary_Upgrade_Acceleration_8_Upgraded.get(1L));
+ OrePrefixes.apiaryUpgrade.add(ItemList.IndustrialApiary_Upgrade_PRODUCTION.get(1L));
+ OrePrefixes.apiaryUpgrade.add(ItemList.IndustrialApiary_Upgrade_PLAINS.get(1L));
+ OrePrefixes.apiaryUpgrade.add(ItemList.IndustrialApiary_Upgrade_LIGHT.get(1L));
+ OrePrefixes.apiaryUpgrade.add(ItemList.IndustrialApiary_Upgrade_FLOWERING.get(1L));
+ OrePrefixes.apiaryUpgrade.add(ItemList.IndustrialApiary_Upgrade_WINTER.get(1L));
+ OrePrefixes.apiaryUpgrade.add(ItemList.IndustrialApiary_Upgrade_DRYER.get(1L));
+ OrePrefixes.apiaryUpgrade.add(ItemList.IndustrialApiary_Upgrade_AUTOMATION.get(1L));
+ OrePrefixes.apiaryUpgrade.add(ItemList.IndustrialApiary_Upgrade_HUMIDIFIER.get(1L));
+ OrePrefixes.apiaryUpgrade.add(ItemList.IndustrialApiary_Upgrade_HELL.get(1L));
+ OrePrefixes.apiaryUpgrade.add(ItemList.IndustrialApiary_Upgrade_POLLEN.get(1L));
+ OrePrefixes.apiaryUpgrade.add(ItemList.IndustrialApiary_Upgrade_DESERT.get(1L));
+ OrePrefixes.apiaryUpgrade.add(ItemList.IndustrialApiary_Upgrade_COOLER.get(1L));
+ OrePrefixes.apiaryUpgrade.add(ItemList.IndustrialApiary_Upgrade_LIFESPAN.get(1L));
+ OrePrefixes.apiaryUpgrade.add(ItemList.IndustrialApiary_Upgrade_SEAL.get(1L));
+ OrePrefixes.apiaryUpgrade.add(ItemList.IndustrialApiary_Upgrade_STABILIZER.get(1L));
+ OrePrefixes.apiaryUpgrade.add(ItemList.IndustrialApiary_Upgrade_JUNGLE.get(1L));
+ OrePrefixes.apiaryUpgrade.add(ItemList.IndustrialApiary_Upgrade_TERRITORY.get(1L));
+ OrePrefixes.apiaryUpgrade.add(ItemList.IndustrialApiary_Upgrade_OCEAN.get(1L));
+ OrePrefixes.apiaryUpgrade.add(ItemList.IndustrialApiary_Upgrade_SKY.get(1L));
+ OrePrefixes.apiaryUpgrade.add(ItemList.IndustrialApiary_Upgrade_HEATER.get(1L));
+ OrePrefixes.apiaryUpgrade.add(ItemList.IndustrialApiary_Upgrade_SIEVE.get(1L));
+ OrePrefixes.apiaryUpgrade.add(ItemList.IndustrialApiary_Upgrade_UNLIGHT.get(1L));
+
+ ItemList.NuclearStar.set(
+ addItem(
+ 230,
+ "Nuclear Star",
+ "By the powers of Greg, I command this star to be really hot.",
+ SubTag.NO_UNIFICATION));
+
+ ItemList.Cover_Metrics_Transmitter.set(
+ addItem(
+ 232,
+ "Metrics Transmitter Cover",
+ String.join(
+ "/n ",
+ "Taking Information Panels to the next level!",
+ "Creates a GregTech Advanced Sensor Card when attached",
+ "Works across dimensions or if machine is dismantled",
+ "Removing this cover will destroy the linked card",
+ GT_Values.AuthorQuerns)));
+ GregTech_API.registerCover(
+ ItemList.Cover_Metrics_Transmitter.get(1L),
+ TextureFactory.of(MACHINE_CASINGS[2][0], TextureFactory.of(OVERLAY_METRICS_TRANSMITTER)),
+ new GT_Cover_Metrics_Transmitter(TextureFactory.of(OVERLAY_METRICS_TRANSMITTER)));
+
+ ItemList.Optical_Cpu_Containment_Housing.set(addItem(727, "Optical CPU Containment Housing", "CPU Housing", o));
+ ItemList.Optically_Perfected_CPU.set(addItem(726, "Optically Perfected CPU", "Perfected CPU!", o));
+ ItemList.Optically_Compatible_Memory.set(addItem(725, "Optically Compatible Memory", "Its in the name!", o));
+
+ ItemList.Timepiece.set(addItem(757, "Timepiece", "Beware of the kid with the hat", o));
+
+ int whiteDwarfIDs = 729;
+ ItemList.White_Dwarf_Shape_Extruder_Plate.set(
+ addItem(
+ whiteDwarfIDs++,
+ "White Dwarf Extruder Shape (Plate)",
+ "Ultra Strong Stellar Shape for making Plates"));
+ ItemList.White_Dwarf_Shape_Extruder_Rod.set(
+ addItem(whiteDwarfIDs++, "White Dwarf Extruder Shape (Rod)", "Ultra Strong Stellar Shape for making Rods"));
+ ItemList.White_Dwarf_Shape_Extruder_Bolt.set(
+ addItem(
+ whiteDwarfIDs++,
+ "White Dwarf Extruder Shape (Bolt)",
+ "Ultra Strong Stellar Shape for making Bolts"));
+ ItemList.White_Dwarf_Shape_Extruder_Ring.set(
+ addItem(
+ whiteDwarfIDs++,
+ "White Dwarf Extruder Shape (Ring)",
+ "Ultra Strong Stellar Shape for making Rings"));
+ ItemList.White_Dwarf_Shape_Extruder_Cell.set(
+ addItem(
+ whiteDwarfIDs++,
+ "White Dwarf Extruder Shape (Cell)",
+ "Ultra Strong Stellar Shape for making Cells"));
+ ItemList.White_Dwarf_Shape_Extruder_Ingot.set(
+ addItem(
+ whiteDwarfIDs++,
+ "White Dwarf Extruder Shape (Ingot)",
+ "Ultra Strong Stellar Shape for, wait, can't we just use a Furnace?"));
+ ItemList.White_Dwarf_Shape_Extruder_Wire.set(
+ addItem(
+ whiteDwarfIDs++,
+ "White Dwarf Extruder Shape (Wire)",
+ "Ultra Strong Stellar Shape for making Wires"));
+ ItemList.White_Dwarf_Shape_Extruder_Casing.set(
+ addItem(
+ whiteDwarfIDs++,
+ "White Dwarf Extruder Shape (Casing)",
+ "Ultra Strong Stellar Shape for making Item Casings"));
+ ItemList.White_Dwarf_Shape_Extruder_Pipe_Tiny.set(
+ addItem(
+ whiteDwarfIDs++,
+ "White Dwarf Extruder Shape (Tiny Pipe)",
+ "Ultra Strong Stellar Shape for making tiny Pipes"));
+ ItemList.White_Dwarf_Shape_Extruder_Pipe_Small.set(
+ addItem(
+ whiteDwarfIDs++,
+ "White Dwarf Extruder Shape (Small Pipe)",
+ "Ultra Strong Stellar Shape for making small Pipes"));
+ ItemList.White_Dwarf_Shape_Extruder_Pipe_Medium.set(
+ addItem(
+ whiteDwarfIDs++,
+ "White Dwarf Extruder Shape (Normal Pipe)",
+ "Ultra Strong Stellar Shape for making Pipes"));
+ ItemList.White_Dwarf_Shape_Extruder_Pipe_Large.set(
+ addItem(
+ whiteDwarfIDs++,
+ "White Dwarf Extruder Shape (Large Pipe)",
+ "Ultra Strong Stellar Shape for making large Pipes"));
+ ItemList.White_Dwarf_Shape_Extruder_Pipe_Huge.set(
+ addItem(
+ whiteDwarfIDs++,
+ "White Dwarf Extruder Shape (Huge Pipe)",
+ "Ultra Strong Stellar Shape for making full Block Pipes"));
+ ItemList.White_Dwarf_Shape_Extruder_Block.set(
+ addItem(
+ whiteDwarfIDs++,
+ "White Dwarf Extruder Shape (Block)",
+ "Ultra Strong Stellar Shape for making Blocks"));
+ ItemList.White_Dwarf_Shape_Extruder_Sword.set(
+ addItem(
+ whiteDwarfIDs++,
+ "White Dwarf Extruder Shape (Sword Blade)",
+ "Ultra Strong Stellar Shape for making Swords"));
+ ItemList.White_Dwarf_Shape_Extruder_Pickaxe.set(
+ addItem(
+ whiteDwarfIDs++,
+ "White Dwarf Extruder Shape (Pickaxe Head)",
+ "Ultra Strong Stellar Shape for making Pickaxes"));
+ ItemList.White_Dwarf_Shape_Extruder_Shovel.set(
+ addItem(
+ whiteDwarfIDs++,
+ "White Dwarf Extruder Shape (Shovel Head)",
+ "Ultra Strong Stellar Shape for making Shovels"));
+ ItemList.White_Dwarf_Shape_Extruder_Axe.set(
+ addItem(
+ whiteDwarfIDs++,
+ "White Dwarf Extruder Shape (Axe Head)",
+ "Ultra Strong Stellar Shape for making Axes"));
+ ItemList.White_Dwarf_Shape_Extruder_Hoe.set(
+ addItem(
+ whiteDwarfIDs++,
+ "White Dwarf Extruder Shape (Hoe Head)",
+ "Ultra Strong Stellar Shape for making Hoes"));
+ ItemList.White_Dwarf_Shape_Extruder_Hammer.set(
+ addItem(
+ whiteDwarfIDs++,
+ "White Dwarf Extruder Shape (Hammer Head)",
+ "Ultra Strong Stellar Shape for making Hammers"));
+ ItemList.White_Dwarf_Shape_Extruder_File.set(
+ addItem(
+ whiteDwarfIDs++,
+ "White Dwarf Extruder Shape (File Head)",
+ "Ultra Strong Stellar Shape for making Files"));
+ ItemList.White_Dwarf_Shape_Extruder_Saw.set(
+ addItem(
+ whiteDwarfIDs++,
+ "White Dwarf Extruder Shape (Saw Blade)",
+ "Ultra Strong Stellar Shape for making Saws"));
+ ItemList.White_Dwarf_Shape_Extruder_Gear.set(
+ addItem(
+ whiteDwarfIDs++,
+ "White Dwarf Extruder Shape (Gear)",
+ "Ultra Strong Stellar Shape for making Gears"));
+ ItemList.White_Dwarf_Shape_Extruder_Bottle.set(
+ addItem(
+ whiteDwarfIDs++,
+ "White Dwarf Extruder Shape (Bottle)",
+ "Ultra Strong Stellar Shape for making Bottles"));
+ ItemList.White_Dwarf_Shape_Extruder_Rotor.set(
+ addItem(whiteDwarfIDs++, "White Dwarf Extruder Shape (Rotor)", "Ultra Strong Stellar Shape for a Rotor"));
+ ItemList.White_Dwarf_Shape_Extruder_Small_Gear.set(
+ addItem(
+ whiteDwarfIDs++,
+ "White Dwarf Extruder Shape (Small Gear)",
+ "Ultra Strong Stellar Shape for a Small Gear"));
+ ItemList.White_Dwarf_Shape_Extruder_Turbine_Blade.set(
+ addItem(
+ whiteDwarfIDs++,
+ "White Dwarf Extruder Shape (Turbine Blade)",
+ "Ultra Strong Stellar Extruder Shape for a Turbine Blade"));
+ ItemList.White_Dwarf_Shape_Extruder_ToolHeadDrill.set(
+ addItem(
+ whiteDwarfIDs,
+ "White Dwarf Extruder Shape (Drill Head)",
+ "White Dwarf Extruder Shape for a Drill Head"));
+ }
+
+ @Override
+ public boolean doesShowInCreative(OrePrefixes aPrefix, Materials aMaterial, boolean aDoShowAllItems) {
+ return aDoShowAllItems || (aPrefix.toString()
+ .toLowerCase()
+ .contains("nanite"))
+ || (aPrefix.toString()
+ .toLowerCase()
+ .contains("rawore"));
+ }
+}
diff --git a/src/main/java/gregtech/common/items/GT_MetaGenerated_Item_98.java b/src/main/java/gregtech/common/items/GT_MetaGenerated_Item_98.java
new file mode 100644
index 0000000000..0dab2af2cf
--- /dev/null
+++ b/src/main/java/gregtech/common/items/GT_MetaGenerated_Item_98.java
@@ -0,0 +1,352 @@
+package gregtech.common.items;
+
+import java.util.Arrays;
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+import javax.annotation.Nullable;
+
+import net.minecraft.creativetab.CreativeTabs;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.IIcon;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidContainerRegistry;
+import net.minecraftforge.fluids.FluidRegistry;
+import net.minecraftforge.fluids.FluidStack;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Item;
+import gregtech.api.util.GT_LanguageManager;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_OreDictUnificator;
+import gregtech.api.util.GT_Util;
+import gregtech.api.util.GT_Utility;
+
+/** This class holds cells for non-GT fluids. */
+public class GT_MetaGenerated_Item_98 extends GT_MetaGenerated_Item {
+
+ public static GT_MetaGenerated_Item_98 INSTANCE;
+
+ /**
+ * Registered fluids.
+ *
+ * <p>
+ * When adding a fluid, don't forget to make sure that GregTech loads after the mod that adds that fluid!
+ *
+ * <p>
+ * In order to avoid breaking existing worlds, fluids must not have their IDs changed! The only safe modification
+ * that can be made to this enum is adding new fluids, or removing existing fluids. When removing fluids, maybe
+ * leave a comment mentioning the old ID, so that we don't re-use it for a new fluid.
+ */
+ public enum FluidCell {
+ // Next unused ID: 32
+
+ // GregTech
+ DRILLING_FLUID(5, "liquid_drillingfluid", CellType.REGULAR),
+ SQUID_INK(6, "squidink", CellType.SMALL),
+ BLUE_VITRIOL(22, "solution.bluevitriol", CellType.REGULAR),
+ NICKEL_SULFATE(23, "solution.nickelsulfate", CellType.REGULAR),
+ GREEN_VITRIOL(24, "solution.greenvitriol", CellType.REGULAR),
+ INDIUM_CONCENTRATE(25, "indiumconcentrate", CellType.REGULAR),
+ LEAD_ZINC_SOLUTION(26, "leadzincsolution", CellType.REGULAR),
+
+ // New Horizons Core Mod
+ UNKNOWN_NUTRIENT_AGAR(7, "unknownnutrientagar", CellType.REGULAR),
+ SEAWEED_BROTH(8, "seaweedbroth", CellType.REGULAR),
+ SUPER_HEAVY_RADOX(28, "superheavyradox", CellType.REGULAR),
+ HEAVY_RADOX(29, "heavyradox", CellType.REGULAR),
+ CRACKED_RADOX(30, "crackedradox", CellType.REGULAR),
+ LIGHT_RADOX(31, "lightradox", CellType.REGULAR),
+ SUPER_LIGHT_RADOX(9, "superlightradox", CellType.REGULAR),
+ SODIUM_POTASSIUM(18, "sodiumpotassium", CellType.REGULAR),
+ ENRICHED_BACTERIAL_SLUDGE(19, "enrichedbacterialsludge", CellType.REGULAR),
+ FERMENTED_BACTERIAL_SLUDGE(20, "fermentedbacterialsludge", CellType.REGULAR),
+ POLLUTION(21, "pollution", CellType.REGULAR),
+ XENOXENE(27, "xenoxene", CellType.REGULAR),
+
+ // BartWorks
+ ENZYME_SOLUTION(10, "enzymessollution", CellType.REGULAR),
+ ESCHERICHIA_COLI_FLUID(11, "escherichiakolifluid", CellType.REGULAR),
+ PENICILLIN(12, "penicillin", CellType.REGULAR),
+ FLUORESCENT_DNA(13, "fluorecentddna", CellType.REGULAR),
+ POLYMERASE(17, "polymerase", CellType.REGULAR),
+
+ // Good Generator
+ COMBUSTION_PROMOTER(14, "combustionpromotor", CellType.REGULAR),
+
+ // Galacticraft
+ BACTERIAL_SLUDGE(1, "bacterialsludge", CellType.REGULAR),
+
+ // Railcraft
+ STEAM(0, "steam", CellType.REGULAR),
+
+ // Gendustry
+ BACTERIA(15, "binnie.bacteria", CellType.REGULAR),
+ MUTAGEN(2, "mutagen", CellType.REGULAR),
+ LIQUID_DNA(16, "liquiddna", CellType.REGULAR),
+
+ // Tinker's Construct
+ LIQUID_ENDER(3, "ender", CellType.REGULAR),
+
+ // Hardcore Ender Expansion
+ ENDER_GOO(4, "endergoo", CellType.REGULAR),;
+
+ private final int mId;
+ /** This is the Forge internal fluid name. */
+ private final String mfluidName;
+
+ private final CellType mType;
+
+ @Nullable
+ private ItemStack mStack;
+
+ FluidCell(int aId, String aFluidName, CellType aType) {
+ mId = aId;
+ mfluidName = aFluidName;
+ mType = aType;
+ }
+
+ public int getId() {
+ return mId;
+ }
+
+ public String getFluidName() {
+ return mfluidName;
+ }
+
+ public CellType getDisplayType() {
+ return mType;
+ }
+
+ /**
+ * Get a copy of this stack with stack size 1.
+ * <p>
+ * Always returns non-null stack even if the fluid referenced doesn't exist, so don't assume it's always valid.
+ */
+ public ItemStack get() {
+ trySetStack();
+ return GT_Utility.copy(mStack);
+ }
+
+ /**
+ * Get a copy of this cell WITHOUT copy.
+ * <p>
+ * Always returns non-null stack even if the fluid referenced doesn't exist, so don't assume it's always valid.
+ * <p>
+ * Use with caution.
+ */
+ public ItemStack getNoCopy() {
+ trySetStack();
+ return mStack;
+ }
+
+ /**
+ * Get a copy of this cell with specified stack size.
+ * <p>
+ * Always returns non-null stack even if the fluid referenced doesn't exist, so don't assume it's always valid.
+ */
+ public ItemStack get(int aStackSize) {
+ trySetStack();
+ return GT_Utility.copyAmount(aStackSize, mStack);
+ }
+
+ private void trySetStack() {
+ if (mStack == null) {
+ mStack = new ItemStack(GT_MetaGenerated_Item_98.INSTANCE, 1, mId);
+ }
+ }
+ }
+
+ /** Cell type specifies the cell capacity, appearance, and item name format. */
+ private enum CellType {
+
+ REGULAR(1_000, OrePrefixes.cell),
+ SMALL(144, OrePrefixes.cell),
+ MOLTEN(144, OrePrefixes.cellMolten),
+ PLASMA(1_000, OrePrefixes.cellPlasma);
+
+ private final int capacity;
+ private final OrePrefixes prefix;
+
+ CellType(int capacity, OrePrefixes prefix) {
+ this.capacity = capacity;
+ this.prefix = prefix;
+ }
+ }
+
+ /** Struct class holding data that we need to properly handle a registered fluid cell item. */
+ private static class RegisteredFluidData {
+
+ private final short[] rgba;
+ private final IIconContainer iconContainer;
+
+ private RegisteredFluidData(short[] rgba, IIconContainer iconContainer) {
+ this.rgba = rgba;
+ this.iconContainer = iconContainer;
+ }
+ }
+
+ /**
+ * Map of ID to registered fluid data.
+ *
+ * <p>
+ * Only contains IDs that were successfully registered.
+ */
+ private final Map<Integer, RegisteredFluidData> registeredFluidDataMap;
+
+ private final EnumMap<CellType, IIconContainer> iconContainerMap;
+
+ private GT_MetaGenerated_Item_98() {
+ // For some reason, fluid cells will be rendered only if the metadata ID is less than the
+ // offset. So we will specify maximum offset here.
+ // See: GT_MetaGenerated_Item_Renderer.java
+ super("metaitem.98", (short) 32766, (short) 0);
+
+ registeredFluidDataMap = new HashMap<>();
+ iconContainerMap = new EnumMap<>(CellType.class);
+ }
+
+ /**
+ * Loading needs to happen after the fluids we need have been registered, which means during post-load. However,
+ * cell icons seem to be deleted some time between load and post-load, so we must pre-cache them.
+ */
+ public static synchronized void preInit() {
+ if (INSTANCE == null) INSTANCE = new GT_MetaGenerated_Item_98();
+
+ // We'll just steal the icons from Water. They are all the same anyway (except _NULL is broken for cells).
+ for (CellType cellType : CellType.values()) {
+ IIconContainer iconContainer = Materials.Water.mIconSet.mTextures[cellType.prefix.mTextureIndex];
+ INSTANCE.iconContainerMap.put(cellType, iconContainer);
+ }
+ }
+
+ public static synchronized void init() {
+ INSTANCE.createAllItems();
+ INSTANCE.registerOreDict();
+ }
+
+ private void createAllItems() {
+ for (FluidCell tCell : FluidCell.values()) {
+ tryToInitialize(tCell);
+ }
+
+ // We're not going to use these BitSets, so clear them to save memory.
+ mEnabledItems.clear();
+ mVisibleItems.clear();
+ }
+
+ private void tryToInitialize(FluidCell aCell) {
+ final boolean isStackAlreadySet = aCell.mStack != null;
+
+ int id = aCell.getId();
+ String fluidName = aCell.getFluidName();
+ CellType cellType = aCell.getDisplayType();
+
+ // We'll check for ID uniqueness. Better to throw an exception than silently overwrite some
+ // fluid cells with other fluids due to ID collision.
+ if (registeredFluidDataMap.containsKey(id)) {
+ throw new IllegalStateException("Got ID collision for ID: " + id);
+ }
+
+ aCell.trySetStack();
+
+ Fluid fluid = FluidRegistry.getFluid(fluidName);
+ if (fluid == null) {
+ // The fluid is not guaranteed to exist.
+ // These fluids are non-GT fluids, so the mod may not be present.
+ if (isStackAlreadySet) {
+ throw new RuntimeException(
+ "Cell item for fluid " + fluidName
+ + " has already been created, but the fluid doesn't exist during postload");
+ } else {
+ // fluid doesn't exist and this item has not been referenced
+ return;
+ }
+ }
+
+ FluidStack fluidStack = new FluidStack(fluid, cellType.capacity);
+
+ ItemStack emptyCell = ItemList.Cell_Empty.get(1L);
+ FluidContainerRegistry
+ .registerFluidContainer(new FluidContainerRegistry.FluidContainerData(fluidStack, aCell.mStack, emptyCell));
+
+ GT_LanguageManager.addStringLocalization(
+ getUnlocalizedName(aCell.mStack) + ".name",
+ cellType.prefix.mLocalizedMaterialPre + fluid.getLocalizedName(fluidStack)
+ + cellType.prefix.mLocalizedMaterialPost);
+
+ int color = fluid.getColor();
+ short[] rgba = GT_Util.getRGBaArray(color);
+
+ registeredFluidDataMap.put(id, new RegisteredFluidData(rgba, iconContainerMap.get(cellType)));
+ }
+
+ private void registerOreDict() {
+ // The GregTech ore dictionary requires an entry in the Materials enum, and since the whole
+ // point of this class is to add cell items for non-GregTech fluids, the vast majority of
+ // cell items won't have an associated material. So only a rare few cell items will need to
+ // be registered.
+
+ // Register IC2 steam cell and Railcraft steam cell as synonyms.
+ // There is no steam material, so we'll use Water.cellMolten instead.
+ GT_OreDictUnificator.add(OrePrefixes.cellMolten, Materials.Water, GT_ModHandler.getIC2Item("steamCell", 1L));
+ GT_OreDictUnificator.add(OrePrefixes.cellMolten, Materials.Water, FluidCell.STEAM.getNoCopy());
+ }
+
+ @Override
+ public short[] getRGBa(ItemStack aStack) {
+ RegisteredFluidData fluidData = registeredFluidDataMap.get(aStack.getItemDamage());
+ if (fluidData == null) {
+ return Materials._NULL.mRGBa;
+ }
+
+ return fluidData.rgba;
+ }
+
+ @Override
+ public ItemStack getContainerItem(ItemStack aStack) {
+ return ItemList.Cell_Empty.get(1L);
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void getSubItems(Item aItem, CreativeTabs aCreativeTab, List<ItemStack> aList) {
+ Arrays.stream(FluidCell.values())
+ .filter(fluid -> FluidRegistry.getFluid(fluid.getFluidName()) != null)
+ .map(FluidCell::get)
+ .filter(Objects::nonNull)
+ .forEach(aList::add);
+ }
+
+ @Override
+ public final IIcon getIconFromDamage(int aMetaData) {
+ IIconContainer iconContainer = getIconContainer(aMetaData);
+ if (iconContainer != null) {
+ return iconContainer.getIcon();
+ }
+ return null;
+ }
+
+ @Override
+ public IIconContainer getIconContainer(int aMetaData) {
+ RegisteredFluidData fluidData = registeredFluidDataMap.get(aMetaData);
+ if (fluidData == null) {
+ return null;
+ }
+ return fluidData.iconContainer;
+ }
+
+ @Override
+ public int getItemStackLimit(ItemStack aStack) {
+ return 64;
+ }
+}
diff --git a/src/main/java/gregtech/common/items/GT_MetaGenerated_Item_99.java b/src/main/java/gregtech/common/items/GT_MetaGenerated_Item_99.java
new file mode 100644
index 0000000000..08d6f23164
--- /dev/null
+++ b/src/main/java/gregtech/common/items/GT_MetaGenerated_Item_99.java
@@ -0,0 +1,214 @@
+package gregtech.common.items;
+
+import static gregtech.api.enums.GT_Values.M;
+import static gregtech.api.enums.OrePrefixes.cellMolten;
+
+import java.util.BitSet;
+import java.util.List;
+
+import net.minecraft.creativetab.CreativeTabs;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.IIcon;
+
+import com.google.common.collect.ImmutableList;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.enums.SubTag;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Item;
+import gregtech.api.util.GT_LanguageManager;
+import gregtech.api.util.GT_OreDictUnificator;
+
+public class GT_MetaGenerated_Item_99 extends GT_MetaGenerated_Item {
+
+ public static GT_MetaGenerated_Item_99 INSTANCE;
+
+ /**
+ * Ore prefixes appear in this list in the order in which they will be assigned ID blocks.
+ *
+ * <p>
+ * In order to avoid breaking existing worlds, the entries in this list must not be re-ordered! The only safe
+ * modification that can be made to this list is adding new entries to the end.
+ */
+ private static final ImmutableList<OrePrefixes> CRACKED_CELL_TYPES = ImmutableList.of(
+ OrePrefixes.cellHydroCracked1,
+ OrePrefixes.cellHydroCracked2,
+ OrePrefixes.cellHydroCracked3,
+ OrePrefixes.cellSteamCracked1,
+ OrePrefixes.cellSteamCracked2,
+ OrePrefixes.cellSteamCracked3);
+
+ private static final int NUM_CRACKED_CELL_TYPES = CRACKED_CELL_TYPES.size();
+
+ /**
+ * Assignment of metadata IDs: 0 - 999: Molten cells 10_000 - 15_999: Cracked fluid cells (# IDs used is
+ * NUM_CRACKED_CELL_TYPES * 1_000; update this if you add any)
+ */
+ private final BitSet enabled = new BitSet();
+
+ public GT_MetaGenerated_Item_99() {
+ super("metaitem.99", (short) (10_000 + NUM_CRACKED_CELL_TYPES * 1_000), (short) 0);
+
+ INSTANCE = this;
+
+ for (Materials tMaterial : GregTech_API.sGeneratedMaterials) {
+ if (tMaterial == null || tMaterial.mMetaItemSubID < 0 || tMaterial.mMetaItemSubID >= 1_000) {
+ continue;
+ }
+
+ if ((tMaterial.contains(SubTag.SMELTING_TO_FLUID)) && (!tMaterial.contains(SubTag.NO_SMELTING))
+ && !tMaterial.contains(SubTag.SMELTING_TO_GEM)) {
+ registerMolten(tMaterial, tMaterial.mMetaItemSubID);
+ if (tMaterial.mSmeltInto != tMaterial && tMaterial.mSmeltInto.mMetaItemSubID >= 0
+ && tMaterial.mSmeltInto.mMetaItemSubID < 1_000) {
+ registerMolten(tMaterial.mSmeltInto, tMaterial.mSmeltInto.mMetaItemSubID);
+ }
+ }
+
+ if (tMaterial.canBeCracked()) {
+ registerCracked(tMaterial, tMaterial.mMetaItemSubID);
+ }
+ }
+
+ // We're not going to use these BitSets, so clear them to save memory.
+ mEnabledItems.clear();
+ mVisibleItems.clear();
+ }
+
+ private void registerMolten(Materials tMaterial, int i) {
+ ItemStack tStack = new ItemStack(this, 1, i);
+ enabled.set(i);
+
+ GT_LanguageManager.addStringLocalization(
+ getUnlocalizedName(tStack) + ".name",
+ cellMolten.getDefaultLocalNameFormatForItem(tMaterial));
+ GT_LanguageManager.addStringLocalization(
+ getUnlocalizedName(tStack) + ".tooltip",
+ tMaterial.getToolTip(cellMolten.mMaterialAmount / M));
+
+ if (cellMolten.mIsUnificatable) {
+ GT_OreDictUnificator.set(cellMolten, tMaterial, tStack);
+ } else {
+ GT_OreDictUnificator.registerOre(cellMolten.get(tMaterial), tStack);
+ }
+ }
+
+ private void registerCracked(Materials tMaterial, int i) {
+ int offset = 10_000;
+ for (OrePrefixes prefix : CRACKED_CELL_TYPES) {
+ ItemStack tStack = new ItemStack(this, 1, offset + i);
+ enabled.set(offset + i);
+
+ GT_LanguageManager.addStringLocalization(
+ getUnlocalizedName(tStack) + ".name",
+ prefix.getDefaultLocalNameFormatForItem(tMaterial));
+ GT_LanguageManager.addStringLocalization(
+ getUnlocalizedName(tStack) + ".tooltip",
+ tMaterial.getToolTip(prefix.mMaterialAmount / M));
+
+ if (prefix.mIsUnificatable) {
+ GT_OreDictUnificator.set(prefix, tMaterial, tStack);
+ } else {
+ GT_OreDictUnificator.registerOre(prefix.get(tMaterial), tStack);
+ }
+
+ offset += 1_000;
+ }
+ }
+
+ /** Returns null for item damage out of bounds. */
+ private Materials getMaterial(int damage) {
+ if (damage < 0) {
+ return null;
+ }
+ return GregTech_API.sGeneratedMaterials[damage % 1_000];
+ }
+
+ /** Returns null for item damage out of bounds. */
+ private OrePrefixes getOrePrefix(int damage) {
+ if (damage < 0) {
+ return null;
+ } else if (damage < 1_000) {
+ return cellMolten;
+ } else if (damage >= 10_000 && damage < 10_000 + (NUM_CRACKED_CELL_TYPES * 1_000)) {
+ return CRACKED_CELL_TYPES.get((damage / 1_000) - 10);
+ }
+ return null;
+ }
+
+ @Override
+ public short[] getRGBa(ItemStack aStack) {
+ OrePrefixes prefix = getOrePrefix(aStack.getItemDamage());
+ Materials material = getMaterial(aStack.getItemDamage());
+ if (material == null) {
+ material = Materials._NULL;
+ }
+
+ if (prefix == cellMolten) {
+ return material.mMoltenRGBa;
+ } else {
+ return material.mRGBa;
+ }
+ }
+
+ @Override
+ public String getItemStackDisplayName(ItemStack aStack) {
+ String aName = super.getItemStackDisplayName(aStack);
+ Materials material = getMaterial(aStack.getItemDamage());
+ if (material != null) {
+ return material.getLocalizedNameForItem(aName);
+ }
+ return aName;
+ }
+
+ @Override
+ public ItemStack getContainerItem(ItemStack aStack) {
+ OrePrefixes prefix = getOrePrefix(aStack.getItemDamage());
+ if (prefix != null) {
+ return prefix.mContainerItem;
+ }
+ return null;
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void getSubItems(Item aItem, CreativeTabs aCreativeTab, List<ItemStack> aList) {
+ enabled.stream()
+ .mapToObj(i -> new ItemStack(this, 1, i))
+ .forEach(aList::add);
+ }
+
+ @Override
+ public final IIcon getIconFromDamage(int aMetaData) {
+ IIconContainer iconContainer = getIconContainer(aMetaData);
+ if (iconContainer != null) {
+ return iconContainer.getIcon();
+ }
+ return null;
+ }
+
+ @Override
+ public IIconContainer getIconContainer(int aMetaData) {
+ Materials material = getMaterial(aMetaData);
+ OrePrefixes prefix = getOrePrefix(aMetaData);
+ if (material != null && prefix != null) {
+ return material.mIconSet.mTextures[prefix.mTextureIndex];
+ }
+ return null;
+ }
+
+ @Override
+ public int getItemStackLimit(ItemStack aStack) {
+ OrePrefixes prefix = getOrePrefix(aStack.getItemDamage());
+ if (prefix != null) {
+ return prefix.mDefaultStackSize;
+ } else {
+ return 64;
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/items/GT_MetaGenerated_Tool_01.java b/src/main/java/gregtech/common/items/GT_MetaGenerated_Tool_01.java
new file mode 100644
index 0000000000..309507f2a9
--- /dev/null
+++ b/src/main/java/gregtech/common/items/GT_MetaGenerated_Tool_01.java
@@ -0,0 +1,824 @@
+package gregtech.common.items;
+
+import net.minecraft.init.Blocks;
+import net.minecraft.init.Items;
+import net.minecraft.item.ItemStack;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.ConfigCategories;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.enums.TC_Aspects;
+import gregtech.api.enums.ToolDictNames;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_OreDictUnificator;
+import gregtech.common.tools.GT_Tool_Axe;
+import gregtech.common.tools.GT_Tool_BranchCutter;
+import gregtech.common.tools.GT_Tool_ButcheryKnife;
+import gregtech.common.tools.GT_Tool_BuzzSaw;
+import gregtech.common.tools.GT_Tool_Chainsaw_HV;
+import gregtech.common.tools.GT_Tool_Chainsaw_LV;
+import gregtech.common.tools.GT_Tool_Chainsaw_MV;
+import gregtech.common.tools.GT_Tool_Crowbar;
+import gregtech.common.tools.GT_Tool_Drill_HV;
+import gregtech.common.tools.GT_Tool_Drill_LV;
+import gregtech.common.tools.GT_Tool_Drill_MV;
+import gregtech.common.tools.GT_Tool_File;
+import gregtech.common.tools.GT_Tool_HardHammer;
+import gregtech.common.tools.GT_Tool_Hoe;
+import gregtech.common.tools.GT_Tool_JackHammer;
+import gregtech.common.tools.GT_Tool_Knife;
+import gregtech.common.tools.GT_Tool_Mortar;
+import gregtech.common.tools.GT_Tool_Pickaxe;
+import gregtech.common.tools.GT_Tool_Plow;
+import gregtech.common.tools.GT_Tool_Plunger;
+import gregtech.common.tools.GT_Tool_RollingPin;
+import gregtech.common.tools.GT_Tool_Saw;
+import gregtech.common.tools.GT_Tool_Scoop;
+import gregtech.common.tools.GT_Tool_Screwdriver;
+import gregtech.common.tools.GT_Tool_Screwdriver_LV;
+import gregtech.common.tools.GT_Tool_Sense;
+import gregtech.common.tools.GT_Tool_Shovel;
+import gregtech.common.tools.GT_Tool_SoftHammer;
+import gregtech.common.tools.GT_Tool_Soldering_Iron;
+import gregtech.common.tools.GT_Tool_Sword;
+import gregtech.common.tools.GT_Tool_Turbine_Huge;
+import gregtech.common.tools.GT_Tool_Turbine_Large;
+import gregtech.common.tools.GT_Tool_Turbine_Normal;
+import gregtech.common.tools.GT_Tool_Turbine_Small;
+import gregtech.common.tools.GT_Tool_UniversalSpade;
+import gregtech.common.tools.GT_Tool_WireCutter;
+import gregtech.common.tools.GT_Tool_Wrench;
+import gregtech.common.tools.GT_Tool_Wrench_HV;
+import gregtech.common.tools.GT_Tool_Wrench_LV;
+import gregtech.common.tools.GT_Tool_Wrench_MV;
+import gregtech.common.tools.pocket.GT_Tool_Pocket_BranchCutter;
+import gregtech.common.tools.pocket.GT_Tool_Pocket_File;
+import gregtech.common.tools.pocket.GT_Tool_Pocket_Knife;
+import gregtech.common.tools.pocket.GT_Tool_Pocket_Multitool;
+import gregtech.common.tools.pocket.GT_Tool_Pocket_Saw;
+import gregtech.common.tools.pocket.GT_Tool_Pocket_Screwdriver;
+import gregtech.common.tools.pocket.GT_Tool_Pocket_WireCutter;
+
+public class GT_MetaGenerated_Tool_01 extends GT_MetaGenerated_Tool {
+
+ public static final short SWORD = 0;
+ public static final short PICKAXE = 2;
+ public static final short SHOVEL = 4;
+ public static final short AXE = 6;
+ public static final short HOE = 8;
+ public static final short SAW = 10;
+ public static final short HARDHAMMER = 12;
+ public static final short SOFTMALLET = 14;
+
+ @Deprecated
+ public static final short SOFTHAMMER = SOFTMALLET;
+
+ public static final short WRENCH = 16;
+ public static final short FILE = 18;
+ public static final short CROWBAR = 20;
+ public static final short SCREWDRIVER = 22;
+ public static final short MORTAR = 24;
+ public static final short WIRECUTTER = 26;
+ public static final short SCOOP = 28;
+ public static final short BRANCHCUTTER = 30;
+ public static final short UNIVERSALSPADE = 32;
+ public static final short KNIFE = 34;
+ public static final short BUTCHERYKNIFE = 36;
+
+ @Deprecated
+ public static final short SICKLE = 38;
+
+ public static final short SENSE = 40;
+ public static final short PLOW = 42;
+ public static final short PLUNGER = 44;
+ public static final short ROLLING_PIN = 46;
+ public static final short DRILL_LV = 100;
+ public static final short DRILL_MV = 102;
+ public static final short DRILL_HV = 104;
+ public static final short CHAINSAW_LV = 110;
+ public static final short CHAINSAW_MV = 112;
+ public static final short CHAINSAW_HV = 114;
+ public static final short WRENCH_LV = 120;
+ public static final short WRENCH_MV = 122;
+ public static final short WRENCH_HV = 124;
+ public static final short JACKHAMMER = 130;
+ public static final short BUZZSAW_LV = 140;
+ public static final short BUZZSAW_MV = 142;
+ public static final short BUZZSAW_HV = 144;
+
+ @Deprecated
+ public static final short BUZZSAW = BUZZSAW_LV;
+
+ public static final short SCREWDRIVER_LV = 150;
+ public static final short SCREWDRIVER_MV = 152;
+ public static final short SCREWDRIVER_HV = 154;
+ public static final short SOLDERING_IRON_LV = 160;
+ public static final short SOLDERING_IRON_MV = 162;
+ public static final short SOLDERING_IRON_HV = 164;
+ public static final short TURBINE_SMALL = 170;
+ public static final short TURBINE = 172;
+ public static final short TURBINE_LARGE = 174;
+ public static final short TURBINE_HUGE = 176;
+
+ @Deprecated
+ public static final short TURBINE_BLADE = 178;
+
+ public static final short POCKET_MULTITOOL = 180;
+ public static final short POCKET_BRANCHCUTTER = 182;
+ public static final short POCKET_FILE = 184;
+ public static final short POCKET_KNIFE = 186;
+ public static final short POCKET_SAW = 188;
+ public static final short POCKET_SCREWDRIVER = 190;
+ public static final short POCKET_WIRECUTTER = 192;
+
+ public static GT_MetaGenerated_Tool_01 INSTANCE;
+
+ public GT_MetaGenerated_Tool_01() {
+ super("metatool.01");
+ INSTANCE = this;
+ addTool(
+ SWORD,
+ "Sword",
+ "",
+ new GT_Tool_Sword(),
+ ToolDictNames.craftingToolSword,
+ ToolDictNames.craftingToolBlade,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.INSTRUMENTUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TELUM, 4L));
+ addTool(
+ PICKAXE,
+ "Pickaxe",
+ "",
+ new GT_Tool_Pickaxe(),
+ ToolDictNames.craftingToolPickaxe,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.INSTRUMENTUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.PERFODIO, 4L));
+ addTool(
+ SHOVEL,
+ "Shovel",
+ "",
+ new GT_Tool_Shovel(),
+ ToolDictNames.craftingToolShovel,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.INSTRUMENTUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.PERFODIO, 4L));
+ addTool(
+ AXE,
+ "Axe",
+ "",
+ new GT_Tool_Axe(),
+ ToolDictNames.craftingToolAxe,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.INSTRUMENTUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 2L));
+ addTool(
+ HOE,
+ "Hoe",
+ "",
+ new GT_Tool_Hoe(),
+ ToolDictNames.craftingToolHoe,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.INSTRUMENTUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MESSIS, 4L));
+ addTool(
+ SAW,
+ "Saw",
+ "Can also harvest Ice",
+ new GT_Tool_Saw(),
+ ToolDictNames.craftingToolSaw,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.INSTRUMENTUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 2L));
+ GregTech_API.registerTool(
+ addTool(
+ HARDHAMMER,
+ "Hammer",
+ "Crushes Ores instead of harvesting them",
+ new GT_Tool_HardHammer(),
+ ToolDictNames.craftingToolHardHammer,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.INSTRUMENTUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FABRICO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 2L)),
+ GregTech_API.sHardHammerList);
+ GregTech_API.registerTool(
+ addTool(
+ SOFTMALLET,
+ "Soft Mallet",
+ "",
+ new GT_Tool_SoftHammer(),
+ ToolDictNames.craftingToolSoftHammer,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.INSTRUMENTUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.LIMUS, 4L)),
+ GregTech_API.sSoftHammerList);
+ GregTech_API.registerTool(
+ addTool(
+ WRENCH,
+ "Wrench",
+ "Hold Leftclick to dismantle Machines",
+ new GT_Tool_Wrench(),
+ ToolDictNames.craftingToolWrench,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.INSTRUMENTUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 2L)),
+ GregTech_API.sWrenchList);
+ addTool(
+ FILE,
+ "File",
+ "",
+ new GT_Tool_File(),
+ ToolDictNames.craftingToolFile,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.INSTRUMENTUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FABRICO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 2L));
+ GregTech_API.registerTool(
+ addTool(
+ CROWBAR,
+ "Crowbar",
+ "Dismounts Covers and Rotates Rails",
+ new GT_Tool_Crowbar(),
+ ToolDictNames.craftingToolCrowbar,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.INSTRUMENTUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FABRICO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TELUM, 2L)),
+ GregTech_API.sCrowbarList);
+ GregTech_API.registerTool(
+ addTool(
+ SCREWDRIVER,
+ "Screwdriver",
+ "Adjusts Covers and Machines",
+ new GT_Tool_Screwdriver(),
+ ToolDictNames.craftingToolScrewdriver,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.INSTRUMENTUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FABRICO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 2L)),
+ GregTech_API.sScrewdriverList);
+ addTool(
+ MORTAR,
+ "Mortar",
+ "",
+ new GT_Tool_Mortar(),
+ ToolDictNames.craftingToolMortar,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.INSTRUMENTUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FABRICO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.PERDITIO, 2L));
+ GregTech_API.registerTool(
+ addTool(
+ WIRECUTTER,
+ "Wire Cutter",
+ "",
+ new GT_Tool_WireCutter(),
+ ToolDictNames.craftingToolWireCutter,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.INSTRUMENTUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FABRICO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 2L)),
+ GregTech_API.sWireCutterList);
+ addTool(
+ SCOOP,
+ "Scoop",
+ "",
+ new GT_Tool_Scoop(),
+ ToolDictNames.craftingToolScoop,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.INSTRUMENTUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.BESTIA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.PANNUS, 2L));
+ addTool(
+ BRANCHCUTTER,
+ "Branch Cutter",
+ "",
+ new GT_Tool_BranchCutter(),
+ ToolDictNames.craftingToolBranchCutter,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.INSTRUMENTUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 2L));
+ GregTech_API.registerTool(
+ addTool(
+ UNIVERSALSPADE,
+ "Universal Spade",
+ "",
+ new GT_Tool_UniversalSpade(),
+ ToolDictNames.craftingToolBlade,
+ ToolDictNames.craftingToolShovel,
+ ToolDictNames.craftingToolCrowbar,
+ ToolDictNames.craftingToolSaw,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.INSTRUMENTUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TELUM, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METO, 1L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FABRICO, 1L)),
+ GregTech_API.sCrowbarList);
+ addTool(
+ KNIFE,
+ "Knife",
+ "",
+ new GT_Tool_Knife(),
+ ToolDictNames.craftingToolBlade,
+ ToolDictNames.craftingToolKnife,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.INSTRUMENTUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.TELUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.CORPUS, 2L));
+ addTool(
+ BUTCHERYKNIFE,
+ "Butchery Knife",
+ "Has a slow Attack Rate",
+ new GT_Tool_ButcheryKnife(),
+ ToolDictNames.craftingToolBlade,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.INSTRUMENTUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FABRICO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.CORPUS, 4L));
+
+ addTool(
+ SENSE,
+ "Sense",
+ "Because a Scythe doesn't make Sense",
+ new GT_Tool_Sense(),
+ ToolDictNames.craftingToolBlade,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.INSTRUMENTUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.HERBA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MORTUUS, 2L));
+ addTool(
+ PLOW,
+ "Plow",
+ "Used to get rid of Snow",
+ new GT_Tool_Plow(),
+ ToolDictNames.craftingToolPlow,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.INSTRUMENTUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.GELUM, 2L));
+ addTool(
+ PLUNGER,
+ "Plunger",
+ "",
+ new GT_Tool_Plunger(),
+ ToolDictNames.craftingToolPlunger,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.INSTRUMENTUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.VACUOS, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ITER, 2L));
+ addTool(
+ ROLLING_PIN,
+ "Rolling Pin",
+ "",
+ new GT_Tool_RollingPin(),
+ ToolDictNames.craftingToolRollingPin,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.INSTRUMENTUM, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.LIMUS, 4L));
+
+ addTool(
+ DRILL_LV,
+ "Drill (LV)",
+ "",
+ new GT_Tool_Drill_LV(),
+ ToolDictNames.craftingToolMiningDrill,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.PERFODIO, 4L));
+ addTool(
+ DRILL_MV,
+ "Drill (MV)",
+ "",
+ new GT_Tool_Drill_MV(),
+ ToolDictNames.craftingToolMiningDrill,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.PERFODIO, 4L));
+ addTool(
+ DRILL_HV,
+ "Drill (HV)",
+ "",
+ new GT_Tool_Drill_HV(),
+ ToolDictNames.craftingToolMiningDrill,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.PERFODIO, 4L));
+ addTool(
+ CHAINSAW_LV,
+ "Chainsaw (LV)",
+ "Can also harvest Ice",
+ new GT_Tool_Chainsaw_LV(),
+ ToolDictNames.craftingToolSaw,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 2L));
+ addTool(
+ CHAINSAW_MV,
+ "Chainsaw (MV)",
+ "Can also harvest Ice",
+ new GT_Tool_Chainsaw_MV(),
+ ToolDictNames.craftingToolSaw,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 2L));
+ addTool(
+ CHAINSAW_HV,
+ "Chainsaw (HV)",
+ "Can also harvest Ice",
+ new GT_Tool_Chainsaw_HV(),
+ ToolDictNames.craftingToolSaw,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.METO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 2L));
+ GregTech_API.registerTool(
+ addTool(
+ WRENCH_LV,
+ "Wrench (LV)",
+ "Hold Left Button to dismantle Machines",
+ new GT_Tool_Wrench_LV(),
+ ToolDictNames.craftingToolWrench,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 2L)),
+ GregTech_API.sWrenchList);
+ GregTech_API.registerTool(
+ addTool(
+ WRENCH_MV,
+ "Wrench (MV)",
+ "Hold Left Button to dismantle Machines",
+ new GT_Tool_Wrench_MV(),
+ ToolDictNames.craftingToolWrench,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 2L)),
+ GregTech_API.sWrenchList);
+ GregTech_API.registerTool(
+ addTool(
+ WRENCH_HV,
+ "Wrench (HV)",
+ "Hold Left Button to dismantle Machines",
+ new GT_Tool_Wrench_HV(),
+ ToolDictNames.craftingToolWrench,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 4L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 2L)),
+ GregTech_API.sWrenchList);
+ GregTech_API.registerTool(
+ addTool(
+ JACKHAMMER,
+ "JackHammer (HV)",
+ "Breaks Rocks into pieces",
+ new GT_Tool_JackHammer(),
+ ToolDictNames.craftingToolJackHammer,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.PERFODIO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.PERDITIO, 2L)),
+ GregTech_API.sJackhammerList);
+ addTool(
+ BUZZSAW_LV,
+ "Buzzsaw (LV)",
+ "Not suitable for harvesting Blocks",
+ new GT_Tool_BuzzSaw(),
+ ToolDictNames.craftingToolSaw,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FABRICO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 2L));
+ addTool(
+ BUZZSAW_MV,
+ "Buzzsaw (MV)",
+ "Not suitable for harvesting Blocks",
+ new GT_Tool_BuzzSaw(),
+ ToolDictNames.craftingToolSaw,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FABRICO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 2L));
+ addTool(
+ BUZZSAW_HV,
+ "Buzzsaw (HV)",
+ "Not suitable for harvesting Blocks",
+ new GT_Tool_BuzzSaw(),
+ ToolDictNames.craftingToolSaw,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FABRICO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ARBOR, 2L));
+ GregTech_API.registerTool(
+ addTool(
+ SCREWDRIVER_LV,
+ "Screwdriver (LV)",
+ "Adjusts Covers and Machines",
+ new GT_Tool_Screwdriver_LV(),
+ ToolDictNames.craftingToolScrewdriver,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FABRICO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 2L)),
+ GregTech_API.sScrewdriverList);
+ GregTech_API.registerTool(
+ addTool(
+ SCREWDRIVER_MV,
+ "Screwdriver (MV)",
+ "Adjusts Covers and Machines",
+ new GT_Tool_Screwdriver_LV(),
+ ToolDictNames.craftingToolScrewdriver,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FABRICO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 2L)),
+ GregTech_API.sScrewdriverList);
+ GregTech_API.registerTool(
+ addTool(
+ SCREWDRIVER_HV,
+ "Screwdriver (HV)",
+ "Adjusts Covers and Machines",
+ new GT_Tool_Screwdriver_LV(),
+ ToolDictNames.craftingToolScrewdriver,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FABRICO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 2L)),
+ GregTech_API.sScrewdriverList);
+ GregTech_API.registerTool(
+ addTool(
+ SOLDERING_IRON_LV,
+ "Soldering Iron (LV)",
+ "Fixes burned out Circuits. Needs soldering materials in inventory.",
+ new GT_Tool_Soldering_Iron(),
+ ToolDictNames.craftingToolSolderingIron,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FABRICO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 2L)),
+ GregTech_API.sSolderingToolList);
+ GregTech_API.registerTool(
+ addTool(
+ SOLDERING_IRON_MV,
+ "Soldering Iron (MV)",
+ "Fixes burned out Circuits. Needs soldering materials in inventory.",
+ new GT_Tool_Soldering_Iron(),
+ ToolDictNames.craftingToolSolderingIron,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FABRICO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 2L)),
+ GregTech_API.sSolderingToolList);
+ GregTech_API.registerTool(
+ addTool(
+ SOLDERING_IRON_HV,
+ "Soldering Iron (HV)",
+ "Fixes burned out Circuits. Needs soldering materials in inventory.",
+ new GT_Tool_Soldering_Iron(),
+ ToolDictNames.craftingToolSolderingIron,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.MACHINA, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FABRICO, 2L),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 2L)),
+ GregTech_API.sSolderingToolList);
+
+ addTool(TURBINE_SMALL, "Small Turbine", "Turbine Rotors for your power station", new GT_Tool_Turbine_Small());
+ addTool(TURBINE, "Turbine", "Turbine Rotors for your power station", new GT_Tool_Turbine_Normal());
+ addTool(TURBINE_LARGE, "Large Turbine", "Turbine Rotors for your power station", new GT_Tool_Turbine_Large());
+ addTool(TURBINE_HUGE, "Huge Turbine", "Turbine Rotors for your power station", new GT_Tool_Turbine_Huge());
+
+ addTool(
+ POCKET_MULTITOOL,
+ "Pocket Multitool",
+ "6 useful Tools in one!",
+ new GT_Tool_Pocket_Multitool(POCKET_KNIFE),
+ null,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.INSTRUMENTUM, 6),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FABRICO, 3),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 3));
+ addTool(
+ POCKET_KNIFE,
+ "Pocket Multitool (Knife)",
+ "",
+ new GT_Tool_Pocket_Knife(POCKET_SAW),
+ ToolDictNames.craftingToolKnife,
+ ToolDictNames.craftingToolBlade,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.INSTRUMENTUM, 6),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FABRICO, 3),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 3));
+ addTool(
+ POCKET_SAW,
+ "Pocket Multitool (Saw)",
+ "Can also harvest Ice",
+ new GT_Tool_Pocket_Saw(POCKET_FILE),
+ ToolDictNames.craftingToolSaw,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.INSTRUMENTUM, 6),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FABRICO, 3),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 3));
+ addTool(
+ POCKET_FILE,
+ "Pocket Multitool (File)",
+ "",
+ new GT_Tool_Pocket_File(POCKET_SCREWDRIVER),
+ ToolDictNames.craftingToolFile,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.INSTRUMENTUM, 6),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FABRICO, 3),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 3));
+ GregTech_API.registerTool(
+ addTool(
+ POCKET_SCREWDRIVER,
+ "Pocket Multitool (Screwdriver)",
+ "Adjusts Covers and Machines",
+ new GT_Tool_Pocket_Screwdriver(POCKET_WIRECUTTER),
+ ToolDictNames.craftingToolScrewdriver,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.INSTRUMENTUM, 6),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FABRICO, 3),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 3)),
+ GregTech_API.sScrewdriverList);
+ GregTech_API.registerTool(
+ addTool(
+ POCKET_WIRECUTTER,
+ "Pocket Multitool (Wire Cutter)",
+ "",
+ new GT_Tool_Pocket_WireCutter(POCKET_BRANCHCUTTER),
+ ToolDictNames.craftingToolWireCutter,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.INSTRUMENTUM, 6),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FABRICO, 3),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 3)),
+ GregTech_API.sWireCutterList);
+ addTool(
+ POCKET_BRANCHCUTTER,
+ "Pocket Multitool (Branch Cutter)",
+ "",
+ new GT_Tool_Pocket_BranchCutter(POCKET_MULTITOOL),
+ ToolDictNames.craftingToolBranchCutter,
+ new TC_Aspects.TC_AspectStack(TC_Aspects.INSTRUMENTUM, 6),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.FABRICO, 3),
+ new TC_Aspects.TC_AspectStack(TC_Aspects.ORDO, 3));
+
+ GT_ModHandler.addCraftingRecipe(
+ INSTANCE.getToolWithStats(MORTAR, 1, Materials.Flint, Materials.Stone, null),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { " I ", "SIS", "SSS", 'I', new ItemStack(Items.flint, 1), 'S', OrePrefixes.stone });
+ GT_ModHandler.addCraftingRecipe(
+ INSTANCE.getToolWithStats(MORTAR, 1, Materials.Bronze, Materials.Stone, null),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { " I ", "SIS", "SSS", 'I', OrePrefixes.ingot.get(Materials.Bronze), 'S', OrePrefixes.stone });
+ GT_ModHandler.addCraftingRecipe(
+ INSTANCE.getToolWithStats(MORTAR, 1, Materials.Iron, Materials.Stone, null),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { " I ", "SIS", "SSS", 'I', OrePrefixes.ingot.get(Materials.Iron), 'S', OrePrefixes.stone });
+ GT_ModHandler.addCraftingRecipe(
+ INSTANCE.getToolWithStats(MORTAR, 1, Materials.Steel, Materials.Stone, null),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { " I ", "SIS", "SSS", 'I', OrePrefixes.ingot.get(Materials.Steel), 'S', OrePrefixes.stone });
+ GT_ModHandler.addCraftingRecipe(
+ INSTANCE.getToolWithStats(MORTAR, 1, Materials.WroughtIron, Materials.Stone, null),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { " I ", "SIS", "SSS", 'I', OrePrefixes.ingot.get(Materials.WroughtIron), 'S',
+ OrePrefixes.stone });
+ GT_ModHandler.addCraftingRecipe(
+ INSTANCE.getToolWithStats(MORTAR, 1, Materials.RedSteel, Materials.Stone, null),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { " I ", "SIS", "SSS", 'I', OrePrefixes.ingot.get(Materials.RedSteel), 'S',
+ OrePrefixes.stone });
+ GT_ModHandler.addCraftingRecipe(
+ INSTANCE.getToolWithStats(MORTAR, 1, Materials.BlueSteel, Materials.Stone, null),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { " I ", "SIS", "SSS", 'I', OrePrefixes.ingot.get(Materials.BlueSteel), 'S',
+ OrePrefixes.stone });
+ GT_ModHandler.addCraftingRecipe(
+ INSTANCE.getToolWithStats(MORTAR, 1, Materials.BlackSteel, Materials.Stone, null),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { " I ", "SIS", "SSS", 'I', OrePrefixes.ingot.get(Materials.BlackSteel), 'S',
+ OrePrefixes.stone });
+ GT_ModHandler.addCraftingRecipe(
+ INSTANCE.getToolWithStats(MORTAR, 1, Materials.DamascusSteel, Materials.Stone, null),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { " I ", "SIS", "SSS", 'I', OrePrefixes.ingot.get(Materials.DamascusSteel), 'S',
+ OrePrefixes.stone });
+ GT_ModHandler.addCraftingRecipe(
+ INSTANCE.getToolWithStats(MORTAR, 1, Materials.Thaumium, Materials.Stone, null),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { " I ", "SIS", "SSS", 'I', OrePrefixes.ingot.get(Materials.Thaumium), 'S',
+ OrePrefixes.stone });
+
+ GT_ModHandler.addCraftingRecipe(
+ INSTANCE.getToolWithStats(ROLLING_PIN, 1, Materials.Wood, Materials.Wood, null),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { " S", " I ", "S f", 'I', OrePrefixes.plank.get(Materials.Wood), 'S',
+ OrePrefixes.stick.get(Materials.Wood) });
+ GT_ModHandler.addCraftingRecipe(
+ INSTANCE.getToolWithStats(ROLLING_PIN, 1, Materials.Plastic, Materials.Plastic, null),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { " S", " I ", "S f", 'I', OrePrefixes.ingot.get(Materials.Plastic), 'S',
+ OrePrefixes.stick.get(Materials.Plastic) });
+ GT_ModHandler.addCraftingRecipe(
+ INSTANCE.getToolWithStats(ROLLING_PIN, 1, Materials.Aluminium, Materials.Aluminium, null),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { " S", " I ", "S f", 'I', OrePrefixes.ingot.get(Materials.Aluminium), 'S',
+ OrePrefixes.stick.get(Materials.Aluminium) });
+ GT_ModHandler.addCraftingRecipe(
+ INSTANCE.getToolWithStats(ROLLING_PIN, 1, Materials.StainlessSteel, Materials.StainlessSteel, null),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { " S", " I ", "S f", 'I', OrePrefixes.ingot.get(Materials.StainlessSteel), 'S',
+ OrePrefixes.stick.get(Materials.StainlessSteel) });
+
+ if (!GregTech_API.sSpecialFile.get(ConfigCategories.general, "DisableFlintTools", false)) {
+ GT_ModHandler.addCraftingRecipe(
+ INSTANCE.getToolWithStats(SWORD, 1, Materials.Flint, Materials.Wood, null),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { "F", "F", "S", 'S', OrePrefixes.stick.get(Materials.Wood), 'F',
+ new ItemStack(Items.flint, 1) });
+ GT_ModHandler.addCraftingRecipe(
+ INSTANCE.getToolWithStats(PICKAXE, 1, Materials.Flint, Materials.Wood, null),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { "FFF", " S ", " S ", 'S', OrePrefixes.stick.get(Materials.Wood), 'F',
+ new ItemStack(Items.flint, 1) });
+ GT_ModHandler.addCraftingRecipe(
+ INSTANCE.getToolWithStats(SHOVEL, 1, Materials.Flint, Materials.Wood, null),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { "F", "S", "S", 'S', OrePrefixes.stick.get(Materials.Wood), 'F',
+ new ItemStack(Items.flint, 1) });
+ GT_ModHandler.addCraftingRecipe(
+ INSTANCE.getToolWithStats(AXE, 1, Materials.Flint, Materials.Wood, null),
+ GT_ModHandler.RecipeBits.MIRRORED | GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { "FF", "FS", " S", 'S', OrePrefixes.stick.get(Materials.Wood), 'F',
+ new ItemStack(Items.flint, 1) });
+ GT_ModHandler.addCraftingRecipe(
+ INSTANCE.getToolWithStats(HOE, 1, Materials.Flint, Materials.Wood, null),
+ GT_ModHandler.RecipeBits.MIRRORED | GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { "FF", " S", " S", 'S', OrePrefixes.stick.get(Materials.Wood), 'F',
+ new ItemStack(Items.flint, 1) });
+ GT_ModHandler.addCraftingRecipe(
+ INSTANCE.getToolWithStats(KNIFE, 1, Materials.Flint, Materials.Wood, null),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { "F", "S", 'S', OrePrefixes.stick.get(Materials.Wood), 'F',
+ new ItemStack(Items.flint, 1) });
+
+ GT_ModHandler.addCraftingRecipe(
+ INSTANCE.getToolWithStats(MORTAR, 1, Materials.Flint, Materials.Stone, null),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { " I ", "SIS", "SSS", 'I', new ItemStack(Items.flint, 1), 'S', OrePrefixes.stone });
+ GT_ModHandler.addCraftingRecipe(
+ INSTANCE.getToolWithStats(MORTAR, 1, Materials.Bronze, Materials.Stone, null),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { " I ", "SIS", "SSS", 'I', OrePrefixes.ingot.get(Materials.Bronze), 'S',
+ OrePrefixes.stone });
+ GT_ModHandler.addCraftingRecipe(
+ INSTANCE.getToolWithStats(MORTAR, 1, Materials.Iron, Materials.Stone, null),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { " I ", "SIS", "SSS", 'I', OrePrefixes.ingot.get(Materials.Iron), 'S',
+ OrePrefixes.stone });
+ GT_ModHandler.addCraftingRecipe(
+ INSTANCE.getToolWithStats(MORTAR, 1, Materials.Steel, Materials.Stone, null),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { " I ", "SIS", "SSS", 'I', OrePrefixes.ingot.get(Materials.Steel), 'S',
+ OrePrefixes.stone });
+ GT_ModHandler.addCraftingRecipe(
+ INSTANCE.getToolWithStats(MORTAR, 1, Materials.WroughtIron, Materials.Stone, null),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { " I ", "SIS", "SSS", 'I', OrePrefixes.ingot.get(Materials.WroughtIron), 'S',
+ OrePrefixes.stone });
+ GT_ModHandler.addCraftingRecipe(
+ INSTANCE.getToolWithStats(MORTAR, 1, Materials.RedSteel, Materials.Stone, null),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { " I ", "SIS", "SSS", 'I', OrePrefixes.ingot.get(Materials.RedSteel), 'S',
+ OrePrefixes.stone });
+ GT_ModHandler.addCraftingRecipe(
+ INSTANCE.getToolWithStats(MORTAR, 1, Materials.BlueSteel, Materials.Stone, null),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { " I ", "SIS", "SSS", 'I', OrePrefixes.ingot.get(Materials.BlueSteel), 'S',
+ OrePrefixes.stone });
+ GT_ModHandler.addCraftingRecipe(
+ INSTANCE.getToolWithStats(MORTAR, 1, Materials.BlackSteel, Materials.Stone, null),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { " I ", "SIS", "SSS", 'I', OrePrefixes.ingot.get(Materials.BlackSteel), 'S',
+ OrePrefixes.stone });
+ GT_ModHandler.addCraftingRecipe(
+ INSTANCE.getToolWithStats(MORTAR, 1, Materials.DamascusSteel, Materials.Stone, null),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { " I ", "SIS", "SSS", 'I', OrePrefixes.ingot.get(Materials.DamascusSteel), 'S',
+ OrePrefixes.stone });
+ GT_ModHandler.addCraftingRecipe(
+ INSTANCE.getToolWithStats(MORTAR, 1, Materials.Thaumium, Materials.Stone, null),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { " I ", "SIS", "SSS", 'I', OrePrefixes.ingot.get(Materials.Thaumium), 'S',
+ OrePrefixes.stone });
+
+ GT_ModHandler.addCraftingRecipe(
+ INSTANCE.getToolWithStats(ROLLING_PIN, 1, Materials.Wood, Materials.Wood, null),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { " S", " I ", "S f", 'I', OrePrefixes.plank.get(Materials.Wood), 'S',
+ OrePrefixes.stick.get(Materials.Wood) });
+ GT_ModHandler.addCraftingRecipe(
+ INSTANCE.getToolWithStats(ROLLING_PIN, 1, Materials.Plastic, Materials.Plastic, null),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { " S", " I ", "S f", 'I', OrePrefixes.ingot.get(Materials.Plastic), 'S',
+ OrePrefixes.stick.get(Materials.Plastic) });
+ GT_ModHandler.addCraftingRecipe(
+ INSTANCE.getToolWithStats(ROLLING_PIN, 1, Materials.Aluminium, Materials.Aluminium, null),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { " S", " I ", "S f", 'I', OrePrefixes.ingot.get(Materials.Aluminium), 'S',
+ OrePrefixes.stick.get(Materials.Aluminium) });
+ GT_ModHandler.addCraftingRecipe(
+ INSTANCE.getToolWithStats(ROLLING_PIN, 1, Materials.StainlessSteel, Materials.StainlessSteel, null),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { " S", " I ", "S f", 'I', OrePrefixes.ingot.get(Materials.StainlessSteel), 'S',
+ OrePrefixes.stick.get(Materials.StainlessSteel) });
+ GT_ModHandler.addCraftingRecipe(
+ INSTANCE.getToolWithStats(ROLLING_PIN, 1, Materials.IronWood, Materials.IronWood, null),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { " S", " I ", "S f", 'I', OrePrefixes.ingot.get(Materials.IronWood), 'S',
+ OrePrefixes.stick.get(Materials.IronWood) });
+
+ GT_ModHandler.addShapelessCraftingRecipe(
+ GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Coal, 1L),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { ToolDictNames.craftingToolMortar, new ItemStack(Items.coal, 1) });
+ GT_ModHandler.addShapelessCraftingRecipe(
+ GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Clay, 1L),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { ToolDictNames.craftingToolMortar, new ItemStack(Blocks.clay, 1) });
+ GT_ModHandler.addShapelessCraftingRecipe(
+ GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Wheat, 1L),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { ToolDictNames.craftingToolMortar, new ItemStack(Items.wheat, 1) });
+ GT_ModHandler.addShapelessCraftingRecipe(
+ new ItemStack(Items.flint, 1),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { ToolDictNames.craftingToolMortar, new ItemStack(Blocks.gravel, 1) });
+ GT_ModHandler.addShapelessCraftingRecipe(
+ new ItemStack(Items.blaze_powder, 2),
+ GT_ModHandler.RecipeBits.NOT_REMOVABLE,
+ new Object[] { ToolDictNames.craftingToolMortar, new ItemStack(Items.blaze_rod, 1) });
+
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/items/GT_NeutronReflector_Item.java b/src/main/java/gregtech/common/items/GT_NeutronReflector_Item.java
new file mode 100644
index 0000000000..b2fd104917
--- /dev/null
+++ b/src/main/java/gregtech/common/items/GT_NeutronReflector_Item.java
@@ -0,0 +1,54 @@
+package gregtech.common.items;
+
+import net.minecraft.item.ItemStack;
+
+import gregtech.api.items.GT_Generic_Item;
+import ic2.api.reactor.IReactor;
+import ic2.api.reactor.IReactorComponent;
+
+public class GT_NeutronReflector_Item extends GT_Generic_Item implements IReactorComponent {
+
+ public GT_NeutronReflector_Item(String aUnlocalized, String aEnglish, int aMaxDamage) {
+ super(aUnlocalized, aEnglish, "Undestructable");
+ this.setMaxStackSize(64);
+ this.setMaxDamage(aMaxDamage);
+ }
+
+ @Override
+ public boolean acceptUraniumPulse(IReactor reactor, ItemStack yourStack, ItemStack pulsingStack, int youX, int youY,
+ int pulseX, int pulseY, boolean heatrun) {
+ if (!heatrun) {
+ ((IReactorComponent) pulsingStack.getItem())
+ .acceptUraniumPulse(reactor, pulsingStack, yourStack, pulseX, pulseY, youX, youY, heatrun);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean canStoreHeat(IReactor aReactor, ItemStack aStack, int x, int y) {
+ return false;
+ }
+
+ @Override
+ public int getMaxHeat(IReactor aReactor, ItemStack aStack, int x, int y) {
+ return 0;
+ }
+
+ @Override
+ public int getCurrentHeat(IReactor aReactor, ItemStack aStack, int x, int y) {
+ return 0;
+ }
+
+ @Override
+ public float influenceExplosion(IReactor aReactor, ItemStack aStack) {
+ return -1.0F;
+ }
+
+ @Override
+ public int alterHeat(IReactor aReactor, ItemStack aStack, int x, int y, int aHeat) {
+ return aHeat;
+ }
+
+ @Override
+ public void processChamber(IReactor aReactor, ItemStack aStack, int x, int y, boolean aHeatRun) {}
+}
diff --git a/src/main/java/gregtech/common/items/GT_SensorCard_Item.java b/src/main/java/gregtech/common/items/GT_SensorCard_Item.java
new file mode 100644
index 0000000000..67e5b24a70
--- /dev/null
+++ b/src/main/java/gregtech/common/items/GT_SensorCard_Item.java
@@ -0,0 +1,111 @@
+package gregtech.common.items;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.UUID;
+
+import net.minecraft.creativetab.CreativeTabs;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.ChunkCoordinates;
+import net.minecraft.world.World;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.api.interfaces.tileentity.IGregTechDeviceInformation;
+import gregtech.api.items.GT_Generic_Item;
+import gregtech.api.util.GT_LanguageManager;
+import shedar.mods.ic2.nuclearcontrol.api.CardState;
+import shedar.mods.ic2.nuclearcontrol.api.ICardWrapper;
+import shedar.mods.ic2.nuclearcontrol.api.IPanelDataSource;
+import shedar.mods.ic2.nuclearcontrol.api.IRemoteSensor;
+import shedar.mods.ic2.nuclearcontrol.api.PanelSetting;
+import shedar.mods.ic2.nuclearcontrol.api.PanelString;
+
+public class GT_SensorCard_Item extends GT_Generic_Item implements IRemoteSensor, IPanelDataSource {
+
+ private static final UUID CARD_TYPE = new UUID(0L, 41L);
+
+ private int strCount;
+
+ public GT_SensorCard_Item(String aUnlocalized, String aEnglish) {
+ super(aUnlocalized, aEnglish, "Insert into Display Panel");
+ setMaxStackSize(1);
+ }
+
+ @Override
+ public void addAdditionalToolTips(List<String> aList, ItemStack aStack, EntityPlayer aPlayer) {
+ super.addAdditionalToolTips(aList, aStack, aPlayer);
+ if (aStack != null) {
+ NBTTagCompound tNBT = aStack.getTagCompound();
+ if (tNBT == null) {
+ aList.add(transItem("014", "Missing Coordinates!"));
+ } else {
+ aList.add(transItem("015", "Device at:"));
+ aList.add(
+ String.format(
+ "x: %d, y: %d, z: %d",
+ tNBT.getInteger("x"),
+ tNBT.getInteger("y"),
+ tNBT.getInteger("z")));
+ }
+ }
+ }
+
+ @Override
+ public CardState update(TileEntity aPanel, ICardWrapper aCard, int aMaxRange) {
+ return update(aPanel.getWorldObj(), aCard, aMaxRange);
+ }
+
+ @Override
+ public CardState update(World world, ICardWrapper aCard, int aMaxRange) {
+ ChunkCoordinates target = aCard.getTarget();
+
+ TileEntity tTileEntity = world.getTileEntity(target.posX, target.posY, target.posZ);
+ if (((tTileEntity instanceof IGregTechDeviceInformation))
+ && (((IGregTechDeviceInformation) tTileEntity).isGivingInformation())) {
+ String[] tInfoData = ((IGregTechDeviceInformation) tTileEntity).getInfoData();
+ for (int i = 0; i < tInfoData.length; i++) {
+ aCard.setString("mString" + i, tInfoData[i]);
+ }
+ aCard.setInt("mString", strCount = tInfoData.length);
+ return CardState.OK;
+ }
+ return CardState.NO_TARGET;
+ }
+
+ @Override
+ public List<PanelString> getStringData(int aSettings, ICardWrapper aCard, boolean aLabels) {
+ List<PanelString> rList = new LinkedList<>();
+ for (int i = 0; i < (strCount = aCard.getInt("mString")); i++) {
+ if ((aSettings & 1 << i) != 0) {
+ PanelString line = new PanelString();
+ line.textLeft = GT_LanguageManager.getTranslation(aCard.getString("mString" + i), "\\\\");
+ rList.add(line);
+ }
+ }
+ return rList;
+ }
+
+ @Override
+ public List<PanelSetting> getSettingsList() {
+ List<PanelSetting> rList = new ArrayList<>();
+ for (int i = 0; i < strCount; i++) {
+ rList.add(new PanelSetting(String.valueOf((i + 1)), 1 << i, getCardType()));
+ }
+ return rList;
+ }
+
+ @Override
+ public UUID getCardType() {
+ return CARD_TYPE;
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void getSubItems(Item aItem, CreativeTabs aCreativeTab, List<ItemStack> aOutputSubItems) {}
+}
diff --git a/src/main/java/gregtech/common/items/GT_TierDrone.java b/src/main/java/gregtech/common/items/GT_TierDrone.java
new file mode 100644
index 0000000000..58da852d0e
--- /dev/null
+++ b/src/main/java/gregtech/common/items/GT_TierDrone.java
@@ -0,0 +1,18 @@
+package gregtech.common.items;
+
+import gregtech.api.items.GT_Generic_Item;
+
+public class GT_TierDrone extends GT_Generic_Item {
+
+ private final int level;
+
+ public GT_TierDrone(String aUnlocalized, String aEnglish, String aEnglishTooltip, int level) {
+ super(aUnlocalized, aEnglish, aEnglishTooltip);
+ this.level = level;
+ this.setMaxStackSize(64);
+ }
+
+ public int getLevel() {
+ return level;
+ }
+}
diff --git a/src/main/java/gregtech/common/items/GT_VolumetricFlask.java b/src/main/java/gregtech/common/items/GT_VolumetricFlask.java
new file mode 100644
index 0000000000..50a88f4700
--- /dev/null
+++ b/src/main/java/gregtech/common/items/GT_VolumetricFlask.java
@@ -0,0 +1,361 @@
+package gregtech.common.items;
+
+import static gregtech.api.enums.Mods.GregTech;
+import static gregtech.api.util.GT_Utility.formatNumbers;
+import static ic2.core.util.LiquidUtil.drainContainerStack;
+import static ic2.core.util.LiquidUtil.fillContainerStack;
+import static ic2.core.util.LiquidUtil.placeFluid;
+
+import java.util.List;
+
+import net.minecraft.block.Block;
+import net.minecraft.client.renderer.texture.IIconRegister;
+import net.minecraft.creativetab.CreativeTabs;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.IIcon;
+import net.minecraft.util.MovingObjectPosition;
+import net.minecraft.util.MovingObjectPosition.MovingObjectType;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.FakePlayer;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidRegistry;
+import net.minecraftforge.fluids.FluidStack;
+import net.minecraftforge.fluids.IFluidBlock;
+import net.minecraftforge.fluids.IFluidContainerItem;
+import net.minecraftforge.fluids.IFluidHandler;
+
+import com.gtnewhorizons.modularui.api.ModularUITextures;
+import com.gtnewhorizons.modularui.api.math.Alignment;
+import com.gtnewhorizons.modularui.api.math.Color;
+import com.gtnewhorizons.modularui.api.screen.IItemWithModularUI;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+import com.gtnewhorizons.modularui.common.widget.VanillaButtonWidget;
+import com.gtnewhorizons.modularui.common.widget.textfield.NumericWidget;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.api.gui.modularui.GT_UIInfos;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.items.GT_Generic_Item;
+import gregtech.api.util.GT_Utility;
+import ic2.core.util.LiquidUtil;
+
+public class GT_VolumetricFlask extends GT_Generic_Item implements IFluidContainerItem, IItemWithModularUI {
+
+ private final int maxCapacity;
+ private final String unlocalFlaskName;
+
+ @SideOnly(Side.CLIENT)
+ public IIcon iconWindow;
+
+ public GT_VolumetricFlask(String unlocalized, String english, int maxCapacity) {
+ super(unlocalized, english, null);
+ this.maxCapacity = maxCapacity;
+ unlocalFlaskName = unlocalized;
+ setMaxStackSize(64);
+ setNoRepair();
+ }
+
+ @Override
+ public ItemStack onItemRightClick(ItemStack stack, World world, EntityPlayer player) {
+ if (!world.isRemote && isEmpty(stack) && getMovingObjectPositionFromPlayer(world, player, true) == null)
+ GT_UIInfos.openPlayerHeldItemUI(player);
+ return super.onItemRightClick(stack, world, player);
+ }
+
+ @Override
+ public boolean onItemUse(ItemStack stack, EntityPlayer player, World world, int x, int y, int z, int ordinalSide,
+ float xOffset, float yOffset, float zOffset) {
+ if (player instanceof FakePlayer) {
+ return false;
+ }
+ if (world.isRemote) return false;
+ if (interactWithTank(stack, player, world, x, y, z, ordinalSide)) {
+ return true;
+ }
+ MovingObjectPosition mop = getMovingObjectPositionFromPlayer(world, player, true);
+ if (mop == null) {
+ return false;
+ }
+ if (mop.typeOfHit == MovingObjectType.BLOCK) {
+ x = mop.blockX;
+ y = mop.blockY;
+ z = mop.blockZ;
+ if (!world.canMineBlock(player, x, y, z) || !player.canPlayerEdit(x, y, z, mop.sideHit, stack)) {
+ return false;
+ }
+ if (collectFluidBlock(stack, player, world, x, y, z)) {
+ return true;
+ }
+ ForgeDirection dir = ForgeDirection.VALID_DIRECTIONS[mop.sideHit];
+ FluidStack fluidStack = drainContainerStack(stack, player, 1000, true);
+ if (placeFluid(fluidStack, world, x, y, z)
+ || (player.canPlayerEdit(x + dir.offsetX, y + dir.offsetY, z + dir.offsetZ, mop.sideHit, stack)
+ && placeFluid(fluidStack, world, x + dir.offsetX, y + dir.offsetY, z + dir.offsetZ))) {
+ if (!player.capabilities.isCreativeMode) drainContainerStack(stack, player, 1000, false);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean isEmpty(ItemStack stack) {
+ return getFluid(stack) == null;
+ }
+
+ public int getFreeSpace(ItemStack stack) {
+ int capacity = getCapacity(stack);
+ if (capacity > 0) {
+ FluidStack fluidStack = getFluid(stack);
+ return fluidStack == null ? capacity : capacity - fluidStack.amount;
+ }
+ return 0;
+ }
+
+ public int getMaxCapacity() {
+ return this.maxCapacity;
+ }
+
+ @Override
+ public int getCapacity(ItemStack stack) {
+ int capacity = 1000;
+ if (stack.hasTagCompound()) {
+ NBTTagCompound nbt = stack.getTagCompound();
+ if (nbt.hasKey("Capacity", 3)) capacity = nbt.getInteger("Capacity");
+ }
+ return Math.min(getMaxCapacity(), capacity);
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void registerIcons(IIconRegister aIconRegister) {
+ super.registerIcons(aIconRegister);
+ iconWindow = aIconRegister.registerIcon(GregTech.getResourcePath("gt." + unlocalFlaskName + ".window"));
+ }
+
+ public void setCapacity(ItemStack stack, int capacity) {
+ capacity = Math.min(capacity, getMaxCapacity());
+ NBTTagCompound nbt = stack.getTagCompound();
+ if (nbt == null) {
+ stack.setTagCompound(nbt = new NBTTagCompound());
+ }
+ nbt.setInteger("Capacity", capacity);
+ }
+
+ @Override
+ public FluidStack getFluid(ItemStack stack) {
+ if (stack.hasTagCompound()) {
+ NBTTagCompound nbt = stack.getTagCompound();
+ if (nbt.hasKey("Fluid", 10)) return FluidStack.loadFluidStackFromNBT(nbt.getCompoundTag("Fluid"));
+ }
+ return null;
+ }
+
+ public void setFluid(ItemStack stack, FluidStack fluidStack) {
+ boolean removeFluid = (fluidStack == null) || (fluidStack.amount <= 0);
+ NBTTagCompound nbt = stack.getTagCompound();
+ if (nbt == null) {
+ if (removeFluid) return;
+ stack.setTagCompound(nbt = new NBTTagCompound());
+ }
+ if (removeFluid) {
+ nbt.removeTag("Fluid");
+ if (nbt.hasNoTags()) {
+ stack.setTagCompound(null);
+ }
+ } else {
+ nbt.setTag("Fluid", fluidStack.writeToNBT(new NBTTagCompound()));
+ }
+ }
+
+ @Override
+ public int fill(ItemStack stack, FluidStack resource, boolean doFill) {
+ if (stack.stackSize != 1) return 0;
+ if ((resource == null) || (resource.amount <= 0)) {
+ return 0;
+ }
+ FluidStack fluidStack = getFluid(stack);
+ if (fluidStack == null) {
+ fluidStack = new FluidStack(resource, 0);
+ } else if (!fluidStack.isFluidEqual(resource)) {
+ return 0;
+ }
+ int amount = Math.min(getCapacity(stack) - fluidStack.amount, resource.amount);
+ if ((doFill) && (amount > 0)) {
+ fluidStack.amount += amount;
+ setFluid(stack, fluidStack);
+ }
+ return amount;
+ }
+
+ @Override
+ public FluidStack drain(ItemStack stack, int maxDrain, boolean doDrain) {
+ if (stack.stackSize != 1) return null;
+ FluidStack fluidStack = getFluid(stack);
+ if (fluidStack == null) return null;
+ maxDrain = Math.min(fluidStack.amount, maxDrain);
+ if (doDrain) {
+ fluidStack.amount -= maxDrain;
+ setFluid(stack, fluidStack);
+ }
+ return new FluidStack(fluidStack, maxDrain);
+ }
+
+ @Override
+ protected void addAdditionalToolTips(List<String> info, ItemStack stack, EntityPlayer aPlayer) {
+ FluidStack fs = getFluid(stack);
+ if (fs != null) {
+ info.add(String.format("< %s, %s mB >", GT_Utility.getFluidName(fs, true), formatNumbers(fs.amount)));
+ } else {
+ info.add(String.format("< Empty, %s mB >", formatNumbers(getCapacity(stack))));
+ }
+ info.add("Rightclick on air to set volume (only while empty)");
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void getSubItems(Item item, CreativeTabs creativeTabs, List<ItemStack> itemList) {
+ itemList.add(new ItemStack(this));
+ for (Fluid fluid : FluidRegistry.getRegisteredFluids()
+ .values()) {
+ if (fluid != null) {
+ ItemStack stack = new ItemStack(this);
+ setCapacity(stack, getMaxCapacity());
+ fill(stack, new FluidStack(fluid, Integer.MAX_VALUE), true);
+ itemList.add(stack);
+ }
+ }
+ }
+
+ private boolean interactWithTank(ItemStack stack, EntityPlayer player, World world, int x, int y, int z,
+ int ordinalSide) {
+ if (world.isRemote) {
+ return false;
+ }
+ TileEntity te = world.getTileEntity(x, y, z);
+ if (!(te instanceof IFluidHandler handler)) {
+ return false;
+ }
+ ForgeDirection dir = ForgeDirection.getOrientation(ordinalSide);
+ FluidStack fs = this.getFluid(stack);
+ int capacity = getCapacity(stack);
+ if (fs != null && (!player.isSneaking() || fs.amount >= capacity)) {
+ int amount = handler.fill(dir, fs, false);
+ if (amount > 0) {
+ fs = LiquidUtil.drainContainerStack(stack, player, amount, false);
+ if (fs != null && fs.amount > 0) {
+ handler.fill(dir, fs, true);
+ }
+ }
+ } else {
+ int amount = fs == null ? capacity : capacity - fs.amount;
+ FluidStack input = handler.drain(dir, amount, false);
+ if (input != null && input.amount > 0) {
+ amount = LiquidUtil.fillContainerStack(stack, player, input, false);
+ if (amount > 0) {
+ handler.drain(dir, amount, true);
+ }
+ }
+ }
+ return true;
+ }
+
+ private boolean collectFluidBlock(ItemStack stack, EntityPlayer player, World world, int x, int y, int z) {
+ Block block = world.getBlock(x, y, z);
+ if (block instanceof IFluidBlock liquid) {
+ if (liquid.canDrain(world, x, y, z)) {
+ FluidStack fluid = liquid.drain(world, x, y, z, false);
+ int amount = fillContainerStack(stack, player, fluid, true);
+ if (amount == fluid.amount) {
+ fillContainerStack(stack, player, fluid, false);
+ liquid.drain(world, x, y, z, true);
+ return true;
+ }
+ }
+ } else if (world.getBlockMetadata(x, y, z) == 0) {
+ FluidStack fluid = null;
+ if (block != Blocks.water && block != Blocks.flowing_water) {
+ if (block == Blocks.lava || block == Blocks.flowing_lava) {
+ fluid = new FluidStack(FluidRegistry.LAVA, 1000);
+ }
+ } else {
+ fluid = new FluidStack(FluidRegistry.WATER, 1000);
+ }
+
+ if (fluid != null) {
+ int amount = fillContainerStack(stack, player, fluid, true);
+ if (amount == fluid.amount) {
+ fillContainerStack(stack, player, fluid, false);
+ world.setBlockToAir(x, y, z);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public ModularWindow createWindow(UIBuildContext buildContext, ItemStack stack) {
+ if (!(stack.getItem() instanceof GT_VolumetricFlask)) return null;
+ return new VolumetricFlaskUIFactory(buildContext, stack).createWindow();
+ }
+
+ private class VolumetricFlaskUIFactory {
+
+ private final UIBuildContext buildContext;
+ private int capacity;
+ private final int maxCapacity;
+
+ public VolumetricFlaskUIFactory(UIBuildContext buildContext, ItemStack flask) {
+ this.buildContext = buildContext;
+ GT_VolumetricFlask flaskItem = (GT_VolumetricFlask) flask.getItem();
+ this.capacity = flaskItem.getCapacity(flask);
+ this.maxCapacity = flaskItem.getMaxCapacity();
+ }
+
+ public ModularWindow createWindow() {
+ ModularWindow.Builder builder = ModularWindow.builder(150, 54);
+ builder.setBackground(ModularUITextures.VANILLA_BACKGROUND);
+
+ NumericWidget capacityWidget = new NumericWidget();
+ builder.widget(
+ capacityWidget.setGetter(() -> capacity)
+ .setSetter(value -> setCapacity(getCurrentItem(), capacity = (int) value))
+ .setBounds(1, maxCapacity)
+ .setScrollValues(1, 144, 1000)
+ .setDefaultValue(capacity)
+ .setTextColor(Color.WHITE.dark(1))
+ .setTextAlignment(Alignment.CenterLeft)
+ .setFocusOnGuiOpen(true)
+ .setBackground(GT_UITextures.BACKGROUND_TEXT_FIELD.withOffset(-1, -1, 2, 2))
+ .setPos(8, 8)
+ .setSize(77, 12))
+ .widget(new TextWidget("Capacity").setPos(88, 10))
+ .widget(
+ new VanillaButtonWidget().setDisplayString("Confirm")
+ .setOnClick((clickData, widget) -> {
+ capacityWidget.onRemoveFocus();
+ if (!widget.isClient()) {
+ widget.getWindow()
+ .tryClose();
+ }
+ })
+ .setPos(8, 26)
+ .setSize(48, 20));
+
+ return builder.build();
+ }
+
+ private ItemStack getCurrentItem() {
+ return buildContext.getPlayer().inventory.getCurrentItem();
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/items/ItemComb.java b/src/main/java/gregtech/common/items/ItemComb.java
new file mode 100644
index 0000000000..8fd37fd0d9
--- /dev/null
+++ b/src/main/java/gregtech/common/items/ItemComb.java
@@ -0,0 +1,1908 @@
+package gregtech.common.items;
+
+import static gregtech.api.enums.GT_Values.L;
+import static gregtech.api.enums.GT_Values.NF;
+import static gregtech.api.enums.GT_Values.NI;
+import static gregtech.api.enums.GT_Values.V;
+import static gregtech.api.enums.Mods.AE2FluidCraft;
+import static gregtech.api.enums.Mods.ExtraUtilities;
+import static gregtech.api.enums.Mods.GalaxySpace;
+import static gregtech.api.enums.Mods.GregTech;
+import static gregtech.api.enums.Mods.MagicBees;
+import static gregtech.api.enums.Mods.NewHorizonsCoreMod;
+import static gregtech.api.enums.Mods.Thaumcraft;
+import static gregtech.api.enums.Mods.ThaumicBases;
+import static gregtech.api.recipe.RecipeMaps.autoclaveRecipes;
+import static gregtech.api.recipe.RecipeMaps.centrifugeRecipes;
+import static gregtech.api.recipe.RecipeMaps.fluidExtractionRecipes;
+import static gregtech.api.util.GT_RecipeBuilder.TICKS;
+import static gregtech.api.util.GT_RecipeConstants.CLEANROOM;
+import static gregtech.api.util.GT_RecipeConstants.UniversalChemical;
+
+import java.util.Arrays;
+import java.util.List;
+
+import net.minecraft.client.renderer.texture.IIconRegister;
+import net.minecraft.creativetab.CreativeTabs;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Items;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IIcon;
+import net.minecraftforge.fluids.FluidRegistry;
+import net.minecraftforge.fluids.FluidStack;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMap.Builder;
+
+import cpw.mods.fml.common.registry.GameRegistry;
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import forestry.api.core.Tabs;
+import forestry.api.recipes.RecipeManagers;
+import gregtech.GT_Mod;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.interfaces.IGT_ItemWithMaterialRenderer;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_OreDictUnificator;
+import gregtech.api.util.GT_RecipeBuilder;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.render.items.GT_GeneratedMaterial_Renderer;
+import gregtech.loaders.misc.GT_Bees;
+
+public class ItemComb extends Item implements IGT_ItemWithMaterialRenderer {
+
+ @SideOnly(Side.CLIENT)
+ private IIcon secondIcon;
+
+ public ItemComb() {
+ super();
+ this.setCreativeTab(Tabs.tabApiculture);
+ this.setHasSubtypes(true);
+ this.setUnlocalizedName("gt.comb");
+ GameRegistry.registerItem(this, "gt.comb", GregTech.ID);
+ }
+
+ public ItemStack getStackForType(CombType type) {
+ return new ItemStack(this, 1, type.getId());
+ }
+
+ public ItemStack getStackForType(CombType type, int count) {
+ return new ItemStack(this, count, type.getId());
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void getSubItems(Item item, CreativeTabs tabs, List<ItemStack> list) {
+ for (CombType type : CombType.values()) {
+ if (type.showInList) {
+ list.add(this.getStackForType(type));
+ }
+ }
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public boolean requiresMultipleRenderPasses() {
+ return true;
+ }
+
+ @Override
+ public int getRenderPasses(int meta) {
+ return 2;
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void registerIcons(IIconRegister iconRegister) {
+ this.itemIcon = iconRegister.registerIcon("forestry:beeCombs.0");
+ this.secondIcon = iconRegister.registerIcon("forestry:beeCombs.1");
+ }
+
+ @Override
+ public IIcon getIcon(ItemStack stack, int pass) {
+ return (pass == 0) ? itemIcon : secondIcon;
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public int getColorFromItemStack(ItemStack stack, int pass) {
+ CombType type = CombType.valueOf(stack.getItemDamage());
+ return type.getColours()[GT_Utility.clamp(pass, 0, 1)];
+ }
+
+ @Override
+ public String getItemStackDisplayName(ItemStack stack) {
+ return CombType.valueOf(stack.getItemDamage())
+ .getName();
+ }
+
+ @Override
+ public void addInformation(ItemStack stack, EntityPlayer player, List<String> tooltip, boolean debugInfo) {
+ tooltip.add(EnumChatFormatting.DARK_RED + "Forestry can't process it");
+ }
+
+ @Override
+ public boolean shouldUseCustomRenderer(int aMetaData) {
+ return CombType.valueOf(aMetaData).material.renderer != null;
+ }
+
+ @Override
+ public GT_GeneratedMaterial_Renderer getMaterialRenderer(int aMetaData) {
+ return CombType.valueOf(aMetaData).material.renderer;
+ }
+
+ @Override
+ public boolean allowMaterialRenderer(int aMetaData) {
+ return true;
+ }
+
+ @Override
+ public IIcon getIcon(int aMetaData, int pass) {
+ return (pass == 0) ? itemIcon : secondIcon;
+ }
+
+ @Override
+ public IIcon getOverlayIcon(int aMetaData, int pass) {
+ return null;
+ }
+
+ @Override
+ public short[] getRGBa(ItemStack aStack) {
+ return CombType.valueOf(aStack.getItemDamage()).material.mRGBa;
+ }
+
+ public void initCombsRecipes() {
+
+ // Organic
+ addProcessGT(CombType.LIGNIE, new Materials[] { Materials.Lignite }, Voltage.LV);
+ addProcessGT(CombType.COAL, new Materials[] { Materials.Coal }, Voltage.LV);
+ addCentrifugeToItemStack(
+ CombType.STICKY,
+ new ItemStack[] { ItemList.IC2_Resin.get(1), ItemList.IC2_Plantball.get(1), ItemList.FR_Wax.get(1) },
+ new int[] { 50 * 100, 15 * 100, 50 * 100 },
+ Voltage.ULV);
+ addProcessGT(CombType.OIL, new Materials[] { Materials.Oilsands }, Voltage.LV);
+ addProcessGT(CombType.APATITE, new Materials[] { Materials.Apatite }, Voltage.LV);
+ addCentrifugeToMaterial(
+ CombType.ASH,
+ new Materials[] { Materials.DarkAsh, Materials.Ash },
+ new int[] { 50 * 100, 50 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 50 * 100);
+ addCentrifugeToItemStack(
+ CombType.PHOSPHORUS,
+ new ItemStack[] { Materials.Phosphorus.getDust(1), Materials.TricalciumPhosphate.getDust(2),
+ ItemList.FR_Wax.get(1) },
+ new int[] { 100 * 100, 100 * 100, 100 * 100 },
+ Voltage.HV);
+ addCentrifugeToItemStack(
+ CombType.MICA,
+ new ItemStack[] { Materials.Mica.getDust(2), ItemList.FR_Wax.get(1) },
+ new int[] { 100 * 100, 75 * 100 },
+ Voltage.HV);
+ if (GT_Mod.gregtechproxy.mNerfedCombs) {
+ addCentrifugeToItemStack(
+ CombType.LIGNIE,
+ new ItemStack[] { GT_OreDictUnificator.get(OrePrefixes.gem, Materials.Lignite, 1),
+ ItemList.FR_Wax.get(1) },
+ new int[] { 90 * 100, 50 * 100 },
+ Voltage.ULV);
+ addCentrifugeToItemStack(
+ CombType.COAL,
+ new ItemStack[] { GT_OreDictUnificator.get(OrePrefixes.gem, Materials.Coal, 1),
+ ItemList.FR_Wax.get(1) },
+ new int[] { 5 * 100, 50 * 100 },
+ Voltage.ULV);
+ addCentrifugeToItemStack(
+ CombType.OIL,
+ new ItemStack[] { ItemList.Crop_Drop_OilBerry.get(6), GT_Bees.drop.getStackForType(DropType.OIL),
+ ItemList.FR_Wax.get(1) },
+ new int[] { 100 * 100, 100 * 100, 50 * 100 },
+ Voltage.ULV);
+ } else {
+ addCentrifugeToItemStack(
+ CombType.LIGNIE,
+ new ItemStack[] { GT_OreDictUnificator.get(OrePrefixes.gem, Materials.Lignite, 1),
+ GT_OreDictUnificator.get(OrePrefixes.dustTiny, Materials.Lignite, 1), ItemList.FR_Wax.get(1) },
+ new int[] { 90 * 100, 100 * 100, 50 * 100 },
+ Voltage.ULV);
+ addCentrifugeToItemStack(
+ CombType.COAL,
+ new ItemStack[] { GT_OreDictUnificator.get(OrePrefixes.gem, Materials.Coal, 1),
+ GT_OreDictUnificator.get(OrePrefixes.dustTiny, Materials.Coal, 1), ItemList.FR_Wax.get(1) },
+ new int[] { 5 * 100, 100 * 100, 50 * 100 },
+ Voltage.ULV);
+ addCentrifugeToItemStack(
+ CombType.OIL,
+ new ItemStack[] { ItemList.Crop_Drop_OilBerry.get(6), GT_Bees.drop.getStackForType(DropType.OIL),
+ GT_OreDictUnificator.get(OrePrefixes.dustTiny, Materials.Oilsands, 1), ItemList.FR_Wax.get(1) },
+ new int[] { 100 * 100, 100 * 100, 100 * 100, 50 * 100 },
+ Voltage.ULV);
+ addCentrifugeToMaterial(
+ CombType.APATITE,
+ new Materials[] { Materials.Apatite, Materials.Phosphate },
+ new int[] { 100 * 100, 80 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ }
+ // ic2
+ addCentrifugeToItemStack(
+ CombType.COOLANT,
+ new ItemStack[] { GT_Bees.drop.getStackForType(DropType.COOLANT), ItemList.FR_Wax.get(1) },
+ new int[] { 100 * 100, 100 * 100 },
+ Voltage.HV,
+ 196);
+ addCentrifugeToItemStack(
+ CombType.ENERGY,
+ new ItemStack[] { GT_Bees.drop.getStackForType(DropType.HOT_COOLANT), ItemList.IC2_Energium_Dust.get(1L),
+ ItemList.FR_RefractoryWax.get(1) },
+ new int[] { 20 * 100, 20 * 100, 50 * 100 },
+ Voltage.HV,
+ 196);
+ addCentrifugeToItemStack(
+ CombType.LAPOTRON,
+ new ItemStack[] { GT_Bees.drop.getStackForType(DropType.LAPIS),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.LapotronDust", 1, 0),
+ GT_ModHandler.getModItem(MagicBees.ID, "wax", 1, 2) },
+ new int[] { 20 * 100, 100 * 100, 40 * 100 },
+ Voltage.HV,
+ 240);
+ addCentrifugeToMaterial(
+ CombType.PYROTHEUM,
+ new Materials[] { Materials.Blaze, Materials.Pyrotheum },
+ new int[] { 25 * 100, 20 * 100 },
+ new int[] {},
+ Voltage.HV,
+ NI,
+ 30 * 100);
+ addCentrifugeToItemStack(
+ CombType.CRYOTHEUM,
+ new ItemStack[] { ItemList.FR_RefractoryWax.get(1), Materials.Cryotheum.getDust(1) },
+ new int[] { 50 * 100, 100 * 100 },
+ Voltage.MV);
+ addCentrifugeToItemStack(
+ CombType.BLIZZ,
+ new ItemStack[] { ItemList.FR_RefractoryWax.get(1), Materials.Blizz.getDust(1) },
+ new int[] { 50 * 100, 100 * 100 },
+ Voltage.MV);
+ // Alloy
+ addProcessGT(CombType.REDALLOY, new Materials[] { Materials.RedAlloy }, Voltage.LV);
+ addProcessGT(CombType.REDSTONEALLOY, new Materials[] { Materials.RedstoneAlloy }, Voltage.LV);
+ addProcessGT(CombType.CONDUCTIVEIRON, new Materials[] { Materials.ConductiveIron }, Voltage.MV);
+ addProcessGT(CombType.VIBRANTALLOY, new Materials[] { Materials.VibrantAlloy }, Voltage.HV);
+ addProcessGT(CombType.ENERGETICALLOY, new Materials[] { Materials.EnergeticAlloy }, Voltage.HV);
+ addProcessGT(CombType.ELECTRICALSTEEL, new Materials[] { Materials.ElectricalSteel }, Voltage.LV);
+ addProcessGT(CombType.DARKSTEEL, new Materials[] { Materials.DarkSteel }, Voltage.MV);
+ addProcessGT(CombType.PULSATINGIRON, new Materials[] { Materials.PulsatingIron }, Voltage.HV);
+ addProcessGT(CombType.STAINLESSSTEEL, new Materials[] { Materials.StainlessSteel }, Voltage.HV);
+ addProcessGT(CombType.BEDROCKIUM, new Materials[] { Materials.Bedrockium }, Voltage.EV);
+ addCentrifugeToItemStack(
+ CombType.ENDERIUM,
+ new ItemStack[] { ItemList.FR_RefractoryWax.get(1),
+ GT_OreDictUnificator.get(OrePrefixes.dustSmall, Materials.EnderiumBase, 1),
+ GT_OreDictUnificator.get(OrePrefixes.dustTiny, Materials.Enderium, 1) },
+ new int[] { 50 * 100, 30 * 100, 50 * 100 },
+ Voltage.HV);
+ if (GT_Mod.gregtechproxy.mNerfedCombs) {
+ addCentrifugeToMaterial(
+ CombType.REDALLOY,
+ new Materials[] { Materials.RedAlloy },
+ new int[] { 100 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ ItemList.FR_RefractoryWax.get(1),
+ 50 * 100);
+ addCentrifugeToMaterial(
+ CombType.REDSTONEALLOY,
+ new Materials[] { Materials.RedstoneAlloy },
+ new int[] { 100 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ ItemList.FR_RefractoryWax.get(1),
+ 50 * 100);
+ addCentrifugeToMaterial(
+ CombType.CONDUCTIVEIRON,
+ new Materials[] { Materials.ConductiveIron },
+ new int[] { 90 * 100 },
+ new int[] {},
+ Voltage.MV,
+ ItemList.FR_RefractoryWax.get(1),
+ 50 * 100);
+ addCentrifugeToMaterial(
+ CombType.VIBRANTALLOY,
+ new Materials[] { Materials.VibrantAlloy },
+ new int[] { 70 * 100 },
+ new int[] {},
+ Voltage.HV,
+ ItemList.FR_RefractoryWax.get(1),
+ 50 * 100);
+ addCentrifugeToMaterial(
+ CombType.ENERGETICALLOY,
+ new Materials[] { Materials.EnergeticAlloy },
+ new int[] { 80 * 100 },
+ new int[] {},
+ Voltage.HV,
+ ItemList.FR_RefractoryWax.get(1),
+ 50 * 100);
+ addCentrifugeToMaterial(
+ CombType.ELECTRICALSTEEL,
+ new Materials[] { Materials.ElectricalSteel },
+ new int[] { 100 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ ItemList.FR_RefractoryWax.get(1),
+ 50 * 100);
+ addCentrifugeToMaterial(
+ CombType.DARKSTEEL,
+ new Materials[] { Materials.DarkSteel },
+ new int[] { 100 * 100 },
+ new int[] {},
+ Voltage.MV,
+ ItemList.FR_RefractoryWax.get(1),
+ 50 * 100);
+ addCentrifugeToMaterial(
+ CombType.PULSATINGIRON,
+ new Materials[] { Materials.PulsatingIron },
+ new int[] { 80 * 100 },
+ new int[] {},
+ Voltage.HV,
+ ItemList.FR_RefractoryWax.get(1),
+ 50 * 100);
+ addCentrifugeToMaterial(
+ CombType.STAINLESSSTEEL,
+ new Materials[] { Materials.StainlessSteel },
+ new int[] { 50 * 100 },
+ new int[] {},
+ Voltage.HV,
+ ItemList.FR_RefractoryWax.get(1),
+ 50 * 100);
+ addCentrifugeToMaterial(
+ CombType.BEDROCKIUM,
+ new Materials[] { Materials.Bedrockium },
+ new int[] { 50 * 100 },
+ new int[] {},
+ Voltage.EV,
+ ItemList.FR_RefractoryWax.get(1),
+ 50 * 100);
+
+ } else {
+ addCentrifugeToMaterial(
+ CombType.REDALLOY,
+ new Materials[] { Materials.RedAlloy, Materials.Redstone, Materials.Copper },
+ new int[] { 100 * 100, 75 * 100, 90 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ ItemList.FR_RefractoryWax.get(1),
+ 50 * 100);
+ addCentrifugeToMaterial(
+ CombType.REDSTONEALLOY,
+ new Materials[] { Materials.RedstoneAlloy, Materials.Redstone, Materials.Silicon, Materials.Coal },
+ new int[] { 100 * 100, 90 * 100, 75 * 100, 75 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ ItemList.FR_RefractoryWax.get(1),
+ 50 * 100);
+ addCentrifugeToMaterial(
+ CombType.CONDUCTIVEIRON,
+ new Materials[] { Materials.ConductiveIron, Materials.Silver, Materials.Iron },
+ new int[] { 90 * 100, 55 * 100, 65 * 100 },
+ new int[] {},
+ Voltage.MV,
+ ItemList.FR_RefractoryWax.get(1),
+ 50 * 100);
+ addCentrifugeToMaterial(
+ CombType.VIBRANTALLOY,
+ new Materials[] { Materials.VibrantAlloy, Materials.Chrome },
+ new int[] { 70 * 100, 50 * 100 },
+ new int[] {},
+ Voltage.HV,
+ ItemList.FR_RefractoryWax.get(1),
+ 50 * 100);
+ addCentrifugeToMaterial(
+ CombType.ENERGETICALLOY,
+ new Materials[] { Materials.EnergeticAlloy, Materials.Gold },
+ new int[] { 80 * 100, 60 * 100 },
+ new int[] {},
+ Voltage.HV,
+ ItemList.FR_RefractoryWax.get(1),
+ 50 * 100);
+ addCentrifugeToMaterial(
+ CombType.ELECTRICALSTEEL,
+ new Materials[] { Materials.ElectricalSteel, Materials.Silicon, Materials.Coal },
+ new int[] { 100 * 100, 75 * 100, 75 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ ItemList.FR_RefractoryWax.get(1),
+ 50 * 100);
+ addCentrifugeToMaterial(
+ CombType.DARKSTEEL,
+ new Materials[] { Materials.DarkSteel, Materials.Coal },
+ new int[] { 100 * 100, 75 * 100 },
+ new int[] {},
+ Voltage.MV,
+ ItemList.FR_RefractoryWax.get(1),
+ 50 * 100);
+ addCentrifugeToMaterial(
+ CombType.PULSATINGIRON,
+ new Materials[] { Materials.PulsatingIron, Materials.Iron },
+ new int[] { 80 * 100, 75 * 100 },
+ new int[] {},
+ Voltage.HV,
+ ItemList.FR_RefractoryWax.get(1),
+ 50 * 100);
+ addCentrifugeToMaterial(
+ CombType.STAINLESSSTEEL,
+ new Materials[] { Materials.StainlessSteel, Materials.Iron, Materials.Chrome, Materials.Manganese,
+ Materials.Nickel },
+ new int[] { 50 * 100, 75 * 100, 55 * 100, 75 * 100, 75 * 100 },
+ new int[] {},
+ Voltage.HV,
+ ItemList.FR_RefractoryWax.get(1),
+ 50 * 100);
+ addCentrifugeToMaterial(
+ CombType.BEDROCKIUM,
+ new Materials[] { Materials.Bedrockium },
+ new int[] { 50 * 100 },
+ new int[] {},
+ Voltage.EV,
+ ItemList.FR_RefractoryWax.get(1),
+ 50 * 100);
+ }
+ // Thaumic
+ addProcessGT(CombType.THAUMIUMDUST, new Materials[] { Materials.Thaumium }, Voltage.MV);
+ addCentrifugeToItemStack(
+ CombType.THAUMIUMSHARD,
+ new ItemStack[] { GT_ModHandler.getModItem(MagicBees.ID, "propolis", 1, 1),
+ GT_ModHandler.getModItem(MagicBees.ID, "propolis", 1, 2),
+ GT_ModHandler.getModItem(MagicBees.ID, "propolis", 1, 3),
+ GT_ModHandler.getModItem(MagicBees.ID, "propolis", 1, 4),
+ GT_ModHandler.getModItem(MagicBees.ID, "propolis", 1, 5),
+ GT_ModHandler.getModItem(MagicBees.ID, "propolis", 1, 6),
+ GT_ModHandler.getModItem(MagicBees.ID, "wax", 1, 0) },
+ new int[] { 20 * 100, 20 * 100, 20 * 100, 20 * 100, 20 * 100, 20 * 100, 50 * 100 },
+ Voltage.ULV);
+ addProcessGT(CombType.AMBER, new Materials[] { Materials.Amber }, Voltage.LV);
+ addProcessGT(CombType.QUICKSILVER, new Materials[] { Materials.Cinnabar }, Voltage.LV);
+ addCentrifugeToItemStack(
+ CombType.SALISMUNDUS,
+ new ItemStack[] { GT_ModHandler.getModItem(Thaumcraft.ID, "ItemResource", 1, 14),
+ GT_ModHandler.getModItem(MagicBees.ID, "wax", 1, 0) },
+ new int[] { 100 * 100, 50 * 100 },
+ Voltage.MV);
+ addCentrifugeToItemStack(
+ CombType.TAINTED,
+ new ItemStack[] { GT_ModHandler.getModItem(Thaumcraft.ID, "ItemResource", 1, 11),
+ GT_ModHandler.getModItem(Thaumcraft.ID, "ItemResource", 1, 12),
+ GT_ModHandler.getModItem(Thaumcraft.ID, "blockTaintFibres", 1, 0),
+ GT_ModHandler.getModItem(Thaumcraft.ID, "blockTaintFibres", 1, 1),
+ GT_ModHandler.getModItem(Thaumcraft.ID, "blockTaintFibres", 1, 2),
+ GT_ModHandler.getModItem(MagicBees.ID, "wax", 1, 0) },
+ new int[] { 15 * 100, 15 * 100, 15 * 100, 15 * 100, 15 * 100, 50 * 100 },
+ Voltage.ULV);
+ addProcessGT(CombType.MITHRIL, new Materials[] { Materials.Mithril }, Voltage.HV);
+ addProcessGT(CombType.ASTRALSILVER, new Materials[] { Materials.AstralSilver }, Voltage.HV);
+ addCentrifugeToMaterial(
+ CombType.ASTRALSILVER,
+ new Materials[] { Materials.AstralSilver, Materials.Silver },
+ new int[] { 20 * 100, (GT_Mod.gregtechproxy.mNerfedCombs ? 10 : 75) * 100 },
+ new int[] {},
+ Voltage.HV,
+ GT_ModHandler.getModItem(MagicBees.ID, "wax", 1, 0),
+ 50 * 100);
+ addCentrifugeToItemStack(
+ CombType.THAUMINITE,
+ new ItemStack[] { GT_ModHandler.getModItem(ThaumicBases.ID, "resource", 1, 0),
+ GT_OreDictUnificator.get(OrePrefixes.dustTiny, Materials.Thaumium, 1),
+ GT_ModHandler.getModItem(MagicBees.ID, "wax", 1, 0) },
+ new int[] { 20 * 100, 10 * 100, 50 * 100 },
+ Voltage.HV);
+ addProcessGT(CombType.SHADOWMETAL, new Materials[] { Materials.Shadow }, Voltage.HV);
+ addCentrifugeToMaterial(
+ CombType.SHADOWMETAL,
+ new Materials[] { Materials.Shadow, Materials.ShadowSteel },
+ new int[] { (GT_Mod.gregtechproxy.mNerfedCombs ? 20 : 75) * 100, 10 * 100 },
+ new int[] {},
+ Voltage.HV,
+ GT_ModHandler.getModItem(MagicBees.ID, "wax", 1, 0),
+ 50 * 100);
+ addProcessGT(CombType.DIVIDED, new Materials[] { Materials.Diamond }, Voltage.HV);
+ addCentrifugeToItemStack(
+ CombType.DIVIDED,
+ new ItemStack[] { GT_ModHandler.getModItem(MagicBees.ID, "wax", 1, 0),
+ GT_ModHandler.getModItem(ExtraUtilities.ID, "unstableingot", 1, 1),
+ GT_OreDictUnificator.get(OrePrefixes.dustTiny, Materials.Iron, 1),
+ GT_OreDictUnificator.get(OrePrefixes.dustTiny, Materials.Diamond, 1) },
+ new int[] { 50 * 100, 20 * 100, (GT_Mod.gregtechproxy.mNerfedCombs ? 10 : 75) * 100,
+ (GT_Mod.gregtechproxy.mNerfedCombs ? 5 : 55) * 100 },
+ Voltage.HV);
+ addProcessGT(CombType.SPARKELING, new Materials[] { Materials.NetherStar }, Voltage.EV);
+ addCentrifugeToItemStack(
+ CombType.SPARKELING,
+ new ItemStack[] { GT_ModHandler.getModItem(MagicBees.ID, "wax", 1, 0),
+ GT_ModHandler.getModItem(MagicBees.ID, "miscResources", 2, 5),
+ GT_OreDictUnificator.get(OrePrefixes.dustTiny, Materials.NetherStar, 1) },
+ new int[] { 50 * 100, 10 * 100, (GT_Mod.gregtechproxy.mNerfedCombs ? 10 : 50) * 100 },
+ Voltage.EV);
+ if (GT_Mod.gregtechproxy.mNerfedCombs) {
+ addCentrifugeToMaterial(
+ CombType.THAUMIUMDUST,
+ new Materials[] { Materials.Thaumium },
+ new int[] { 100 * 100 },
+ new int[] {},
+ Voltage.MV,
+ GT_ModHandler.getModItem(MagicBees.ID, "wax", 1, 0),
+ 50 * 100);
+ addCentrifugeToItemStack(
+ CombType.QUICKSILVER,
+ new ItemStack[] { GT_ModHandler.getModItem(MagicBees.ID, "wax", 1, 0),
+ GT_ModHandler.getModItem(Thaumcraft.ID, "ItemNugget", 1, 5) },
+ new int[] { 50 * 100, 100 * 100 },
+ Voltage.ULV);
+ } else {
+ addCentrifugeToMaterial(
+ CombType.THAUMIUMDUST,
+ new Materials[] { Materials.Thaumium, Materials.Iron },
+ new int[] { 100 * 100, 75 * 100 },
+ new int[] {},
+ Voltage.MV,
+ GT_ModHandler.getModItem(MagicBees.ID, "wax", 1, 0),
+ 50 * 100);
+ addCentrifugeToMaterial(
+ CombType.AMBER,
+ new Materials[] { Materials.Amber },
+ new int[] { 100 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ GT_ModHandler.getModItem(MagicBees.ID, "wax", 1, 0),
+ 50 * 100);
+ addCentrifugeToItemStack(
+ CombType.QUICKSILVER,
+ new ItemStack[] { GT_ModHandler.getModItem(MagicBees.ID, "wax", 1, 0),
+ GT_ModHandler.getModItem(Thaumcraft.ID, "ItemNugget", 1, 5),
+ GT_OreDictUnificator.get(OrePrefixes.dustTiny, Materials.Cinnabar, 1) },
+ new int[] { 50 * 100, 100 * 100, 85 * 100 },
+ Voltage.ULV);
+ addCentrifugeToMaterial(
+ CombType.MITHRIL,
+ new Materials[] { Materials.Mithril, Materials.Platinum },
+ new int[] { 75 * 100, 55 * 100 },
+ new int[] {},
+ Voltage.HV,
+ GT_ModHandler.getModItem(MagicBees.ID, "wax", 1, 0),
+ 50 * 100);
+ }
+
+ // Gem Line
+ addProcessGT(CombType.STONE, new Materials[] { Materials.Soapstone }, Voltage.LV);
+ addProcessGT(CombType.CERTUS, new Materials[] { Materials.CertusQuartz }, Voltage.LV);
+ addProcessGT(CombType.FLUIX, new Materials[] { Materials.Fluix }, Voltage.LV);
+ addProcessGT(CombType.REDSTONE, new Materials[] { Materials.Redstone }, Voltage.LV);
+ addCentrifugeToMaterial(
+ CombType.RAREEARTH,
+ new Materials[] { Materials.RareEarth },
+ new int[] { 100 * 100 },
+ new int[] { 1 },
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addProcessGT(CombType.LAPIS, new Materials[] { Materials.Lapis }, Voltage.LV);
+ addProcessGT(CombType.RUBY, new Materials[] { Materials.Ruby }, Voltage.LV);
+ addProcessGT(CombType.REDGARNET, new Materials[] { Materials.GarnetRed }, Voltage.LV);
+ addProcessGT(CombType.YELLOWGARNET, new Materials[] { Materials.GarnetYellow }, Voltage.LV);
+ addProcessGT(CombType.SAPPHIRE, new Materials[] { Materials.Sapphire }, Voltage.LV);
+ addProcessGT(CombType.DIAMOND, new Materials[] { Materials.Diamond }, Voltage.LV);
+ addProcessGT(CombType.OLIVINE, new Materials[] { Materials.Olivine }, Voltage.LV);
+ addProcessGT(CombType.EMERALD, new Materials[] { Materials.Emerald }, Voltage.LV);
+ addProcessGT(CombType.FIRESTONE, new Materials[] { Materials.Firestone }, Voltage.LV);
+ addProcessGT(CombType.PYROPE, new Materials[] { Materials.Pyrope }, Voltage.LV);
+ addProcessGT(CombType.GROSSULAR, new Materials[] { Materials.Grossular }, Voltage.LV);
+ if (GT_Mod.gregtechproxy.mNerfedCombs) {
+ addCentrifugeToMaterial(
+ CombType.STONE,
+ new Materials[] { Materials.Stone, Materials.GraniteBlack, Materials.GraniteRed, Materials.Basalt,
+ Materials.Marble, Materials.Redrock },
+ new int[] { 70 * 100, 50 * 100, 50 * 100, 50 * 100, 50 * 100, 50 * 100 },
+ new int[] { 9, 9, 9, 9, 9, 9 },
+ Voltage.ULV,
+ NI,
+ 50 * 100);
+ addCentrifugeToMaterial(
+ CombType.FLUIX,
+ new Materials[] { Materials.Fluix },
+ new int[] { 25 * 100 },
+ new int[] { 9 },
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ } else {
+ addCentrifugeToMaterial(
+ CombType.STONE,
+ new Materials[] { Materials.Soapstone, Materials.Talc, Materials.Apatite, Materials.Phosphate,
+ Materials.TricalciumPhosphate },
+ new int[] { 95 * 100, 90 * 100, 80 * 100, 75 * 100, 75 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 50 * 100);
+ addCentrifugeToMaterial(
+ CombType.CERTUS,
+ new Materials[] { Materials.CertusQuartz, Materials.Quartzite, Materials.Barite },
+ new int[] { 100 * 100, 80 * 100, 75 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 50 * 100);
+ addCentrifugeToMaterial(
+ CombType.FLUIX,
+ new Materials[] { Materials.Fluix, Materials.Redstone, Materials.CertusQuartz, Materials.NetherQuartz },
+ new int[] { 25 * 100, 90 * 100, 90 * 100, 90 * 100 },
+ new int[] { 9, 1, 1, 1 },
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.REDSTONE,
+ new Materials[] { Materials.Redstone, Materials.Cinnabar },
+ new int[] { 100 * 100, 80 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.LAPIS,
+ new Materials[] { Materials.Lapis, Materials.Sodalite, Materials.Lazurite, Materials.Calcite },
+ new int[] { 100 * 100, 90 * 100, 90 * 100, 85 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.RUBY,
+ new Materials[] { Materials.Ruby, Materials.Redstone },
+ new int[] { 100 * 100, 90 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.REDGARNET,
+ new Materials[] { Materials.GarnetRed, Materials.GarnetYellow },
+ new int[] { 100 * 100, 75 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.YELLOWGARNET,
+ new Materials[] { Materials.GarnetYellow, Materials.GarnetRed },
+ new int[] { 100 * 100, 75 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.SAPPHIRE,
+ new Materials[] { Materials.Sapphire, Materials.GreenSapphire, Materials.Almandine, Materials.Pyrope },
+ new int[] { 100 * 100, 90 * 100, 90 * 100, 75 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.DIAMOND,
+ new Materials[] { Materials.Diamond, Materials.Graphite },
+ new int[] { 100 * 100, 75 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.OLIVINE,
+ new Materials[] { Materials.Olivine, Materials.Bentonite, Materials.Magnesite, Materials.Glauconite },
+ new int[] { 100 * 100, 90 * 100, 80 * 100, 75 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.EMERALD,
+ new Materials[] { Materials.Emerald, Materials.Beryllium, Materials.Thorium },
+ new int[] { 100 * 100, 85 * 100, 75 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.FIRESTONE,
+ new Materials[] { Materials.Firestone },
+ new int[] { 100 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ ItemList.FR_RefractoryWax.get(1),
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.PYROPE,
+ new Materials[] { Materials.Pyrope, Materials.Aluminium, Materials.Magnesium, Materials.Silicon },
+ new int[] { 100 * 100, 75 * 100, 80 * 100, 75 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.GROSSULAR,
+ new Materials[] { Materials.Grossular, Materials.Aluminium, Materials.Silicon },
+ new int[] { 100 * 100, 75 * 100, 75 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ }
+
+ // Metals Line
+ addProcessGT(CombType.SLAG, new Materials[] { Materials.Limestone }, Voltage.LV);
+ addProcessGT(CombType.COPPER, new Materials[] { Materials.Copper }, Voltage.LV);
+ addProcessGT(CombType.TIN, new Materials[] { Materials.Tin }, Voltage.LV);
+ addProcessGT(CombType.LEAD, new Materials[] { Materials.Lead }, Voltage.LV);
+ addProcessGT(CombType.INDIUM, new Materials[] { Materials.Indium }, Voltage.ZPM);
+ addProcessGT(CombType.NICKEL, new Materials[] { Materials.Nickel }, Voltage.LV);
+ addProcessGT(CombType.ZINC, new Materials[] { Materials.Zinc }, Voltage.LV);
+ addProcessGT(CombType.SILVER, new Materials[] { Materials.Silver }, Voltage.LV);
+ addProcessGT(CombType.CRYOLITE, new Materials[] { Materials.Cryolite }, Voltage.LV);
+ addProcessGT(CombType.GOLD, new Materials[] { Materials.Gold }, Voltage.LV);
+ addProcessGT(CombType.SULFUR, new Materials[] { Materials.Sulfur }, Voltage.LV);
+ addProcessGT(CombType.GALLIUM, new Materials[] { Materials.Gallium }, Voltage.LV);
+ addProcessGT(CombType.ARSENIC, new Materials[] { Materials.Arsenic }, Voltage.LV);
+ addProcessGT(CombType.IRON, new Materials[] { Materials.Iron }, Voltage.LV);
+ addProcessGT(CombType.STEEL, new Materials[] { Materials.Steel }, Voltage.LV);
+ if (GT_Mod.gregtechproxy.mNerfedCombs) {
+ addCentrifugeToMaterial(
+ CombType.SLAG,
+ new Materials[] { Materials.Stone, Materials.GraniteBlack, Materials.GraniteRed },
+ new int[] { 50 * 100, 20 * 100, 20 * 100 },
+ new int[] { 9, 9, 9 },
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.COPPER,
+ new Materials[] { Materials.Copper },
+ new int[] { 70 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.TIN,
+ new Materials[] { Materials.Tin },
+ new int[] { 60 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.LEAD,
+ new Materials[] { Materials.Lead },
+ new int[] { 45 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.IRON,
+ new Materials[] { Materials.Iron },
+ new int[] { 30 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.STEEL,
+ new Materials[] { Materials.Steel },
+ new int[] { 40 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.SILVER,
+ new Materials[] { Materials.Silver },
+ new int[] { 80 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.CRYOLITE,
+ new Materials[] { Materials.Cryolite },
+ new int[] { 80 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.SULFUR,
+ new Materials[] { Materials.Sulfur },
+ new int[] { 100 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ } else {
+ addCentrifugeToMaterial(
+ CombType.SLAG,
+ new Materials[] { Materials.Salt, Materials.RockSalt, Materials.Lepidolite, Materials.Spodumene,
+ Materials.Monazite },
+ new int[] { 100 * 100, 100 * 100, 100 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.COPPER,
+ new Materials[] { Materials.Copper, Materials.Tetrahedrite, Materials.Chalcopyrite, Materials.Malachite,
+ Materials.Pyrite, Materials.Stibnite },
+ new int[] { 100 * 100, 85 * 100, 95 * 100, 80 * 100, 75 * 100, 65 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.TIN,
+ new Materials[] { Materials.Tin, Materials.Cassiterite, Materials.CassiteriteSand },
+ new int[] { 100 * 100, 85 * 100, 65 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.LEAD,
+ new Materials[] { Materials.Lead, Materials.Galena },
+ new int[] { 100 * 100, 75 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+
+ addCentrifugeToMaterial(
+ CombType.IRON,
+ new Materials[] { Materials.Iron, Materials.Magnetite, Materials.BrownLimonite,
+ Materials.YellowLimonite, Materials.VanadiumMagnetite, Materials.MeteoricIron },
+ new int[] { 100 * 100, 90 * 100, 85 * 100, 85 * 100, 80 * 100, 75 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.LEAD,
+ new Materials[] { Materials.Steel, Materials.Magnetite, Materials.VanadiumMagnetite,
+ Materials.Molybdenite, Materials.Molybdenum, Materials.MeteoricIron },
+ new int[] { 100 * 100, 90 * 100, 80 * 100, 65 * 100, 65 * 100, 75 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+
+ addCentrifugeToMaterial(
+ CombType.NICKEL,
+ new Materials[] { Materials.Nickel, Materials.Garnierite, Materials.Pentlandite, Materials.Cobaltite,
+ Materials.Wulfenite, Materials.Powellite },
+ new int[] { 100 * 100, 85 * 100, 85 * 100, 80 * 100, 75 * 100, 75 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.ZINC,
+ new Materials[] { Materials.Zinc, Materials.Sphalerite, Materials.Sulfur },
+ new int[] { 100 * 100, 80 * 100, 75 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.SILVER,
+ new Materials[] { Materials.Silver, Materials.Galena },
+ new int[] { 100 * 100, 80 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.CRYOLITE,
+ new Materials[] { Materials.Cryolite, Materials.Silver },
+ new int[] { 100 * 100, 80 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.GOLD,
+ new Materials[] { Materials.Gold },
+ new int[] { 100 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.SULFUR,
+ new Materials[] { Materials.Sulfur, Materials.Pyrite, Materials.Sphalerite },
+ new int[] { 100 * 100, 90 * 100, 80 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.GALLIUM,
+ new Materials[] { Materials.Gallium, Materials.Niobium },
+ new int[] { 80 * 100, 75 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.ARSENIC,
+ new Materials[] { Materials.Arsenic, Materials.Bismuth, Materials.Antimony },
+ new int[] { 80 * 100, 70 * 100, 70 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ }
+
+ // Rare Metals Line
+ addProcessGT(CombType.BAUXITE, new Materials[] { Materials.Bauxite }, Voltage.LV);
+ addProcessGT(CombType.ALUMINIUM, new Materials[] { Materials.Aluminium }, Voltage.LV);
+ addProcessGT(CombType.MANGANESE, new Materials[] { Materials.Manganese }, Voltage.LV);
+ addProcessGT(CombType.TITANIUM, new Materials[] { Materials.Titanium }, Voltage.EV);
+ addProcessGT(CombType.MAGNESIUM, new Materials[] { Materials.Magnesium }, Voltage.LV);
+ addProcessGT(CombType.CHROME, new Materials[] { Materials.Chrome }, Voltage.HV);
+ addProcessGT(CombType.TUNGSTEN, new Materials[] { Materials.Tungsten }, Voltage.IV);
+ addProcessGT(CombType.PLATINUM, new Materials[] { Materials.Platinum }, Voltage.HV);
+ addProcessGT(CombType.MOLYBDENUM, new Materials[] { Materials.Molybdenum }, Voltage.LV);
+ addProcessGT(CombType.IRIDIUM, new Materials[] { Materials.Iridium }, Voltage.IV);
+ addProcessGT(CombType.PALLADIUM, new Materials[] { Materials.Palladium }, Voltage.IV);
+ addProcessGT(CombType.OSMIUM, new Materials[] { Materials.Osmium }, Voltage.IV);
+ addProcessGT(CombType.LITHIUM, new Materials[] { Materials.Lithium }, Voltage.MV);
+ addProcessGT(CombType.ELECTROTINE, new Materials[] { Materials.Electrotine }, Voltage.MV);
+ addProcessGT(CombType.DRACONIC, new Materials[] { Materials.Draconium }, Voltage.IV);
+ addProcessGT(CombType.AWAKENEDDRACONIUM, new Materials[] { Materials.DraconiumAwakened }, Voltage.ZPM);
+ if (GT_Mod.gregtechproxy.mNerfedCombs) {
+ addCentrifugeToItemStack(
+ CombType.SALT,
+ new ItemStack[] { GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Salt, 6),
+ GT_OreDictUnificator.get(OrePrefixes.dust, Materials.RockSalt, 6), ItemList.FR_Wax.get(1),
+ GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Saltpeter, 6) },
+ new int[] { 100 * 100, 100 * 100, 50 * 100, 25 * 100 },
+ Voltage.MV,
+ 160);
+ } else {
+ addCentrifugeToMaterial(
+ CombType.BAUXITE,
+ new Materials[] { Materials.Bauxite, Materials.Aluminium },
+ new int[] { 75 * 100, 55 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.ALUMINIUM,
+ new Materials[] { Materials.Aluminium, Materials.Bauxite },
+ new int[] { 60 * 100, 80 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.MANGANESE,
+ new Materials[] { Materials.Manganese, Materials.Grossular, Materials.Spessartine, Materials.Pyrolusite,
+ Materials.Tantalite },
+ new int[] { 30 * 100, 100 * 100, 100 * 100, 100 * 100, 100 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.TITANIUM,
+ new Materials[] { Materials.Titanium, Materials.Ilmenite, Materials.Bauxite, Materials.Rutile },
+ new int[] { 90 * 100, 80 * 100, 75 * 100, 75 * 100 },
+ new int[] {},
+ Voltage.EV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.MAGNESIUM,
+ new Materials[] { Materials.Magnesium, Materials.Magnesite },
+ new int[] { 100 * 100, 80 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.CHROME,
+ new Materials[] { Materials.Chrome, Materials.Ruby, Materials.Chromite, Materials.Redstone,
+ Materials.Neodymium, Materials.Bastnasite },
+ new int[] { 50 * 100, 100 * 100, 50 * 100, 100 * 100, 80 * 100, 80 * 100 },
+ new int[] {},
+ Voltage.HV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.TUNGSTEN,
+ new Materials[] { Materials.Tungsten, Materials.Tungstate, Materials.Scheelite, Materials.Lithium },
+ new int[] { 50 * 100, 80 * 100, 75 * 100, 75 * 100 },
+ new int[] {},
+ Voltage.IV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.PLATINUM,
+ new Materials[] { Materials.Platinum, Materials.Cooperite, Materials.Palladium },
+ new int[] { 40 * 100, 40 * 100, 40 * 100 },
+ new int[] {},
+ Voltage.HV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.MOLYBDENUM,
+ new Materials[] { Materials.Molybdenum, Materials.Molybdenite, Materials.Powellite,
+ Materials.Wulfenite },
+ new int[] { 100 * 100, 80 * 100, 75 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.IRIDIUM,
+ new Materials[] { Materials.Iridium, Materials.Osmium },
+ new int[] { 20 * 100, 15 * 100 },
+ new int[] {},
+ Voltage.IV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.OSMIUM,
+ new Materials[] { Materials.Osmium, Materials.Iridium },
+ new int[] { 25 * 100, 15 * 100 },
+ new int[] {},
+ Voltage.IV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.LITHIUM,
+ new Materials[] { Materials.Lithium, Materials.Aluminium },
+ new int[] { 85 * 100, 75 * 100 },
+ new int[] {},
+ Voltage.MV,
+ NI,
+ 30 * 100);
+ addCentrifugeToItemStack(
+ CombType.SALT,
+ new ItemStack[] { GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Salt, 6),
+ GT_OreDictUnificator.get(OrePrefixes.dust, Materials.RockSalt, 6), ItemList.FR_Wax.get(1),
+ GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Saltpeter, 6) },
+ new int[] { 100 * 100, 100 * 100, 50 * 100, 25 * 100 },
+ Voltage.MV,
+ 160);
+ }
+
+ // Radioactive Line
+ addProcessGT(CombType.ALMANDINE, new Materials[] { Materials.Almandine }, Voltage.LV);
+ addProcessGT(CombType.URANIUM, new Materials[] { Materials.Uranium }, Voltage.EV);
+ addProcessGT(CombType.PLUTONIUM, new Materials[] { Materials.Plutonium }, Voltage.EV);
+ addProcessGT(CombType.NAQUADAH, new Materials[] { Materials.Naquadah }, Voltage.IV);
+ addProcessGT(CombType.NAQUADRIA, new Materials[] { Materials.Naquadria }, Voltage.LuV);
+ addProcessGT(CombType.THORIUM, new Materials[] { Materials.Thorium }, Voltage.EV);
+ addProcessGT(CombType.LUTETIUM, new Materials[] { Materials.Lutetium }, Voltage.IV);
+ addProcessGT(CombType.AMERICIUM, new Materials[] { Materials.Americium }, Voltage.LuV);
+ addProcessGT(CombType.NEUTRONIUM, new Materials[] { Materials.Neutronium }, Voltage.UHV);
+ if (!GT_Mod.gregtechproxy.mNerfedCombs) {
+ addCentrifugeToMaterial(
+ CombType.ALMANDINE,
+ new Materials[] { Materials.Almandine, Materials.Pyrope, Materials.Sapphire, Materials.GreenSapphire },
+ new int[] { 90 * 100, 80 * 100, 75 * 100, 75 * 100 },
+ new int[] {},
+ Voltage.ULV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.URANIUM,
+ new Materials[] { Materials.Uranium, Materials.Pitchblende, Materials.Uraninite, Materials.Uranium235 },
+ new int[] { 50 * 100, 65 * 100, 75 * 100, 50 * 100 },
+ new int[] {},
+ Voltage.EV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.PLUTONIUM,
+ new Materials[] { Materials.Plutonium, Materials.Uranium235 },
+ new int[] { 10, 5 },
+ new int[] {},
+ Voltage.EV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.NAQUADAH,
+ new Materials[] { Materials.Naquadah, Materials.NaquadahEnriched, Materials.Naquadria },
+ new int[] { 10 * 100, 5 * 100, 5 * 100 },
+ new int[] {},
+ Voltage.IV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.NAQUADRIA,
+ new Materials[] { Materials.Naquadria, Materials.NaquadahEnriched, Materials.Naquadah },
+ new int[] { 10 * 100, 10 * 100, 15 * 100 },
+ new int[] {},
+ Voltage.LuV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.THORIUM,
+ new Materials[] { Materials.Thorium, Materials.Uranium, Materials.Coal },
+ new int[] { 75 * 100, 75 * 100 * 100, 95 * 100 },
+ new int[] {},
+ Voltage.EV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.LUTETIUM,
+ new Materials[] { Materials.Lutetium, Materials.Thorium },
+ new int[] { 35 * 100, 55 * 100 },
+ new int[] {},
+ Voltage.IV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.AMERICIUM,
+ new Materials[] { Materials.Americium, Materials.Lutetium },
+ new int[] { 25 * 100, 45 * 100 },
+ new int[] {},
+ Voltage.LuV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.NEUTRONIUM,
+ new Materials[] { Materials.Neutronium, Materials.Americium },
+ new int[] { 15 * 100, 35 * 100 },
+ new int[] {},
+ Voltage.UHV,
+ NI,
+ 30 * 100);
+ }
+
+ // Twilight
+ addCentrifugeToItemStack(
+ CombType.NAGA,
+ new ItemStack[] { GT_ModHandler.getModItem(MagicBees.ID, "propolis", 1L, 4),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.NagaScaleChip", 1L, 0),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.NagaScaleFragment", 1L, 0),
+ ItemList.FR_Wax.get(1) },
+ new int[] { 5 * 100, 33 * 100, 8 * 100, 30 * 100 },
+ Voltage.MV);
+ addCentrifugeToItemStack(
+ CombType.LICH,
+ new ItemStack[] { GT_ModHandler.getModItem(MagicBees.ID, "propolis", 1L, 5),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.LichBoneChip", 1L, 0),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.LichBoneFragment", 1L, 0),
+ ItemList.FR_Wax.get(1) },
+ new int[] { 5 * 100, 33 * 100, 8 * 100, 30 * 100 },
+ Voltage.HV);
+ addCentrifugeToItemStack(
+ CombType.HYDRA,
+ new ItemStack[] { GT_ModHandler.getModItem(MagicBees.ID, "propolis", 1L, 1),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.FieryBloodDrop", 1L, 0),
+ GT_Bees.drop.getStackForType(DropType.HYDRA), ItemList.FR_Wax.get(1) },
+ new int[] { 5 * 100, 33 * 100, 8 * 100, 30 * 100 },
+ Voltage.HV);
+ addCentrifugeToItemStack(
+ CombType.URGHAST,
+ new ItemStack[] { GT_ModHandler.getModItem(MagicBees.ID, "propolis", 1L, 2),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.CarminiteChip", 1L, 0),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.CarminiteFragment", 1L, 0),
+ ItemList.FR_Wax.get(1) },
+ new int[] { 5 * 100, 33 * 100, 8 * 100, 30 * 100 },
+ Voltage.EV);
+ addCentrifugeToItemStack(
+ CombType.SNOWQUEEN,
+ new ItemStack[] { GT_ModHandler.getModItem(MagicBees.ID, "propolis", 1L, 3),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.SnowQueenBloodDrop", 1L, 0),
+ GT_Bees.drop.getStackForType(DropType.SNOW_QUEEN), ItemList.FR_Wax.get(1) },
+ new int[] { 5 * 100, 33 * 100, 8 * 100, 30 * 100 },
+ Voltage.EV);
+
+ // HEE
+ addCentrifugeToItemStack(
+ CombType.ENDDUST,
+ new ItemStack[] { GT_ModHandler.getModItem(MagicBees.ID, "wax", 1L, 0),
+ GT_Bees.propolis.getStackForType(PropolisType.End), GT_Bees.drop.getStackForType(DropType.ENDERGOO),
+ Materials.Endstone.getBlocks(4) },
+ new int[] { 20 * 100, 15 * 100, 10 * 100, 100 * 100 },
+ Voltage.HV);
+ addCentrifugeToItemStack(
+ CombType.STARDUST,
+ new ItemStack[] { GT_ModHandler.getModItem(MagicBees.ID, "wax", 1L, 0),
+ GT_Bees.propolis.getStackForType(PropolisType.Stardust),
+ GT_Bees.drop.getStackForType(DropType.ENDERGOO) },
+ new int[] { 20 * 100, 15 * 100, 10 * 100 },
+ Voltage.HV);
+ addCentrifugeToItemStack(
+ CombType.ECTOPLASMA,
+ new ItemStack[] { GT_ModHandler.getModItem(MagicBees.ID, "wax", 1L, 0),
+ GT_Bees.propolis.getStackForType(PropolisType.Ectoplasma),
+ GT_Bees.drop.getStackForType(DropType.ENDERGOO) },
+ new int[] { 25 * 100, 10 * 100, 15 * 100 },
+ Voltage.EV);
+ addCentrifugeToItemStack(
+ CombType.ARCANESHARD,
+ new ItemStack[] { GT_ModHandler.getModItem(MagicBees.ID, "wax", 1L, 0),
+ GT_Bees.propolis.getStackForType(PropolisType.Arcaneshard),
+ GT_Bees.drop.getStackForType(DropType.ENDERGOO) },
+ new int[] { 25 * 100, 10 * 100, 15 * 100 },
+ Voltage.EV);
+ addCentrifugeToItemStack(
+ CombType.DRAGONESSENCE,
+ new ItemStack[] { GT_ModHandler.getModItem(MagicBees.ID, "wax", 1L, 0),
+ GT_Bees.propolis.getStackForType(PropolisType.Dragonessence),
+ GT_Bees.drop.getStackForType(DropType.ENDERGOO) },
+ new int[] { 30 * 100, (int) (7.5 * 100), 20 * 100 },
+ Voltage.IV);
+ addCentrifugeToItemStack(
+ CombType.ENDERMAN,
+ new ItemStack[] { GT_ModHandler.getModItem(MagicBees.ID, "wax", 1L, 0),
+ GT_Bees.propolis.getStackForType(PropolisType.Enderman),
+ GT_Bees.drop.getStackForType(DropType.ENDERGOO) },
+ new int[] { 3000, 750, 2000 },
+ Voltage.IV);
+ addCentrifugeToItemStack(
+ CombType.SILVERFISH,
+ new ItemStack[] { GT_ModHandler.getModItem(MagicBees.ID, "wax", 1L, 0),
+ GT_Bees.propolis.getStackForType(PropolisType.Silverfish),
+ GT_Bees.drop.getStackForType(DropType.ENDERGOO), new ItemStack(Items.spawn_egg, 1, 60) },
+ new int[] { 25 * 100, 10 * 100, 20 * 100, 15 * 100 },
+ Voltage.EV);
+ addProcessGT(CombType.ENDIUM, new Materials[] { Materials.HeeEndium }, Voltage.HV);
+ if (!GT_Mod.gregtechproxy.mNerfedCombs) {
+ addCentrifugeToMaterial(
+ CombType.ENDIUM,
+ new Materials[] { Materials.HeeEndium },
+ new int[] { 50 * 100 },
+ new int[] {},
+ Voltage.HV,
+ GT_ModHandler.getModItem(MagicBees.ID, "wax", 1L, 0),
+ 20 * 100);
+ }
+ addCentrifugeToItemStack(
+ CombType.RUNEI,
+ new ItemStack[] { GT_ModHandler.getModItem(MagicBees.ID, "wax", 1L, 0),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.RuneOfPowerFragment", 1L, 0),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.RuneOfAgilityFragment", 1L, 0),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.RuneOfVigorFragment", 1L, 0),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.RuneOfDefenseFragment", 1L, 0),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.RuneOfMagicFragment", 1L, 0) },
+ new int[] { 25 * 100, 5 * 100, 5 * 100, 5 * 100, 5 * 100, 5 * 100 },
+ Voltage.IV);
+ addCentrifugeToItemStack(
+ CombType.RUNEII,
+ new ItemStack[] { GT_ModHandler.getModItem(MagicBees.ID, "wax", 1L, 0),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.RuneOfVoidFragment", 1L, 0) },
+ new int[] { 50 * 100, (int) (2.5 * 100) },
+ Voltage.IV);
+ addCentrifugeToItemStack(
+ CombType.FIREESSENSE,
+ new ItemStack[] { GT_ModHandler.getModItem(MagicBees.ID, "wax", 1L, 0),
+ GT_Bees.propolis.getStackForType(PropolisType.Fireessence),
+ GT_Bees.drop.getStackForType(DropType.ENDERGOO) },
+ new int[] { 30 * 100, (int) (7.5 * 100), 20 * 100 },
+ Voltage.IV);
+ // Walrus Recipe
+ if (AE2FluidCraft.isModLoaded()) {
+ addCentrifugeToItemStack(
+ CombType.WALRUS,
+ new ItemStack[] { GT_ModHandler.getModItem(AE2FluidCraft.ID, "walrus", 1L, 0) },
+ new int[] { 100 * 100 },
+ Voltage.LV);
+ }
+ // Space Line
+ addCentrifugeToItemStack(
+ CombType.SPACE,
+ new ItemStack[] { ItemList.FR_Wax.get(1L), ItemList.FR_RefractoryWax.get(1L),
+ GT_Bees.drop.getStackForType(DropType.OXYGEN),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.CoinSpace", 1L, 0) },
+ new int[] { 50 * 100, 30 * 100, 15 * 100, 5 * 100 },
+ Voltage.HV);
+ addProcessGT(CombType.METEORICIRON, new Materials[] { Materials.MeteoricIron }, Voltage.HV);
+ addProcessGT(CombType.DESH, new Materials[] { Materials.Desh }, Voltage.EV);
+ addProcessGT(CombType.LEDOX, new Materials[] { Materials.Ledox }, Voltage.EV);
+ addProcessGT(CombType.CALLISTOICE, new Materials[] { Materials.CallistoIce }, Voltage.IV);
+ addProcessGT(CombType.MYTRYL, new Materials[] { Materials.Mytryl }, Voltage.IV);
+ addProcessGT(CombType.QUANTIUM, new Materials[] { Materials.Quantium }, Voltage.IV);
+ addProcessGT(CombType.ORIHARUKON, new Materials[] { Materials.Oriharukon }, Voltage.IV);
+ addProcessGT(CombType.INFUSEDGOLD, new Materials[] { Materials.InfusedGold }, Voltage.IV);
+ addCentrifugeToMaterial(
+ CombType.INFUSEDGOLD,
+ new Materials[] { Materials.InfusedGold, Materials.Gold },
+ new int[] { (GT_Mod.gregtechproxy.mNerfedCombs ? 20 : 50) * 100,
+ (GT_Mod.gregtechproxy.mNerfedCombs ? 10 : 30) * 100 },
+ new int[] {},
+ Voltage.IV,
+ 200,
+ NI,
+ 10 * 100);
+ addProcessGT(CombType.MYSTERIOUSCRYSTAL, new Materials[] { Materials.MysteriousCrystal }, Voltage.LuV);
+ addCentrifugeToMaterial(
+ CombType.MYSTERIOUSCRYSTAL,
+ new Materials[] { Materials.MysteriousCrystal },
+ new int[] { (GT_Mod.gregtechproxy.mNerfedCombs ? 10 : 40) * 100,
+ (GT_Mod.gregtechproxy.mNerfedCombs ? 15 : 50) * 100 },
+ new int[] {},
+ Voltage.LuV,
+ 512,
+ NI,
+ 50 * 100);
+ addProcessGT(CombType.BLACKPLUTONIUM, new Materials[] { Materials.BlackPlutonium }, Voltage.LuV);
+ addProcessGT(CombType.TRINIUM, new Materials[] { Materials.Trinium }, Voltage.ZPM);
+ if (!GT_Mod.gregtechproxy.mNerfedCombs) {
+ addCentrifugeToMaterial(
+ CombType.METEORICIRON,
+ new Materials[] { Materials.MeteoricIron, Materials.Iron },
+ new int[] { 85 * 100, 100 * 100 },
+ new int[] {},
+ Voltage.HV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.DESH,
+ new Materials[] { Materials.Desh, Materials.Titanium },
+ new int[] { 75 * 100, 50 * 100 },
+ new int[] {},
+ Voltage.EV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.LEDOX,
+ new Materials[] { Materials.Ledox, Materials.CallistoIce, Materials.Lead },
+ new int[] { 65 * 100, 55 * 100, 85 * 100 },
+ new int[] {},
+ Voltage.EV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.CALLISTOICE,
+ new Materials[] { Materials.CallistoIce, Materials.Ledox, Materials.Lead },
+ new int[] { 65 * 100, 75 * 100, 100 * 100 },
+ new int[] {},
+ Voltage.IV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.MYTRYL,
+ new Materials[] { Materials.Mytryl, Materials.Mithril },
+ new int[] { 55 * 100, 50 * 100 },
+ new int[] {},
+ Voltage.IV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.QUANTIUM,
+ new Materials[] { Materials.Quantium, Materials.Osmium },
+ new int[] { 50 * 100, 60 * 100 },
+ new int[] {},
+ Voltage.IV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.ORIHARUKON,
+ new Materials[] { Materials.Oriharukon, Materials.Lead },
+ new int[] { 50 * 100, 75 * 100 },
+ new int[] {},
+ Voltage.IV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.BLACKPLUTONIUM,
+ new Materials[] { Materials.BlackPlutonium, Materials.Plutonium },
+ new int[] { 25 * 100, 50 * 100 },
+ new int[] {},
+ Voltage.LuV,
+ NI,
+ 30 * 100);
+ addCentrifugeToMaterial(
+ CombType.TRINIUM,
+ new Materials[] { Materials.Trinium, Materials.Iridium },
+ new int[] { 35 * 100, 45 * 100 },
+ new int[] {},
+ Voltage.ZPM,
+ NI,
+ 30 * 100);
+ }
+
+ // Planet Line
+ addCentrifugeToItemStack(
+ CombType.MOON,
+ new ItemStack[] { ItemList.FR_Wax.get(1L),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.MoonStoneDust", 1L, 0) },
+ new int[] { 50 * 100, 30 * 100 },
+ Voltage.MV,
+ 300);
+ addCentrifugeToItemStack(
+ CombType.MARS,
+ new ItemStack[] { ItemList.FR_Wax.get(1L),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.MarsStoneDust", 1L, 0) },
+ new int[] { 50 * 100, 30 * 100 },
+ Voltage.HV,
+ 300);
+ addCentrifugeToItemStack(
+ CombType.JUPITER,
+ new ItemStack[] { GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.IoStoneDust", 1L, 0),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.EuropaIceDust", 1L, 0),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.EuropaStoneDust", 1L, 0),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.GanymedeStoneDust", 1L, 0),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.CallistoStoneDust", 1L, 0),
+ GT_OreDictUnificator.get(OrePrefixes.dustTiny, Materials.CallistoIce, 1L), ItemList.FR_Wax.get(1L) },
+ new int[] { 30 * 100, 30 * 100, 30 * 100, 30 * 100, 30 * 100, 5 * 100, 50 * 100 },
+ Voltage.HV,
+ 300);
+ addCentrifugeToItemStack(
+ CombType.MERCURY,
+ new ItemStack[] { ItemList.FR_Wax.get(1L),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.MercuryCoreDust", 1L, 0),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.MercuryStoneDust", 1L, 0) },
+ new int[] { 50 * 100, 30 * 100, 30 * 100 },
+ Voltage.EV,
+ 300);
+ addCentrifugeToItemStack(
+ CombType.VENUS,
+ new ItemStack[] { ItemList.FR_Wax.get(1L),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.VenusStoneDust", 1L, 0) },
+ new int[] { 50 * 100, 30 * 100 },
+ Voltage.EV,
+ 300);
+ addCentrifugeToItemStack(
+ CombType.SATURN,
+ new ItemStack[] { ItemList.FR_Wax.get(1L),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.EnceladusStoneDust", 1L, 0),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.TitanStoneDust", 1L, 0) },
+ new int[] { 50 * 100, 30 * 100, 30 * 100 },
+ Voltage.IV,
+ 300);
+ addCentrifugeToItemStack(
+ CombType.URANUS,
+ new ItemStack[] { ItemList.FR_Wax.get(1L),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.MirandaStoneDust", 1L, 0),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.OberonStoneDust", 1L, 0) },
+ new int[] { 50 * 100, 30 * 100, 30 * 100 },
+ Voltage.IV,
+ 300);
+ addCentrifugeToItemStack(
+ CombType.NEPTUN,
+ new ItemStack[] { ItemList.FR_Wax.get(1L),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.ProteusStoneDust", 1L, 0),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.TritonStoneDust", 1L, 0) },
+ new int[] { 50 * 100, 30 * 100, 30 * 100 },
+ Voltage.IV,
+ 300);
+ addCentrifugeToItemStack(
+ CombType.PLUTO,
+ new ItemStack[] { ItemList.FR_Wax.get(1L),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.PlutoStoneDust", 1L, 0),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.PlutoIceDust", 1L, 0) },
+ new int[] { 50 * 100, 30 * 100, 30 * 100 },
+ Voltage.LuV,
+ 300);
+ addCentrifugeToItemStack(
+ CombType.HAUMEA,
+ new ItemStack[] { ItemList.FR_Wax.get(1L),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.HaumeaStoneDust", 1L, 0) },
+ new int[] { 50 * 100, 30 * 100 },
+ Voltage.LuV,
+ 300);
+ addCentrifugeToItemStack(
+ CombType.MAKEMAKE,
+ new ItemStack[] { ItemList.FR_Wax.get(1L),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.MakeMakeStoneDust", 1L, 0) },
+ new int[] { 50 * 100, 30 * 100 },
+ Voltage.LuV,
+ 300);
+ addCentrifugeToItemStack(
+ CombType.CENTAURI,
+ new ItemStack[] { ItemList.FR_Wax.get(1L),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.CentauriASurfaceDust", 1L, 0),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.CentauriAStoneDust", 1L, 0) },
+ new int[] { 50 * 100, 30 * 100, 30 * 100 },
+ Voltage.ZPM,
+ 300);
+ addCentrifugeToItemStack(
+ CombType.TCETI,
+ new ItemStack[] { ItemList.FR_Wax.get(1L),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.TCetiEStoneDust", 1L, 0) },
+ new int[] { 50 * 100, 30 * 100 },
+ Voltage.ZPM,
+ 300);
+ addCentrifugeToItemStack(
+ CombType.BARNARDA,
+ new ItemStack[] { ItemList.FR_Wax.get(1L),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.BarnardaEStoneDust", 1L, 0),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.BarnardaFStoneDust", 1L, 0) },
+ new int[] { 50 * 100, 30 * 100, 30 * 100 },
+ Voltage.ZPM,
+ 300);
+ addCentrifugeToItemStack(
+ CombType.VEGA,
+ new ItemStack[] { ItemList.FR_Wax.get(1L),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.VegaBStoneDust", 1L, 0) },
+ new int[] { 50 * 100, 30 * 100 },
+ Voltage.ZPM,
+ 300);
+ if (GalaxySpace.isModLoaded()) {
+ addCentrifugeToItemStack(
+ CombType.SEAWEED,
+ new ItemStack[] { ItemList.FR_Wax.get(1L),
+ GT_ModHandler.getModItem(GalaxySpace.ID, "tcetiedandelions", 1L, 0) },
+ new int[] { 50 * 100, 100 * 100 },
+ Voltage.UV,
+ 100);
+ }
+ // Infinity Line
+ addCentrifugeToMaterial(
+ CombType.INFINITYCATALYST,
+ new Materials[] { Materials.InfinityCatalyst, Materials.Neutronium },
+ new int[] { 25 * 100, 20 * 100 },
+ new int[] {},
+ Voltage.ZPM,
+ 100,
+ NI,
+ 50 * 100);
+
+ // (Noble)gas Line
+ addFluidExtractorProcess(CombType.HELIUM, Materials.Helium.getGas(250), Voltage.HV);
+ addFluidExtractorProcess(CombType.ARGON, Materials.Argon.getGas(250), Voltage.MV);
+ addFluidExtractorProcess(CombType.NITROGEN, Materials.Nitrogen.getGas(500), Voltage.MV);
+ addFluidExtractorProcess(CombType.HYDROGEN, Materials.Hydrogen.getGas(500), Voltage.MV);
+ addFluidExtractorProcess(CombType.FLUORINE, Materials.Fluorine.getGas(250), Voltage.MV);
+ addFluidExtractorProcess(CombType.OXYGEN, Materials.Oxygen.getGas(500), Voltage.MV);
+ // Organic part 2, unknown liquid
+ // yes, unknowwater. It's not a typo, it's how it is spelled. Stupid game.
+ addFluidExtractorProcess(CombType.UNKNOWNWATER, FluidRegistry.getFluidStack("unknowwater", 250), Voltage.ZPM);
+ /*
+ * TODO: update this comment
+ * The Centrifuge Recipes for Infused Shards and Nether/End-Shard from the Infused Shard Line are below the
+ * NobleGas Lines for Xenon and co. in GT_MachineRecipeLoader.java In Lines 1525
+ */
+ }
+
+ /**
+ * Currently only used for CombType.MOLYBDENUM
+ *
+ * @param circuitNumber should not conflict with addProcessGT
+ *
+ **/
+ public void addAutoclaveProcess(CombType comb, Materials aMaterial, Voltage volt, int circuitNumber) {
+ if (GT_OreDictUnificator.get(OrePrefixes.crushedPurified, aMaterial, 4) == NI) {
+ return;
+ }
+ GT_RecipeBuilder recipeBuilder = GT_Values.RA.stdBuilder();
+ recipeBuilder
+ .itemInputs(GT_Utility.copyAmount(9, getStackForType(comb)), GT_Utility.getIntegratedCircuit(circuitNumber))
+ .itemOutputs(GT_OreDictUnificator.get(OrePrefixes.crushedPurified, aMaterial, 4))
+ .fluidInputs(Materials.UUMatter.getFluid(Math.max(1, ((aMaterial.getMass() + volt.getUUAmplifier()) / 10))))
+ .duration(((int) (aMaterial.getMass() * 128)) * TICKS)
+ .eut(volt.getAutoClaveEnergy());
+ if (volt.compareTo(Voltage.HV) > 0) {
+ recipeBuilder.requiresCleanRoom();
+ }
+ recipeBuilder.addTo(autoclaveRecipes);
+ }
+
+ public void addFluidExtractorProcess(CombType comb, FluidStack fluid, Voltage volt) {
+ if (fluid == null) {
+ return;
+ }
+
+ int duration = (fluid.getFluid()
+ .getDensity() * 128 > 0
+ ? (fluid.getFluid()
+ .getDensity() * 100)
+ : 128);
+ int eut = volt.getSimpleEnergy() / 2;
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(GT_Utility.copyAmount(1, getStackForType(comb)))
+ .fluidOutputs(fluid)
+ .duration(duration)
+ .eut(eut)
+ .addTo(fluidExtractionRecipes);
+ }
+
+ /**
+ * this only adds Chemical and AutoClave process. If you need Centrifuge recipe. use addCentrifugeToMaterial or
+ * addCentrifugeToItemStack
+ *
+ * @param volt This determine the required Tier of process for this recipes. This decide the required aEU/t,
+ * progress time, required additional UU-Matter, requirement of cleanRoom, needed fluid stack for
+ * Chemical.
+ * @param aMaterial result of Material that should be generated by this process.
+ **/
+ public void addProcessGT(CombType comb, Materials[] aMaterial, Voltage volt) {
+ ItemStack tComb = getStackForType(comb);
+ for (Materials materials : aMaterial) {
+ if (GT_OreDictUnificator.get(OrePrefixes.crushedPurified, materials, 4) != null) {
+ ItemStack combInput;
+ ItemStack combOutput;
+ FluidStack fluidInput;
+ FluidStack fluidOutput;
+ int durationTicks;
+ int eut;
+ boolean requiresCleanroom;
+ switch (comb) {
+ case NEUTRONIUM -> {
+ combInput = GT_Utility.copyAmount(4, tComb);
+ combOutput = Materials.Neutronium.getNuggets(1);
+ fluidInput = volt.getFluidAccordingToCombTier();
+ fluidOutput = Materials.Neutronium.getMolten(576);
+ durationTicks = volt.getComplexTime() * 17;
+ eut = volt.getChemicalEnergy();
+ requiresCleanroom = volt.compareTo(Voltage.IV) > 0;
+ }
+ case OSMIUM -> {
+ combInput = GT_Utility.copyAmount(4, tComb);
+ combOutput = Materials.Osmium.getNuggets(1);
+ fluidInput = volt.getFluidAccordingToCombTier();
+ fluidOutput = Materials.Osmium.getMolten(288);
+ durationTicks = volt.getComplexTime() * 17;
+ eut = volt.getChemicalEnergy();
+ requiresCleanroom = volt.compareTo(Voltage.IV) > 0;
+ }
+ case PLATINUM -> {
+ combInput = GT_Utility.copyAmount(4, tComb);
+ combOutput = Materials.Platinum.getNuggets(1);
+ fluidInput = volt.getFluidAccordingToCombTier();
+ fluidOutput = Materials.Platinum.getMolten(288);
+ durationTicks = volt.getComplexTime() * 10;
+ eut = volt.getChemicalEnergy();
+ requiresCleanroom = volt.compareTo(Voltage.HV) > 0;
+ }
+ case IRIDIUM -> {
+ combInput = GT_Utility.copyAmount(4, tComb);
+ combOutput = Materials.Iridium.getNuggets(1);
+ fluidInput = volt.getFluidAccordingToCombTier();
+ fluidOutput = Materials.Iridium.getMolten(288);
+ durationTicks = volt.getComplexTime() * 14;
+ eut = volt.getChemicalEnergy();
+ requiresCleanroom = volt.compareTo(Voltage.EV) > 0;
+ }
+ default -> {
+ combInput = GT_Utility.copyAmount(4, tComb);
+ combOutput = GT_OreDictUnificator.get(OrePrefixes.crushedPurified, materials, 4);
+ fluidInput = volt.getFluidAccordingToCombTier();
+ fluidOutput = null;
+ durationTicks = volt.getComplexTime();
+ eut = volt.getChemicalEnergy();
+ requiresCleanroom = volt.compareTo(Voltage.IV) > 0;
+ }
+ }
+ GT_RecipeBuilder recipeBuilder = GT_Values.RA.stdBuilder();
+ recipeBuilder.itemInputs(combInput)
+ .itemOutputs(combOutput)
+ .fluidInputs(fluidInput);
+ if (fluidOutput != null) {
+ recipeBuilder.fluidOutputs(fluidOutput);
+ }
+ recipeBuilder.duration(durationTicks)
+ .eut(eut)
+ .metadata(CLEANROOM, requiresCleanroom)
+ .addTo(UniversalChemical);
+ }
+ }
+ }
+
+ /**
+ * this method only adds Centrifuge based on Material. If volt is lower than MV than it will also adds forestry
+ * centrifuge recipe.
+ *
+ * @param comb BeeComb
+ * @param aMaterial resulting Material of processing. can be more than 6. but over 6 will be ignored in Gregtech
+ * Centrifuge.
+ * @param chance chance to get result, 10000 == 100%
+ * @param volt required Voltage Tier for this recipe, this also affect the duration, amount of UU-Matter, and
+ * needed liquid type and amount for chemical reactor
+ * @param stackSize This parameter can be null, in that case stack size will be just 1. This handle the stackSize of
+ * the resulting Item, and Also the Type of Item. if this value is multiple of 9, than related
+ * Material output will be dust, if this value is multiple of 4 than output will be Small dust,
+ * else the output will be Tiny dust
+ * @param beeWax if this is null, then the comb will product default Bee wax. But if aMaterial is more than 5,
+ * beeWax will be ignored in Gregtech Centrifuge.
+ * @param waxChance have same format like "chance"
+ **/
+ public void addCentrifugeToMaterial(CombType comb, Materials[] aMaterial, int[] chance, int[] stackSize,
+ Voltage volt, ItemStack beeWax, int waxChance) {
+ addCentrifugeToMaterial(comb, aMaterial, chance, stackSize, volt, volt.getSimpleTime(), beeWax, waxChance);
+ }
+
+ public void addCentrifugeToMaterial(CombType comb, Materials[] aMaterial, int[] chance, int[] stackSize,
+ Voltage volt, int duration, ItemStack beeWax, int waxChance) {
+ ItemStack[] aOutPut = new ItemStack[aMaterial.length + 1];
+ stackSize = Arrays.copyOf(stackSize, aMaterial.length);
+ chance = Arrays.copyOf(chance, aOutPut.length);
+ chance[chance.length - 1] = waxChance;
+ for (int i = 0; i < (aMaterial.length); i++) {
+ if (chance[i] == 0) {
+ continue;
+ }
+ if (Math.max(1, stackSize[i]) % 9 == 0) {
+ aOutPut[i] = GT_OreDictUnificator.get(OrePrefixes.dust, aMaterial[i], (Math.max(1, stackSize[i]) / 9));
+ } else if (Math.max(1, stackSize[i]) % 4 == 0) {
+ aOutPut[i] = GT_OreDictUnificator.get(OrePrefixes.dust, aMaterial[i], (Math.max(1, stackSize[i]) / 4));
+ } else {
+ aOutPut[i] = GT_OreDictUnificator.get(OrePrefixes.dust, aMaterial[i], Math.max(1, stackSize[i]));
+ }
+ }
+ if (beeWax != NI) {
+ aOutPut[aOutPut.length - 1] = beeWax;
+ } else {
+ aOutPut[aOutPut.length - 1] = ItemList.FR_Wax.get(1);
+ }
+
+ addCentrifugeToItemStack(comb, aOutPut, chance, volt, duration);
+ }
+
+ /**
+ * @param volt required Tier of system. If it's lower than MV, it will also add forestry centrifuge.
+ * @param aItem can be more than 6. but Over 6 will be ignored in Gregtech Centrifuge.
+ **/
+ public void addCentrifugeToItemStack(CombType comb, ItemStack[] aItem, int[] chance, Voltage volt) {
+ addCentrifugeToItemStack(comb, aItem, chance, volt, volt.getSimpleTime());
+ }
+
+ public void addCentrifugeToItemStack(CombType comb, ItemStack[] aItem, int[] chance, Voltage volt, int duration) {
+ ItemStack tComb = getStackForType(comb);
+ Builder<ItemStack, Float> Product = new ImmutableMap.Builder<>();
+ for (int i = 0; i < aItem.length; i++) {
+ if (aItem[i] == NI) {
+ continue;
+ }
+ Product.put(aItem[i], chance[i] / 10000.0f);
+ }
+
+ if (volt.compareTo(Voltage.MV) < 0 || !GT_Mod.gregtechproxy.mNerfedCombs) {
+ RecipeManagers.centrifugeManager.addRecipe(40, tComb, Product.build());
+ }
+
+ GT_Values.RA.stdBuilder()
+ .itemInputs(tComb)
+ .itemOutputs(aItem)
+ .outputChances(chance)
+ .duration(duration)
+ .eut(volt.getSimpleEnergy())
+ .addTo(centrifugeRecipes);
+ }
+
+ public void registerOreDict() {
+ for (CombType comb : CombType.values()) {
+ ItemStack tComb = getStackForType(comb);
+ GT_OreDictUnificator.registerOre(OrePrefixes.beeComb.name(), tComb);
+ OrePrefixes.beeComb.add(tComb);
+ if (comb.voltage != null) GT_OreDictUnificator.registerOre("comb" + comb.voltage.name(), tComb);
+ }
+ }
+
+ enum Voltage {
+
+ ULV,
+ LV,
+ MV,
+ HV,
+ EV,
+ IV,
+ LuV,
+ ZPM,
+ UV,
+ UHV,
+ UEV,
+ UIV,
+ UMV,
+ UXV,
+ MAX;
+
+ public int getVoltage() {
+ return (int) V[this.ordinal()];
+ }
+
+ /** @return aEU/t needed for chemical and autoclave process related to the Tier **/
+ public int getVoltageFromEU() {
+ return (int) Math.max(Math.floor(Math.log(2 * this.getVoltage()) / Math.log(4) - 1), 0);
+ }
+
+ /** @return Voltage tier according to EU provided. 0 = ULV, 1 = LV, 2 = MV ... **/
+ public int getChemicalEnergy() {
+ return this.getVoltage() * 3 / 4;
+ }
+
+ public int getAutoClaveEnergy() {
+ return (int) ((this.getVoltage() * 3 / 4) * (Math.max(1, Math.pow(2, 5 - this.ordinal()))));
+ }
+
+ /** @return FluidStack needed for chemical process related to the Tier **/
+ public FluidStack getComplexChemical() {
+ if (this.compareTo(Voltage.MV) < 0) {
+ return Materials.HydrofluoricAcid.getFluid((this.compareTo(Voltage.ULV) > 0) ? 1000 : 500);
+ } else if (this.compareTo(Voltage.HV) < 0) {
+ return GT_ModHandler.getDistilledWater(1000L);
+ } else if (this.compareTo(Voltage.LuV) < 0) {
+ return Materials.HydrofluoricAcid.getFluid((long) (Math.pow(2, this.compareTo(Voltage.HV)) * L));
+ } else if (this.compareTo(Voltage.UHV) < 0) {
+ return FluidRegistry.getFluidStack("mutagen", (int) (Math.pow(2, this.compareTo(Voltage.LuV)) * L));
+ } else {
+ return NF;
+ }
+ }
+
+ /** @return FluidStack needed for chemical process related to the Tier **/
+ public FluidStack getFluidAccordingToCombTier() {
+ // checking what Voltage tier the Comb is
+ // cascading from IV to UMV since all recipes use HydrofluiricAcid
+ // for later tiers, just add the corresponding tier to a case
+ int fluidAmount = this.getFluidAmount();
+ return switch (this.getVoltageFromEU()) {
+ case 0 ->
+ /* ULV */
+ Materials.Water.getFluid(fluidAmount);
+ case 1 ->
+ /* LV */
+ Materials.SulfuricAcid.getFluid(fluidAmount);
+ case 2 ->
+ /* MV */
+ Materials.HydrochloricAcid.getFluid(fluidAmount);
+ case 3 ->
+ /* HV */
+ Materials.PhosphoricAcid.getFluid(fluidAmount);
+ case 4 ->
+ /* EV */
+ Materials.HydrofluoricAcid.getFluid(this.getFluidAmount());
+ default -> Materials.PhthalicAcid.getFluid(fluidAmount);
+ };
+ }
+
+ /** @return additional required UU-Matter amount for Autoclave process related to the Tier **/
+ public int getUUAmplifier() {
+ return 9 * ((this.compareTo(Voltage.MV) < 0) ? 1 : this.compareTo(Voltage.MV));
+ }
+
+ /** @return duration needed for Chemical process related to the Tier **/
+ public int getComplexTime() {
+ return 64 + this.ordinal() * 32;
+ }
+
+ /** @return Fluid amount needed for Chemical process related to the Tier **/
+ public int getFluidAmount() {
+ return 9 * this.getSimpleTime() / 3;
+ }
+
+ /** @return duration needed for Centrifuge process related to the Tier **/
+ public int getSimpleTime() {
+ if (!GT_Mod.gregtechproxy.mNerfedCombs) {
+ return 96 + this.ordinal() * 32;
+ } else {
+ // ULV, LV needs 128ticks, MV need 256 ticks, HV need 384 ticks, EV need 512 ticks, IV need 640 ticks
+ return 128 * (Math.max(1, this.ordinal()));
+ }
+ }
+
+ /** @return aEU/t needed for Centrifuge process related to the Tier **/
+ public int getSimpleEnergy() {
+ if (this == Voltage.ULV) {
+ return 5;
+ } else {
+ return (this.getVoltage() / 16) * 15;
+ }
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/items/ItemDrop.java b/src/main/java/gregtech/common/items/ItemDrop.java
new file mode 100644
index 0000000000..5aab9dff48
--- /dev/null
+++ b/src/main/java/gregtech/common/items/ItemDrop.java
@@ -0,0 +1,241 @@
+package gregtech.common.items;
+
+import static gregtech.api.enums.Mods.ExtraBees;
+import static gregtech.api.enums.Mods.Forestry;
+import static gregtech.api.enums.Mods.GregTech;
+import static gregtech.api.enums.Mods.HardcoreEnderExpansion;
+import static gregtech.api.enums.Mods.MagicBees;
+import static gregtech.api.enums.Mods.NewHorizonsCoreMod;
+import static gregtech.api.recipe.RecipeMaps.fluidExtractionRecipes;
+import static gregtech.api.util.GT_RecipeBuilder.SECONDS;
+import static gregtech.api.util.GT_RecipeBuilder.TICKS;
+
+import java.util.List;
+
+import net.minecraft.client.renderer.texture.IIconRegister;
+import net.minecraft.creativetab.CreativeTabs;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.IIcon;
+import net.minecraftforge.fluids.FluidRegistry;
+import net.minecraftforge.fluids.FluidStack;
+
+import cpw.mods.fml.common.registry.GameRegistry;
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import forestry.api.core.Tabs;
+import forestry.api.recipes.RecipeManagers;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.TierEU;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_RecipeBuilder;
+
+public class ItemDrop extends Item {
+
+ @SideOnly(Side.CLIENT)
+ private IIcon secondIcon;
+
+ public ItemDrop() {
+ super();
+ this.setCreativeTab(Tabs.tabApiculture);
+ this.setHasSubtypes(true);
+ this.setUnlocalizedName("gt.drop");
+ GameRegistry.registerItem(this, "gt.drop", GregTech.ID);
+ }
+
+ public ItemStack getStackForType(DropType type) {
+ return new ItemStack(this, 1, type.ordinal());
+ }
+
+ public ItemStack getStackForType(DropType type, int count) {
+ return new ItemStack(this, count, type.ordinal());
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void getSubItems(Item item, CreativeTabs tabs, List<ItemStack> list) {
+ for (DropType type : DropType.values()) {
+ if (type.showInList) {
+ list.add(this.getStackForType(type));
+ }
+ }
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public boolean requiresMultipleRenderPasses() {
+ return true;
+ }
+
+ @Override
+ public int getRenderPasses(int meta) {
+ return 2;
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void registerIcons(IIconRegister iconRegister) {
+ this.itemIcon = iconRegister.registerIcon("forestry:honeyDrop.0");
+ this.secondIcon = iconRegister.registerIcon("forestry:honeyDrop.1");
+ }
+
+ @Override
+ public IIcon getIcon(ItemStack stack, int pass) {
+ return (pass == 0) ? itemIcon : secondIcon;
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public int getColorFromItemStack(ItemStack stack, int pass) {
+ int meta = Math.max(0, Math.min(DropType.values().length - 1, stack.getItemDamage()));
+ int colour = DropType.values()[meta].getColours()[0];
+
+ if (pass >= 1) {
+ colour = DropType.values()[meta].getColours()[1];
+ }
+
+ return colour;
+ }
+
+ @Override
+ public String getItemStackDisplayName(ItemStack stack) {
+ return DropType.values()[stack.getItemDamage()].getName();
+ }
+
+ public void initDropsRecipes() {
+ ItemStack tDrop;
+
+ tDrop = getStackForType(DropType.OIL);
+ addProcessLV(
+ tDrop,
+ Materials.OilHeavy.getFluid(100L),
+ GT_ModHandler.getModItem(Forestry.ID, "propolis", 1L, 0),
+ 3000,
+ 8);
+ RecipeManagers.squeezerManager.addRecipe(
+ 40,
+ new ItemStack[] { tDrop },
+ Materials.OilHeavy.getFluid(100L),
+ GT_ModHandler.getModItem(Forestry.ID, "propolis", 1L, 0),
+ 30);
+ tDrop = getStackForType(DropType.COOLANT);
+ addProcessLV(
+ tDrop,
+ new FluidStack(FluidRegistry.getFluid("ic2coolant"), 100),
+ GT_ModHandler.getModItem(MagicBees.ID, "propolis", 1L, 0),
+ 3000,
+ 8);
+ RecipeManagers.squeezerManager.addRecipe(
+ 40,
+ new ItemStack[] { tDrop },
+ new FluidStack(FluidRegistry.getFluid("ic2coolant"), 100),
+ GT_ModHandler.getModItem(MagicBees.ID, "propolis", 1L, 0),
+ 30);
+ tDrop = getStackForType(DropType.HOT_COOLANT);
+ addProcessLV(
+ tDrop,
+ new FluidStack(FluidRegistry.getFluid("ic2hotcoolant"), 100),
+ GT_ModHandler.getModItem(MagicBees.ID, "propolis", 1L, 2),
+ 3000,
+ 8);
+ RecipeManagers.squeezerManager.addRecipe(
+ 40,
+ new ItemStack[] { tDrop },
+ new FluidStack(FluidRegistry.getFluid("ic2hotcoolant"), 100),
+ GT_ModHandler.getModItem(MagicBees.ID, "propolis", 1L, 2),
+ 30);
+ tDrop = getStackForType(DropType.SNOW_QUEEN);
+ addProcessMV(
+ tDrop,
+ Materials.FierySteel.getFluid(200L),
+ GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.SnowQueenBloodDrop", 1L, 0),
+ 1500,
+ 48);
+ tDrop = getStackForType(DropType.LAPIS);
+ addProcessLV(
+ tDrop,
+ new FluidStack(FluidRegistry.getFluid("ic2coolant"), 200),
+ GT_ModHandler.getModItem(MagicBees.ID, "propolis", 1L, 3),
+ 5000,
+ 1200,
+ 2);
+ RecipeManagers.squeezerManager.addRecipe(
+ 400,
+ new ItemStack[] { tDrop },
+ new FluidStack(FluidRegistry.getFluid("ic2coolant"), 100),
+ GT_ModHandler.getModItem(MagicBees.ID, "propolis", 1L, 3),
+ 30);
+ tDrop = getStackForType(DropType.HYDRA);
+ addProcessMV(
+ tDrop,
+ Materials.FierySteel.getFluid(50L),
+ GT_ModHandler.getModItem(MagicBees.ID, "propolis", 1L, 2),
+ 3000,
+ 8);
+ tDrop = getStackForType(DropType.OXYGEN);
+ addProcessLV(
+ tDrop,
+ new FluidStack(FluidRegistry.getFluid("liquidoxygen"), 100),
+ GT_ModHandler.getModItem(ExtraBees.ID, "propolis", 1L, 2),
+ 250,
+ 1200,
+ 8);
+ RecipeManagers.squeezerManager.addRecipe(
+ 400,
+ new ItemStack[] { tDrop },
+ new FluidStack(FluidRegistry.getFluid("ic2coolant"), 100),
+ GT_ModHandler.getModItem(ExtraBees.ID, "propolis", 1L, 2),
+ 30);
+ tDrop = getStackForType(DropType.ENDERGOO);
+ if (HardcoreEnderExpansion.isModLoaded())
+ addProcessHV(tDrop, new FluidStack(FluidRegistry.getFluid("endergoo"), 500), GT_Values.NI, 1000);
+ }
+
+ public void addProcessLV(ItemStack tDrop, FluidStack aOutput, ItemStack aOutput2, int aChance, int aEUt) {
+ GT_Values.RA.stdBuilder()
+ .itemInputs(tDrop)
+ .itemOutputs(aOutput2)
+ .outputChances(aChance)
+ .fluidOutputs(aOutput)
+ .duration(1 * SECONDS + 12 * TICKS)
+ .eut(aEUt)
+ .addTo(fluidExtractionRecipes);
+ }
+
+ public void addProcessLV(ItemStack tDrop, FluidStack aOutput, ItemStack aOutput2, int aChance, int aDuration,
+ int aEUt) {
+ GT_Values.RA.stdBuilder()
+ .itemInputs(tDrop)
+ .itemOutputs(aOutput2)
+ .outputChances(aChance)
+ .fluidOutputs(aOutput)
+ .duration(aDuration)
+ .eut(aEUt)
+ .addTo(fluidExtractionRecipes);
+ }
+
+ public void addProcessMV(ItemStack tDrop, FluidStack aOutput, ItemStack aOutput2, int aChance, int aEUt) {
+ GT_Values.RA.stdBuilder()
+ .itemInputs(tDrop)
+ .itemOutputs(aOutput2)
+ .outputChances(aChance)
+ .fluidOutputs(aOutput)
+ .duration(6 * SECONDS + 8 * TICKS)
+ .eut(aEUt)
+ .addTo(fluidExtractionRecipes);
+ }
+
+ public void addProcessHV(ItemStack tDrop, FluidStack aOutput, ItemStack aOutput2, int aChance) {
+ GT_RecipeBuilder recipeBuilder = GT_Values.RA.stdBuilder();
+ recipeBuilder.itemInputs(tDrop);
+ if (aOutput2 != GT_Values.NI) {
+ recipeBuilder.itemOutputs(aOutput2)
+ .outputChances(aChance);
+ }
+ recipeBuilder.fluidOutputs(aOutput)
+ .duration(24 * SECONDS)
+ .eut(TierEU.RECIPE_HV)
+ .addTo(fluidExtractionRecipes);
+ }
+}
diff --git a/src/main/java/gregtech/common/items/ItemPollen.java b/src/main/java/gregtech/common/items/ItemPollen.java
new file mode 100644
index 0000000000..70e2d64514
--- /dev/null
+++ b/src/main/java/gregtech/common/items/ItemPollen.java
@@ -0,0 +1,89 @@
+package gregtech.common.items;
+
+import static gregtech.api.enums.Mods.GregTech;
+
+import java.util.List;
+
+import net.minecraft.client.renderer.texture.IIconRegister;
+import net.minecraft.creativetab.CreativeTabs;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.IIcon;
+
+import cpw.mods.fml.common.registry.GameRegistry;
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import forestry.api.core.Tabs;
+
+public class ItemPollen extends Item {
+
+ @SideOnly(Side.CLIENT)
+ private IIcon secondIcon;
+
+ public ItemPollen() {
+ super();
+ this.setCreativeTab(Tabs.tabApiculture);
+ this.setHasSubtypes(true);
+ this.setUnlocalizedName("gt.pollen");
+ GameRegistry.registerItem(this, "gt.pollen", GregTech.ID);
+ }
+
+ public ItemStack getStackForType(PollenType type) {
+ return new ItemStack(this, 1, type.ordinal());
+ }
+
+ public ItemStack getStackForType(PollenType type, int count) {
+ return new ItemStack(this, count, type.ordinal());
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void getSubItems(Item item, CreativeTabs tabs, List<ItemStack> list) {
+ for (PollenType type : PollenType.values()) {
+ if (type.showInList) {
+ list.add(this.getStackForType(type));
+ }
+ }
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public boolean requiresMultipleRenderPasses() {
+ return true;
+ }
+
+ @Override
+ public int getRenderPasses(int meta) {
+ return 2;
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void registerIcons(IIconRegister iconRegister) {
+ this.itemIcon = iconRegister.registerIcon("forestry:pollen.0");
+ this.secondIcon = iconRegister.registerIcon("forestry:pollen.1");
+ }
+
+ @Override
+ public IIcon getIcon(ItemStack stack, int pass) {
+ return (pass == 0) ? itemIcon : secondIcon;
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public int getColorFromItemStack(ItemStack stack, int pass) {
+ int meta = Math.max(0, Math.min(PollenType.values().length - 1, stack.getItemDamage()));
+ int colour = PollenType.values()[meta].getColours()[0];
+
+ if (pass >= 1) {
+ colour = PollenType.values()[meta].getColours()[1];
+ }
+
+ return colour;
+ }
+
+ @Override
+ public String getItemStackDisplayName(ItemStack stack) {
+ return PollenType.values()[stack.getItemDamage()].getName();
+ }
+}
diff --git a/src/main/java/gregtech/common/items/ItemPropolis.java b/src/main/java/gregtech/common/items/ItemPropolis.java
new file mode 100644
index 0000000000..1c0d727bda
--- /dev/null
+++ b/src/main/java/gregtech/common/items/ItemPropolis.java
@@ -0,0 +1,141 @@
+package gregtech.common.items;
+
+import static gregtech.api.enums.Mods.GregTech;
+import static gregtech.api.enums.Mods.HardcoreEnderExpansion;
+import static gregtech.api.enums.Mods.NewHorizonsCoreMod;
+import static gregtech.api.recipe.RecipeMaps.fluidExtractionRecipes;
+import static gregtech.api.util.GT_RecipeBuilder.SECONDS;
+import static gregtech.api.util.GT_RecipeBuilder.TICKS;
+
+import java.util.List;
+
+import net.minecraft.client.renderer.texture.IIconRegister;
+import net.minecraft.creativetab.CreativeTabs;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.IIcon;
+import net.minecraftforge.fluids.FluidRegistry;
+
+import cpw.mods.fml.common.registry.GameRegistry;
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import forestry.api.core.Tabs;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.enums.TierEU;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_OreDictUnificator;
+
+public class ItemPropolis extends Item {
+
+ @SideOnly(Side.CLIENT)
+ private IIcon secondIcon;
+
+ public ItemPropolis() {
+ super();
+ this.setCreativeTab(Tabs.tabApiculture);
+ this.setHasSubtypes(true);
+ this.setUnlocalizedName("gt.propolis");
+ GameRegistry.registerItem(this, "gt.propolis", GregTech.ID);
+ }
+
+ public ItemStack getStackForType(PropolisType type) {
+ return new ItemStack(this, 1, type.ordinal());
+ }
+
+ public ItemStack getStackForType(PropolisType type, int count) {
+ return new ItemStack(this, count, type.ordinal());
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void getSubItems(Item item, CreativeTabs tabs, List<ItemStack> list) {
+ for (PropolisType type : PropolisType.values()) {
+ if (type.showInList) {
+ list.add(this.getStackForType(type));
+ }
+ }
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void registerIcons(IIconRegister iconRegister) {
+ this.itemIcon = iconRegister.registerIcon("forestry:propolis.0");
+ }
+
+ @Override
+ public IIcon getIcon(ItemStack stack, int pass) {
+ return itemIcon;
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public int getColorFromItemStack(ItemStack stack, int pass) {
+ int meta = Math.max(0, Math.min(PropolisType.values().length - 1, stack.getItemDamage()));
+ return PropolisType.values()[meta].getColours();
+ }
+
+ @Override
+ public String getItemStackDisplayName(ItemStack stack) {
+ return PropolisType.values()[stack.getItemDamage()].getName();
+ }
+
+ public void initPropolisRecipes() {
+ ItemStack tPropolis;
+
+ tPropolis = getStackForType(PropolisType.End);
+ addProcessHV(tPropolis, GT_ModHandler.getModItem(HardcoreEnderExpansion.ID, "end_powder", 1, 0));
+ tPropolis = getStackForType(PropolisType.Stardust);
+ addProcessHV(tPropolis, GT_ModHandler.getModItem(HardcoreEnderExpansion.ID, "stardust", 1, 0));
+ tPropolis = getStackForType(PropolisType.Ectoplasma);
+ addProcessEV(tPropolis, GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.EctoplasmaChip", 1, 0));
+ tPropolis = getStackForType(PropolisType.Arcaneshard);
+ addProcessEV(tPropolis, GT_ModHandler.getModItem(NewHorizonsCoreMod.ID, "item.ArcaneShardChip", 1, 0));
+ tPropolis = getStackForType(PropolisType.Dragonessence);
+ addProcessIV(tPropolis, GT_ModHandler.getModItem(HardcoreEnderExpansion.ID, "essence", 16, 0));
+ tPropolis = getStackForType(PropolisType.Enderman);
+ addProcessIV(tPropolis, GT_ModHandler.getModItem(HardcoreEnderExpansion.ID, "enderman_head", 1, 0));
+ tPropolis = getStackForType(PropolisType.Silverfish);
+ addProcessEV(tPropolis, GT_ModHandler.getModItem(HardcoreEnderExpansion.ID, "silverfish_blood", 1, 0));
+ tPropolis = getStackForType(PropolisType.Endium);
+ addProcessHV(tPropolis, GT_OreDictUnificator.get(OrePrefixes.dustSmall, Materials.HeeEndium, 1));
+ tPropolis = getStackForType(PropolisType.Fireessence);
+ addProcessIV(tPropolis, GT_ModHandler.getModItem(HardcoreEnderExpansion.ID, "essence", 16, 1));
+
+ // addRecipe(tDrop, aOutput, aOutput2, aChance, aDuration, aEUt);
+ }
+
+ public void addProcessHV(ItemStack tPropolis, ItemStack aOutput2) {
+ GT_Values.RA.stdBuilder()
+ .itemInputs(tPropolis)
+ .itemOutputs(aOutput2)
+ .outputChances(5000)
+ .fluidOutputs(FluidRegistry.getFluidStack("endergoo", 100))
+ .duration(2 * SECONDS + 10 * TICKS)
+ .eut(TierEU.RECIPE_HV)
+ .addTo(fluidExtractionRecipes);
+ }
+
+ public void addProcessEV(ItemStack tPropolis, ItemStack aOutput2) {
+ GT_Values.RA.stdBuilder()
+ .itemInputs(tPropolis)
+ .itemOutputs(aOutput2)
+ .outputChances(2500)
+ .fluidOutputs(FluidRegistry.getFluidStack("endergoo", 200))
+ .duration(5 * SECONDS)
+ .eut(TierEU.RECIPE_EV)
+ .addTo(fluidExtractionRecipes);
+ }
+
+ public void addProcessIV(ItemStack tPropolis, ItemStack aOutput2) {
+ GT_Values.RA.stdBuilder()
+ .itemInputs(tPropolis)
+ .itemOutputs(aOutput2)
+ .outputChances(1500)
+ .fluidOutputs(FluidRegistry.getFluidStack("endergoo", 300))
+ .duration(7 * SECONDS + 10 * TICKS)
+ .eut(TierEU.RECIPE_IV)
+ .addTo(fluidExtractionRecipes);
+ }
+}
diff --git a/src/main/java/gregtech/common/items/PollenType.java b/src/main/java/gregtech/common/items/PollenType.java
new file mode 100644
index 0000000000..3cd9484b69
--- /dev/null
+++ b/src/main/java/gregtech/common/items/PollenType.java
@@ -0,0 +1,35 @@
+package gregtech.common.items;
+
+import gregtech.api.enums.Materials;
+import gregtech.api.util.GT_LanguageManager;
+
+public enum PollenType {
+
+ MATRIX("matrix", true);
+
+ private static final int[][] colours = new int[][] { { 0x19191B, 0x303032 }, };
+ public boolean showInList;
+ public Materials material;
+ public int chance;
+ private final String name;
+
+ PollenType(String pName, boolean show) {
+ this.name = pName;
+ this.showInList = show;
+ }
+
+ public void setHidden() {
+ this.showInList = false;
+ }
+
+ public String getName() {
+ return GT_LanguageManager.addStringLocalization(
+ "pollen." + this.name,
+ this.name.substring(0, 1)
+ .toUpperCase() + this.name.substring(1) + " Pollen");
+ }
+
+ public int[] getColours() {
+ return colours[this.ordinal()];
+ }
+}
diff --git a/src/main/java/gregtech/common/items/PropolisType.java b/src/main/java/gregtech/common/items/PropolisType.java
new file mode 100644
index 0000000000..e6f08b0cfa
--- /dev/null
+++ b/src/main/java/gregtech/common/items/PropolisType.java
@@ -0,0 +1,46 @@
+package gregtech.common.items;
+
+import gregtech.api.enums.Materials;
+import gregtech.api.util.GT_LanguageManager;
+
+public enum PropolisType {
+
+ End("End", true),
+ Ectoplasma("Ectoplasma", true),
+ Arcaneshard("Arcaneshard", true),
+ Stardust("Stardust", true),
+ Dragonessence("Dragonessence", true),
+ Enderman("Enderman", true),
+ Silverfish("Silverfish", true),
+ Endium("Endium", true),
+ Fireessence("Fireessence", true);
+
+ private static final int[] colours = new int[] { 0xCC00FA, 0xDCB0E5, 0x9010AD, 0xFFFF00, 0x911ECE, 0x161616,
+ 0xEE053D, 0xa0ffff, 0xD41238 };
+
+ public boolean showInList;
+ public Materials material;
+ public int chance;
+ private final String name;
+
+ PropolisType(String pName, boolean show) {
+ this.name = pName;
+ this.showInList = show;
+ }
+
+ public void setHidden() {
+ this.showInList = false;
+ }
+
+ public String getName() {
+ // return "gt.comb."+this.name;
+ return GT_LanguageManager.addStringLocalization(
+ "propolis." + this.name,
+ this.name.substring(0, 1)
+ .toUpperCase() + this.name.substring(1) + " Propolis");
+ }
+
+ public int getColours() {
+ return colours[this.ordinal()];
+ }
+}
diff --git a/src/main/java/gregtech/common/items/behaviors/Behaviour_Arrow.java b/src/main/java/gregtech/common/items/behaviors/Behaviour_Arrow.java
new file mode 100644
index 0000000000..8005009d14
--- /dev/null
+++ b/src/main/java/gregtech/common/items/behaviors/Behaviour_Arrow.java
@@ -0,0 +1,141 @@
+package gregtech.common.items.behaviors;
+
+import net.minecraft.block.BlockDispenser;
+import net.minecraft.dispenser.IBlockSource;
+import net.minecraft.dispenser.IPosition;
+import net.minecraft.enchantment.Enchantment;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.projectile.EntityArrow;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.EnumFacing;
+import net.minecraft.world.World;
+
+import gregtech.api.enums.SubTag;
+import gregtech.api.items.GT_MetaBase_Item;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.entities.GT_Entity_Arrow;
+
+public class Behaviour_Arrow extends Behaviour_None {
+
+ public static Behaviour_Arrow DEFAULT_WOODEN = new Behaviour_Arrow(GT_Entity_Arrow.class, 1.0F, 6.0F);
+ public static Behaviour_Arrow DEFAULT_PLASTIC = new Behaviour_Arrow(GT_Entity_Arrow.class, 1.5F, 6.0F);
+ private final int mLevel;
+ private final Enchantment mEnchantment;
+ private final float mSpeedMultiplier;
+ private final float mPrecision;
+ private final Class<? extends GT_Entity_Arrow> mArrow;
+
+ public Behaviour_Arrow(Class<? extends GT_Entity_Arrow> aArrow, float aSpeed, float aPrecision) {
+ this(aArrow, aSpeed, aPrecision, null, 0);
+ }
+
+ public Behaviour_Arrow(Class<? extends GT_Entity_Arrow> aArrow, float aSpeed, float aPrecision,
+ Enchantment aEnchantment, int aLevel) {
+ this.mArrow = aArrow;
+ this.mSpeedMultiplier = aSpeed;
+ this.mPrecision = aPrecision;
+ this.mEnchantment = aEnchantment;
+ this.mLevel = aLevel;
+ }
+
+ @Override
+ public boolean onLeftClickEntity(GT_MetaBase_Item aItem, ItemStack aStack, EntityPlayer aPlayer, Entity aEntity) {
+ if ((aEntity instanceof EntityLivingBase)) {
+ GT_Utility.GT_EnchantmentHelper.applyBullshitA((EntityLivingBase) aEntity, aPlayer, aStack);
+ GT_Utility.GT_EnchantmentHelper.applyBullshitB(aPlayer, aEntity, aStack);
+ if (!aPlayer.capabilities.isCreativeMode) {
+ aStack.stackSize -= 1;
+ }
+ if (aStack.stackSize <= 0) {
+ aPlayer.destroyCurrentEquippedItem();
+ }
+ return false;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean isItemStackUsable(GT_MetaBase_Item aItem, ItemStack aStack) {
+ if ((this.mEnchantment != null) && (this.mLevel > 0)) {
+ NBTTagCompound tNBT = GT_Utility.ItemNBT.getNBT(aStack);
+ if (!tNBT.getBoolean("GT.HasBeenUpdated")) {
+ tNBT.setBoolean("GT.HasBeenUpdated", true);
+ GT_Utility.ItemNBT.setNBT(aStack, tNBT);
+ GT_Utility.ItemNBT.addEnchantment(aStack, this.mEnchantment, this.mLevel);
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean canDispense(GT_MetaBase_Item aItem, IBlockSource aSource, ItemStack aStack) {
+ return true;
+ }
+
+ @Override
+ public ItemStack onDispense(GT_MetaBase_Item aItem, IBlockSource aSource, ItemStack aStack) {
+ World aWorld = aSource.getWorld();
+ IPosition tPosition = BlockDispenser.func_149939_a(aSource);
+ EnumFacing tFacing = BlockDispenser.func_149937_b(aSource.getBlockMetadata());
+ GT_Entity_Arrow tEntityArrow = (GT_Entity_Arrow) getProjectile(
+ aItem,
+ SubTag.PROJECTILE_ARROW,
+ aStack,
+ aWorld,
+ tPosition.getX(),
+ tPosition.getY(),
+ tPosition.getZ());
+ if (tEntityArrow != null) {
+ tEntityArrow.setThrowableHeading(
+ tFacing.getFrontOffsetX(),
+ tFacing.getFrontOffsetY() + 0.1F,
+ tFacing.getFrontOffsetZ(),
+ this.mSpeedMultiplier * 1.1F,
+ this.mPrecision);
+ tEntityArrow.setArrowItem(aStack);
+ tEntityArrow.canBePickedUp = 1;
+ aWorld.spawnEntityInWorld(tEntityArrow);
+ if (aStack.stackSize < 100) {
+ aStack.stackSize -= 1;
+ }
+ return aStack;
+ }
+ return super.onDispense(aItem, aSource, aStack);
+ }
+
+ @Override
+ public boolean hasProjectile(GT_MetaBase_Item aItem, SubTag aProjectileType, ItemStack aStack) {
+ return aProjectileType == SubTag.PROJECTILE_ARROW;
+ }
+
+ @Override
+ public EntityArrow getProjectile(GT_MetaBase_Item aItem, SubTag aProjectileType, ItemStack aStack, World aWorld,
+ double aX, double aY, double aZ) {
+ if (!hasProjectile(aItem, aProjectileType, aStack)) {
+ return null;
+ }
+ GT_Entity_Arrow rArrow = (GT_Entity_Arrow) GT_Utility
+ .callConstructor(this.mArrow.getName(), -1, null, true, new Object[] { aWorld, aX, aY, aZ });
+ rArrow.setArrowItem(aStack);
+ return rArrow;
+ }
+
+ @Override
+ public EntityArrow getProjectile(GT_MetaBase_Item aItem, SubTag aProjectileType, ItemStack aStack, World aWorld,
+ EntityLivingBase aEntity, float aSpeed) {
+ if (!hasProjectile(aItem, aProjectileType, aStack)) {
+ return null;
+ }
+ GT_Entity_Arrow rArrow = (GT_Entity_Arrow) GT_Utility.callConstructor(
+ this.mArrow.getName(),
+ -1,
+ null,
+ true,
+ new Object[] { aWorld, aEntity, this.mSpeedMultiplier * aSpeed });
+ rArrow.setArrowItem(aStack);
+ return rArrow;
+ }
+}
diff --git a/src/main/java/gregtech/common/items/behaviors/Behaviour_Arrow_Potion.java b/src/main/java/gregtech/common/items/behaviors/Behaviour_Arrow_Potion.java
new file mode 100644
index 0000000000..3643de7b77
--- /dev/null
+++ b/src/main/java/gregtech/common/items/behaviors/Behaviour_Arrow_Potion.java
@@ -0,0 +1,71 @@
+package gregtech.common.items.behaviors;
+
+import net.minecraft.enchantment.Enchantment;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.projectile.EntityArrow;
+import net.minecraft.item.ItemStack;
+import net.minecraft.potion.PotionEffect;
+import net.minecraft.world.World;
+
+import gregtech.api.enums.SubTag;
+import gregtech.api.items.GT_MetaBase_Item;
+import gregtech.common.entities.GT_Entity_Arrow_Potion;
+
+public class Behaviour_Arrow_Potion extends Behaviour_Arrow {
+
+ private final int[] mPotions;
+
+ public Behaviour_Arrow_Potion(float aSpeed, float aPrecision, int... aPotions) {
+ super(GT_Entity_Arrow_Potion.class, aSpeed, aPrecision);
+ this.mPotions = aPotions;
+ }
+
+ public Behaviour_Arrow_Potion(float aSpeed, float aPrecision, Enchantment aEnchantment, int aLevel,
+ int... aPotions) {
+ super(GT_Entity_Arrow_Potion.class, aSpeed, aPrecision, aEnchantment, aLevel);
+ this.mPotions = aPotions;
+ }
+
+ @Override
+ public boolean onLeftClickEntity(GT_MetaBase_Item aItem, ItemStack aStack, EntityPlayer aPlayer, Entity aEntity) {
+ if ((aEntity instanceof EntityLivingBase)) {
+ for (int i = 3; i < this.mPotions.length; i += 4) {
+ if (aEntity.worldObj.rand.nextInt(100) < this.mPotions[i]) {
+ ((EntityLivingBase) aEntity).addPotionEffect(
+ new PotionEffect(
+ this.mPotions[(i - 3)],
+ this.mPotions[(i - 2)],
+ this.mPotions[(i - 1)],
+ false));
+ }
+ }
+ }
+ return super.onLeftClickEntity(aItem, aStack, aPlayer, aEntity);
+ }
+
+ @Override
+ public EntityArrow getProjectile(GT_MetaBase_Item aItem, SubTag aProjectileType, ItemStack aStack, World aWorld,
+ double aX, double aY, double aZ) {
+ if (!hasProjectile(aItem, aProjectileType, aStack)) {
+ return null;
+ }
+ GT_Entity_Arrow_Potion rArrow = new GT_Entity_Arrow_Potion(aWorld, aX, aY, aZ);
+ rArrow.setArrowItem(aStack);
+ rArrow.setPotions(this.mPotions);
+ return rArrow;
+ }
+
+ @Override
+ public EntityArrow getProjectile(GT_MetaBase_Item aItem, SubTag aProjectileType, ItemStack aStack, World aWorld,
+ EntityLivingBase aEntity, float aSpeed) {
+ if (!hasProjectile(aItem, aProjectileType, aStack)) {
+ return null;
+ }
+ GT_Entity_Arrow_Potion rArrow = new GT_Entity_Arrow_Potion(aWorld, aEntity, aSpeed);
+ rArrow.setArrowItem(aStack);
+ rArrow.setPotions(this.mPotions);
+ return rArrow;
+ }
+}
diff --git a/src/main/java/gregtech/common/items/behaviors/Behaviour_Cover_Tool.java b/src/main/java/gregtech/common/items/behaviors/Behaviour_Cover_Tool.java
new file mode 100644
index 0000000000..4241e07e4b
--- /dev/null
+++ b/src/main/java/gregtech/common/items/behaviors/Behaviour_Cover_Tool.java
@@ -0,0 +1,193 @@
+package gregtech.common.items.behaviors;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTBase;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.SoundResource;
+import gregtech.api.interfaces.IItemBehaviour;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.items.GT_MetaBase_Item;
+import gregtech.api.util.GT_CoverBehaviorBase;
+import gregtech.api.util.GT_LanguageManager;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.ISerializableObject;
+
+public class Behaviour_Cover_Tool extends Behaviour_None {
+
+ public static final IItemBehaviour<GT_MetaBase_Item> INSTANCE = new Behaviour_Cover_Tool();
+ private final String mTooltip = GT_LanguageManager
+ .addStringLocalization("gt.behaviour.cover_copy_paste", "Can copy/paste cover data.");
+
+ private ISerializableObject mStoredData = GregTech_API.sNoBehavior.createDataObject();
+ private int mCoverType;
+ private int mTickRateAddition = 0;
+
+ @Override
+ public boolean onItemUseFirst(GT_MetaBase_Item aItem, ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX,
+ int aY, int aZ, ForgeDirection side, float hitX, float hitY, float hitZ) {
+ if (aWorld.isRemote) {
+ return false;
+ }
+ final NBTTagCompound tNBT = aStack.getTagCompound();
+ final TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ final boolean isCopyMode = aPlayer.isSneaking();
+ initDataFromNBT(tNBT);
+ if (((aPlayer instanceof EntityPlayerMP)) && (aItem.canUse(aStack, 100.0D))) {
+ if (isCopyMode) {
+ ArrayList<String> tList = new ArrayList<>();
+ doCopy(tTileEntity, aWorld, aX, aY, aZ, side, hitX, hitY, hitZ, tList);
+ aItem.discharge(aStack, 100.0D, Integer.MAX_VALUE, true, false, false);
+ writeListToNBT(tList, tNBT, aPlayer);
+ saveDataToNBT(tNBT);
+ } else {
+ doPaste(tTileEntity, side, hitX, hitY, hitZ, aPlayer);
+ aItem.discharge(aStack, 25.0D, Integer.MAX_VALUE, true, false, false);
+ }
+ }
+ GT_Utility.doSoundAtClient(SoundResource.IC2_TOOLS_OD_SCANNER, 1, 1.0F, aX, aY, aZ);
+ return aPlayer instanceof EntityPlayerMP;
+ }
+
+ private void initDataFromNBT(NBTTagCompound aNBT) {
+ if (aNBT != null) {
+ mCoverType = aNBT.getInteger("mCoverType");
+ GT_CoverBehaviorBase<?> tBehavior = GregTech_API.getCoverBehaviorNew(mCoverType);
+ NBTBase tData = aNBT.getTag("mCoverData");
+ if (tData != null) mStoredData = tBehavior.createDataObject(tData);
+ else mStoredData = GregTech_API.sNoBehavior.createDataObject();
+ mTickRateAddition = aNBT.hasKey("mTickRateAddition") ? aNBT.getInteger("mTickRateAddition") : 0;
+ }
+ }
+
+ private void saveDataToNBT(NBTTagCompound aNBT) {
+ aNBT.setInteger("mCoverType", mCoverType);
+ if (mStoredData == null) mStoredData = GregTech_API.sNoBehavior.createDataObject();
+ aNBT.setTag("mCoverData", mStoredData.saveDataToNBT());
+ aNBT.setInteger("mTickRateAddition", mTickRateAddition);
+ }
+
+ @SuppressWarnings("rawtypes")
+ private void writeListToNBT(List aList, NBTTagCompound aNBT, EntityPlayer aPlayer) {
+ if (aList != null && aNBT != null) {
+ int tSize = aList.size();
+ aNBT.setInteger("dataLinesCount", tSize);
+ for (int i = 0; i < tSize; i++) {
+ aNBT.setString("dataLines" + i, (String) aList.get(i));
+ GT_Utility.sendChatToPlayer(aPlayer, (String) aList.get(i));
+ }
+ }
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ private void doCopy(TileEntity aTileEntity, World aWorld, int aX, int aY, int aZ, ForgeDirection side, float hitX,
+ float hitY, float hitZ, List aList) {
+ aList.add(
+ "----- X: " + EnumChatFormatting.AQUA
+ + GT_Utility.formatNumbers(aX)
+ + EnumChatFormatting.RESET
+ + " Y: "
+ + EnumChatFormatting.AQUA
+ + GT_Utility.formatNumbers(aY)
+ + EnumChatFormatting.RESET
+ + " Z: "
+ + EnumChatFormatting.AQUA
+ + GT_Utility.formatNumbers(aZ)
+ + EnumChatFormatting.RESET
+ + " D: "
+ + EnumChatFormatting.AQUA
+ + aWorld.provider.dimensionId
+ + EnumChatFormatting.RESET
+ + " -----");
+ if (aTileEntity instanceof ICoverable tCoverable) {
+ final ForgeDirection tSide = tCoverable.getCoverItemAtSide(side) != null ? side
+ : tCoverable.getCoverItemAtSide(GT_Utility.determineWrenchingSide(side, hitX, hitY, hitZ)) != null
+ ? GT_Utility.determineWrenchingSide(side, hitX, hitY, hitZ)
+ : ForgeDirection.UNKNOWN;
+ if (tSide != ForgeDirection.UNKNOWN) {
+ if (tCoverable.getCoverBehaviorAtSideNew(tSide)
+ .allowsCopyPasteTool()) {
+ mStoredData = tCoverable.getComplexCoverDataAtSide(tSide);
+ mCoverType = tCoverable.getCoverIDAtSide(tSide);
+ mTickRateAddition = tCoverable.getCoverInfoAtSide(tSide)
+ .getTickRateAddition();
+
+ aList.add("Block Side: " + EnumChatFormatting.AQUA + tSide.name() + EnumChatFormatting.RESET);
+ aList.add(
+ "Cover Type: " + EnumChatFormatting.GREEN
+ + tCoverable.getCoverItemAtSide(tSide)
+ .getDisplayName()
+ + EnumChatFormatting.RESET);
+ } else {
+ mStoredData = GregTech_API.sNoBehavior.createDataObject();
+ mCoverType = 0;
+ mTickRateAddition = 0;
+ aList.add("Copy unavailable for this cover type");
+ }
+ } else {
+ mStoredData = GregTech_API.sNoBehavior.createDataObject();
+ mCoverType = 0;
+ mTickRateAddition = 0;
+ aList.add("No Cover Found");
+ }
+ } else {
+ mStoredData = GregTech_API.sNoBehavior.createDataObject();
+ mCoverType = 0;
+ mTickRateAddition = 0;
+ aList.add("No Cover Found");
+ }
+ }
+
+ private void doPaste(TileEntity aTileEntity, ForgeDirection side, float hitX, float hitY, float hitZ,
+ EntityPlayer aPlayer) {
+ if (aTileEntity instanceof ICoverable tCoverable) {
+ if (mCoverType == 0 || mStoredData == null) {
+ GT_Utility.sendChatToPlayer(aPlayer, "Please Copy a Valid Cover First.");
+ return;
+ }
+ final ForgeDirection tSide = tCoverable.getCoverItemAtSide(side) != null ? side
+ : tCoverable.getCoverItemAtSide(GT_Utility.determineWrenchingSide(side, hitX, hitY, hitZ)) != null
+ ? GT_Utility.determineWrenchingSide(side, hitX, hitY, hitZ)
+ : ForgeDirection.UNKNOWN;
+ if (tSide != ForgeDirection.UNKNOWN) {
+ int tCoverID = tCoverable.getCoverIDAtSide(tSide);
+ if (tCoverID == mCoverType) {
+ tCoverable.setCoverDataAtSide(tSide, mStoredData);
+ tCoverable.getCoverInfoAtSide(tSide)
+ .setTickRateAddition(mTickRateAddition);
+ GT_Utility.sendChatToPlayer(aPlayer, "Cover Data Pasted.");
+ } else {
+ GT_Utility.sendChatToPlayer(aPlayer, "Not Matched Cover.");
+ }
+ } else {
+ GT_Utility.sendChatToPlayer(aPlayer, "No Cover Found.");
+ }
+ }
+ }
+
+ @Override
+ public List<String> getAdditionalToolTips(GT_MetaBase_Item aItem, List<String> aList, ItemStack aStack) {
+ try {
+ final NBTTagCompound tNBT = aStack.getTagCompound();
+ final int tSize = tNBT.getInteger("dataLinesCount");
+ if (tSize < 1) throw new Exception();
+ aList.add(EnumChatFormatting.BLUE + "Stored Cover Data:");
+ for (int i = 0; i < tSize; i++) {
+ aList.add(EnumChatFormatting.RESET + tNBT.getString("dataLines" + i));
+ }
+ } catch (Exception e) {
+ aList.add(this.mTooltip);
+ }
+ return aList;
+ }
+}
diff --git a/src/main/java/gregtech/common/items/behaviors/Behaviour_Crowbar.java b/src/main/java/gregtech/common/items/behaviors/Behaviour_Crowbar.java
new file mode 100644
index 0000000000..97d3da4ca3
--- /dev/null
+++ b/src/main/java/gregtech/common/items/behaviors/Behaviour_Crowbar.java
@@ -0,0 +1,61 @@
+package gregtech.common.items.behaviors;
+
+import static gregtech.api.enums.Mods.Railcraft;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.ItemStack;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.enums.SoundResource;
+import gregtech.api.items.GT_MetaBase_Item;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_Utility;
+
+public class Behaviour_Crowbar extends Behaviour_None {
+
+ private final int mVanillaCosts;
+ private final int mEUCosts;
+
+ public Behaviour_Crowbar(int aVanillaCosts, int aEUCosts) {
+ this.mVanillaCosts = aVanillaCosts;
+ this.mEUCosts = aEUCosts;
+ }
+
+ @Override
+ public boolean onItemUseFirst(GT_MetaBase_Item aItem, ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX,
+ int aY, int aZ, ForgeDirection side, float hitX, float hitY, float hitZ) {
+ if (aWorld.isRemote) {
+ return false;
+ }
+ if (GT_ModHandler.getModItem(Railcraft.ID, "fluid.creosote.bucket", 1L) != null) {
+ return false;
+ }
+ Block aBlock = aWorld.getBlock(aX, aY, aZ);
+ if (aBlock == null) {
+ return false;
+ }
+ byte aMeta = (byte) aWorld.getBlockMetadata(aX, aY, aZ);
+ if (aBlock == Blocks.rail) {
+ if (GT_ModHandler.damageOrDechargeItem(aStack, this.mVanillaCosts, this.mEUCosts, aPlayer)) {
+ aWorld.isRemote = true;
+ aWorld.setBlock(aX, aY, aZ, aBlock, (aMeta + 1) % 10, 0);
+ aWorld.isRemote = false;
+ GT_Utility.sendSoundToPlayers(aWorld, SoundResource.RANDOM_BREAK, 1.0F, -1.0F, aX, aY, aZ);
+ }
+ return true;
+ }
+ if ((aBlock == Blocks.detector_rail) || (aBlock == Blocks.activator_rail) || (aBlock == Blocks.golden_rail)) {
+ if (GT_ModHandler.damageOrDechargeItem(aStack, this.mVanillaCosts, this.mEUCosts, aPlayer)) {
+ aWorld.isRemote = true;
+ aWorld.setBlock(aX, aY, aZ, aBlock, aMeta / 8 * 8 + (aMeta % 8 + 1) % 6, 0);
+ aWorld.isRemote = false;
+ GT_Utility.sendSoundToPlayers(aWorld, SoundResource.RANDOM_BREAK, 1.0F, -1.0F, aX, aY, aZ);
+ }
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/src/main/java/gregtech/common/items/behaviors/Behaviour_DataOrb.java b/src/main/java/gregtech/common/items/behaviors/Behaviour_DataOrb.java
new file mode 100644
index 0000000000..ae0627446c
--- /dev/null
+++ b/src/main/java/gregtech/common/items/behaviors/Behaviour_DataOrb.java
@@ -0,0 +1,105 @@
+package gregtech.common.items.behaviors;
+
+import java.util.List;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+
+import gregtech.api.items.GT_MetaBase_Item;
+import gregtech.api.util.GT_Utility;
+
+public class Behaviour_DataOrb extends Behaviour_None {
+
+ public static void copyInventory(ItemStack[] aInventory, ItemStack[] aNewContent, int aIndexlength) {
+ for (int i = 0; i < aIndexlength; i++) {
+ if (aNewContent[i] == null) {
+ aInventory[i] = null;
+ } else {
+ aInventory[i] = GT_Utility.copyOrNull(aNewContent[i]);
+ }
+ }
+ }
+
+ public static String getDataName(ItemStack aStack) {
+ NBTTagCompound tNBT = aStack.getTagCompound();
+ if (tNBT == null) {
+ return "";
+ }
+ return tNBT.getString("mDataName");
+ }
+
+ public static String getDataTitle(ItemStack aStack) {
+ NBTTagCompound tNBT = aStack.getTagCompound();
+ if (tNBT == null) {
+ return "";
+ }
+ return tNBT.getString("mDataTitle");
+ }
+
+ public static NBTTagCompound setDataName(ItemStack aStack, String aDataName) {
+ NBTTagCompound tNBT = aStack.getTagCompound();
+ if (tNBT == null) {
+ tNBT = new NBTTagCompound();
+ }
+ tNBT.setString("mDataName", aDataName);
+ aStack.setTagCompound(tNBT);
+ return tNBT;
+ }
+
+ public static NBTTagCompound setDataTitle(ItemStack aStack, String aDataTitle) {
+ NBTTagCompound tNBT = aStack.getTagCompound();
+ if (tNBT == null) {
+ tNBT = new NBTTagCompound();
+ }
+ tNBT.setString("mDataTitle", aDataTitle);
+ aStack.setTagCompound(tNBT);
+ return tNBT;
+ }
+
+ public static ItemStack[] getNBTInventory(ItemStack aStack) {
+ ItemStack[] tInventory = new ItemStack[256];
+ NBTTagCompound tNBT = aStack.getTagCompound();
+ if (tNBT == null) {
+ return tInventory;
+ }
+ NBTTagList tNBT_ItemList = tNBT.getTagList("Inventory", 10);
+ for (int i = 0; i < tNBT_ItemList.tagCount(); i++) {
+ NBTTagCompound tag = tNBT_ItemList.getCompoundTagAt(i);
+ byte slot = tag.getByte("Slot");
+ if (slot >= 0) {
+ tInventory[slot] = GT_Utility.loadItem(tag);
+ }
+ }
+ return tInventory;
+ }
+
+ public static NBTTagCompound setNBTInventory(ItemStack aStack, ItemStack[] aInventory) {
+ NBTTagCompound tNBT = aStack.getTagCompound();
+ if (tNBT == null) {
+ tNBT = new NBTTagCompound();
+ }
+ NBTTagList tNBT_ItemList = new NBTTagList();
+ for (int i = 0; i < aInventory.length; i++) {
+ ItemStack stack = aInventory[i];
+ if (stack != null) {
+ NBTTagCompound tag = new NBTTagCompound();
+ tag.setByte("Slot", (byte) i);
+ stack.writeToNBT(tag);
+ tNBT_ItemList.appendTag(tag);
+ }
+ }
+ tNBT.setTag("Inventory", tNBT_ItemList);
+ aStack.setTagCompound(tNBT);
+ return tNBT;
+ }
+
+ @Override
+ public List<String> getAdditionalToolTips(GT_MetaBase_Item aItem, List<String> aList, ItemStack aStack) {
+ if (!(getDataTitle(aStack).length() == 0)) {
+ aList.add(getDataTitle(aStack));
+ aList.add(getDataName(aStack));
+ }
+ return aList;
+ }
+}
diff --git a/src/main/java/gregtech/common/items/behaviors/Behaviour_DataStick.java b/src/main/java/gregtech/common/items/behaviors/Behaviour_DataStick.java
new file mode 100644
index 0000000000..e9db3195c2
--- /dev/null
+++ b/src/main/java/gregtech/common/items/behaviors/Behaviour_DataStick.java
@@ -0,0 +1,52 @@
+package gregtech.common.items.behaviors;
+
+import java.util.List;
+
+import net.minecraft.item.ItemStack;
+
+import gregtech.api.items.GT_MetaBase_Item;
+import gregtech.api.util.GT_Utility;
+
+public class Behaviour_DataStick extends Behaviour_None {
+
+ @Override
+ public List<String> getAdditionalToolTips(GT_MetaBase_Item aItem, List<String> aList, ItemStack aStack) {
+ String tString = GT_Utility.ItemNBT.getBookTitle(aStack);
+ if (GT_Utility.isStringValid(tString)) {
+ aList.add(tString);
+ }
+ tString = GT_Utility.ItemNBT.getBookAuthor(aStack);
+ if (GT_Utility.isStringValid(tString)) {
+ aList.add("by " + tString);
+ }
+ short tMapID = GT_Utility.ItemNBT.getMapID(aStack);
+ if (tMapID >= 0) {
+ aList.add("Map ID: " + tMapID);
+ }
+ tString = GT_Utility.ItemNBT.getPunchCardData(aStack);
+ if (GT_Utility.isStringValid(tString)) {
+ aList.add("Punch Card Data");
+ int i = 0;
+ int j = tString.length();
+ for (; i < j; i += 64) {
+ aList.add(tString.substring(i, Math.min(i + 64, j)));
+ }
+ }
+ short sTier = GT_Utility.ItemNBT.getNBT(aStack)
+ .getShort("rocket_tier");
+ if (sTier > 0 && sTier < 100) {
+ aList.add("Rocket Schematic Tier: " + sTier);
+ } else if (sTier >= 100) {
+ switch (sTier) {
+ case 100 -> aList.add("Moonbuggy Schematic");
+ case 101 -> aList.add("Cargo-Rocket Schematic");
+ case 102 -> aList.add("Astro-Miner Schematic");
+ }
+ }
+ long lastUpdate = GT_Utility.ItemNBT.getNBT(aStack)
+ .getLong("lastUpdate");
+ if (lastUpdate != 0) aList.add(String.format("Last update at: %tc", lastUpdate));
+
+ return aList;
+ }
+}
diff --git a/src/main/java/gregtech/common/items/behaviors/Behaviour_Hoe.java b/src/main/java/gregtech/common/items/behaviors/Behaviour_Hoe.java
new file mode 100644
index 0000000000..167eccdf49
--- /dev/null
+++ b/src/main/java/gregtech/common/items/behaviors/Behaviour_Hoe.java
@@ -0,0 +1,72 @@
+package gregtech.common.items.behaviors;
+
+import java.util.List;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.ItemStack;
+import net.minecraft.world.World;
+import net.minecraftforge.common.MinecraftForge;
+import net.minecraftforge.event.entity.player.UseHoeEvent;
+
+import cpw.mods.fml.common.eventhandler.Event;
+import gregtech.api.items.GT_MetaBase_Item;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.util.GT_LanguageManager;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.WorldSpawnedEventBuilder;
+
+public class Behaviour_Hoe extends Behaviour_None {
+
+ private final int mCosts;
+ private final String mTooltip = GT_LanguageManager.addStringLocalization("gt.behaviour.hoe", "Can till Dirt");
+
+ public Behaviour_Hoe(int aCosts) {
+ this.mCosts = aCosts;
+ }
+
+ @Override
+ public boolean onItemUse(GT_MetaBase_Item aItem, ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX,
+ int aY, int aZ, int ordinalSide, float hitX, float hitY, float hitZ) {
+ if (!aPlayer.canPlayerEdit(aX, aY, aZ, ordinalSide, aStack)) {
+ return false;
+ }
+ UseHoeEvent event = new UseHoeEvent(aPlayer, aStack, aWorld, aX, aY, aZ);
+ if (MinecraftForge.EVENT_BUS.post(event)) {
+ return false;
+ }
+ if (event.getResult() == Event.Result.ALLOW) {
+ if (!aPlayer.capabilities.isCreativeMode) {
+ ((GT_MetaGenerated_Tool) aItem).doDamage(aStack, this.mCosts);
+ }
+ return true;
+ }
+ Block aBlock = aWorld.getBlock(aX, aY, aZ);
+ if ((ordinalSide != 0) && (GT_Utility.isBlockAir(aWorld, aX, aY + 1, aZ))
+ && ((aBlock == Blocks.grass) || (aBlock == Blocks.dirt))) {
+ new WorldSpawnedEventBuilder.SoundEventBuilder()
+ .setVolume((Blocks.farmland.stepSound.getVolume() + 1.0F) / 2.0F)
+ .setPitch(Blocks.farmland.stepSound.getPitch() * 0.8F)
+ .setIdentifier(Blocks.farmland.stepSound.getStepResourcePath())
+ .setPosition(aX + 0.5F, aY + 0.5F, aZ + 0.5F)
+ .setWorld(aWorld)
+ .run();
+ if (aWorld.isRemote) {
+ return true;
+ }
+ aWorld.setBlock(aX, aY, aZ, Blocks.farmland);
+ if (!aPlayer.capabilities.isCreativeMode) {
+ ((GT_MetaGenerated_Tool) aItem).doDamage(aStack, this.mCosts);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public List<String> getAdditionalToolTips(GT_MetaBase_Item aItem, List<String> aList, ItemStack aStack) {
+ aList.add(this.mTooltip);
+ return aList;
+ }
+}
diff --git a/src/main/java/gregtech/common/items/behaviors/Behaviour_Lighter.java b/src/main/java/gregtech/common/items/behaviors/Behaviour_Lighter.java
new file mode 100644
index 0000000000..a4c26e2254
--- /dev/null
+++ b/src/main/java/gregtech/common/items/behaviors/Behaviour_Lighter.java
@@ -0,0 +1,140 @@
+package gregtech.common.items.behaviors;
+
+import java.util.List;
+
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.monster.EntityCreeper;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraft.init.Items;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import codechicken.lib.math.MathHelper;
+import gregtech.api.enums.SoundResource;
+import gregtech.api.items.GT_MetaBase_Item;
+import gregtech.api.util.GT_LanguageManager;
+import gregtech.api.util.GT_Utility;
+
+public class Behaviour_Lighter extends Behaviour_None {
+
+ private final ItemStack mEmptyLighter;
+ private final ItemStack mUsedLighter;
+ private final ItemStack mFullLighter;
+ private final long mFuelAmount;
+ private final String mTooltip = GT_LanguageManager
+ .addStringLocalization("gt.behaviour.lighter.tooltip", "Can light things on Fire");
+ private final String mTooltipUses = GT_LanguageManager
+ .addStringLocalization("gt.behaviour.lighter.uses", "Remaining Uses:");
+ private final String mTooltipUnstackable = GT_LanguageManager
+ .addStringLocalization("gt.behaviour.unstackable", "Not usable when stacked!");
+
+ public Behaviour_Lighter(ItemStack aEmptyLighter, ItemStack aUsedLighter, ItemStack aFullLighter,
+ long aFuelAmount) {
+ this.mFullLighter = aFullLighter;
+ this.mUsedLighter = aUsedLighter;
+ this.mEmptyLighter = aEmptyLighter;
+ this.mFuelAmount = aFuelAmount;
+ }
+
+ @Override
+ public boolean onLeftClickEntity(GT_MetaBase_Item aItem, ItemStack aStack, EntityPlayer aPlayer, Entity aEntity) {
+ if ((aPlayer.worldObj.isRemote) || (aStack.stackSize != 1)) {
+ return false;
+ }
+ boolean rOutput = false;
+ if ((aEntity instanceof EntityCreeper)) {
+ prepare(aStack);
+ long tFuelAmount = GT_Utility.ItemNBT.getLighterFuel(aStack);
+ if (GT_Utility.areStacksEqual(aStack, this.mUsedLighter, true)) {
+ GT_Utility.sendSoundToPlayers(
+ aPlayer.worldObj,
+ SoundResource.FIRE_IGNITE,
+ 1.0F,
+ 1.0F,
+ MathHelper.floor_double(aEntity.posX),
+ MathHelper.floor_double(aEntity.posY),
+ MathHelper.floor_double(aEntity.posZ));
+ ((EntityCreeper) aEntity).func_146079_cb();
+ if (!aPlayer.capabilities.isCreativeMode) {
+ tFuelAmount -= 1L;
+ }
+ rOutput = true;
+ }
+ GT_Utility.ItemNBT.setLighterFuel(aStack, tFuelAmount);
+ if (tFuelAmount <= 0L) {
+ useUp(aStack);
+ }
+ }
+ return rOutput;
+ }
+
+ @Override
+ public boolean onItemUse(GT_MetaBase_Item aItem, ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX,
+ int aY, int aZ, int ordinalSide, float hitX, float hitY, float hitZ) {
+ return false;
+ }
+
+ @Override
+ public boolean onItemUseFirst(GT_MetaBase_Item aItem, ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX,
+ int aY, int aZ, ForgeDirection side, float hitX, float hitY, float hitZ) {
+ if ((aWorld.isRemote) || (aStack.stackSize != 1)) {
+ return false;
+ }
+ boolean rOutput = false;
+
+ aX += side.offsetX;
+ aY += side.offsetY;
+ aZ += side.offsetZ;
+ if ((!GT_Utility.isBlockAir(aWorld, aX, aY, aZ))
+ || (!aPlayer.canPlayerEdit(aX, aY, aZ, side.ordinal(), aStack))) {
+ return false;
+ }
+ prepare(aStack);
+ long tFuelAmount = GT_Utility.ItemNBT.getLighterFuel(aStack);
+ if (GT_Utility.areStacksEqual(aStack, this.mUsedLighter, true)) {
+ GT_Utility.sendSoundToPlayers(aWorld, SoundResource.FIRE_IGNITE, 1.0F, 1.0F, aX, aY, aZ);
+ aWorld.setBlock(aX, aY, aZ, Blocks.fire);
+ if (!aPlayer.capabilities.isCreativeMode) {
+ tFuelAmount -= 1L;
+ }
+ rOutput = true;
+ }
+ GT_Utility.ItemNBT.setLighterFuel(aStack, tFuelAmount);
+ if (tFuelAmount <= 0L) {
+ useUp(aStack);
+ }
+ return rOutput;
+ }
+
+ private void prepare(ItemStack aStack) {
+ if (GT_Utility.areStacksEqual(aStack, this.mFullLighter, true)) {
+ aStack.func_150996_a(this.mUsedLighter.getItem());
+ Items.feather.setDamage(aStack, Items.feather.getDamage(this.mUsedLighter));
+ GT_Utility.ItemNBT.setLighterFuel(aStack, this.mFuelAmount);
+ }
+ }
+
+ private void useUp(ItemStack aStack) {
+ if (this.mEmptyLighter == null) {
+ aStack.stackSize -= 1;
+ } else {
+ aStack.func_150996_a(this.mEmptyLighter.getItem());
+ Items.feather.setDamage(aStack, Items.feather.getDamage(this.mEmptyLighter));
+ }
+ }
+
+ @Override
+ public List<String> getAdditionalToolTips(GT_MetaBase_Item aItem, List<String> aList, ItemStack aStack) {
+ aList.add(this.mTooltip);
+ NBTTagCompound tNBT = aStack.getTagCompound();
+ long tFuelAmount = tNBT == null ? this.mFuelAmount
+ : GT_Utility.areStacksEqual(aStack, this.mFullLighter, true) ? this.mFuelAmount
+ : tNBT.getLong("GT.LighterFuel");
+ aList.add(this.mTooltipUses + " " + tFuelAmount);
+ aList.add(this.mTooltipUnstackable);
+ return aList;
+ }
+}
diff --git a/src/main/java/gregtech/common/items/behaviors/Behaviour_None.java b/src/main/java/gregtech/common/items/behaviors/Behaviour_None.java
new file mode 100644
index 0000000000..4ce7f60da0
--- /dev/null
+++ b/src/main/java/gregtech/common/items/behaviors/Behaviour_None.java
@@ -0,0 +1,96 @@
+package gregtech.common.items.behaviors;
+
+import java.util.List;
+
+import net.minecraft.block.BlockDispenser;
+import net.minecraft.dispenser.BehaviorDefaultDispenseItem;
+import net.minecraft.dispenser.IBlockSource;
+import net.minecraft.dispenser.IPosition;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.projectile.EntityArrow;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.EnumFacing;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.enums.SubTag;
+import gregtech.api.interfaces.IItemBehaviour;
+import gregtech.api.items.GT_MetaBase_Item;
+import gregtech.api.util.GT_Utility;
+
+public class Behaviour_None implements IItemBehaviour<GT_MetaBase_Item> {
+
+ @Override
+ public boolean onLeftClickEntity(GT_MetaBase_Item aItem, ItemStack aStack, EntityPlayer aPlayer, Entity aEntity) {
+ return false;
+ }
+
+ @Override
+ public boolean onItemUse(GT_MetaBase_Item aItem, ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX,
+ int aY, int aZ, int ordinalSide, float hitX, float hitY, float hitZ) {
+ return false;
+ }
+
+ @Override
+ public boolean onItemUseFirst(GT_MetaBase_Item aItem, ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX,
+ int aY, int aZ, ForgeDirection side, float hitX, float hitY, float hitZ) {
+ return false;
+ }
+
+ @Override
+ public ItemStack onItemRightClick(GT_MetaBase_Item aItem, ItemStack aStack, World aWorld, EntityPlayer aPlayer) {
+ return aStack;
+ }
+
+ @Override
+ public List<String> getAdditionalToolTips(GT_MetaBase_Item aItem, List<String> aList, ItemStack aStack) {
+ return aList;
+ }
+
+ @Override
+ public void onUpdate(GT_MetaBase_Item aItem, ItemStack aStack, World aWorld, Entity aPlayer, int aTimer,
+ boolean aIsInHand) {}
+
+ @Override
+ public boolean isItemStackUsable(GT_MetaBase_Item aItem, ItemStack aStack) {
+ return true;
+ }
+
+ @Override
+ public boolean canDispense(GT_MetaBase_Item aItem, IBlockSource aSource, ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public ItemStack onDispense(GT_MetaBase_Item aItem, IBlockSource aSource, ItemStack aStack) {
+ EnumFacing enumfacing = BlockDispenser.func_149937_b(aSource.getBlockMetadata());
+ IPosition iposition = BlockDispenser.func_149939_a(aSource);
+ ItemStack itemstack1 = aStack.splitStack(1);
+ BehaviorDefaultDispenseItem.doDispense(aSource.getWorld(), itemstack1, 6, enumfacing, iposition);
+ return aStack;
+ }
+
+ @Override
+ public boolean hasProjectile(GT_MetaBase_Item aItem, SubTag aProjectileType, ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public EntityArrow getProjectile(GT_MetaBase_Item aItem, SubTag aProjectileType, ItemStack aStack, World aWorld,
+ double aX, double aY, double aZ) {
+ return null;
+ }
+
+ @Override
+ public EntityArrow getProjectile(GT_MetaBase_Item aItem, SubTag aProjectileType, ItemStack aStack, World aWorld,
+ EntityLivingBase aEntity, float aSpeed) {
+ return null;
+ }
+
+ @Deprecated
+ public String trans(String aKey, String aEnglish) {
+ return GT_Utility.trans(aKey, aEnglish);
+ }
+}
diff --git a/src/main/java/gregtech/common/items/behaviors/Behaviour_Plunger_Essentia.java b/src/main/java/gregtech/common/items/behaviors/Behaviour_Plunger_Essentia.java
new file mode 100644
index 0000000000..867eb25103
--- /dev/null
+++ b/src/main/java/gregtech/common/items/behaviors/Behaviour_Plunger_Essentia.java
@@ -0,0 +1,54 @@
+package gregtech.common.items.behaviors;
+
+import java.util.List;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.enums.SoundResource;
+import gregtech.api.items.GT_MetaBase_Item;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.util.GT_LanguageManager;
+import gregtech.api.util.GT_Utility;
+import thaumcraft.api.aspects.IEssentiaTransport;
+
+public class Behaviour_Plunger_Essentia extends Behaviour_None {
+
+ private final int mCosts;
+ private final String mTooltip = GT_LanguageManager
+ .addStringLocalization("gt.behaviour.plunger.essentia", "Clears Essentia from Containers and Tubes");
+
+ public Behaviour_Plunger_Essentia(int aCosts) {
+ this.mCosts = aCosts;
+ }
+
+ @Override
+ public boolean onItemUseFirst(GT_MetaBase_Item aItem, ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX,
+ int aY, int aZ, ForgeDirection side, float hitX, float hitY, float hitZ) {
+ if (aWorld.isRemote) {
+ return false;
+ }
+ TileEntity aTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if (((aTileEntity instanceof IEssentiaTransport)) && ((aPlayer.capabilities.isCreativeMode)
+ || (((GT_MetaGenerated_Tool) aItem).doDamage(aStack, this.mCosts)))) {
+ GT_Utility.sendSoundToPlayers(aWorld, SoundResource.IC2_TOOLS_RUBBER_TRAMPOLINE, 1.0F, -1.0F, aX, aY, aZ);
+ for (ForgeDirection tDirection : ForgeDirection.VALID_DIRECTIONS) {
+ ((IEssentiaTransport) aTileEntity).takeEssentia(
+ ((IEssentiaTransport) aTileEntity).getEssentiaType(tDirection),
+ ((IEssentiaTransport) aTileEntity).getEssentiaAmount(tDirection),
+ tDirection);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public List<String> getAdditionalToolTips(GT_MetaBase_Item aItem, List<String> aList, ItemStack aStack) {
+ aList.add(this.mTooltip);
+ return aList;
+ }
+}
diff --git a/src/main/java/gregtech/common/items/behaviors/Behaviour_Plunger_Fluid.java b/src/main/java/gregtech/common/items/behaviors/Behaviour_Plunger_Fluid.java
new file mode 100644
index 0000000000..c62cb5c4e5
--- /dev/null
+++ b/src/main/java/gregtech/common/items/behaviors/Behaviour_Plunger_Fluid.java
@@ -0,0 +1,75 @@
+package gregtech.common.items.behaviors;
+
+import java.util.List;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.IFluidHandler;
+
+import gregtech.api.enums.SoundResource;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.items.GT_MetaBase_Item;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicTank;
+import gregtech.api.util.GT_LanguageManager;
+import gregtech.api.util.GT_Utility;
+
+public class Behaviour_Plunger_Fluid extends Behaviour_None {
+
+ private final int mCosts;
+ private final String mTooltip = GT_LanguageManager
+ .addStringLocalization("gt.behaviour.plunger.fluid", "Clears 1000 Liters of Fluid from Tanks");
+
+ public Behaviour_Plunger_Fluid(int aCosts) {
+ this.mCosts = aCosts;
+ }
+
+ @Override
+ public boolean onItemUseFirst(GT_MetaBase_Item aItem, ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX,
+ int aY, int aZ, ForgeDirection side, float hitX, float hitY, float hitZ) {
+ if (aWorld.isRemote) {
+ return false;
+ }
+ TileEntity aTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if ((aTileEntity instanceof IFluidHandler)) {
+ for (ForgeDirection tDirection : ForgeDirection.VALID_DIRECTIONS) {
+ if (((IFluidHandler) aTileEntity).drain(tDirection, 1000, false) != null) {
+ if ((aPlayer.capabilities.isCreativeMode)
+ || (((GT_MetaGenerated_Tool) aItem).doDamage(aStack, this.mCosts))) {
+ ((IFluidHandler) aTileEntity).drain(tDirection, 1000, true);
+ GT_Utility.sendSoundToPlayers(
+ aWorld,
+ SoundResource.IC2_TOOLS_RUBBER_TRAMPOLINE,
+ 1.0F,
+ -1.0F,
+ aX,
+ aY,
+ aZ);
+ return true;
+ }
+ }
+ }
+ }
+ if (aTileEntity instanceof IGregTechTileEntity tTileEntity) {
+ IMetaTileEntity mTileEntity = tTileEntity.getMetaTileEntity();
+ if (mTileEntity instanceof GT_MetaTileEntity_BasicTank machine) {
+ if (machine.mFluid != null && machine.mFluid.amount > 0)
+ machine.mFluid.amount = machine.mFluid.amount - Math.min(machine.mFluid.amount, 1000);
+ GT_Utility
+ .sendSoundToPlayers(aWorld, SoundResource.IC2_TOOLS_RUBBER_TRAMPOLINE, 1.0F, -1.0F, aX, aY, aZ);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public List<String> getAdditionalToolTips(GT_MetaBase_Item aItem, List<String> aList, ItemStack aStack) {
+ aList.add(this.mTooltip);
+ return aList;
+ }
+}
diff --git a/src/main/java/gregtech/common/items/behaviors/Behaviour_Plunger_Item.java b/src/main/java/gregtech/common/items/behaviors/Behaviour_Plunger_Item.java
new file mode 100644
index 0000000000..a5fa868a00
--- /dev/null
+++ b/src/main/java/gregtech/common/items/behaviors/Behaviour_Plunger_Item.java
@@ -0,0 +1,88 @@
+package gregtech.common.items.behaviors;
+
+import java.util.HashMap;
+import java.util.List;
+
+import net.minecraft.entity.item.EntityItem;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.enums.SoundResource;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntityItemPipe;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.items.GT_MetaBase_Item;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.util.GT_LanguageManager;
+import gregtech.api.util.GT_Utility;
+
+public class Behaviour_Plunger_Item extends Behaviour_None {
+
+ private final int mCosts;
+ private final String mTooltip = GT_LanguageManager
+ .addStringLocalization("gt.behaviour.plunger.item", "Clears Items from Pipes");
+
+ public Behaviour_Plunger_Item(int aCosts) {
+ this.mCosts = aCosts;
+ }
+
+ @Override
+ public boolean onItemUseFirst(GT_MetaBase_Item aItem, ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX,
+ int aY, int aZ, ForgeDirection side, float hitX, float hitY, float hitZ) {
+ if (aWorld.isRemote) {
+ return false;
+ }
+ TileEntity aTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if (aTileEntity instanceof IGregTechTileEntity gtTE) {
+ IMetaTileEntity tMetaTileEntity = gtTE.getMetaTileEntity();
+ if ((tMetaTileEntity instanceof IMetaTileEntityItemPipe)) {
+ for (IMetaTileEntityItemPipe tTileEntity : GT_Utility
+ .sortMapByValuesAcending(
+ IMetaTileEntityItemPipe.Util
+ .scanPipes((IMetaTileEntityItemPipe) tMetaTileEntity, new HashMap<>(), 0L, false, true))
+ .keySet()) {
+ int i = 0;
+ for (int j = tTileEntity.getSizeInventory(); i < j; i++) {
+ if (tTileEntity.isValidSlot(i)) {
+ if ((tTileEntity.getStackInSlot(i) != null) && ((aPlayer.capabilities.isCreativeMode)
+ || (((GT_MetaGenerated_Tool) aItem).doDamage(aStack, this.mCosts)))) {
+ final ItemStack tStack = tTileEntity.decrStackSize(i, 64);
+ if (tStack != null) {
+ final EntityItem tEntity = new EntityItem(
+ aWorld,
+ gtTE.getOffsetX(side, 1) + 0.5D,
+ gtTE.getOffsetY(side, 1) + 0.5D,
+ gtTE.getOffsetZ(side, 1) + 0.5D,
+ tStack);
+ tEntity.motionX = 0.0D;
+ tEntity.motionY = 0.0D;
+ tEntity.motionZ = 0.0D;
+ aWorld.spawnEntityInWorld(tEntity);
+ GT_Utility.sendSoundToPlayers(
+ aWorld,
+ SoundResource.IC2_TOOLS_RUBBER_TRAMPOLINE,
+ 1.0F,
+ -1.0F,
+ aX,
+ aY,
+ aZ);
+ }
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public List<String> getAdditionalToolTips(GT_MetaBase_Item aItem, List<String> aList, ItemStack aStack) {
+ aList.add(this.mTooltip);
+ return aList;
+ }
+}
diff --git a/src/main/java/gregtech/common/items/behaviors/Behaviour_PrintedPages.java b/src/main/java/gregtech/common/items/behaviors/Behaviour_PrintedPages.java
new file mode 100644
index 0000000000..e3c4d58525
--- /dev/null
+++ b/src/main/java/gregtech/common/items/behaviors/Behaviour_PrintedPages.java
@@ -0,0 +1,39 @@
+package gregtech.common.items.behaviors;
+
+import java.util.List;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+
+import gregtech.api.items.GT_MetaBase_Item;
+import gregtech.api.util.GT_Utility;
+
+public class Behaviour_PrintedPages extends Behaviour_None {
+
+ public static String getTitle(ItemStack aStack) {
+ NBTTagCompound tNBT = aStack.getTagCompound();
+ if (tNBT == null) {
+ return "";
+ }
+ return tNBT.getString("title");
+ }
+
+ public static String getAuthor(ItemStack aStack) {
+ NBTTagCompound tNBT = aStack.getTagCompound();
+ if (tNBT == null) {
+ return "";
+ }
+ return tNBT.getString("author");
+ }
+
+ @Override
+ public List<String> getAdditionalToolTips(GT_MetaBase_Item aItem, List<String> aList, ItemStack aStack) {
+ if (GT_Utility.isStringValid(getTitle(aStack))) {
+ aList.add(getTitle(aStack));
+ }
+ if (GT_Utility.isStringValid(getAuthor(aStack))) {
+ aList.add("by " + getAuthor(aStack));
+ }
+ return aList;
+ }
+}
diff --git a/src/main/java/gregtech/common/items/behaviors/Behaviour_Prospecting.java b/src/main/java/gregtech/common/items/behaviors/Behaviour_Prospecting.java
new file mode 100644
index 0000000000..e64722fb87
--- /dev/null
+++ b/src/main/java/gregtech/common/items/behaviors/Behaviour_Prospecting.java
@@ -0,0 +1,159 @@
+package gregtech.common.items.behaviors;
+
+import java.util.List;
+import java.util.Random;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.BlockLiquid;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.ItemStack;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.IFluidBlock;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.SoundResource;
+import gregtech.api.items.GT_MetaBase_Item;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.objects.ItemData;
+import gregtech.api.objects.XSTR;
+import gregtech.api.util.GT_LanguageManager;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_OreDictUnificator;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.blocks.GT_Block_Ores_Abstract;
+import gregtech.common.blocks.GT_TileEntity_Ores;
+
+public class Behaviour_Prospecting extends Behaviour_None {
+
+ private final int mVanillaCosts;
+ private final int mEUCosts;
+ private final String mTooltip = GT_LanguageManager
+ .addStringLocalization("gt.behaviour.prospecting", "Usable for Prospecting");
+
+ public Behaviour_Prospecting(int aVanillaCosts, int aEUCosts) {
+ this.mVanillaCosts = aVanillaCosts;
+ this.mEUCosts = aEUCosts;
+ }
+
+ @Override
+ public boolean onItemUseFirst(GT_MetaBase_Item aItem, ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX,
+ int aY, int aZ, ForgeDirection side, float hitX, float hitY, float hitZ) {
+ if (aWorld.isRemote) {
+ return false;
+ }
+ Block aBlock = aWorld.getBlock(aX, aY, aZ);
+ if (aBlock == null) {
+ return false;
+ }
+ byte aMeta = (byte) aWorld.getBlockMetadata(aX, aY, aZ);
+
+ ItemData tAssociation = GT_OreDictUnificator.getAssociation(new ItemStack(aBlock, 1, aMeta));
+ if (tAssociation != null && tAssociation.mPrefix != null
+ && tAssociation.mMaterial != null
+ && tAssociation.mPrefix.toString()
+ .startsWith("ore")) {
+ GT_Utility.sendChatToPlayer(
+ aPlayer,
+ GT_Utility.trans("100", "This is ") + tAssociation.mMaterial.mMaterial.mDefaultLocalName
+ + GT_Utility.trans("101", " Ore."));
+ GT_Utility.sendSoundToPlayers(aWorld, SoundResource.RANDOM_ANVIL_USE, 1.0F, -1.0F, aX, aY, aZ);
+ return true;
+ }
+
+ if (aBlock.isReplaceableOreGen(aWorld, aX, aY, aZ, Blocks.stone)
+ || aBlock.isReplaceableOreGen(aWorld, aX, aY, aZ, Blocks.netherrack)
+ || aBlock.isReplaceableOreGen(aWorld, aX, aY, aZ, Blocks.end_stone)
+ || aBlock.isReplaceableOreGen(aWorld, aX, aY, aZ, GregTech_API.sBlockStones)
+ || aBlock.isReplaceableOreGen(aWorld, aX, aY, aZ, GregTech_API.sBlockGranites)
+ || aBlock == GregTech_API.sBlockOresUb1
+ || aBlock == GregTech_API.sBlockOresUb2
+ || aBlock == GregTech_API.sBlockOresUb3
+ || aBlock == GregTech_API.sBlockOres1) {
+ if (GT_ModHandler.damageOrDechargeItem(aStack, this.mVanillaCosts, this.mEUCosts, aPlayer)) {
+ GT_Utility.sendSoundToPlayers(aWorld, SoundResource.RANDOM_ANVIL_USE, 1.0F, -1.0F, aX, aY, aZ);
+ int tMetaID;
+ int tQuality = aItem instanceof GT_MetaGenerated_Tool ? aItem.getHarvestLevel(aStack, "") : 0;
+ int tX = aX, tY = aY, tZ = aZ;
+ Block tBlock;
+ for (int i = 0, j = 6 + tQuality; i < j; i++) {
+ tX -= side.offsetX;
+ tY -= side.offsetY;
+ tZ -= side.offsetZ;
+
+ tBlock = aWorld.getBlock(tX, tY, tZ);
+ if (tBlock == Blocks.lava || tBlock == Blocks.flowing_lava) {
+ GT_Utility
+ .sendChatToPlayer(aPlayer, GT_Utility.trans("102", "There is Lava behind this Rock."));
+ break;
+ }
+ if (tBlock instanceof BlockLiquid || tBlock instanceof IFluidBlock) {
+ GT_Utility
+ .sendChatToPlayer(aPlayer, GT_Utility.trans("103", "There is a Liquid behind this Rock."));
+ break;
+ }
+ if (tBlock == Blocks.monster_egg || !GT_Utility.hasBlockHitBox(aWorld, tX, tY, tZ)) {
+ GT_Utility.sendChatToPlayer(
+ aPlayer,
+ GT_Utility.trans("104", "There is an Air Pocket behind this Rock."));
+ break;
+ }
+ if (tBlock != aBlock) {
+ if (i < 4) GT_Utility.sendChatToPlayer(
+ aPlayer,
+ GT_Utility.trans("105", "Material is changing behind this Rock."));
+ break;
+ }
+ }
+
+ final Random tRandom = new XSTR(aX ^ aY ^ aZ ^ side.ordinal());
+ for (int i = 0, j = 9 + 2 * tQuality; i < j; i++) {
+ tX = aX - 4 - tQuality + tRandom.nextInt(j);
+ tY = aY - 4 - tQuality + tRandom.nextInt(j);
+ tZ = aZ - 4 - tQuality + tRandom.nextInt(j);
+ tBlock = aWorld.getBlock(tX, tY, tZ);
+ if (tBlock instanceof GT_Block_Ores_Abstract) {
+ final TileEntity tTileEntity = aWorld.getTileEntity(tX, tY, tZ);
+ if (tTileEntity instanceof GT_TileEntity_Ores) {
+ final Materials tMaterial = GregTech_API.sGeneratedMaterials[((GT_TileEntity_Ores) tTileEntity).mMetaData
+ % 1000];
+ if (tMaterial != null && tMaterial != Materials._NULL) {
+ GT_Utility.sendChatToPlayer(
+ aPlayer,
+ GT_Utility.trans("106", "Found traces of ") + tMaterial.mDefaultLocalName
+ + GT_Utility.trans("101", " Ore."));
+ return true;
+ }
+ }
+ } else {
+ tMetaID = aWorld.getBlockMetadata(tX, tY, tZ);
+ tAssociation = GT_OreDictUnificator.getAssociation(new ItemStack(tBlock, 1, tMetaID));
+ if (tAssociation != null && tAssociation.mPrefix != null
+ && tAssociation.mMaterial != null
+ && tAssociation.mPrefix.toString()
+ .startsWith("ore")) {
+ GT_Utility.sendChatToPlayer(
+ aPlayer,
+ GT_Utility.trans("106", "Found traces of ")
+ + tAssociation.mMaterial.mMaterial.mDefaultLocalName
+ + GT_Utility.trans("101", " Ore."));
+ return true;
+ }
+ }
+ }
+ GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("107", "No Ores found."));
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public List<String> getAdditionalToolTips(GT_MetaBase_Item aItem, List<String> aList, ItemStack aStack) {
+ aList.add(this.mTooltip);
+ return aList;
+ }
+}
diff --git a/src/main/java/gregtech/common/items/behaviors/Behaviour_Scanner.java b/src/main/java/gregtech/common/items/behaviors/Behaviour_Scanner.java
new file mode 100644
index 0000000000..22b708e384
--- /dev/null
+++ b/src/main/java/gregtech/common/items/behaviors/Behaviour_Scanner.java
@@ -0,0 +1,65 @@
+package gregtech.common.items.behaviors;
+
+import java.util.ArrayList;
+import java.util.List;
+
+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.util.EnumChatFormatting;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.enums.SoundResource;
+import gregtech.api.interfaces.IItemBehaviour;
+import gregtech.api.items.GT_MetaBase_Item;
+import gregtech.api.util.GT_LanguageManager;
+import gregtech.api.util.GT_Utility;
+
+public class Behaviour_Scanner extends Behaviour_None {
+
+ public static final IItemBehaviour<GT_MetaBase_Item> INSTANCE = new Behaviour_Scanner();
+ private final String mTooltip = GT_LanguageManager
+ .addStringLocalization("gt.behaviour.scanning", "Can scan Blocks in World");
+
+ @Override
+ public boolean onItemUseFirst(GT_MetaBase_Item aItem, ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX,
+ int aY, int aZ, ForgeDirection side, float hitX, float hitY, float hitZ) {
+ final NBTTagCompound tNBT = aStack.getTagCompound();
+ if (((aPlayer instanceof EntityPlayerMP)) && (aItem.canUse(aStack, 20000.0D))) {
+ final ArrayList<String> tList = new ArrayList<>();
+ if (aItem.use(
+ aStack,
+ GT_Utility.getCoordinateScan(tList, aPlayer, aWorld, 1, aX, aY, aZ, side, hitX, hitY, hitZ),
+ aPlayer)) {
+ final int tList_sS = tList.size();
+ tNBT.setInteger("dataLinesCount", tList_sS);
+ for (int i = 0; i < tList_sS; i++) {
+ tNBT.setString("dataLines" + i, tList.get(i));
+ GT_Utility.sendChatToPlayer(aPlayer, tList.get(i));
+ }
+ }
+ return true;
+ }
+ GT_Utility.doSoundAtClient(SoundResource.IC2_TOOLS_OD_SCANNER, 1, 1.0F, aX, aY, aZ);
+ // doGuiAtClient()
+ return aPlayer instanceof EntityPlayerMP;
+ }
+
+ @Override
+ public List<String> getAdditionalToolTips(GT_MetaBase_Item aItem, List<String> aList, ItemStack aStack) {
+ try {
+ NBTTagCompound tNBT = aStack.getTagCompound();
+ int lines = tNBT.getInteger("dataLinesCount");
+ if (lines < 1) throw new Exception();
+ aList.add(EnumChatFormatting.BLUE + "Block scan data result:");
+ for (int i = 0; i < lines; i++) {
+ aList.add(EnumChatFormatting.RESET + tNBT.getString("dataLines" + i));
+ }
+ } catch (Exception e) {
+ aList.add(this.mTooltip);
+ }
+ return aList;
+ }
+}
diff --git a/src/main/java/gregtech/common/items/behaviors/Behaviour_Scoop.java b/src/main/java/gregtech/common/items/behaviors/Behaviour_Scoop.java
new file mode 100644
index 0000000000..65be65a96d
--- /dev/null
+++ b/src/main/java/gregtech/common/items/behaviors/Behaviour_Scoop.java
@@ -0,0 +1,63 @@
+package gregtech.common.items.behaviors;
+
+import java.util.List;
+
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.item.EntityItem;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+
+import forestry.api.lepidopterology.EnumFlutterType;
+import forestry.api.lepidopterology.IButterfly;
+import forestry.api.lepidopterology.IEntityButterfly;
+import gregtech.api.items.GT_MetaBase_Item;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.util.GT_LanguageManager;
+
+public class Behaviour_Scoop extends Behaviour_None {
+
+ private final int mCosts;
+ private final String mTooltip = GT_LanguageManager
+ .addStringLocalization("gt.behaviour.scoop", "Catches Butterflies on Leftclick");
+
+ public Behaviour_Scoop(int aCosts) {
+ this.mCosts = aCosts;
+ }
+
+ @Override
+ public boolean onLeftClickEntity(GT_MetaBase_Item aItem, ItemStack aStack, EntityPlayer aPlayer, Entity aEntity) {
+ if ((aEntity instanceof IEntityButterfly)) {
+ if (aPlayer.worldObj.isRemote) {
+ return true;
+ }
+ if ((aPlayer.capabilities.isCreativeMode)
+ || (((GT_MetaGenerated_Tool) aItem).doDamage(aStack, this.mCosts))) {
+ IButterfly tButterfly = ((IEntityButterfly) aEntity).getButterfly();
+ tButterfly.getGenome()
+ .getPrimary()
+ .getRoot()
+ .getBreedingTracker(aEntity.worldObj, aPlayer.getGameProfile())
+ .registerCatch(tButterfly);
+ aPlayer.worldObj.spawnEntityInWorld(
+ new EntityItem(
+ aPlayer.worldObj,
+ aEntity.posX,
+ aEntity.posY,
+ aEntity.posZ,
+ tButterfly.getGenome()
+ .getPrimary()
+ .getRoot()
+ .getMemberStack(tButterfly.copy(), EnumFlutterType.BUTTERFLY.ordinal())));
+ aEntity.setDead();
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public List<String> getAdditionalToolTips(GT_MetaBase_Item aItem, List<String> aList, ItemStack aStack) {
+ aList.add(this.mTooltip);
+ return aList;
+ }
+}
diff --git a/src/main/java/gregtech/common/items/behaviors/Behaviour_Screwdriver.java b/src/main/java/gregtech/common/items/behaviors/Behaviour_Screwdriver.java
new file mode 100644
index 0000000000..d940226b84
--- /dev/null
+++ b/src/main/java/gregtech/common/items/behaviors/Behaviour_Screwdriver.java
@@ -0,0 +1,52 @@
+package gregtech.common.items.behaviors;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.ItemStack;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.enums.SoundResource;
+import gregtech.api.items.GT_MetaBase_Item;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_Utility;
+
+public class Behaviour_Screwdriver extends Behaviour_None {
+
+ private final int mVanillaCosts;
+ private final int mEUCosts;
+
+ public Behaviour_Screwdriver(int aVanillaCosts, int aEUCosts) {
+ this.mVanillaCosts = aVanillaCosts;
+ this.mEUCosts = aEUCosts;
+ }
+
+ @Override
+ public boolean onItemUseFirst(GT_MetaBase_Item aItem, ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX,
+ int aY, int aZ, ForgeDirection side, float hitX, float hitY, float hitZ) {
+ if (aWorld.isRemote) {
+ return false;
+ }
+ Block aBlock = aWorld.getBlock(aX, aY, aZ);
+ if (aBlock == null) {
+ return false;
+ }
+ byte aMeta = (byte) aWorld.getBlockMetadata(aX, aY, aZ);
+ if ((aBlock == Blocks.unpowered_repeater) || (aBlock == Blocks.powered_repeater)) {
+ if (GT_ModHandler.damageOrDechargeItem(aStack, this.mVanillaCosts, this.mEUCosts, aPlayer)) {
+ aWorld.setBlockMetadataWithNotify(aX, aY, aZ, aMeta / 4 * 4 + (aMeta % 4 + 1) % 4, 3);
+ GT_Utility.sendSoundToPlayers(aWorld, SoundResource.IC2_TOOLS_WRENCH, 1.0F, -1.0F, aX, aY, aZ);
+ }
+ return true;
+ }
+ if ((aBlock == Blocks.unpowered_comparator) || (aBlock == Blocks.powered_comparator)) {
+ if (GT_ModHandler.damageOrDechargeItem(aStack, this.mVanillaCosts, this.mEUCosts, aPlayer)) {
+ aWorld.setBlockMetadataWithNotify(aX, aY, aZ, aMeta / 4 * 4 + (aMeta % 4 + 1) % 4, 3);
+ GT_Utility.sendSoundToPlayers(aWorld, SoundResource.IC2_TOOLS_WRENCH, 1.0F, -1.0F, aX, aY, aZ);
+ }
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/src/main/java/gregtech/common/items/behaviors/Behaviour_Sense.java b/src/main/java/gregtech/common/items/behaviors/Behaviour_Sense.java
new file mode 100644
index 0000000000..b2ab0031ad
--- /dev/null
+++ b/src/main/java/gregtech/common/items/behaviors/Behaviour_Sense.java
@@ -0,0 +1,56 @@
+package gregtech.common.items.behaviors;
+
+import java.util.List;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.items.GT_MetaBase_Item;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.util.GT_LanguageManager;
+import ic2.api.crops.ICropTile;
+
+public class Behaviour_Sense extends Behaviour_None {
+
+ private final int mCosts;
+ private final String mTooltip = GT_LanguageManager
+ .addStringLocalization("gt.behaviour.sense", "Rightclick to harvest Crop Sticks");
+
+ public Behaviour_Sense(int aCosts) {
+ this.mCosts = aCosts;
+ }
+
+ @Override
+ public boolean onItemUseFirst(GT_MetaBase_Item aItem, ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX,
+ int aY, int aZ, ForgeDirection side, float hitX, float hitY, float hitZ) {
+ if (aWorld.isRemote) {
+ return false;
+ }
+ TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if ((tTileEntity instanceof ICropTile)) {
+ for (int i = -2; i < 3; i++) {
+ for (int j = -2; j < 3; j++) {
+ for (int k = -2; k < 3; k++) {
+ if ((aStack.stackSize > 0)
+ && (((tTileEntity = aWorld.getTileEntity(aX + i, aY + j, aZ + k)) instanceof ICropTile))
+ && (((ICropTile) tTileEntity).harvest(true))
+ && (!aPlayer.capabilities.isCreativeMode)) {
+ ((GT_MetaGenerated_Tool) aItem).doDamage(aStack, this.mCosts / 20);
+ }
+ }
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public List<String> getAdditionalToolTips(GT_MetaBase_Item aItem, List<String> aList, ItemStack aStack) {
+ aList.add(this.mTooltip);
+ return aList;
+ }
+}
diff --git a/src/main/java/gregtech/common/items/behaviors/Behaviour_SensorKit.java b/src/main/java/gregtech/common/items/behaviors/Behaviour_SensorKit.java
new file mode 100644
index 0000000000..b12159d058
--- /dev/null
+++ b/src/main/java/gregtech/common/items/behaviors/Behaviour_SensorKit.java
@@ -0,0 +1,56 @@
+package gregtech.common.items.behaviors;
+
+import java.util.List;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.inventory.IInventory;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.enums.ItemList;
+import gregtech.api.interfaces.tileentity.IGregTechDeviceInformation;
+import gregtech.api.items.GT_MetaBase_Item;
+import gregtech.api.util.GT_LanguageManager;
+import gregtech.api.util.GT_Utility;
+
+public class Behaviour_SensorKit extends Behaviour_None {
+
+ private final String mTooltip = GT_LanguageManager.addStringLocalization(
+ "gt.behaviour.sensorkit.tooltip",
+ "Used to display Information using the Mod Nuclear Control");
+
+ @Override
+ public boolean onItemUseFirst(GT_MetaBase_Item aItem, ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX,
+ int aY, int aZ, ForgeDirection side, float hitX, float hitY, float hitZ) {
+ if ((aPlayer instanceof EntityPlayerMP)) {
+ TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if (((tTileEntity instanceof IInventory)) && (!((IInventory) tTileEntity).isUseableByPlayer(aPlayer))) {
+ return false;
+ }
+ if (((tTileEntity instanceof IGregTechDeviceInformation))
+ && (((IGregTechDeviceInformation) tTileEntity).isGivingInformation())) {
+ GT_Utility.setStack(aStack, ItemList.NC_SensorCard.get(aStack.stackSize));
+ NBTTagCompound tNBT = aStack.getTagCompound();
+ if (tNBT == null) {
+ tNBT = new NBTTagCompound();
+ }
+ tNBT.setInteger("x", aX);
+ tNBT.setInteger("y", aY);
+ tNBT.setInteger("z", aZ);
+ aStack.setTagCompound(tNBT);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public List<String> getAdditionalToolTips(GT_MetaBase_Item aItem, List<String> aList, ItemStack aStack) {
+ aList.add(this.mTooltip);
+ return aList;
+ }
+}
diff --git a/src/main/java/gregtech/common/items/behaviors/Behaviour_SoftHammer.java b/src/main/java/gregtech/common/items/behaviors/Behaviour_SoftHammer.java
new file mode 100644
index 0000000000..159a0c4b27
--- /dev/null
+++ b/src/main/java/gregtech/common/items/behaviors/Behaviour_SoftHammer.java
@@ -0,0 +1,131 @@
+package gregtech.common.items.behaviors;
+
+import java.util.List;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.ItemStack;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.enums.SoundResource;
+import gregtech.api.items.GT_MetaBase_Item;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.util.GT_LanguageManager;
+import gregtech.api.util.GT_Utility;
+
+public class Behaviour_SoftHammer extends Behaviour_None {
+
+ private final int mCosts;
+ private final String mTooltip = GT_LanguageManager
+ .addStringLocalization("gt.behaviour.softhammer", "Activates and Deactivates Machines");
+
+ public Behaviour_SoftHammer(int aCosts) {
+ this.mCosts = aCosts;
+ }
+
+ @Override
+ public boolean onItemUseFirst(GT_MetaBase_Item aItem, ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX,
+ int aY, int aZ, ForgeDirection side, float hitX, float hitY, float hitZ) {
+ if (aWorld.isRemote) {
+ return false;
+ }
+ Block aBlock = aWorld.getBlock(aX, aY, aZ);
+ if (aBlock == null) {
+ return false;
+ }
+ byte aMeta = (byte) aWorld.getBlockMetadata(aX, aY, aZ);
+ if (aBlock == Blocks.lit_redstone_lamp) {
+ if ((aPlayer.capabilities.isCreativeMode)
+ || (((GT_MetaGenerated_Tool) aItem).doDamage(aStack, this.mCosts))) {
+ aWorld.isRemote = true;
+ aWorld.setBlock(aX, aY, aZ, Blocks.redstone_lamp, 0, 0);
+ aWorld.isRemote = false;
+ GT_Utility
+ .sendSoundToPlayers(aWorld, SoundResource.IC2_TOOLS_RUBBER_TRAMPOLINE, 1.0F, -1.0F, aX, aY, aZ);
+ }
+ return true;
+ }
+ if (aBlock == Blocks.redstone_lamp) {
+ if ((aPlayer.capabilities.isCreativeMode)
+ || (((GT_MetaGenerated_Tool) aItem).doDamage(aStack, this.mCosts))) {
+ aWorld.isRemote = true;
+ aWorld.setBlock(aX, aY, aZ, Blocks.lit_redstone_lamp, 0, 0);
+ aWorld.isRemote = false;
+ GT_Utility
+ .sendSoundToPlayers(aWorld, SoundResource.IC2_TOOLS_RUBBER_TRAMPOLINE, 1.0F, -1.0F, aX, aY, aZ);
+ }
+ return true;
+ }
+ if (aBlock == Blocks.golden_rail) {
+ if ((aPlayer.capabilities.isCreativeMode)
+ || (((GT_MetaGenerated_Tool) aItem).doDamage(aStack, this.mCosts))) {
+ aWorld.isRemote = true;
+ aWorld.setBlock(aX, aY, aZ, aBlock, (aMeta + 8) % 16, 0);
+ aWorld.isRemote = false;
+ GT_Utility
+ .sendSoundToPlayers(aWorld, SoundResource.IC2_TOOLS_RUBBER_TRAMPOLINE, 1.0F, -1.0F, aX, aY, aZ);
+ }
+ return true;
+ }
+ if (aBlock == Blocks.activator_rail) {
+ if ((aPlayer.capabilities.isCreativeMode)
+ || (((GT_MetaGenerated_Tool) aItem).doDamage(aStack, this.mCosts))) {
+ aWorld.isRemote = true;
+ aWorld.setBlock(aX, aY, aZ, aBlock, (aMeta + 8) % 16, 0);
+ aWorld.isRemote = false;
+ GT_Utility
+ .sendSoundToPlayers(aWorld, SoundResource.IC2_TOOLS_RUBBER_TRAMPOLINE, 1.0F, -1.0F, aX, aY, aZ);
+ }
+ return true;
+ }
+ if ((aBlock == Blocks.log) || (aBlock == Blocks.log2) || (aBlock == Blocks.hay_block)) {
+ if ((aPlayer.capabilities.isCreativeMode)
+ || (((GT_MetaGenerated_Tool) aItem).doDamage(aStack, this.mCosts))) {
+ aWorld.setBlockMetadataWithNotify(aX, aY, aZ, (aMeta + 4) % 12, 3);
+ }
+ return true;
+ }
+ if ((aBlock == Blocks.piston) || (aBlock == Blocks.sticky_piston)
+ || (aBlock == Blocks.dispenser)
+ || (aBlock == Blocks.dropper)) {
+ if ((aPlayer.capabilities.isCreativeMode)
+ || (((GT_MetaGenerated_Tool) aItem).doDamage(aStack, this.mCosts))) {
+ aWorld.setBlockMetadataWithNotify(aX, aY, aZ, (aMeta + 1) % 6, 3);
+ GT_Utility
+ .sendSoundToPlayers(aWorld, SoundResource.IC2_TOOLS_RUBBER_TRAMPOLINE, 1.0F, -1.0F, aX, aY, aZ);
+ }
+ return true;
+ }
+ if ((aBlock == Blocks.pumpkin) || (aBlock == Blocks.lit_pumpkin)
+ || (aBlock == Blocks.furnace)
+ || (aBlock == Blocks.lit_furnace)
+ || (aBlock == Blocks.chest)
+ || (aBlock == Blocks.trapped_chest)) {
+ if ((aPlayer.capabilities.isCreativeMode)
+ || (((GT_MetaGenerated_Tool) aItem).doDamage(aStack, this.mCosts))) {
+ aWorld.setBlockMetadataWithNotify(aX, aY, aZ, (aMeta - 1) % 4 + 2, 3);
+ GT_Utility
+ .sendSoundToPlayers(aWorld, SoundResource.IC2_TOOLS_RUBBER_TRAMPOLINE, 1.0F, -1.0F, aX, aY, aZ);
+ }
+ return true;
+ }
+ if (aBlock == Blocks.hopper) {
+ if ((aPlayer.capabilities.isCreativeMode)
+ || (((GT_MetaGenerated_Tool) aItem).doDamage(aStack, this.mCosts))) {
+ aWorld.setBlockMetadataWithNotify(aX, aY, aZ, (aMeta + 1) % 6 != 1 ? (aMeta + 1) % 6 : 2, 3);
+ GT_Utility
+ .sendSoundToPlayers(aWorld, SoundResource.IC2_TOOLS_RUBBER_TRAMPOLINE, 1.0F, -1.0F, aX, aY, aZ);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public List<String> getAdditionalToolTips(GT_MetaBase_Item aItem, List<String> aList, ItemStack aStack) {
+ aList.add(this.mTooltip);
+ return aList;
+ }
+}
diff --git a/src/main/java/gregtech/common/items/behaviors/Behaviour_Sonictron.java b/src/main/java/gregtech/common/items/behaviors/Behaviour_Sonictron.java
new file mode 100644
index 0000000000..dbab764507
--- /dev/null
+++ b/src/main/java/gregtech/common/items/behaviors/Behaviour_Sonictron.java
@@ -0,0 +1,135 @@
+package gregtech.common.items.behaviors;
+
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.enums.GT_Values;
+import gregtech.api.interfaces.IItemBehaviour;
+import gregtech.api.items.GT_MetaBase_Item;
+import gregtech.api.util.GT_Utility;
+
+public class Behaviour_Sonictron extends Behaviour_None {
+
+ public static final IItemBehaviour<GT_MetaBase_Item> INSTANCE = new Behaviour_Sonictron();
+
+ public static int getCurrentIndex(ItemStack aStack) {
+ NBTTagCompound tNBTTagCompound = aStack.getTagCompound();
+ if (tNBTTagCompound == null) {
+ tNBTTagCompound = new NBTTagCompound();
+ }
+ return tNBTTagCompound.getInteger("mCurrentIndex");
+ }
+
+ public static int getTickTimer(ItemStack aStack) {
+ NBTTagCompound tNBTTagCompound = aStack.getTagCompound();
+ if (tNBTTagCompound == null) {
+ tNBTTagCompound = new NBTTagCompound();
+ }
+ return tNBTTagCompound.getInteger("mTickTimer");
+ }
+
+ public static NBTTagCompound setCurrentIndex(ItemStack aStack, int aIndex) {
+ NBTTagCompound tNBTTagCompound = aStack.getTagCompound();
+ if (tNBTTagCompound == null) {
+ tNBTTagCompound = new NBTTagCompound();
+ }
+ tNBTTagCompound.setInteger("mCurrentIndex", aIndex);
+ return tNBTTagCompound;
+ }
+
+ public static NBTTagCompound setTickTimer(ItemStack aStack, int aTime) {
+ NBTTagCompound tNBTTagCompound = aStack.getTagCompound();
+ if (tNBTTagCompound == null) {
+ tNBTTagCompound = new NBTTagCompound();
+ }
+ tNBTTagCompound.setInteger("mTickTimer", aTime);
+ return tNBTTagCompound;
+ }
+
+ public static ItemStack[] getNBTInventory(ItemStack aStack) {
+ ItemStack[] tInventory = new ItemStack[64];
+ NBTTagCompound tNBT = aStack.getTagCompound();
+ if (tNBT == null) {
+ return tInventory;
+ }
+ NBTTagList tNBT_ItemList = tNBT.getTagList("Inventory", 10);
+ for (int i = 0; i < tNBT_ItemList.tagCount(); i++) {
+ NBTTagCompound tag = tNBT_ItemList.getCompoundTagAt(i);
+ byte slot = tag.getByte("Slot");
+ if ((slot >= 0) && (slot < tInventory.length)) {
+ tInventory[slot] = GT_Utility.loadItem(tag);
+ }
+ }
+ return tInventory;
+ }
+
+ public static NBTTagCompound setNBTInventory(ItemStack aStack, ItemStack[] aInventory) {
+ NBTTagCompound tNBT = aStack.getTagCompound();
+ if (tNBT == null) {
+ tNBT = new NBTTagCompound();
+ }
+ NBTTagList tNBT_ItemList = new NBTTagList();
+ for (int i = 0; i < aInventory.length; i++) {
+ ItemStack stack = aInventory[i];
+ if (stack != null) {
+ NBTTagCompound tag = new NBTTagCompound();
+ tag.setByte("Slot", (byte) i);
+ stack.writeToNBT(tag);
+ tNBT_ItemList.appendTag(tag);
+ }
+ }
+ tNBT.setTag("Inventory", tNBT_ItemList);
+ aStack.setTagCompound(tNBT);
+ return tNBT;
+ }
+
+ public static void copyInventory(ItemStack[] aInventory, ItemStack[] aNewContent, int aIndexlength) {
+ for (int i = 0; i < aIndexlength; i++) {
+ if (aNewContent[i] == null) {
+ aInventory[i] = null;
+ } else {
+ aInventory[i] = GT_Utility.copyOrNull(aNewContent[i]);
+ }
+ }
+ }
+
+ @Override
+ public boolean onItemUseFirst(GT_MetaBase_Item aItem, ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX,
+ int aY, int aZ, ForgeDirection side, float hitX, float hitY, float hitZ) {
+ setCurrentIndex(aStack, -1);
+ return false;
+ }
+
+ @Override
+ public ItemStack onItemRightClick(GT_MetaBase_Item aItem, ItemStack aStack, World aWorld, EntityPlayer aPlayer) {
+ setCurrentIndex(aStack, 0);
+ return aStack;
+ }
+
+ @Override
+ public void onUpdate(GT_MetaBase_Item aItem, ItemStack aStack, World aWorld, Entity aPlayer, int aTimer,
+ boolean aIsInHand) {
+ int tTickTimer = getTickTimer(aStack);
+ int tCurrentIndex = getCurrentIndex(aStack);
+ if ((tTickTimer++ % 2 == 0) && (tCurrentIndex > -1)) {
+ ItemStack[] tInventory = getNBTInventory(aStack);
+ GT_Values.GT.doSonictronSound(
+ tInventory[tCurrentIndex],
+ aPlayer.worldObj,
+ aPlayer.posX,
+ aPlayer.posY,
+ aPlayer.posZ);
+ tCurrentIndex++;
+ if (tCurrentIndex > 63) {
+ tCurrentIndex = -1;
+ }
+ }
+ setTickTimer(aStack, tTickTimer);
+ setCurrentIndex(aStack, tCurrentIndex);
+ }
+}
diff --git a/src/main/java/gregtech/common/items/behaviors/Behaviour_Spray_Color.java b/src/main/java/gregtech/common/items/behaviors/Behaviour_Spray_Color.java
new file mode 100644
index 0000000000..cbc698d474
--- /dev/null
+++ b/src/main/java/gregtech/common/items/behaviors/Behaviour_Spray_Color.java
@@ -0,0 +1,222 @@
+package gregtech.common.items.behaviors;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.BlockColored;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraft.init.Items;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.Vec3;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import appeng.api.implementations.tiles.IColorableTile;
+import appeng.api.util.AEColor;
+import appeng.block.networking.BlockCableBus;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.ConfigCategories;
+import gregtech.api.enums.Dyes;
+import gregtech.api.enums.SoundResource;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.items.GT_MetaBase_Item;
+import gregtech.api.util.GT_LanguageManager;
+import gregtech.api.util.GT_Utility;
+
+public class Behaviour_Spray_Color extends Behaviour_None {
+
+ private final ItemStack mEmpty;
+ private final ItemStack mUsed;
+ private final ItemStack mFull;
+ private final long mUses;
+ private final byte mColor;
+ private final Collection<Block> mAllowedVanillaBlocks = Arrays.asList(
+ Blocks.glass,
+ Blocks.glass_pane,
+ Blocks.stained_glass,
+ Blocks.stained_glass_pane,
+ Blocks.carpet,
+ Blocks.hardened_clay);
+ protected String mTooltip;
+ private final String mTooltipUses = GT_LanguageManager
+ .addStringLocalization("gt.behaviour.paintspray.uses", "Remaining Uses:");
+ private final String mTooltipUnstackable = GT_LanguageManager
+ .addStringLocalization("gt.behaviour.unstackable", "Not usable when stacked!");
+ private final String mTooltipChain = GT_LanguageManager.addStringLocalization(
+ "gt.behaviour.paintspray.chain",
+ "If used while sneaking it will spray a chain of blocks");
+
+ private final String mTooltipChainAmount = GT_LanguageManager.addStringLocalization(
+ "gt.behaviour.paintspray.chain",
+ "Sprays up to %d blocks, in the direction you're looking at");
+
+ public Behaviour_Spray_Color(ItemStack aEmpty, ItemStack aUsed, ItemStack aFull, long aUses, int aColor) {
+ this.mEmpty = aEmpty;
+ this.mUsed = aUsed;
+ this.mFull = aFull;
+ this.mUses = aUses;
+ this.mColor = ((byte) aColor);
+ this.mTooltip = GT_LanguageManager.addStringLocalization(
+ "gt.behaviour.paintspray." + this.mColor + ".tooltip",
+ "Can Color things in " + Dyes.get(this.mColor).mName);
+ }
+
+ public Behaviour_Spray_Color(ItemStack aEmpty, ItemStack aUsed, ItemStack aFull, long aUses) {
+ this.mEmpty = aEmpty;
+ this.mUsed = aUsed;
+ this.mFull = aFull;
+ this.mUses = aUses;
+ this.mColor = 0;
+ mTooltip = "";
+ }
+
+ @Override
+ public boolean onItemUseFirst(GT_MetaBase_Item aItem, ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX,
+ int aY, int aZ, ForgeDirection side, float hitX, float hitY, float hitZ) {
+ if ((aWorld.isRemote) || (aStack.stackSize != 1)) {
+ return false;
+ }
+ boolean rOutput = false;
+ if (!aPlayer.canPlayerEdit(aX, aY, aZ, side.ordinal(), aStack)) {
+ return false;
+ }
+ NBTTagCompound tNBT = aStack.getTagCompound();
+ if (tNBT == null) {
+ tNBT = new NBTTagCompound();
+ }
+ long tUses = tNBT.getLong("GT.RemainingPaint");
+ if (GT_Utility.areStacksEqual(aStack, this.mFull, true)) {
+ aStack.func_150996_a(this.mUsed.getItem());
+ Items.feather.setDamage(aStack, Items.feather.getDamage(this.mUsed));
+ tUses = this.mUses;
+ }
+ int painted = 0;
+ int maxPainted = GregTech_API.sSpecialFile.get(ConfigCategories.general, "SprayCanChainRange", 256);
+ ForgeDirection lookSide;
+ Vec3 look = aPlayer.getLookVec();
+ double absX = Math.abs(look.xCoord);
+ double absY = Math.abs(look.yCoord);
+ double absZ = Math.abs(look.zCoord);
+ if (absX > absY && absX > absZ) {
+ lookSide = look.xCoord > 0 ? ForgeDirection.EAST : ForgeDirection.WEST;
+ } else if (absY > absX && absY > absZ) {
+ lookSide = look.yCoord > 0 ? ForgeDirection.UP : ForgeDirection.DOWN;
+ } else {
+ lookSide = look.zCoord > 0 ? ForgeDirection.SOUTH : ForgeDirection.NORTH;
+ }
+ Block initialBlock = aWorld.getBlock(aX, aY, aZ);
+ int initialBlockMeta = aWorld.getBlockMetadata(aX, aY, aZ);
+ TileEntity initialTE = aWorld.getTileEntity(aX, aY, aZ);
+ while ((GT_Utility.areStacksEqual(aStack, this.mUsed, true)) && (colorize(aWorld, aX, aY, aZ, side, aPlayer))) {
+ GT_Utility.sendSoundToPlayers(aWorld, SoundResource.IC2_TOOLS_PAINTER, 1.0F, 1.0F, aX, aY, aZ);
+ if (!aPlayer.capabilities.isCreativeMode) {
+ tUses -= 1L;
+ }
+ rOutput = true;
+ painted++;
+ if (painted >= maxPainted && maxPainted != -1) break;
+ if (!aPlayer.isSneaking() || tUses <= 0) break;
+ switch (lookSide) {
+ case UP -> aY += 1;
+ case DOWN -> aY -= 1;
+ case NORTH -> aZ -= 1;
+ case SOUTH -> aZ += 1;
+ case WEST -> aX -= 1;
+ case EAST -> aX += 1;
+ default -> throw new IllegalArgumentException("Unexpected value: " + lookSide);
+ }
+
+ if (aWorld.getBlock(aX, aY, aZ) != initialBlock) break;
+ if (aWorld.getBlockMetadata(aX, aY, aZ) != initialBlockMeta) break;
+
+ /*
+ * Check if the initial block had a TE and if the next one does, check if its the same kind.
+ * else one does and the other doesnt, thus stop checking.
+ */
+ TileEntity targetTE = aWorld.getTileEntity(aX, aY, aZ);
+ if (initialTE == null ^ targetTE == null) break;
+ if (initialTE != null && targetTE != null) {
+ if (!initialTE.getClass()
+ .isInstance(targetTE)) break;
+
+ if (initialTE instanceof IGregTechTileEntity currentGTTile
+ && targetTE instanceof IGregTechTileEntity targetGTTile) {
+ if (currentGTTile.getMetaTileID() != targetGTTile.getMetaTileID()) break;
+ }
+ }
+ }
+ tNBT.removeTag("GT.RemainingPaint");
+ if (tUses > 0L) {
+ tNBT.setLong("GT.RemainingPaint", tUses);
+ }
+ if (tNBT.hasNoTags()) {
+ aStack.setTagCompound(null);
+ } else {
+ aStack.setTagCompound(tNBT);
+ }
+ if (tUses <= 0L) {
+ if (this.mEmpty == null) {
+ aStack.stackSize -= 1;
+ } else {
+ aStack.func_150996_a(this.mEmpty.getItem());
+ Items.feather.setDamage(aStack, Items.feather.getDamage(this.mEmpty));
+ }
+ }
+ return rOutput;
+ }
+
+ protected boolean colorize(World aWorld, int aX, int aY, int aZ, ForgeDirection side, EntityPlayer player) {
+ final Block aBlock = aWorld.getBlock(aX, aY, aZ);
+ if (aBlock != Blocks.air) {
+ if (this.mAllowedVanillaBlocks.contains(aBlock) || aBlock instanceof BlockColored) {
+ if (aBlock == Blocks.hardened_clay) {
+ aWorld.setBlock(aX, aY, aZ, Blocks.stained_hardened_clay, (~this.mColor) & 0xF, 3);
+ return true;
+ }
+ if (aBlock == Blocks.glass_pane) {
+ aWorld.setBlock(aX, aY, aZ, Blocks.stained_glass_pane, (~this.mColor) & 0xF, 3);
+ return true;
+ }
+ if (aBlock == Blocks.glass) {
+ aWorld.setBlock(aX, aY, aZ, Blocks.stained_glass, (~this.mColor) & 0xF, 3);
+ return true;
+ }
+ if (aWorld.getBlockMetadata(aX, aY, aZ) == ((~this.mColor) & 0xF)) {
+ return false;
+ }
+ aWorld.setBlockMetadataWithNotify(aX, aY, aZ, (~this.mColor) & 0xF, 3);
+ return true;
+ }
+
+ if (aBlock instanceof IColorableTile) {
+ return ((IColorableTile) aBlock).recolourBlock(side, AEColor.values()[(~this.mColor) & 0xF], player);
+ }
+
+ if (aBlock instanceof BlockCableBus) {
+ return ((BlockCableBus) aBlock).recolourBlock(aWorld, aX, aY, aZ, side, (~this.mColor) & 0xF, player);
+ }
+ }
+ return aBlock.recolourBlock(aWorld, aX, aY, aZ, side, (~this.mColor) & 0xF);
+ }
+
+ @Override
+ public List<String> getAdditionalToolTips(GT_MetaBase_Item aItem, List<String> aList, ItemStack aStack) {
+ aList.add(this.mTooltip);
+ aList.add(this.mTooltipChain);
+ aList.add(
+ String.format(
+ this.mTooltipChainAmount,
+ GregTech_API.sSpecialFile.get(ConfigCategories.general, "SprayCanChainRange", 256)));
+ NBTTagCompound tNBT = aStack.getTagCompound();
+ long tRemainingPaint = tNBT == null ? this.mUses
+ : GT_Utility.areStacksEqual(aStack, this.mFull, true) ? this.mUses : tNBT.getLong("GT.RemainingPaint");
+ aList.add(this.mTooltipUses + " " + tRemainingPaint);
+ aList.add(this.mTooltipUnstackable);
+ return aList;
+ }
+}
diff --git a/src/main/java/gregtech/common/items/behaviors/Behaviour_Spray_Color_Remover.java b/src/main/java/gregtech/common/items/behaviors/Behaviour_Spray_Color_Remover.java
new file mode 100644
index 0000000000..0b73b4f7fc
--- /dev/null
+++ b/src/main/java/gregtech/common/items/behaviors/Behaviour_Spray_Color_Remover.java
@@ -0,0 +1,48 @@
+package gregtech.common.items.behaviors;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.ItemStack;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import appeng.api.implementations.tiles.IColorableTile;
+import appeng.api.util.AEColor;
+import appeng.block.networking.BlockCableBus;
+import gregtech.api.interfaces.tileentity.IColoredTileEntity;
+import gregtech.api.util.GT_LanguageManager;
+
+public class Behaviour_Spray_Color_Remover extends Behaviour_Spray_Color {
+
+ public Behaviour_Spray_Color_Remover(ItemStack aEmpty, ItemStack aUsed, ItemStack aFull, long aUses) {
+ super(aEmpty, aUsed, aFull, aUses);
+ this.mTooltip = GT_LanguageManager
+ .addStringLocalization("gt.behaviour.paintspray.solvent.tooltip", "Can remove paint from things");
+ }
+
+ @Override
+ protected boolean colorize(World aWorld, int aX, int aY, int aZ, ForgeDirection side, EntityPlayer player) {
+ final Block aBlock = aWorld.getBlock(aX, aY, aZ);
+ if (aBlock != Blocks.air) {
+ if (aBlock instanceof IColorableTile) {
+ return ((IColorableTile) aBlock).recolourBlock(side, AEColor.Transparent, player);
+ }
+
+ if (aBlock instanceof BlockCableBus) {
+ return ((BlockCableBus) aBlock)
+ .recolourBlock(aWorld, aX, aY, aZ, side, AEColor.Transparent.ordinal(), player);
+ }
+
+ TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if (tTileEntity instanceof IColoredTileEntity gte) {
+ if (gte.getColorization() >= 0) {
+ gte.setColorization((byte) -1);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
diff --git a/src/main/java/gregtech/common/items/behaviors/Behaviour_Switch_Metadata.java b/src/main/java/gregtech/common/items/behaviors/Behaviour_Switch_Metadata.java
new file mode 100644
index 0000000000..03cf29b9dd
--- /dev/null
+++ b/src/main/java/gregtech/common/items/behaviors/Behaviour_Switch_Metadata.java
@@ -0,0 +1,67 @@
+package gregtech.common.items.behaviors;
+
+import java.util.List;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraft.init.Items;
+import net.minecraft.item.ItemStack;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.items.GT_Generic_Block;
+import gregtech.api.items.GT_MetaBase_Item;
+import gregtech.api.util.GT_Util;
+import gregtech.api.util.GT_Utility;
+
+public class Behaviour_Switch_Metadata extends Behaviour_None {
+
+ public final int mSwitchIndex;
+ public final boolean mCheckTarget, mShowModeSwitchTooltip;
+
+ public Behaviour_Switch_Metadata(int aSwitchIndex) {
+ this(aSwitchIndex, false);
+ }
+
+ public Behaviour_Switch_Metadata(int aSwitchIndex, boolean aCheckTarget) {
+ this(aSwitchIndex, aCheckTarget, false);
+ }
+
+ public Behaviour_Switch_Metadata(int aSwitchIndex, boolean aCheckTarget, boolean aShowModeSwitchTooltip) {
+ mSwitchIndex = aSwitchIndex;
+ mCheckTarget = aCheckTarget;
+ mShowModeSwitchTooltip = aShowModeSwitchTooltip;
+ }
+
+ @Override
+ public List<String> getAdditionalToolTips(GT_MetaBase_Item aItem, List<String> aList, ItemStack aStack) {
+ if (mShowModeSwitchTooltip) aList.add(GT_Utility.trans("330", "Sneak Rightclick to switch Mode"));
+ return aList;
+ }
+
+ @Override
+ public boolean onItemUseFirst(GT_MetaBase_Item aItem, ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX,
+ int aY, int aZ, ForgeDirection side, float aHitX, float aHitY, float aHitZ) {
+ if (aStack != null && (aPlayer == null || aPlayer.isSneaking()) && !aWorld.isRemote) {
+ if (mCheckTarget) {
+ Block aBlock = aWorld.blockExists(aX, aY, aZ) ? aWorld.getBlock(aX, aY, aZ) : Blocks.air;
+ if (aBlock instanceof GT_Generic_Block) {
+ Items.feather.setDamage(aStack, (short) mSwitchIndex);
+ GT_Utility.updateItemStack(aStack);
+ return true;
+ }
+ if (GT_Util.getTileEntity(aWorld, aX, aY, aZ, true) == null) {
+ Items.feather.setDamage(aStack, (short) mSwitchIndex);
+ GT_Utility.updateItemStack(aStack);
+ return true;
+ }
+ return false;
+ }
+ Items.feather.setDamage(aStack, (short) mSwitchIndex);
+ GT_Utility.updateItemStack(aStack);
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/src/main/java/gregtech/common/items/behaviors/Behaviour_Switch_Mode.java b/src/main/java/gregtech/common/items/behaviors/Behaviour_Switch_Mode.java
new file mode 100644
index 0000000000..1e93362882
--- /dev/null
+++ b/src/main/java/gregtech/common/items/behaviors/Behaviour_Switch_Mode.java
@@ -0,0 +1,53 @@
+package gregtech.common.items.behaviors;
+
+import java.util.List;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.MovingObjectPosition;
+import net.minecraft.world.World;
+
+import gregtech.api.items.GT_MetaBase_Item;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.util.GT_Utility;
+
+public class Behaviour_Switch_Mode extends Behaviour_None {
+
+ public Behaviour_Switch_Mode() {}
+
+ @Override
+ public ItemStack onItemRightClick(GT_MetaBase_Item aItem, ItemStack aStack, World aWorld, EntityPlayer aPlayer) {
+ if (aStack != null && (aPlayer == null || aPlayer.isSneaking()) && !aWorld.isRemote) {
+
+ GT_MetaGenerated_Tool itemTool = (GT_MetaGenerated_Tool) aItem;
+ final byte maxMode = itemTool.getToolMaxMode(aStack);
+ if (maxMode == 1) {
+ return aStack;
+ }
+
+ MovingObjectPosition mop = GT_Utility.getPlayerLookingTarget();
+ if (mop == null) {
+ byte currentMode = itemTool.getToolMode(aStack);
+ currentMode = (byte) ((currentMode + 1) % maxMode);
+ itemTool.setToolMode(aStack, currentMode);
+ }
+ return aStack;
+ }
+ return aStack;
+ }
+
+ @Override
+ public List<String> getAdditionalToolTips(GT_MetaBase_Item aItem, List<String> aList, ItemStack aStack) {
+ super.getAdditionalToolTips(aItem, aList, aStack);
+ if ((aItem instanceof GT_MetaGenerated_Tool)) {
+ GT_MetaGenerated_Tool itemTool = (GT_MetaGenerated_Tool) aItem;
+ final int maxMode = itemTool.getToolMaxMode(aStack);
+ if (maxMode > 1) {
+ aList.add("Shift+Rclick to change mode");
+ }
+ }
+
+ return aList;
+ }
+
+}
diff --git a/src/main/java/gregtech/common/items/behaviors/Behaviour_Wrench.java b/src/main/java/gregtech/common/items/behaviors/Behaviour_Wrench.java
new file mode 100644
index 0000000000..16c5c3f948
--- /dev/null
+++ b/src/main/java/gregtech/common/items/behaviors/Behaviour_Wrench.java
@@ -0,0 +1,278 @@
+package gregtech.common.items.behaviors;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.BooleanSupplier;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.ItemStack;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.oredict.OreDictionary;
+
+import appeng.api.parts.IPartHost;
+import appeng.api.util.IOrientable;
+import appeng.tile.misc.TileInterface;
+import gregtech.api.enums.SoundResource;
+import gregtech.api.items.GT_MetaBase_Item;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.util.GT_LanguageManager;
+import gregtech.api.util.GT_Utility;
+import ic2.api.tile.IWrenchable;
+
+public class Behaviour_Wrench extends Behaviour_None {
+
+ private final int mCosts;
+ private final String mTooltip = GT_LanguageManager
+ .addStringLocalization("gt.behaviour.wrench", "Rotates Blocks on Rightclick");
+
+ public Behaviour_Wrench(int aCosts) {
+ this.mCosts = aCosts;
+ }
+
+ @Override
+ public boolean onItemUseFirst(GT_MetaBase_Item aItem, ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX,
+ int aY, int aZ, ForgeDirection side, float hitX, float hitY, float hitZ) {
+ final Block aBlock = aWorld.getBlock(aX, aY, aZ);
+ if (aBlock == null) {
+ return false;
+ }
+ final int aMeta = aWorld.getBlockMetadata(aX, aY, aZ);
+ final short targetSideOrdinal = (short) GT_Utility.determineWrenchingSide(side, hitX, hitY, hitZ)
+ .ordinal();
+ final TileEntity aTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+
+ final WrenchHandler handler = new WrenchHandler(
+ aBlock,
+ aMeta,
+ targetSideOrdinal,
+ aTileEntity,
+ aPlayer,
+ aWorld,
+ aX,
+ aY,
+ aZ,
+ aStack,
+ (GT_MetaGenerated_Tool) aItem,
+ mCosts);
+
+ try {
+ return handler.handle() && !aWorld.isRemote;
+ } catch (Throwable ignored) {}
+ return false;
+ }
+
+ /**
+ * <p>
+ * A class to simplify wrenching operation,
+ * stopping "checking creative", "trying to damage tool",
+ * "doing the logic" and "playing sound" again and again.
+ * This should have been a record, but it's not available in Java 8.
+ * </p>
+ * <p>
+ * {@link WrenchHandler#handle()} is the entry point of main logic.
+ * </p>
+ */
+ private static class WrenchHandler {
+
+ boolean handle() {
+ ForgeDirection direction = ForgeDirection.getOrientation(targetSideOrdinal);
+
+ // AE2 logic
+ // default to change the up facing
+ // sneak to change the forward facing
+ if (tileEntity instanceof IOrientable orientable) {
+ if (!orientable.canBeRotated()) return false;
+ ForgeDirection front = orientable.getForward();
+ ForgeDirection up = orientable.getUp();
+
+ // mainly for me-interfaces, whose initial orientation is UNKNOWN
+ if (front == ForgeDirection.UNKNOWN) {
+ if (direction == ForgeDirection.UP || direction == ForgeDirection.DOWN)
+ front = ForgeDirection.NORTH;
+ else front = ForgeDirection.UP;
+ }
+
+ ForgeDirection back = front.getOpposite();
+ ForgeDirection down = up.getOpposite();
+
+ if (tileEntity instanceof TileInterface) {
+ if (player.isSneaking()) return false;
+ if (direction == down) {
+ return doWrenchOperation(costs, () -> {
+ orientable.setOrientation(ForgeDirection.UNKNOWN, ForgeDirection.UNKNOWN);
+ return true;
+ });
+ }
+ // interface's up-side is opposite to the arrow on texture
+ // make it intuitive by rotating it to the opposite side.
+ direction = direction.getOpposite();
+ up = up.getOpposite();
+ } else if (direction == up || direction == front) {
+ // rotate around the direction axis
+ final var tempFront = front;
+ final var tempUp = up;
+ if (!player.isSneaking() && direction == up) return doWrenchOperation(costs, () -> {
+ orientable.setOrientation(tempFront.getRotation(tempUp), tempUp);
+ return true;
+ });
+ if (player.isSneaking() && direction == front) return doWrenchOperation(costs, () -> {
+ orientable.setOrientation(
+ tempFront,
+ tempUp.getRotation(tempFront)
+ .getRotation(tempFront));
+ return true;
+ });
+ }
+
+ if (player.isSneaking()) {
+ if (direction == up || direction == down) {
+ orientable.setOrientation(direction, down.getRotation(front.getRotation(direction)));
+ } else orientable.setOrientation(direction, up);
+ } else {
+ if (direction == front || direction == back) {
+ orientable.setOrientation(back.getRotation(up.getRotation(direction)), direction);
+ } else orientable.setOrientation(front, direction);
+ }
+
+ return damageWrench(costs);
+ }
+ if (world.isRemote) return false;
+ // IC2 Wrenchable
+ if (tileEntity instanceof IWrenchable wrenchable) {
+ if (wrenchable.wrenchCanSetFacing(player, targetSideOrdinal)) {
+ return doWrenchOperation(costs, () -> {
+ wrenchable.setFacing(targetSideOrdinal);
+ return true;
+ });
+ }
+ return false;
+ }
+
+ if (block == Blocks.powered_repeater || block == Blocks.unpowered_repeater
+ || block == Blocks.powered_comparator
+ || block == Blocks.unpowered_comparator) return setBlockMeta(costs, meta / 4 * 4 + (meta % 4 + 1) % 4);
+
+ // hopper cannot face sky
+ if (block == Blocks.hopper && targetSideOrdinal != 1) return setBlockMeta(costs, targetSideOrdinal);
+
+ if (isVanillaAllSideRotatable(block)) if (meta < 6) return setBlockMeta(costs, targetSideOrdinal);
+
+ // blocks like chests and furnaces have only four directions
+ if (isVanillaCantFaceAxisY(block)) {
+ if (targetSideOrdinal > 1) return setBlockMeta(costs, targetSideOrdinal);
+ else return false;
+ }
+ if (tileEntity instanceof IPartHost) return false;
+
+ final int logWoodId = OreDictionary.getOreID("logWood");
+ if (Arrays.stream(OreDictionary.getOreIDs(new ItemStack(block)))
+ .anyMatch(id -> id == logWoodId)) {
+ // The meta just work
+ return setBlockMeta(costs, (meta + 4) % 12);
+ }
+
+ // vanilla block rotate logic
+ if ((Arrays.asList(block.getValidRotations(world, x, y, z))
+ .contains(direction))) return rotateBlock(costs, direction);
+ return false;
+
+ // GT blocks' rotations are done by blocks themselves after this returning false
+ }
+
+ private final Block block;
+ private final short targetSideOrdinal;
+ private final TileEntity tileEntity;
+ private final EntityPlayer player;
+ private final World world;
+ private final int x, y, z, meta;
+ private final ItemStack stack;
+
+ private final GT_MetaGenerated_Tool item;
+ private final int costs;
+
+ public WrenchHandler(Block block, int meta, short targetSideOrdinal, TileEntity tileEntity, EntityPlayer player,
+ World world, int x, int y, int z, ItemStack stack, GT_MetaGenerated_Tool item, int costs) {
+ this.block = block;
+ this.meta = meta;
+ this.targetSideOrdinal = targetSideOrdinal;
+ this.tileEntity = tileEntity;
+ this.player = player;
+ this.world = world;
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.stack = stack;
+ this.item = item;
+ this.costs = costs;
+ }
+
+ /**
+ * this will run the operation, damage the tool and play the sound if possible (creative mode or
+ * {@link GT_MetaGenerated_Tool#canWrench(EntityPlayer, int, int, int)})
+ *
+ * @param damage damage to be applied to the wrench
+ * @param operation the real operation of the click
+ * @return true if the operation was successful
+ * @see #setBlockMeta(int, int)
+ * @see #rotateBlock(int, ForgeDirection)
+ * @see #rotateBlock(int, ForgeDirection)
+ */
+ boolean doWrenchOperation(int damage, BooleanSupplier operation) {
+ if (player.capabilities.isCreativeMode || item.canWrench(player, x, y, z)) {
+ if (operation.getAsBoolean()) {
+ item.doDamage(stack, damage);
+ GT_Utility.sendSoundToPlayers(world, SoundResource.IC2_TOOLS_WRENCH, 1.0F, -1.0F, x, y, z);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ boolean setBlockMeta(int damage, int newMeta) {
+ return doWrenchOperation(damage, () -> setBlockMetadataWithNotify(newMeta));
+ }
+
+ boolean rotateBlock(int damage, ForgeDirection direction) {
+ return doWrenchOperation(damage, () -> block.rotateBlock(world, x, y, z, direction));
+ }
+
+ boolean damageWrench(int damage) {
+ return doWrenchOperation(damage, () -> true);
+ }
+
+ private boolean setBlockMetadataWithNotify(int newMeta) {
+ return world.setBlockMetadataWithNotify(x, y, z, newMeta, 3);
+ }
+
+ }
+
+ public static boolean isVanillaRotatable(Block block) {
+ return isVanillaCantFaceAxisY(block) || isVanillaAllSideRotatable(block) || block == Blocks.hopper;
+ }
+
+ public static boolean isVanillaCantFaceAxisY(Block block) {
+ return GT_Utility.arrayContains(
+ block,
+ Blocks.pumpkin,
+ Blocks.lit_pumpkin,
+ Blocks.furnace,
+ Blocks.lit_furnace,
+ Blocks.chest,
+ Blocks.trapped_chest,
+ Blocks.ender_chest);
+ }
+
+ public static boolean isVanillaAllSideRotatable(Block block) {
+ return GT_Utility.arrayContains(block, Blocks.piston, Blocks.sticky_piston, Blocks.dispenser, Blocks.dropper);
+ }
+
+ @Override
+ public List<String> getAdditionalToolTips(GT_MetaBase_Item aItem, List<String> aList, ItemStack aStack) {
+ aList.add(this.mTooltip);
+ return aList;
+ }
+}
diff --git a/src/main/java/gregtech/common/items/behaviors/Behaviour_WrittenBook.java b/src/main/java/gregtech/common/items/behaviors/Behaviour_WrittenBook.java
new file mode 100644
index 0000000000..0f645a93a9
--- /dev/null
+++ b/src/main/java/gregtech/common/items/behaviors/Behaviour_WrittenBook.java
@@ -0,0 +1,40 @@
+package gregtech.common.items.behaviors;
+
+import java.util.List;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.entity.EntityPlayerSP;
+import net.minecraft.client.gui.GuiScreenBook;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.world.World;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.api.items.GT_MetaBase_Item;
+import gregtech.api.util.GT_Utility;
+
+public class Behaviour_WrittenBook extends Behaviour_None {
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public boolean onItemUse(GT_MetaBase_Item aItem, ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX,
+ int aY, int aZ, int ordinalSide, float hitX, float hitY, float hitZ) {
+ if ((GT_Utility.isStringValid(GT_Utility.ItemNBT.getBookTitle(aStack)))
+ && ((aPlayer instanceof EntityPlayerSP))) {
+ Minecraft.getMinecraft()
+ .displayGuiScreen(new GuiScreenBook(aPlayer, aStack, false));
+ }
+ return true;
+ }
+
+ @Override
+ public List<String> getAdditionalToolTips(GT_MetaBase_Item aItem, List<String> aList, ItemStack aStack) {
+ String tTitle = GT_Utility.ItemNBT.getBookTitle(aStack);
+ if (GT_Utility.isStringValid(tTitle)) {
+ aList.add(tTitle);
+ aList.add("by " + GT_Utility.ItemNBT.getBookAuthor(aStack));
+ }
+ return aList;
+ }
+}
diff --git a/src/main/java/gregtech/common/misc/GT_ClientPollutionMap.java b/src/main/java/gregtech/common/misc/GT_ClientPollutionMap.java
new file mode 100644
index 0000000000..6e40e5860c
--- /dev/null
+++ b/src/main/java/gregtech/common/misc/GT_ClientPollutionMap.java
@@ -0,0 +1,140 @@
+package gregtech.common.misc;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.entity.EntityClientPlayerMP;
+import net.minecraft.util.MathHelper;
+
+public class GT_ClientPollutionMap {
+
+ private static final byte RADIUS = 24;
+ private static final byte DISTANCE_RELOAD_MAP = 5; // When player moved x chunks, shift the map to new center.
+ private static final byte SIZE = RADIUS * 2 + 1; // Area to keep stored.
+
+ private int x0, z0;
+ private int dim;
+
+ private boolean initialized = false;
+
+ private static short[][] chunkMatrix; // short because reasons.
+
+ public GT_ClientPollutionMap() {}
+
+ public void reset() {
+ initialized = false;
+ }
+
+ private void initialize(int playerChunkX, int playerChunkZ, int dimension) {
+ initialized = true;
+ chunkMatrix = new short[SIZE][SIZE];
+ x0 = playerChunkX;
+ z0 = playerChunkZ;
+ dim = dimension;
+ }
+
+ public void addChunkPollution(int chunkX, int chunkZ, int pollution) {
+ EntityClientPlayerMP player = Minecraft.getMinecraft().thePlayer;
+ if (player == null || player.worldObj == null) return;
+
+ int playerXChunk = MathHelper.floor_double(player.posX) >> 4;
+ int playerZChunk = MathHelper.floor_double(player.posZ) >> 4; // posX/Z seems to be always loaded,
+
+ if (!initialized) {
+ initialize(playerXChunk, playerZChunk, player.dimension);
+ }
+
+ if (dim != player.dimension) {
+ initialize(playerXChunk, playerZChunk, player.dimension);
+ }
+
+ if (Math.abs(x0 - playerXChunk) > DISTANCE_RELOAD_MAP || Math.abs(z0 - playerZChunk) > DISTANCE_RELOAD_MAP)
+ shiftCenter(playerXChunk, playerZChunk);
+
+ int relX = chunkX - x0 + RADIUS;
+ if (relX >= SIZE || relX < 0) // out of bounds
+ return;
+ int relZ = chunkZ - z0 + RADIUS;
+ if (relZ >= SIZE || relZ < 0) // out of bounds
+ return;
+
+ pollution = pollution / 225;
+ if (pollution > Short.MAX_VALUE) // Sanity
+ chunkMatrix[relX][relZ] = Short.MAX_VALUE; // Max pollution = 7,3mill
+ else if (pollution < 0) chunkMatrix[relX][relZ] = 0;
+ else chunkMatrix[relX][relZ] = (short) (pollution);
+ }
+
+ // xy interpolation, between 4 chunks as corners, unknown treated as 0.
+ public int getPollution(double fx, double fz) {
+ if (!initialized) return 0;
+ int x = MathHelper.floor_double(fx);
+ int z = MathHelper.floor_double(fz);
+ int xDiff = ((x - 8) >> 4) - x0;
+ int zDiff = ((z - 8) >> 4) - z0;
+
+ if (xDiff < -RADIUS || zDiff < -RADIUS || xDiff >= RADIUS || zDiff >= RADIUS) return 0;
+
+ // coordinates in shifted chunk.
+ x = (x - 8) % 16;
+ z = (z - 8) % 16;
+ if (x < 0) x = 16 + x;
+ if (z < 0) z = 16 + z;
+
+ int xi = 15 - x;
+ int zi = 15 - z;
+
+ // read pollution in 4 corner chunks
+ int offsetX = RADIUS + xDiff;
+ int offsetZ = RADIUS + zDiff;
+
+ int c00 = chunkMatrix[offsetX][offsetZ];
+ int c10 = chunkMatrix[offsetX + 1][offsetZ];
+ int c01 = chunkMatrix[offsetX][offsetZ + 1];
+ int c11 = chunkMatrix[offsetX + 1][offsetZ + 1];
+
+ // Is divided by 15*15 but is handled when storing chunk data.
+ return c00 * xi * zi + c10 * x * zi + c01 * xi * z + c11 * x * z;
+ }
+
+ // shift the matrix to fit new center
+ private void shiftCenter(int chunkX, int chunkZ) {
+ int xDiff = chunkX - x0;
+ int zDiff = chunkZ - z0;
+ boolean[] allEmpty = new boolean[SIZE]; // skip check z row if its empty.
+ if (xDiff > 0) for (byte x = 0; x < SIZE; x++) {
+ int xOff = x + xDiff;
+ if (xOff < SIZE) {
+ chunkMatrix[x] = chunkMatrix[xOff].clone();
+ } else {
+ chunkMatrix[x] = new short[SIZE];
+ allEmpty[x] = true;
+ }
+ }
+ else if (xDiff < 0) for (byte x = SIZE - 1; x >= 0; x--) {
+ int xOff = x + xDiff;
+ if (xOff > 0) {
+ chunkMatrix[x] = chunkMatrix[xOff].clone();
+ } else {
+ chunkMatrix[x] = new short[SIZE];
+ allEmpty[x] = true;
+ }
+ }
+
+ if (zDiff > 0) for (byte x = 0; x < SIZE; x++) {
+ if (allEmpty[x]) continue;
+ for (int z = 0; z < SIZE; z++) {
+ int zOff = z + zDiff;
+ chunkMatrix[x][z] = (zOff < SIZE) ? chunkMatrix[x][zOff] : 0;
+ }
+ }
+ else if (zDiff < 0) for (byte x = 0; x < SIZE; x++) {
+ if (allEmpty[x]) continue;
+ for (int z = SIZE - 1; z >= 0; z--) {
+ int zOff = z + zDiff;
+ chunkMatrix[x][z] = (zOff > 0) ? chunkMatrix[x][zOff] : 0;
+ }
+ }
+
+ x0 = chunkX;
+ z0 = chunkZ;
+ }
+}
diff --git a/src/main/java/gregtech/common/misc/GT_Command.java b/src/main/java/gregtech/common/misc/GT_Command.java
new file mode 100644
index 0000000000..3bf73b6300
--- /dev/null
+++ b/src/main/java/gregtech/common/misc/GT_Command.java
@@ -0,0 +1,340 @@
+package gregtech.common.misc;
+
+import static gregtech.common.misc.WirelessNetworkManager.addEUToGlobalEnergyMap;
+import static gregtech.common.misc.WirelessNetworkManager.getUserEU;
+import static gregtech.common.misc.WirelessNetworkManager.setUserEU;
+
+import java.lang.reflect.Field;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import java.util.stream.Stream;
+
+import net.minecraft.command.CommandBase;
+import net.minecraft.command.ICommandSender;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.ChunkCoordinates;
+import net.minecraft.util.EnumChatFormatting;
+
+import com.gtnewhorizon.structurelib.StructureLib;
+
+import gregtech.GT_Mod;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.objects.GT_ChunkManager;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.GT_Pollution;
+import gregtech.common.misc.spaceprojects.SpaceProjectManager;
+
+public final class GT_Command extends CommandBase {
+
+ @Override
+ public String getCommandName() {
+ return "gt";
+ }
+
+ @Override
+ public String getCommandUsage(ICommandSender sender) {
+ return "Usage: gt <subcommand>. Valid subcommands are: toggle, chunks, pollution.";
+ }
+
+ private void printHelp(ICommandSender sender) {
+ sender.addChatMessage(
+ new ChatComponentText(
+ "Usage: gt <toggle|chunks|pollution|global_energy_add|global_energy_set|global_energy_join>"));
+ sender.addChatMessage(new ChatComponentText("\"toggle D1\" - toggles general.Debug (D1)"));
+ sender.addChatMessage(new ChatComponentText("\"toggle D2\" - toggles general.Debug2 (D2)"));
+ sender.addChatMessage(new ChatComponentText("\"toggle debugCleanroom\" - toggles cleanroom debug log"));
+ sender.addChatMessage(new ChatComponentText("\"toggle debugDriller\" - toggles oil drill debug log"));
+ sender.addChatMessage(new ChatComponentText("\"toggle debugBlockPump\" - Possible issues with pumps"));
+ sender.addChatMessage(new ChatComponentText("\"toggle debugBlockMiner\" - Possible issues with miners"));
+ sender.addChatMessage(
+ new ChatComponentText("\"toggle debugEntityCramming\" - How long it takes and how many entities it finds"));
+ sender.addChatMessage(new ChatComponentText("\"toggle debugWorldGen\" - toggles generic worldgen debug"));
+ sender.addChatMessage(new ChatComponentText("\"toggle debugOrevein\" - toggles worldgen ore vein debug"));
+ sender.addChatMessage(new ChatComponentText("\"toggle debugSmallOres\" - toggles worldgen small vein debug"));
+ sender.addChatMessage(new ChatComponentText("\"toggle debugStones\" - toggles worldgen stones debug"));
+ sender.addChatMessage(new ChatComponentText("\"toggle debugChunkloaders\" - toggles chunkloaders debug"));
+ sender.addChatMessage(new ChatComponentText("\"toggle debugMulti\" - toggles structurelib debug"));
+ sender.addChatMessage(new ChatComponentText("\"chunks\" - print a list of the force loaded chunks"));
+ sender.addChatMessage(
+ new ChatComponentText(
+ "\"pollution <amount>\" - adds the <amount> of the pollution to the current chunk, "
+ + "\n if <amount> isnt specified, will add"
+ + GT_Mod.gregtechproxy.mPollutionSmogLimit
+ + "gibbl."));
+ sender.addChatMessage(new ChatComponentText(EnumChatFormatting.GOLD + " --- Global wireless EU controls ---"));
+ sender.addChatMessage(new ChatComponentText("Allows you to set the amount of EU in a users wireless network."));
+ sender.addChatMessage(
+ new ChatComponentText(
+ "Usage:" + EnumChatFormatting.RED
+ + " global_energy_set "
+ + EnumChatFormatting.BLUE
+ + "[Name] "
+ + EnumChatFormatting.LIGHT_PURPLE
+ + "[EU]"));
+ sender.addChatMessage(
+ new ChatComponentText("Allows you to add EU to a users wireless network. Also accepts negative numbers."));
+ sender.addChatMessage(
+ new ChatComponentText(
+ "Usage:" + EnumChatFormatting.RED
+ + " global_energy_add "
+ + EnumChatFormatting.BLUE
+ + "[Name] "
+ + EnumChatFormatting.LIGHT_PURPLE
+ + "[EU]"));
+ sender.addChatMessage(
+ new ChatComponentText(
+ "Allows you to join two users together into one network. Can be undone by writing the users name twice."));
+ sender.addChatMessage(
+ new ChatComponentText(
+ "Usage:" + EnumChatFormatting.RED
+ + " global_energy_join "
+ + EnumChatFormatting.BLUE
+ + "[User joining] [User to join]"));
+ sender.addChatMessage(new ChatComponentText("Shows the amount of EU in a users energy network."));
+ sender.addChatMessage(
+ new ChatComponentText(
+ "Usage:" + EnumChatFormatting.RED + " global_energy_display " + EnumChatFormatting.BLUE + "[Name]"));
+ }
+
+ @Override
+ public List<String> addTabCompletionOptions(ICommandSender sender, String[] ss) {
+ List<String> l = new ArrayList<>();
+ String test = ss.length == 0 ? "" : ss[0].trim();
+ if (ss.length == 0 || ss.length == 1 && (test.isEmpty() || Stream
+ .of(
+ "toggle",
+ "chunks",
+ "pollution",
+ "global_energy_add",
+ "global_energy_set",
+ "global_energy_join",
+ "global_energy_display")
+ .anyMatch(s -> s.startsWith(test)))) {
+ Stream
+ .of(
+ "toggle",
+ "chunks",
+ "pollution",
+ "global_energy_add",
+ "global_energy_set",
+ "global_energy_join",
+ "global_energy_display")
+ .filter(s -> test.isEmpty() || s.startsWith(test))
+ .forEach(l::add);
+ } else if (test.equals("toggle")) {
+ String test1 = ss[1].trim();
+ Stream
+ .of(
+ "D1",
+ "D2",
+ "debugCleanroom",
+ "debugDriller",
+ "debugBlockPump",
+ "debugBlockMiner",
+ "debugWorldGen",
+ "debugEntityCramming",
+ "debugOrevein",
+ "debugSmallOres",
+ "debugStones",
+ "debugChunkloaders",
+ "debugMulti",
+ "debugWorldData")
+ .filter(s -> test1.isEmpty() || s.startsWith(test1))
+ .forEach(l::add);
+ }
+ return l;
+ }
+
+ @Override
+ public void processCommand(ICommandSender sender, String[] strings) {
+ if (strings.length < 1) {
+ printHelp(sender);
+ return;
+ }
+ switch (strings[0]) {
+ case "toggle" -> {
+ if (strings.length < 2) {
+ printHelp(sender);
+ return;
+ }
+ if ("debugMulti".equals(strings[1])) {
+ StructureLib.DEBUG_MODE = !StructureLib.DEBUG_MODE;
+ sender.addChatMessage(
+ new ChatComponentText(strings[1] + " = " + (StructureLib.DEBUG_MODE ? "true" : "false")));
+ return;
+ }
+ try {
+ Field field = GT_Values.class.getDeclaredField(strings[1]);
+ if (field.getType() != boolean.class) {
+ sender.addChatMessage(new ChatComponentText("Wrong variable: " + strings[1]));
+ return;
+ }
+ boolean b = !field.getBoolean(null);
+ field.setBoolean(null, b);
+ sender.addChatMessage(new ChatComponentText(strings[1] + " = " + (b ? "true" : "false")));
+ } catch (Exception e) {
+ sender.addChatMessage(new ChatComponentText("No such variable: " + strings[0]));
+ }
+ }
+ case "chunks" -> {
+ GT_ChunkManager.printTickets();
+ sender.addChatMessage(new ChatComponentText("Forced chunks logged to GregTech.log"));
+ }
+ case "pollution" -> {
+ ChunkCoordinates coordinates = sender.getPlayerCoordinates();
+ int amount = (strings.length < 2) ? GT_Mod.gregtechproxy.mPollutionSmogLimit
+ : Integer.parseInt(strings[1]);
+ GT_Pollution.addPollution(
+ sender.getEntityWorld()
+ .getChunkFromBlockCoords(coordinates.posX, coordinates.posZ),
+ amount);
+ }
+ case "global_energy_add" -> {
+ String username = strings[1];
+ String formatted_username = EnumChatFormatting.BLUE + username + EnumChatFormatting.RESET;
+ UUID uuid = SpaceProjectManager.getPlayerUUIDFromName(username);
+
+ String EU_String = strings[2];
+
+ // Usage is /gt global_energy_add username EU
+
+ String EU_string_formatted = EnumChatFormatting.RED
+ + GT_Utility.formatNumbers(new BigInteger(EU_String))
+ + EnumChatFormatting.RESET;
+
+ if (addEUToGlobalEnergyMap(uuid, new BigInteger(EU_String))) sender.addChatMessage(
+ new ChatComponentText(
+ "Successfully added " + EU_string_formatted
+ + "EU to the global energy network of "
+ + formatted_username
+ + "."));
+ else sender.addChatMessage(
+ new ChatComponentText(
+ "Failed to add " + EU_string_formatted
+ + "EU to the global energy map of "
+ + formatted_username
+ + ". Insufficient energy in network. "));
+
+ sender.addChatMessage(
+ new ChatComponentText(
+ formatted_username + " currently has "
+ + EnumChatFormatting.RED
+ + GT_Utility.formatNumbers(new BigInteger(getUserEU(uuid).toString()))
+ + EnumChatFormatting.RESET
+ + "EU in their network."));
+
+ }
+ case "global_energy_set" -> {
+
+ // Usage is /gt global_energy_set username EU
+
+ String username = strings[1];
+ String formatted_username = EnumChatFormatting.BLUE + username + EnumChatFormatting.RESET;
+ UUID uuid = SpaceProjectManager.getPlayerUUIDFromName(username);
+
+ String EU_String_0 = strings[2];
+
+ if ((new BigInteger(EU_String_0).compareTo(BigInteger.ZERO)) < 0) {
+ sender.addChatMessage(
+ new ChatComponentText("Cannot set a users energy network to a negative value."));
+ break;
+ }
+
+ setUserEU(uuid, new BigInteger(EU_String_0));
+
+ sender.addChatMessage(
+ new ChatComponentText(
+ "Successfully set " + formatted_username
+ + "'s global energy network to "
+ + EnumChatFormatting.RED
+ + GT_Utility.formatNumbers(new BigInteger(EU_String_0))
+ + EnumChatFormatting.RESET
+ + "EU."));
+
+ }
+ case "global_energy_join" -> {
+
+ // Usage is /gt global_energy_join username_of_you username_to_join
+
+ String usernameSubject = strings[1];
+ String usernameTeam = strings[2];
+
+ String formattedUsernameSubject = EnumChatFormatting.BLUE + usernameSubject + EnumChatFormatting.RESET;
+ String formattedUsernameTeam = EnumChatFormatting.BLUE + usernameTeam + EnumChatFormatting.RESET;
+
+ UUID uuidSubject = SpaceProjectManager.getPlayerUUIDFromName(usernameSubject);
+ UUID uuidTeam = SpaceProjectManager.getLeader(SpaceProjectManager.getPlayerUUIDFromName(usernameTeam));
+
+ if (uuidSubject.equals(uuidTeam)) {
+ // leave team
+ SpaceProjectManager.putInTeam(uuidSubject, uuidSubject);
+ sender.addChatMessage(
+ new ChatComponentText(
+ "User " + formattedUsernameSubject + " has rejoined their own global energy network."));
+ break;
+ }
+
+ // join other's team
+
+ if (uuidSubject.equals(uuidTeam)) {
+ sender.addChatMessage(new ChatComponentText("They are already in the same network!"));
+ break;
+ }
+
+ SpaceProjectManager.putInTeam(uuidSubject, uuidTeam);
+
+ sender.addChatMessage(
+ new ChatComponentText(
+ "Success! " + formattedUsernameSubject + " has joined " + formattedUsernameTeam + "."));
+ sender.addChatMessage(
+ new ChatComponentText(
+ "To undo this simply join your own network again with /gt global_energy_join "
+ + formattedUsernameSubject
+ + " "
+ + formattedUsernameSubject
+ + "."));
+
+ }
+ case "global_energy_display" -> {
+
+ // Usage is /gt global_energy_display username.
+
+ String username = strings[1];
+ String formatted_username = EnumChatFormatting.BLUE + username + EnumChatFormatting.RESET;
+ UUID userUUID = SpaceProjectManager.getPlayerUUIDFromName(username);
+
+ if (!SpaceProjectManager.isInTeam(userUUID)) {
+ sender.addChatMessage(
+ new ChatComponentText("User " + formatted_username + " has no global energy network."));
+ break;
+ }
+ UUID teamUUID = SpaceProjectManager.getLeader(userUUID);
+
+ sender.addChatMessage(
+ new ChatComponentText(
+ "User " + formatted_username
+ + " has "
+ + EnumChatFormatting.RED
+ + GT_Utility.formatNumbers(getUserEU(userUUID))
+ + EnumChatFormatting.RESET
+ + "EU in their network."));
+ if (!userUUID.equals(teamUUID)) sender.addChatMessage(
+ new ChatComponentText(
+ "User " + formatted_username
+ + " is currently in network of "
+ + EnumChatFormatting.BLUE
+ + SpaceProjectManager.getPlayerNameFromUUID(teamUUID)
+ + EnumChatFormatting.RESET
+ + "."));
+
+ }
+ default -> {
+ sender
+ .addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "Invalid command/syntax detected."));
+ printHelp(sender);
+ }
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/misc/GT_DrillingLogicDelegate.java b/src/main/java/gregtech/common/misc/GT_DrillingLogicDelegate.java
new file mode 100644
index 0000000000..9cf7fd7cf8
--- /dev/null
+++ b/src/main/java/gregtech/common/misc/GT_DrillingLogicDelegate.java
@@ -0,0 +1,266 @@
+package gregtech.common.misc;
+
+import static gregtech.api.enums.GT_Values.debugBlockMiner;
+
+import java.util.List;
+
+import net.minecraft.block.Block;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.ItemStack;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraftforge.common.util.FakePlayer;
+
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.util.GT_Log;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.blocks.GT_TileEntity_Ores;
+
+/** @author Relvl on 27.01.2022 */
+@SuppressWarnings("ObjectEquality")
+public class GT_DrillingLogicDelegate {
+
+ public static final ItemStack MINING_PIPE_STACK = GT_ModHandler.getIC2Item("miningPipe", 0);
+ public static final Block MINING_PIPE_BLOCK = GT_Utility.getBlockFromStack(MINING_PIPE_STACK);
+ public static final Block MINING_PIPE_TIP_BLOCK = GT_Utility
+ .getBlockFromStack(GT_ModHandler.getIC2Item("miningPipeTip", 0));
+
+ /** The owner machine pointer */
+ private final GT_IDrillingLogicDelegateOwner owner;
+
+ /** Is pipe retracting process done and halts? */
+ private boolean isRetractDone;
+ /** Is machine ran out of mining pipes in its inventory and halts? */
+ private boolean isWaitingForPipeItem;
+ /** Pipe tip depth (relative to machine Y position, NEGATIVE). */
+ private int tipDepth;
+ /** Cached fake player */
+ private FakePlayer mFakePlayer;
+
+ public GT_DrillingLogicDelegate(GT_IDrillingLogicDelegateOwner owner) {
+ this.owner = owner;
+ }
+
+ /** Descents a pipe tip one plock deeper. */
+ public boolean descent(IGregTechTileEntity te) {
+ if (!te.isAllowedToWork()) {
+ return false;
+ }
+
+ int xCoord = te.getXCoord();
+ int zCoord = te.getZCoord();
+ int yCoord = te.getYCoord();
+ int checkY = yCoord + tipDepth - 1;
+ boolean isHitsTheVoid = checkY < 0;
+ boolean isHitsBedrock = GT_Utility.getBlockHardnessAt(te.getWorld(), xCoord, checkY, zCoord) < 0;
+ boolean isFakePlayerAllowed = canFakePlayerInteract(te, xCoord, checkY, zCoord);
+
+ if (isHitsTheVoid || isHitsBedrock || !isFakePlayerAllowed) {
+ // Disable and start retracting process.
+ te.disableWorking();
+ if (debugBlockMiner) {
+ if (isHitsTheVoid) {
+ GT_Log.out.println("MINER: Hit bottom");
+ }
+ if (isHitsBedrock) {
+ GT_Log.out.println("MINER: Hit block with -1 hardness");
+ }
+ if (!isFakePlayerAllowed) {
+ GT_Log.out.println("MINER: Unable to set mining pipe tip");
+ }
+ }
+ return false;
+ }
+
+ // Replace the tip onto pipe
+ if (te.getBlockOffset(0, tipDepth, 0) == MINING_PIPE_TIP_BLOCK) {
+ te.getWorld()
+ .setBlock(xCoord, yCoord + tipDepth, zCoord, MINING_PIPE_BLOCK);
+ }
+ // Get and decrease pipe from the machine
+ boolean pipeTaken = owner.pullInputs(MINING_PIPE_STACK.getItem(), 1, false);
+ if (!pipeTaken) {
+ // If there was nothing - waiting for the pipes (just for prevent unnecessary checks)
+ isWaitingForPipeItem = true;
+ return false;
+ }
+
+ // If there is something - mine it
+ Block block = te.getBlockOffset(0, tipDepth - 1, 0);
+ if (!block.isAir(te.getWorld(), xCoord, yCoord, zCoord)) {
+ mineBlock(te, block, xCoord, yCoord + tipDepth - 1, zCoord);
+ }
+
+ // Descent the pipe tip
+ te.getWorld()
+ .setBlock(xCoord, yCoord + tipDepth - 1, zCoord, MINING_PIPE_TIP_BLOCK);
+ tipDepth--;
+ return true;
+ }
+
+ public void onOwnerPostTick(IGregTechTileEntity te, long tick) {
+ // If the machine was disabled - try to retract pipe
+ if (!te.isAllowedToWork()) {
+ onPostTickRetract(te, tick);
+ return;
+ }
+ // If the machine was re-enabled - we should reset the retracting process
+ isRetractDone = false;
+ }
+
+ /** If the machine are disabled - tried to retract pipe. */
+ private void onPostTickRetract(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ if (isRetractDone) {
+ return;
+ }
+ // If retracting process just touch the miner
+ if (tipDepth == 0) {
+ isRetractDone = true;
+ return;
+ }
+ // Once per N ticks (depends on tier)
+ if ((aTick % (owner.getMachineSpeed() / 5)) != 0) {
+ return;
+ }
+
+ // Check we can push pipe back to machine (inputs allowed for this case!)
+ boolean canPush = owner.pushOutputs(MINING_PIPE_STACK, 1, true, true);
+ if (!canPush) {
+ return;
+ }
+
+ // Inspect target block - it should be a pipe tip, else something went wrong.
+ Block targetBlock = aBaseMetaTileEntity.getBlockOffset(0, tipDepth, 0);
+ if (targetBlock != MINING_PIPE_TIP_BLOCK && targetBlock != MINING_PIPE_BLOCK) {
+ return;
+ }
+
+ // Retract the pipe/tip
+ int xCoord = aBaseMetaTileEntity.getXCoord();
+ int yCoord = aBaseMetaTileEntity.getYCoord();
+ int zCoord = aBaseMetaTileEntity.getZCoord();
+ int actualDrillY = yCoord + tipDepth;
+ // Move the pipe tip position
+ if (actualDrillY < yCoord - 1) {
+ owner.getBaseMetaTileEntity()
+ .getWorld()
+ .setBlock(xCoord, actualDrillY + 1, zCoord, MINING_PIPE_TIP_BLOCK);
+ }
+ // Remove the old pipe tip
+ aBaseMetaTileEntity.getWorld()
+ .setBlock(xCoord, actualDrillY, zCoord, Blocks.air, 0, /* send to client without neighbour updates */ 2);
+
+ // Return the pipe back to the machine (inputs allowed for this case!)
+ owner.pushOutputs(MINING_PIPE_STACK, 1, false, true);
+
+ tipDepth++;
+ }
+
+ /** Minings the block if it is possible. */
+ public void mineBlock(IGregTechTileEntity te, Block block, int x, int y, int z) {
+ if (!GT_Utility.eraseBlockByFakePlayer(getFakePlayer(te), x, y, z, true)) {
+ return;
+ }
+
+ List<ItemStack> drops = getBlockDrops(block, x, y, z);
+
+ boolean canFitDrops = true;
+ for (ItemStack drop : drops) {
+ canFitDrops &= owner.pushOutputs(drop, drop.stackSize, true, false);
+ }
+ if (!canFitDrops) {
+ return;
+ }
+ for (ItemStack drop : drops) {
+ owner.pushOutputs(drop, drop.stackSize, false, false);
+ }
+
+ short metaData = 0;
+ TileEntity tTileEntity = owner.getBaseMetaTileEntity()
+ .getTileEntity(x, y, z);
+ if (tTileEntity instanceof GT_TileEntity_Ores) {
+ metaData = ((GT_TileEntity_Ores) tTileEntity).mMetaData;
+ }
+
+ ItemStack cobble = GT_Utility.getCobbleForOre(block, metaData);
+ te.getWorld()
+ .setBlock(
+ x,
+ y,
+ z,
+ Block.getBlockFromItem(cobble.getItem()),
+ cobble.getItemDamage(), /* cause updates(1) + send to client(2) */
+ 3);
+ }
+
+ /**
+ * Returns NEGATIVE (eg -5) depth of current drilling Y world level. RELATIVELY TO MINER ENTITY! This means '(miner
+ * world Y) + depth = (actual world Y)'.
+ */
+ public int getTipDepth() {
+ return tipDepth;
+ }
+
+ /** Looking for the lowest continuous pipe. */
+ public void findTipDepth() {
+ IGregTechTileEntity ownerTe = owner.getBaseMetaTileEntity();
+ if (!ownerTe.isServerSide()) {
+ return;
+ }
+ while (true) {
+ Block block = ownerTe.getBlockOffset(0, tipDepth - 1, 0);
+ if (block != MINING_PIPE_BLOCK && block != MINING_PIPE_TIP_BLOCK) {
+ return;
+ }
+ tipDepth--;
+ }
+ }
+
+ /**
+ * Creates and provides the Fake Player for owners. todo maybe will provide player owner uuid? im sure some servers
+ * not allow to fakers, in griefing reasons.
+ */
+ public FakePlayer getFakePlayer(IGregTechTileEntity te) {
+ if (mFakePlayer == null) {
+ mFakePlayer = GT_Utility.getFakePlayer(te);
+ }
+ if (mFakePlayer != null) {
+ mFakePlayer.setWorld(te.getWorld());
+ mFakePlayer.setPosition(te.getXCoord(), te.getYCoord(), te.getZCoord());
+ }
+ return mFakePlayer;
+ }
+
+ public boolean canFakePlayerInteract(IGregTechTileEntity te, int xCoord, int yCoord, int zCoord) {
+ return GT_Utility
+ .setBlockByFakePlayer(getFakePlayer(te), xCoord, yCoord, zCoord, MINING_PIPE_TIP_BLOCK, 0, true);
+ }
+
+ /** Get target block drops. We need to encapsulate everyting of mining in this class. */
+ private List<ItemStack> getBlockDrops(final Block oreBlock, int posX, int posY, int posZ) {
+ return oreBlock.getDrops(
+ owner.getBaseMetaTileEntity()
+ .getWorld(),
+ posX,
+ posY,
+ posZ,
+ owner.getBaseMetaTileEntity()
+ .getMetaID(posX, posY, posZ),
+ owner.getMachineTier());
+ }
+
+ /** Can the owner continue doing its work? If we await new pipes - it cannot. */
+ public boolean canContinueDrilling(long tick) {
+ if (isWaitingForPipeItem) {
+ if (tick % 5 != 0) {
+ return false;
+ }
+ boolean hasPipe = owner.pullInputs(MINING_PIPE_STACK.getItem(), 1, true);
+ if (hasPipe) {
+ isWaitingForPipeItem = false;
+ }
+ return hasPipe;
+ }
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/common/misc/GT_IDrillingLogicDelegateOwner.java b/src/main/java/gregtech/common/misc/GT_IDrillingLogicDelegateOwner.java
new file mode 100644
index 0000000000..9b10b6fcf0
--- /dev/null
+++ b/src/main/java/gregtech/common/misc/GT_IDrillingLogicDelegateOwner.java
@@ -0,0 +1,22 @@
+package gregtech.common.misc;
+
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+
+/** @author Relvl on 27.01.2022 */
+public interface GT_IDrillingLogicDelegateOwner extends IMetaTileEntity {
+
+ /** Returns the machine actual tier. */
+ int getMachineTier();
+
+ /** Returns the machine current processing speed. */
+ int getMachineSpeed();
+
+ /** Pulls (or check can pull) items from an input slots. */
+ boolean pullInputs(Item item, int count, boolean simulate);
+
+ /** Pushes (or check can push) item to output slots. */
+ boolean pushOutputs(ItemStack stack, int count, boolean simulate, boolean allowInputSlots);
+}
diff --git a/src/main/java/gregtech/common/misc/GlobalEnergyWorldSavedData.java b/src/main/java/gregtech/common/misc/GlobalEnergyWorldSavedData.java
new file mode 100644
index 0000000000..1a03012649
--- /dev/null
+++ b/src/main/java/gregtech/common/misc/GlobalEnergyWorldSavedData.java
@@ -0,0 +1,125 @@
+package gregtech.common.misc;
+
+import static gregtech.common.misc.GlobalVariableStorage.GlobalEnergy;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.math.BigInteger;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.world.World;
+import net.minecraft.world.WorldSavedData;
+import net.minecraft.world.storage.MapStorage;
+import net.minecraftforge.event.world.WorldEvent;
+
+import cpw.mods.fml.common.eventhandler.SubscribeEvent;
+import gregtech.common.misc.spaceprojects.SpaceProjectManager;
+
+public class GlobalEnergyWorldSavedData extends WorldSavedData {
+
+ public static GlobalEnergyWorldSavedData INSTANCE;
+
+ private static final String DATA_NAME = "GregTech_WirelessEUWorldSavedData";
+
+ private static final String GlobalEnergyNBTTag = "GregTech_GlobalEnergy_MapNBTTag";
+ private static final String GlobalEnergyTeamNBTTag = "GregTech_GlobalEnergyTeam_MapNBTTag";
+
+ private static void loadInstance(World world) {
+
+ GlobalEnergy.clear();
+
+ MapStorage storage = world.mapStorage;
+ INSTANCE = (GlobalEnergyWorldSavedData) storage.loadData(GlobalEnergyWorldSavedData.class, DATA_NAME);
+ if (INSTANCE == null) {
+ INSTANCE = new GlobalEnergyWorldSavedData();
+ storage.setData(DATA_NAME, INSTANCE);
+ }
+ INSTANCE.markDirty();
+ }
+
+ @SuppressWarnings("unused")
+ @SubscribeEvent
+ public void onWorldLoad(WorldEvent.Load event) {
+ if (!event.world.isRemote && event.world.provider.dimensionId == 0) {
+ loadInstance(event.world);
+ }
+ }
+
+ public GlobalEnergyWorldSavedData() {
+ super(DATA_NAME);
+ }
+
+ @SuppressWarnings("unused")
+ public GlobalEnergyWorldSavedData(String name) {
+ super(name);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public void readFromNBT(NBTTagCompound nbtTagCompound) {
+
+ try {
+ byte[] ba = nbtTagCompound.getByteArray(GlobalEnergyNBTTag);
+ InputStream byteArrayInputStream = new ByteArrayInputStream(ba);
+ ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
+ Object data = objectInputStream.readObject();
+ HashMap<Object, BigInteger> hashData = (HashMap<Object, BigInteger>) data;
+ for (Map.Entry<Object, BigInteger> entry : hashData.entrySet()) {
+ try {
+ GlobalEnergy.put(
+ UUID.fromString(
+ entry.getKey()
+ .toString()),
+ entry.getValue());
+ } catch (RuntimeException ignored) {
+ // probably a malformed uuid. in any case, try carry on with the load
+ }
+ }
+ } catch (IOException | ClassNotFoundException exception) {
+ System.out.println(GlobalEnergyNBTTag + " FAILED");
+ exception.printStackTrace();
+ }
+ try {
+ if (!nbtTagCompound.hasKey(GlobalEnergyTeamNBTTag)) return;
+ byte[] ba = nbtTagCompound.getByteArray(GlobalEnergyTeamNBTTag);
+ InputStream byteArrayInputStream = new ByteArrayInputStream(ba);
+ ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
+ Object data = objectInputStream.readObject();
+ HashMap<String, String> oldTeams = (HashMap<String, String>) data;
+ for (String member : oldTeams.keySet()) {
+ String leader = oldTeams.get(member);
+ try {
+ SpaceProjectManager.putInTeam(UUID.fromString(member), UUID.fromString(leader));
+ } catch (RuntimeException ignored) {
+ // probably a malformed uuid. in any case, try carry on with the load
+ }
+ }
+ } catch (IOException | ClassNotFoundException exception) {
+ System.out.println(GlobalEnergyTeamNBTTag + " FAILED");
+ exception.printStackTrace();
+ }
+ }
+
+ @Override
+ public void writeToNBT(NBTTagCompound nbtTagCompound) {
+
+ try {
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
+ objectOutputStream.writeObject(GlobalEnergy);
+ objectOutputStream.flush();
+ byte[] data = byteArrayOutputStream.toByteArray();
+ nbtTagCompound.setByteArray(GlobalEnergyNBTTag, data);
+ } catch (IOException exception) {
+ System.out.println(GlobalEnergyNBTTag + " SAVE FAILED");
+ exception.printStackTrace();
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/misc/GlobalMetricsCoverDatabase.java b/src/main/java/gregtech/common/misc/GlobalMetricsCoverDatabase.java
new file mode 100644
index 0000000000..33e8198bd6
--- /dev/null
+++ b/src/main/java/gregtech/common/misc/GlobalMetricsCoverDatabase.java
@@ -0,0 +1,492 @@
+package gregtech.common.misc;
+
+import static net.minecraftforge.common.util.Constants.NBT.TAG_BYTE_ARRAY;
+import static net.minecraftforge.common.util.Constants.NBT.TAG_COMPOUND;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+
+import net.minecraft.entity.item.EntityItem;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagByteArray;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraft.util.StatCollector;
+import net.minecraft.world.WorldSavedData;
+import net.minecraft.world.storage.MapStorage;
+import net.minecraftforge.common.ForgeHooks;
+import net.minecraftforge.common.MinecraftForge;
+import net.minecraftforge.event.entity.item.ItemExpireEvent;
+import net.minecraftforge.event.world.BlockEvent;
+import net.minecraftforge.event.world.ExplosionEvent.Detonate;
+import net.minecraftforge.event.world.WorldEvent;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import cpw.mods.fml.common.eventhandler.SubscribeEvent;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.covers.CoverInfo;
+import gregtech.common.covers.GT_Cover_Metrics_Transmitter;
+import gregtech.common.events.MetricsCoverDataEvent;
+import gregtech.common.events.MetricsCoverHostDeconstructedEvent;
+import gregtech.common.events.MetricsCoverSelfDestructEvent;
+
+/**
+ * Catches and provides data transmitted from deployed Metrics Transmitter covers. Only stores one result per frequency
+ * at a time. Metrics covers are intended to overwrite an old result every time they emit a new event.
+ * <br />
+ * <br />
+ * This information is only partially persisted; frequencies that are in a non-operational state will be written to
+ * disk, while operational frequencies are volatile. The assumption is that any frequency with a broadcasting card will,
+ * fairly quickly, re-assert its presence. Conversely, one-time events like deconstruction or self-destruction can occur
+ * while the card is in a container, rotting on the ground, etc.
+ */
+public class GlobalMetricsCoverDatabase extends WorldSavedData {
+
+ private static GlobalMetricsCoverDatabase INSTANCE;
+
+ /** Holds received metrics. */
+ private static final Map<UUID, Data> DATABASE = new ConcurrentHashMap<>();
+ /** Used to speed up event handlers dealing with block breaking and explosions. Not persisted. */
+ private static final Map<Coordinates, Set<UUID>> REVERSE_LOOKUP = new ConcurrentHashMap<>();
+
+ private static final String DATA_NAME = "GregTech_MetricsCoverDatabase";
+ private static final String DECONSTRUCTED_KEY = "GregTech_MetricsCoverDatabase_Deconstructed";
+ private static final String SELF_DESTRUCTED_KEY = "GregTech_MetricsCoverDatabase_SelfDestructed";
+
+ public GlobalMetricsCoverDatabase() {
+ this(DATA_NAME);
+ }
+
+ public GlobalMetricsCoverDatabase(String name) {
+ super(name);
+ }
+
+ @SuppressWarnings("unused")
+ @SubscribeEvent
+ public void receiveMetricsData(MetricsCoverDataEvent event) {
+ final Coordinates coordinates = event.getCoordinates();
+ store(event.getFrequency(), State.OPERATIONAL, event.getPayload(), coordinates);
+
+ if (!REVERSE_LOOKUP.containsKey(coordinates)) {
+ REVERSE_LOOKUP.put(coordinates, new HashSet<>());
+ }
+ REVERSE_LOOKUP.get(coordinates)
+ .add(event.getFrequency());
+ }
+
+ @SuppressWarnings("unused")
+ @SubscribeEvent
+ public void receiveHostDeconstructed(MetricsCoverHostDeconstructedEvent event) {
+ cullReverseLookupEntry(event.getFrequency());
+ store(event.getFrequency(), State.HOST_DECONSTRUCTED);
+ }
+
+ @SuppressWarnings("unused")
+ @SubscribeEvent
+ public void receiveSelfDestruct(MetricsCoverSelfDestructEvent event) {
+ cullReverseLookupEntry(event.getFrequency());
+ store(event.getFrequency(), State.SELF_DESTRUCTED);
+ }
+
+ @SuppressWarnings("unused")
+ @SubscribeEvent
+ public void onWorldLoad(WorldEvent.Load event) {
+ if (event.world.isRemote || event.world.provider.dimensionId != 0) {
+ return;
+ }
+
+ DATABASE.clear();
+
+ final MapStorage storage = event.world.mapStorage;
+ INSTANCE = (GlobalMetricsCoverDatabase) storage.loadData(GlobalMetricsCoverDatabase.class, DATA_NAME);
+ if (INSTANCE == null) {
+ INSTANCE = new GlobalMetricsCoverDatabase();
+ storage.setData(DATA_NAME, INSTANCE);
+ }
+
+ INSTANCE.markDirty();
+ }
+
+ @SuppressWarnings("unused")
+ @SubscribeEvent
+ public void onBlockBreak(BlockEvent.BreakEvent event) {
+ final Coordinates coords = new Coordinates(event.world.provider.getDimensionName(), event.x, event.y, event.z);
+ // In case someone else wants to listen to these, go the roundabout way.
+ final Set<UUID> uuids = REVERSE_LOOKUP.get(coords);
+ if (uuids != null) {
+ uuids.forEach(
+ uuid -> MinecraftForge.EVENT_BUS.post(
+ ForgeHooks.canHarvestBlock(event.block, event.getPlayer(), event.blockMetadata)
+ && !event.getPlayer().capabilities.isCreativeMode ? new MetricsCoverHostDeconstructedEvent(uuid)
+ : new MetricsCoverSelfDestructEvent(uuid)));
+ }
+ }
+
+ @SuppressWarnings("unused")
+ @SubscribeEvent
+ public void onExplosion(Detonate event) {
+ final String dimensionName = event.world.provider.getDimensionName();
+
+ event.getAffectedBlocks()
+ .forEach(chunkPosition -> {
+ final Set<UUID> uuids = REVERSE_LOOKUP.get(
+ new Coordinates(
+ dimensionName,
+ chunkPosition.chunkPosX,
+ chunkPosition.chunkPosY,
+ chunkPosition.chunkPosZ));
+
+ if (uuids != null) {
+ uuids.forEach(uuid -> MinecraftForge.EVENT_BUS.post(new MetricsCoverSelfDestructEvent(uuid)));
+ }
+ });
+
+ event.getAffectedEntities().forEach(entity -> {
+ if (entity instanceof final EntityItem entityItem) {
+ getCoverUUIDsFromItemStack(entityItem.getEntityItem())
+ .forEach(uuid -> MinecraftForge.EVENT_BUS.post(new MetricsCoverSelfDestructEvent(uuid)));
+ }
+ });
+ }
+
+ @SuppressWarnings("unused")
+ @SubscribeEvent
+ public void onItemExpiration(ItemExpireEvent event) {
+ getCoverUUIDsFromItemStack(event.entityItem.getEntityItem())
+ .forEach(uuid -> MinecraftForge.EVENT_BUS.post(new MetricsCoverSelfDestructEvent(uuid)));
+ }
+
+ /**
+ * Get the data for a frequency, if it exists.
+ *
+ * @param frequency The UUID corresponding to the frequency to retrieve.
+ * @return An Optional with the frequency's data, or an empty Optional if it doesn't exist.
+ */
+ @NotNull
+ public static Optional<Data> getData(UUID frequency) {
+ return Optional.ofNullable(DATABASE.get(frequency));
+ }
+
+ /**
+ * Once a card has received the fact that it has self-destructed, this method can be called to free up its spot
+ * in the database. Does nothing if the frequency is missing or is not in a self-destructed state.
+ *
+ * @param frequency The UUID corresponding to the frequency to possibly cull.
+ */
+ public static void clearSelfDestructedFrequency(UUID frequency) {
+ getData(frequency).ifPresent(data -> {
+ if (data.getState() == State.SELF_DESTRUCTED) {
+ DATABASE.remove(frequency);
+ tryMarkDirty();
+ }
+ });
+ }
+
+ @Override
+ public void readFromNBT(NBTTagCompound nbtTagCompound) {
+ final NBTTagList deconstructed = nbtTagCompound.getTagList(DECONSTRUCTED_KEY, TAG_BYTE_ARRAY);
+ final NBTTagList selfDestructed = nbtTagCompound.getTagList(SELF_DESTRUCTED_KEY, TAG_BYTE_ARRAY);
+
+ for (int i = 0; i < deconstructed.tagCount(); i++) {
+ final NBTTagByteArray byteArray = (NBTTagByteArray) deconstructed.removeTag(0);
+ reconstituteUUID(byteArray.func_150292_c())
+ .ifPresent(uuid -> DATABASE.put(uuid, new Data(State.HOST_DECONSTRUCTED)));
+ }
+
+ for (int i = 0; i < selfDestructed.tagCount(); i++) {
+ final NBTTagByteArray byteArray = (NBTTagByteArray) selfDestructed.removeTag(0);
+ reconstituteUUID(byteArray.func_150292_c())
+ .ifPresent(uuid -> DATABASE.put(uuid, new Data(State.SELF_DESTRUCTED)));
+ }
+ }
+
+ @Override
+ public void writeToNBT(NBTTagCompound nbtTagCompound) {
+ // We only care about persisting frequencies that aren't operational.
+ final NBTTagList deconstructed = new NBTTagList();
+ final NBTTagList selfDestructed = new NBTTagList();
+ DATABASE.forEach((uuid, data) -> {
+ switch (data.getState()) {
+ case HOST_DECONSTRUCTED -> deconstructed.appendTag(new NBTTagByteArray(dumpUUID(uuid)));
+ case SELF_DESTRUCTED -> selfDestructed.appendTag(new NBTTagByteArray(dumpUUID(uuid)));
+ }
+ });
+
+ if (deconstructed.tagCount() > 0) {
+ nbtTagCompound.setTag(DECONSTRUCTED_KEY, deconstructed);
+ }
+ if (selfDestructed.tagCount() > 0) {
+ nbtTagCompound.setTag(SELF_DESTRUCTED_KEY, selfDestructed);
+ }
+ }
+
+ /**
+ * Stores the new result and flag the static {@link MapStorage} instance as dirty if the information updated. Will
+ * not flag dirty for any data in the {@link State#OPERATIONAL OPERATIONAL} state since they aren't stored.
+ *
+ * @param frequency Maps to a unique deployed cover.
+ * @param state The new cover state.
+ */
+ private static void store(@NotNull UUID frequency, @NotNull State state) {
+ store(frequency, state, null, null);
+ }
+
+ /**
+ * Stores the new result and flag the static {@link MapStorage} instance as dirty if the information updated. Will
+ * not flag dirty for any data in the {@link State#OPERATIONAL OPERATIONAL} state since they aren't stored.
+ *
+ * @param frequency Maps to a unique deployed cover.
+ * @param state The new cover state.
+ * @param payload A list of strings to display on the information panel, if the card is slotted properly.
+ * @param coordinates Coordinates of the active machine (including dimension.)
+ */
+ private static void store(@NotNull UUID frequency, @NotNull State state, @Nullable List<String> payload,
+ @Nullable Coordinates coordinates) {
+ final Data newData = new Data(state, payload, coordinates);
+ final Data oldData = DATABASE.put(frequency, newData);
+
+ if (state != State.OPERATIONAL && (oldData == null || oldData != newData)) {
+ tryMarkDirty();
+ }
+ }
+
+ private static void tryMarkDirty() {
+ if (INSTANCE != null) {
+ INSTANCE.markDirty();
+ }
+ }
+
+ private static byte[] dumpUUID(UUID uuid) {
+ ByteBuffer buffer = ByteBuffer.wrap(new byte[16]);
+ buffer.putLong(uuid.getMostSignificantBits());
+ buffer.putLong(uuid.getLeastSignificantBits());
+ return buffer.array();
+ }
+
+ @NotNull
+ private static Optional<UUID> reconstituteUUID(byte[] bytes) throws IllegalArgumentException {
+ if (bytes.length != 16) {
+ return Optional.empty();
+ }
+
+ ByteBuffer buffer = ByteBuffer.wrap(bytes);
+ return Optional.of(new UUID(buffer.getLong(), buffer.getLong()));
+ }
+
+ private static void cullReverseLookupEntry(UUID frequency) {
+ getData(frequency).ifPresent(data -> {
+ if (data.state == State.OPERATIONAL && REVERSE_LOOKUP.containsKey(data.coordinates)) {
+ final Set<UUID> set = REVERSE_LOOKUP.get(data.coordinates);
+ set.remove(frequency);
+ if (set.isEmpty()) {
+ REVERSE_LOOKUP.remove(data.coordinates);
+ }
+ }
+ });
+ }
+
+ private static Stream<UUID> getCoverUUIDsFromItemStack(final ItemStack stack) {
+ if (stack.hasTagCompound() && stack.getTagCompound()
+ .hasKey(GT_Values.NBT.COVERS, TAG_COMPOUND)) {
+ final NBTTagList tagList = stack.getTagCompound()
+ .getTagList(GT_Values.NBT.COVERS, TAG_COMPOUND);
+ return IntStream.range(0, tagList.tagCount())
+ .mapToObj(tagList::getCompoundTagAt)
+ .map(nbt -> new CoverInfo(null, nbt).getCoverData())
+ .filter(
+ serializableObject -> serializableObject instanceof GT_Cover_Metrics_Transmitter.MetricsTransmitterData)
+ .map(data -> ((GT_Cover_Metrics_Transmitter.MetricsTransmitterData) data).getFrequency());
+ }
+ return Stream.empty();
+ }
+
+ /**
+ * Data transmitted by a Metrics Transmitter cover.
+ * <p>
+ * Since only negative states ({@link State#HOST_DECONSTRUCTED HOST_DECONSTRUCTED} and
+ * {@link State#SELF_DESTRUCTED SELF DESTRUCTED}) are persisted, additional fields can be added to this data with
+ * little consequence. Ensure that any new fields are nullable, and make any getter for these fields return an
+ * {@link Optional}.
+ */
+ public static class Data {
+
+ @NotNull
+ private final State state;
+ @Nullable
+ private final List<String> payload;
+ @Nullable
+ private final Coordinates coordinates;
+
+ public Data(@NotNull State state) {
+ this.state = state;
+ this.payload = null;
+ this.coordinates = null;
+ }
+
+ public Data(@NotNull State state, @Nullable List<String> payload) {
+ this.state = state;
+ this.payload = payload;
+ this.coordinates = null;
+ }
+
+ public Data(@NotNull State state, @Nullable List<String> payload, @Nullable Coordinates coordinates) {
+ this.state = state;
+ this.payload = payload;
+ this.coordinates = coordinates;
+
+ }
+
+ /**
+ * Retrieves the payload for this data. Only present if the frequency is in an
+ * {@link State#OPERATIONAL operational} state. Will be cleared if the frequency goes into a
+ * {@link State#HOST_DECONSTRUCTED host-deconstructed} or {@link State#SELF_DESTRUCTED self-destructed} state.
+ *
+ * @return The data if present, or an empty Optional otherwise.
+ */
+ @NotNull
+ public Optional<List<String>> getPayload() {
+ return Optional.ofNullable(payload);
+ }
+
+ /**
+ * Gets the state of the frequency.
+ *
+ * @return The state
+ */
+ @NotNull
+ public State getState() {
+ return state;
+ }
+
+ /**
+ * Gets the last known coordinates for the machine broadcasting metrics. Will only be present in an
+ * {@link State#OPERATIONAL operational} state.
+ *
+ * @return The coordinates
+ */
+ @NotNull
+ public Optional<Coordinates> getCoordinates() {
+ return Optional.ofNullable(coordinates);
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ final Data data = (Data) o;
+ return state == data.state && Objects.equals(payload, data.payload)
+ && Objects.equals(coordinates, data.coordinates);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(state, payload, coordinates);
+ }
+ }
+
+ @SuppressWarnings("ClassCanBeRecord")
+ public static class Coordinates {
+
+ private final String dimension;
+ private final int x;
+ private final int y;
+ private final int z;
+
+ public Coordinates(final String dimension, final int x, final int y, final int z) {
+ this.dimension = dimension;
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public int getX() {
+ return x;
+ }
+
+ public int getY() {
+ return y;
+ }
+
+ public int getZ() {
+ return z;
+ }
+
+ public String getDimension() {
+ return dimension;
+ }
+
+ public String getLocalizedCoordinates() {
+ return StatCollector.translateToLocalFormatted(
+ "gt.db.metrics_cover.coords",
+ GT_Utility.formatNumbers(x),
+ GT_Utility.formatNumbers(y),
+ GT_Utility.formatNumbers(z));
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ final Coordinates that = (Coordinates) o;
+ return x == that.x && y == that.y && z == that.z && Objects.equals(dimension, that.dimension);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(dimension, x, y, z);
+ }
+ }
+
+ public enum State {
+ // NOTE: type cannot be 0, as NuclearControl returns a 0 when querying for an integer from an item stack's NBT
+ // data when it really means null.
+
+ /** The machine is online and broadcasting metrics. */
+ OPERATIONAL(1),
+ /**
+ * The machine was picked up, but the cover is still attached. Will transition to operational state if the
+ * machine is placed back down and started up again.
+ */
+ HOST_DECONSTRUCTED(2),
+ /**
+ * Cover was removed from its host machine, or machine was destroyed (in the limited number of ways we can
+ * detect.) Any frequency in this state will no longer get updates nor leave this state.
+ */
+ SELF_DESTRUCTED(3);
+
+ private static final Map<Integer, State> VALID_TYPE_INTEGERS = Arrays.stream(State.values())
+ .collect(Collectors.toMap(State::getType, Function.identity()));
+ private final int type;
+
+ State(final int type) {
+ if (type <= 0) {
+ throw new IllegalArgumentException("A state must have a positive, nonzero type parameter.");
+ }
+ this.type = type;
+ }
+
+ @NotNull
+ public static Optional<State> find(int candidate) {
+ return Optional.ofNullable(VALID_TYPE_INTEGERS.get(candidate));
+ }
+
+ public int getType() {
+ return type;
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/misc/GlobalVariableStorage.java b/src/main/java/gregtech/common/misc/GlobalVariableStorage.java
new file mode 100644
index 0000000000..27aad0a11f
--- /dev/null
+++ b/src/main/java/gregtech/common/misc/GlobalVariableStorage.java
@@ -0,0 +1,15 @@
+package gregtech.common.misc;
+
+import java.math.BigInteger;
+import java.util.HashMap;
+import java.util.UUID;
+
+public abstract class GlobalVariableStorage {
+ // --------------------- NEVER access these maps! Use the methods provided! ---------------------
+
+ // Global EU map.
+ public static HashMap<UUID, BigInteger> GlobalEnergy = new HashMap<>(100, 0.9f);
+
+ // ----------------------------------------------------------------------------------------------
+
+}
diff --git a/src/main/java/gregtech/common/misc/WirelessNetworkManager.java b/src/main/java/gregtech/common/misc/WirelessNetworkManager.java
new file mode 100644
index 0000000000..17107b4e50
--- /dev/null
+++ b/src/main/java/gregtech/common/misc/WirelessNetworkManager.java
@@ -0,0 +1,93 @@
+package gregtech.common.misc;
+
+import static gregtech.common.misc.GlobalVariableStorage.GlobalEnergy;
+
+import java.math.BigInteger;
+import java.util.UUID;
+
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.common.misc.spaceprojects.SpaceProjectManager;
+
+public class WirelessNetworkManager {
+
+ private WirelessNetworkManager() {}
+
+ public static void strongCheckOrAddUser(UUID user_uuid) {
+ SpaceProjectManager.checkOrCreateTeam(user_uuid);
+ if (!GlobalEnergy.containsKey(user_uuid)) {
+ GlobalEnergy.put(SpaceProjectManager.getLeader(user_uuid), BigInteger.ZERO);
+ }
+ }
+
+ // ------------------------------------------------------------------------------------
+ // Add EU to the users global energy. You can enter a negative number to subtract it.
+ // If the value goes below 0 it will return false and not perform the operation.
+ // BigIntegers have much slower operations than longs/ints. You should call these methods
+ // as infrequently as possible and bulk store values to add to the global map.
+ public static boolean addEUToGlobalEnergyMap(UUID user_uuid, BigInteger EU) {
+ // Mark the data as dirty and in need of saving.
+ try {
+ GlobalEnergyWorldSavedData.INSTANCE.markDirty();
+ } catch (Exception exception) {
+ System.out.println("COULD NOT MARK GLOBAL ENERGY AS DIRTY IN ADD EU");
+ exception.printStackTrace();
+ }
+
+ // Get the team UUID. Users are by default in a team with a UUID equal to their player UUID.
+ UUID teamUUID = SpaceProjectManager.getLeader(user_uuid);
+
+ // Get the teams total energy stored. If they are not in the map, return 0 EU.
+ BigInteger totalEU = GlobalEnergy.getOrDefault(teamUUID, BigInteger.ZERO);
+ totalEU = totalEU.add(EU);
+
+ // If there is sufficient EU then complete the operation and return true.
+ if (totalEU.signum() >= 0) {
+ GlobalEnergy.put(teamUUID, totalEU);
+ return true;
+ }
+
+ // There is insufficient EU so cancel the operation and return false.
+ return false;
+ }
+
+ public static boolean addEUToGlobalEnergyMap(UUID user_uuid, long EU) {
+ return addEUToGlobalEnergyMap(user_uuid, BigInteger.valueOf(EU));
+ }
+
+ public static boolean addEUToGlobalEnergyMap(UUID user_uuid, int EU) {
+ return addEUToGlobalEnergyMap(user_uuid, BigInteger.valueOf(EU));
+ }
+
+ // ------------------------------------------------------------------------------------
+
+ public static BigInteger getUserEU(UUID user_uuid) {
+ return GlobalEnergy.getOrDefault(SpaceProjectManager.getLeader(user_uuid), BigInteger.ZERO);
+ }
+
+ // This overwrites the EU in the network. Only use this if you are absolutely sure you know what you are doing.
+ public static void setUserEU(UUID user_uuid, BigInteger EU) {
+ // Mark the data as dirty and in need of saving.
+ try {
+ GlobalEnergyWorldSavedData.INSTANCE.markDirty();
+ } catch (Exception exception) {
+ System.out.println("COULD NOT MARK GLOBAL ENERGY AS DIRTY IN SET EU");
+ exception.printStackTrace();
+ }
+
+ GlobalEnergy.put(SpaceProjectManager.getLeader(user_uuid), EU);
+ }
+
+ public static void clearGlobalEnergyInformationMaps() {
+ // Do not use this unless you are 100% certain you know what you are doing.
+ GlobalEnergy.clear();
+ }
+
+ public static UUID processInitialSettings(final IGregTechTileEntity machine) {
+
+ // UUID and username of the owner.
+ final UUID UUID = machine.getOwnerUuid();
+
+ SpaceProjectManager.checkOrCreateTeam(UUID);
+ return UUID;
+ }
+}
diff --git a/src/main/java/gregtech/common/misc/spaceprojects/SpaceProjectManager.java b/src/main/java/gregtech/common/misc/spaceprojects/SpaceProjectManager.java
new file mode 100644
index 0000000000..323b22e20a
--- /dev/null
+++ b/src/main/java/gregtech/common/misc/spaceprojects/SpaceProjectManager.java
@@ -0,0 +1,309 @@
+package gregtech.common.misc.spaceprojects;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.server.MinecraftServer;
+import net.minecraftforge.fluids.FluidStack;
+
+import org.apache.commons.lang3.tuple.Pair;
+
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.util.GT_Recipe;
+import gregtech.common.misc.spaceprojects.interfaces.ISpaceBody;
+import gregtech.common.misc.spaceprojects.interfaces.ISpaceProject;
+
+/**
+ * @author BlueWeabo
+ */
+public class SpaceProjectManager {
+
+ /**
+ * Do not use! Only meant to be used in SpaceProjectWorldSavedData.java
+ */
+ public static Map<UUID, Map<Pair<ISpaceBody, String>, ISpaceProject>> spaceTeamProjects = new HashMap<>();
+ /**
+ * Do not use! Only meant to be used in SpaceProjectWorldSavedData.java Stores a Players UUID to the Leader UUID,
+ * players in lone groups give back their own UUID.
+ */
+ public static Map<UUID, UUID> spaceTeams = new HashMap<>();
+
+ /**
+ * Stores all the locations to a hash map to be accessed easier instead of through an enum
+ */
+ private static final HashMap<String, ISpaceBody> spaceLocations = new HashMap<>();
+
+ /**
+ * Stores all projects that have been made. Only adds them to this map if {@link #addProject(ISpaceProject)} has
+ * been used
+ */
+ private static final Map<String, ISpaceProject> spaceProjects = new HashMap<>();
+
+ // #region Space Project Team Helper methods
+
+ /**
+ * Used to get a specific project of the team dependent on the location and the project's name
+ */
+ public static ISpaceProject getTeamProject(UUID member, ISpaceBody location, String projectName) {
+ Map<Pair<ISpaceBody, String>, ISpaceProject> map = spaceTeamProjects.get(getLeader(member));
+ if (map == null) {
+ return null;
+ }
+ return map.get(Pair.of(location, projectName));
+ }
+
+ /**
+ * Makes a new Map for the teams if they don't have one. Adds a project to the team's project map.
+ *
+ * @param member Member of the team.
+ * @param location The location of where the project will belong to.
+ * @param projectName The name of the project being added.
+ * @param project Project which will be added to the team.
+ * @return Returns true when a project was added to the map of the player. Returns false otherwise.
+ */
+ public static boolean addTeamProject(UUID member, ISpaceBody location, String projectName, ISpaceProject project) {
+ if (!spaceTeamProjects.containsKey(getLeader(member)) || spaceTeamProjects.get(getLeader(member)) == null) {
+ spaceTeamProjects.put(getLeader(member), new HashMap<>());
+ }
+
+ Map<Pair<ISpaceBody, String>, ISpaceProject> map = spaceTeamProjects.get(getLeader(member));
+ if (map.containsKey(Pair.of(location, projectName))) {
+ return false;
+ }
+
+ project.setProjectLocation(location);
+ map.put(Pair.of(location, projectName), project);
+ if (SpaceProjectWorldSavedData.INSTANCE != null) {
+ SpaceProjectWorldSavedData.INSTANCE.markDirty();
+ }
+ return true;
+ }
+
+ /**
+ * Check whether a team has a project or not
+ *
+ * @param member Member of the team
+ * @param project The project, which you are checking for. This only compares the internal names of the project.
+ * @return True if the team has said project, false otherwise
+ */
+ public static boolean teamHasProject(UUID member, ISpaceProject project) {
+ Map<Pair<ISpaceBody, String>, ISpaceProject> map = spaceTeamProjects.get(getLeader(member));
+ if (map == null) {
+ return false;
+ }
+
+ return map.containsValue(project);
+ }
+
+ /**
+ * Used to handle when 2 players want to join together in a team. Player A can join player B's team. If player C
+ * gets an invite from A, C will join player B's team.
+ *
+ * @param teamMember Member which is joining the teamLeader
+ * @param teamLeader Leader of the party
+ */
+ public static void putInTeam(UUID teamMember, UUID teamLeader) {
+ if (teamMember.equals(teamLeader)) {
+ spaceTeams.put(teamMember, teamLeader);
+ } else if (!spaceTeams.get(teamLeader)
+ .equals(teamLeader)) {
+ putInTeam(teamMember, spaceTeams.get(teamLeader));
+ } else {
+ spaceTeams.put(teamMember, teamLeader);
+ }
+
+ if (SpaceProjectWorldSavedData.INSTANCE != null) {
+ SpaceProjectWorldSavedData.INSTANCE.markDirty();
+ }
+ }
+
+ /**
+ * Used to give back the UUID of the team leader.
+ *
+ * @return The UUID of the team leader.
+ */
+ public static UUID getLeader(UUID teamMember) {
+ checkOrCreateTeam(teamMember);
+ return spaceTeams.get(teamMember);
+ }
+
+ /**
+ * Used the multiblocks to check whether a given player has a team or not. If they don't have a team create one
+ * where they are their own leader.
+ *
+ * @param teamMember Member to check for.
+ */
+ public static void checkOrCreateTeam(UUID teamMember) {
+ if (spaceTeams.containsKey(teamMember)) {
+ return;
+ }
+
+ spaceTeams.put(teamMember, teamMember);
+ if (SpaceProjectWorldSavedData.INSTANCE != null) {
+ SpaceProjectWorldSavedData.INSTANCE.markDirty();
+ }
+ }
+
+ public static boolean isInTeam(UUID member) {
+ return spaceTeams.containsKey(member);
+ }
+
+ /**
+ * Will give back all the projects a team has made or is making.
+ *
+ * @param member UUID of the team member, used to find the leader of the team.
+ * @return All the projects a team has.
+ */
+ public static Collection<ISpaceProject> getTeamSpaceProjects(UUID member) {
+ Map<Pair<ISpaceBody, String>, ISpaceProject> map = spaceTeamProjects.get(getLeader(member));
+ if (map == null) {
+ return null;
+ }
+
+ return map.values();
+ }
+
+ /**
+ * Getting the project of a Team or a new copy.
+ *
+ * @param member UUID of the team member, which is used to find the team leader.
+ * @param projectName The name of the project, which needs to be found.
+ * @param location The location at which the project is found at.
+ * @return the project that the team has or a copy of a project.
+ */
+ public static ISpaceProject getTeamProjectOrCopy(UUID member, String projectName, ISpaceBody location) {
+ Map<Pair<ISpaceBody, String>, ISpaceProject> map = spaceTeamProjects.get(getLeader(member));
+ if (map == null) {
+ return getProject(projectName);
+ }
+
+ return map.getOrDefault(Pair.of(location, projectName), getProject(projectName));
+ }
+
+ // #endregion
+
+ // #region Project Helper methods
+
+ public static class FakeSpaceProjectRecipe extends GT_Recipe {
+
+ public final String projectName;
+
+ public FakeSpaceProjectRecipe(boolean aOptimize, ItemStack[] aInputs, FluidStack[] aFluidInputs, int aDuration,
+ int aEUt, int aSpecialValue, String projectName) {
+ super(aOptimize, aInputs, null, null, null, aFluidInputs, null, aDuration, aEUt, aSpecialValue);
+ this.projectName = projectName;
+ }
+ }
+
+ /**
+ * Used to add projects to the internal map.
+ *
+ * @param project Newly created project.
+ */
+ public static void addProject(ISpaceProject project) {
+ spaceProjects.put(project.getProjectName(), project);
+ RecipeMaps.spaceProjectFakeRecipes.add(
+ new FakeSpaceProjectRecipe(
+ false,
+ project.getTotalItemsCost(),
+ project.getTotalFluidsCost(),
+ project.getProjectBuildTime(),
+ (int) project.getProjectVoltage(),
+ project.getTotalStages(),
+ project.getProjectName()));
+ }
+
+ /**
+ * @param projectName Internal name of the project.
+ * @return a copy of the stored project.
+ */
+ public static ISpaceProject getProject(String projectName) {
+ ISpaceProject tProject = spaceProjects.get(projectName);
+ return tProject != null ? tProject.copy() : null;
+ }
+
+ /**
+ * Should only be used for GUIs!
+ *
+ * @return The Map that the projects are stored at.
+ */
+ public static Map<String, ISpaceProject> getProjectsMap() {
+ return spaceProjects;
+ }
+
+ /**
+ * Should only be used for GUIs!
+ *
+ * @return A Collection of all the projects contained in the map.
+ */
+ public static Collection<ISpaceProject> getAllProjects() {
+ return spaceProjects.values();
+ }
+
+ // #endregion
+
+ // #region Location Helper methods
+
+ /**
+ * Adds a location to the internal map. For it to be used later
+ *
+ * @param location to add to the internal map
+ */
+ public static void addLocation(ISpaceBody location) {
+ spaceLocations.put(location.getName(), location);
+ }
+
+ /**
+ *
+ * @return a Collection of all locations, which have been registered.
+ */
+ public static Collection<ISpaceBody> getLocations() {
+ return spaceLocations.values();
+ }
+
+ /**
+ *
+ * @return a Collection fo all location names, which have been registered
+ */
+ public static Collection<String> getLocationNames() {
+ return spaceLocations.keySet();
+ }
+
+ /**
+ *
+ * @param locationName Name used to search for the location
+ * @return The location, which has been registered with said name
+ */
+ public static ISpaceBody getLocation(String locationName) {
+ return spaceLocations.get(locationName);
+ }
+
+ // #endregion
+
+ // #region General Helper methods
+
+ /**
+ * Gets the UUID using the player's username
+ */
+ public static UUID getPlayerUUIDFromName(String playerName) {
+ return MinecraftServer.getServer()
+ .func_152358_ax()
+ .func_152655_a(playerName)
+ .getId();
+ }
+
+ /**
+ * Gets the player's name using their UUID
+ */
+ public static String getPlayerNameFromUUID(UUID playerUUID) {
+ return MinecraftServer.getServer()
+ .func_152358_ax()
+ .func_152652_a(playerUUID)
+ .getName();
+ }
+
+ // #endregion
+}
diff --git a/src/main/java/gregtech/common/misc/spaceprojects/SpaceProjectWorldSavedData.java b/src/main/java/gregtech/common/misc/spaceprojects/SpaceProjectWorldSavedData.java
new file mode 100644
index 0000000000..12f0005aea
--- /dev/null
+++ b/src/main/java/gregtech/common/misc/spaceprojects/SpaceProjectWorldSavedData.java
@@ -0,0 +1,343 @@
+package gregtech.common.misc.spaceprojects;
+
+import static gregtech.common.misc.spaceprojects.SpaceProjectManager.spaceTeamProjects;
+import static gregtech.common.misc.spaceprojects.SpaceProjectManager.spaceTeams;
+import static gregtech.common.misc.spaceprojects.enums.JsonVariables.MAP_MAP;
+import static gregtech.common.misc.spaceprojects.enums.JsonVariables.MAP_PAIR;
+import static gregtech.common.misc.spaceprojects.enums.JsonVariables.MAP_PROJECT;
+import static gregtech.common.misc.spaceprojects.enums.JsonVariables.MAP_UUID;
+import static gregtech.common.misc.spaceprojects.enums.JsonVariables.PAIR_LEFT;
+import static gregtech.common.misc.spaceprojects.enums.JsonVariables.PAIR_RIGHT;
+import static gregtech.common.misc.spaceprojects.enums.JsonVariables.PROJECT_CURRENT_STAGE;
+import static gregtech.common.misc.spaceprojects.enums.JsonVariables.PROJECT_CURRENT_UPGRADE;
+import static gregtech.common.misc.spaceprojects.enums.JsonVariables.PROJECT_LOCATION;
+import static gregtech.common.misc.spaceprojects.enums.JsonVariables.PROJECT_NAME;
+import static gregtech.common.misc.spaceprojects.enums.JsonVariables.PROJECT_UPGRADES_BUILT;
+import static gregtech.common.misc.spaceprojects.enums.JsonVariables.UPGRADE_CURRENT_STAGE;
+import static gregtech.common.misc.spaceprojects.enums.JsonVariables.UPGRADE_NAME;
+import static gregtech.common.misc.spaceprojects.enums.JsonVariables.UPGRADE_PROJECT_PARENT;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.UUID;
+
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.world.World;
+import net.minecraft.world.WorldSavedData;
+import net.minecraft.world.storage.MapStorage;
+import net.minecraftforge.event.world.WorldEvent;
+
+import org.apache.commons.lang3.tuple.Pair;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonWriter;
+
+import cpw.mods.fml.common.eventhandler.SubscribeEvent;
+import gregtech.common.misc.spaceprojects.enums.SolarSystem;
+import gregtech.common.misc.spaceprojects.interfaces.ISpaceBody;
+import gregtech.common.misc.spaceprojects.interfaces.ISpaceProject;
+import gregtech.common.misc.spaceprojects.interfaces.ISpaceProject.ISP_Upgrade;
+
+/**
+ * This class is used so that I can write and read to a json file before the world is opened. On server starting is too
+ * late for this as the data stored in the files is needed before entities load their nbt data
+ *
+ * @author BlueWeabo
+ */
+public class SpaceProjectWorldSavedData extends WorldSavedData {
+
+ public static SpaceProjectWorldSavedData INSTANCE;
+
+ private static final Gson GSON_SPACE_PROJECT = new GsonBuilder().serializeNulls()
+ .enableComplexMapKeySerialization()
+ .registerTypeAdapter(spaceTeamProjects.getClass(), new SpaceTeamProjectsMapAdapter())
+ .registerTypeAdapter(Map.class, new SpaceTeamProjectsMapAdapter())
+ .registerTypeAdapter(
+ Pair.of((ISpaceBody) SolarSystem.Ariel, "")
+ .getClass(),
+ new PairAdapter())
+ .registerTypeAdapter(Pair.class, new PairAdapter())
+ .registerTypeAdapter(ISpaceProject.class, new SpaceProjectAdapter())
+ .registerTypeAdapter(ISP_Upgrade.class, new SP_UpgradeAdapter())
+ .registerTypeHierarchyAdapter(ISpaceProject.class, new SpaceProjectAdapter())
+ .registerTypeHierarchyAdapter(ISP_Upgrade.class, new SP_UpgradeAdapter())
+ .create();
+ private static final Gson GSON_TEAMS = new GsonBuilder().serializeNulls()
+ .create();
+
+ private static final String DATA_NAME = "GT_SpaceProjectData";
+
+ private static final String SPACE_TEAM_PROJECTS_JSON = "spaceTeamProject.json";
+
+ private static final String SPACE_TEAMS_JSON = "spaceTeams.json";
+
+ private static File spaceTeamsFile;
+ private static File teamProjectsFile;
+
+ public SpaceProjectWorldSavedData() {
+ super(DATA_NAME);
+ }
+
+ public SpaceProjectWorldSavedData(String aData) {
+ super(aData);
+ }
+
+ @Override
+ public void readFromNBT(NBTTagCompound aNBT) {
+ try (JsonReader reader = new JsonReader(new FileReader(teamProjectsFile))) {
+ spaceTeamProjects = GSON_SPACE_PROJECT.fromJson(reader, spaceTeamProjects.getClass());
+ } catch (Exception e) {
+ System.out.print("FAILED TO LOAD: " + SPACE_TEAM_PROJECTS_JSON);
+ e.printStackTrace();
+ }
+
+ try (JsonReader reader = new JsonReader(new FileReader(spaceTeamsFile))) {
+ HashMap<UUID, UUID> jsonMap = GSON_TEAMS.fromJson(reader, spaceTeams.getClass());
+ for (UUID member : jsonMap.keySet()) {
+ spaceTeams.put(member, jsonMap.get(member));
+ }
+ } catch (Exception e) {
+ System.out.print("FAILED TO LOAD: " + SPACE_TEAMS_JSON);
+ e.printStackTrace();
+ }
+
+ if (spaceTeamProjects == null) {
+ spaceTeamProjects = new HashMap<>();
+ }
+
+ if (spaceTeams == null) {
+ spaceTeams = new HashMap<>();
+ }
+ }
+
+ @Override
+ public void writeToNBT(NBTTagCompound aNBT) {
+ if (spaceTeamProjects != null) {
+ try (JsonWriter writer = new JsonWriter(new FileWriter(teamProjectsFile))) {
+ GSON_SPACE_PROJECT.toJson(spaceTeamProjects, spaceTeamProjects.getClass(), writer);
+ } catch (Exception ex) {
+ System.out.print("FAILED TO SAVE: " + SPACE_TEAM_PROJECTS_JSON);
+ ex.printStackTrace();
+ }
+ }
+
+ if (spaceTeams != null) {
+ try (JsonWriter writer = new JsonWriter(new FileWriter(spaceTeamsFile))) {
+ GSON_TEAMS.toJson(spaceTeams, spaceTeams.getClass(), writer);
+ } catch (Exception ex) {
+ System.out.print("FAILED TO SAVE: " + SPACE_TEAMS_JSON);
+ ex.printStackTrace();
+ }
+ }
+ }
+
+ private static void loadInstance(World aWorld) {
+ if (spaceTeamProjects != null) {
+ spaceTeamProjects.clear();
+ } else {
+ spaceTeamProjects = new HashMap<>();
+ }
+ if (spaceTeams != null) {
+ spaceTeams.clear();
+ } else {
+ spaceTeams = new HashMap<>();
+ }
+ spaceTeamsFile = new File(
+ aWorld.getSaveHandler()
+ .getWorldDirectory(),
+ SPACE_TEAMS_JSON);
+ teamProjectsFile = new File(
+ aWorld.getSaveHandler()
+ .getWorldDirectory(),
+ SPACE_TEAM_PROJECTS_JSON);
+ MapStorage tStorage = aWorld.mapStorage;
+ INSTANCE = (SpaceProjectWorldSavedData) tStorage.loadData(SpaceProjectWorldSavedData.class, DATA_NAME);
+ if (INSTANCE == null) {
+ INSTANCE = new SpaceProjectWorldSavedData();
+ tStorage.setData(DATA_NAME, INSTANCE);
+ }
+ INSTANCE.markDirty();
+ }
+
+ @SubscribeEvent
+ public void onWorldLoad(WorldEvent.Load aEvent) {
+ if (!aEvent.world.isRemote && aEvent.world.provider.dimensionId == 0) {
+ loadInstance(aEvent.world);
+ }
+ }
+
+ private static class PairAdapter
+ implements JsonSerializer<Pair<ISpaceBody, String>>, JsonDeserializer<Pair<ISpaceBody, String>> {
+
+ @Override
+ public JsonElement serialize(Pair<ISpaceBody, String> src, Type typeOfSrc, JsonSerializationContext context) {
+ JsonObject pair = new JsonObject();
+ pair.addProperty(
+ PAIR_LEFT,
+ src.getLeft()
+ .getName());
+ pair.addProperty(PAIR_RIGHT, src.getRight());
+ return pair;
+ }
+
+ @Override
+ public Pair<ISpaceBody, String> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
+ throws JsonParseException {
+ Pair<ISpaceBody, String> pair = null;
+ if (json.isJsonObject()) {
+ JsonObject obj = json.getAsJsonObject();
+ pair = Pair.of(
+ SpaceProjectManager.getLocation(
+ obj.get(PAIR_LEFT)
+ .getAsString()),
+ obj.get(PAIR_RIGHT)
+ .getAsString());
+ }
+ return pair;
+ }
+ }
+
+ private static class SpaceProjectAdapter implements JsonSerializer<ISpaceProject>, JsonDeserializer<ISpaceProject> {
+
+ @Override
+ public JsonElement serialize(ISpaceProject src, Type typeOfSrc, JsonSerializationContext context) {
+ JsonObject obj = new JsonObject();
+ obj.addProperty(PROJECT_NAME, src.getProjectName());
+ obj.addProperty(PROJECT_CURRENT_STAGE, src.getCurrentStage());
+ obj.addProperty(
+ PROJECT_LOCATION,
+ src.getProjectLocation()
+ .getName());
+ obj.add(PROJECT_CURRENT_UPGRADE, context.serialize(src.getUpgradeBeingBuilt()));
+ obj.add(PROJECT_UPGRADES_BUILT, context.serialize(src.getAllBuiltUpgrades()));
+ return obj;
+ }
+
+ @Override
+ public ISpaceProject deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
+ throws JsonParseException {
+ if (!json.isJsonObject()) {
+ return null;
+ }
+ JsonObject obj = json.getAsJsonObject();
+ String projectName = obj.get(PROJECT_NAME)
+ .getAsString();
+ ISpaceProject project = SpaceProjectManager.getProject(projectName);
+ int projectCurrentStage = obj.get(PROJECT_CURRENT_STAGE)
+ .getAsInt();
+ ISP_Upgrade[] projectUpgradesBuilt = new ISP_Upgrade[0];
+ projectUpgradesBuilt = context
+ .deserialize(obj.get(PROJECT_UPGRADES_BUILT), projectUpgradesBuilt.getClass());
+ ISP_Upgrade projectCurrentUpgrade = context
+ .deserialize(obj.get(PROJECT_CURRENT_UPGRADE), ISP_Upgrade.class);
+ ISpaceBody projectLocation = SpaceProjectManager.getLocation(
+ obj.get(PROJECT_LOCATION)
+ .getAsString());
+ project.setBuiltUpgrade(projectUpgradesBuilt);
+ project.setProjectLocation(projectLocation);
+ project.setProjectCurrentStage(projectCurrentStage);
+ project.setCurrentUpgradeBeingBuilt(projectCurrentUpgrade);
+ return project;
+ }
+ }
+
+ private static class SP_UpgradeAdapter implements JsonSerializer<ISP_Upgrade>, JsonDeserializer<ISP_Upgrade> {
+
+ @Override
+ public JsonElement serialize(ISP_Upgrade src, Type typeOfSrc, JsonSerializationContext context) {
+ JsonObject obj = new JsonObject();
+ obj.addProperty(UPGRADE_NAME, src.getUpgradeName());
+ obj.addProperty(
+ UPGRADE_PROJECT_PARENT,
+ src.getParentProject()
+ .getProjectName());
+ obj.addProperty(UPGRADE_CURRENT_STAGE, src.getCurrentStage());
+ return obj;
+ }
+
+ @Override
+ public ISP_Upgrade deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
+ throws JsonParseException {
+ if (!json.isJsonObject()) {
+ return null;
+ }
+ JsonObject obj = json.getAsJsonObject();
+ String projectName = obj.get(UPGRADE_PROJECT_PARENT)
+ .getAsString();
+ ISpaceProject project = SpaceProjectManager.getProject(projectName);
+ ISP_Upgrade upgrade = project.getUpgrade(
+ obj.get(UPGRADE_NAME)
+ .getAsString());
+ if (upgrade == null) {
+ return null;
+ }
+ upgrade = upgrade.copy();
+ upgrade.setUpgradeCurrentStage(
+ obj.get(UPGRADE_CURRENT_STAGE)
+ .getAsInt());
+ return upgrade;
+ }
+ }
+
+ private static class SpaceTeamProjectsMapAdapter
+ implements JsonSerializer<Map<UUID, Map<Pair<ISpaceBody, String>, ISpaceProject>>>,
+ JsonDeserializer<Map<UUID, Map<Pair<ISpaceBody, String>, ISpaceProject>>> {
+
+ @Override
+ public JsonElement serialize(Map<UUID, Map<Pair<ISpaceBody, String>, ISpaceProject>> src, Type typeOfSrc,
+ JsonSerializationContext context) {
+ JsonArray map = new JsonArray();
+ for (Entry<UUID, Map<Pair<ISpaceBody, String>, ISpaceProject>> firstEntry : src.entrySet()) {
+ JsonObject teamMap = new JsonObject();
+ teamMap.add(MAP_UUID, context.serialize(firstEntry.getKey()));
+ JsonArray teamProjectMap = new JsonArray();
+ for (Entry<Pair<ISpaceBody, String>, ISpaceProject> secondEntry : firstEntry.getValue()
+ .entrySet()) {
+ JsonObject projectMap = new JsonObject();
+ projectMap.add(MAP_PAIR, context.serialize(secondEntry.getKey()));
+ projectMap.add(MAP_PROJECT, context.serialize(secondEntry.getValue()));
+ teamProjectMap.add(projectMap);
+ }
+ teamMap.add(MAP_MAP, teamProjectMap);
+ map.add(teamMap);
+ }
+ return map;
+ }
+
+ @Override
+ public Map<UUID, Map<Pair<ISpaceBody, String>, ISpaceProject>> deserialize(JsonElement json, Type typeOfT,
+ JsonDeserializationContext context) throws JsonParseException {
+ JsonArray mapArray = json.getAsJsonArray();
+ Map<UUID, Map<Pair<ISpaceBody, String>, ISpaceProject>> map = new HashMap<>();
+ for (JsonElement teamMapElement : mapArray) {
+ JsonObject teamMap = teamMapElement.getAsJsonObject();
+ UUID uuid = context.deserialize(teamMap.get(MAP_UUID), UUID.class);
+ Map<Pair<ISpaceBody, String>, ISpaceProject> projectMap = new HashMap<>();
+ for (JsonElement teamProjectMapElement : teamMap.get(MAP_MAP)
+ .getAsJsonArray()) {
+ JsonObject teamProjectMap = teamProjectMapElement.getAsJsonObject();
+ Pair<ISpaceBody, String> pair = context.deserialize(teamProjectMap.get(MAP_PAIR), Pair.class);
+ ISpaceProject project = context.deserialize(teamProjectMap.get(MAP_PROJECT), ISpaceProject.class);
+ projectMap.put(pair, project);
+ }
+ map.put(uuid, projectMap);
+ }
+ return map;
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/misc/spaceprojects/base/SP_Requirements.java b/src/main/java/gregtech/common/misc/spaceprojects/base/SP_Requirements.java
new file mode 100644
index 0000000000..b910b5e344
--- /dev/null
+++ b/src/main/java/gregtech/common/misc/spaceprojects/base/SP_Requirements.java
@@ -0,0 +1,74 @@
+package gregtech.common.misc.spaceprojects.base;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import gregtech.common.misc.spaceprojects.enums.SpaceBodyType;
+import gregtech.common.misc.spaceprojects.enums.StarType;
+import gregtech.common.misc.spaceprojects.interfaces.ISpaceProject;
+import gregtech.common.misc.spaceprojects.interfaces.ISpaceProject.ISP_Requirements;
+import gregtech.common.misc.spaceprojects.interfaces.ISpaceProject.ISP_Upgrade;
+
+/**
+ * @author BlueWeabo
+ */
+public class SP_Requirements implements ISP_Requirements {
+
+ // #region Variables
+
+ protected SpaceBodyType spaceBody = SpaceBodyType.NONE;
+ protected StarType star = StarType.NotAStar;
+ protected List<ISpaceProject> spaceProjects = new ArrayList<>();
+ protected List<ISP_Upgrade> upgrades = new ArrayList<>();
+
+ // #endregion
+
+ // #region Getters
+
+ @Override
+ public SpaceBodyType getBodyType() {
+ return spaceBody;
+ }
+
+ @Override
+ public StarType getStarType() {
+ return star;
+ }
+
+ @Override
+ public List<ISpaceProject> getProjects() {
+ return spaceProjects;
+ }
+
+ @Override
+ public List<ISP_Upgrade> getUpgrades() {
+ return upgrades;
+ }
+
+ // #endregion
+
+ // #region Setters/Builder
+
+ public SP_Requirements setSpaceBodyType(SpaceBodyType spaceBodyType) {
+ spaceBody = spaceBodyType;
+ return this;
+ }
+
+ public SP_Requirements setStarType(StarType starType) {
+ star = starType;
+ return this;
+ }
+
+ public SP_Requirements setUpgrades(ISP_Upgrade... requirementUpgrades) {
+ upgrades.addAll(Arrays.asList(requirementUpgrades));
+ return this;
+ }
+
+ public SP_Requirements setSpaceProjects(ISpaceProject... requirementProjects) {
+ spaceProjects.addAll(Arrays.asList(requirementProjects));
+ return this;
+ }
+
+ // #endregion
+}
diff --git a/src/main/java/gregtech/common/misc/spaceprojects/base/SP_Upgrade.java b/src/main/java/gregtech/common/misc/spaceprojects/base/SP_Upgrade.java
new file mode 100644
index 0000000000..835a57f277
--- /dev/null
+++ b/src/main/java/gregtech/common/misc/spaceprojects/base/SP_Upgrade.java
@@ -0,0 +1,362 @@
+package gregtech.common.misc.spaceprojects.base;
+
+import java.util.UUID;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.StatCollector;
+import net.minecraftforge.fluids.FluidStack;
+
+import gregtech.common.misc.spaceprojects.SpaceProjectManager;
+import gregtech.common.misc.spaceprojects.enums.SpaceBodyType;
+import gregtech.common.misc.spaceprojects.enums.UpgradeStatus;
+import gregtech.common.misc.spaceprojects.interfaces.ISpaceProject;
+import gregtech.common.misc.spaceprojects.interfaces.ISpaceProject.ISP_Upgrade;
+
+/**
+ * @author BlueWeabo
+ */
+public class SP_Upgrade implements ISP_Upgrade {
+
+ // #region Variables
+
+ protected String name;
+ protected String unlocalizedName;
+ protected ItemStack[] itemsCost;
+ protected FluidStack[] fluidsCost;
+ protected int totalStages;
+ protected int currentStage;
+ protected int buildTime;
+ protected long voltage;
+ protected SP_Requirements requirements;
+ protected ISpaceProject projectBelongingTo;
+
+ // #endregion
+
+ // #region Getters
+
+ @Override
+ public String getUpgradeName() {
+ return name;
+ }
+
+ @Override
+ public String getUnlocalizedName() {
+ return unlocalizedName;
+ }
+
+ @Override
+ public String getLocalizedName() {
+ return StatCollector.translateToLocal(unlocalizedName);
+ }
+
+ @Override
+ public ItemStack[] getItemsCostPerStage() {
+ return itemsCost;
+ }
+
+ @Override
+ public ItemStack getItemCostPerStage(int index) {
+ if (itemsCost == null || index < 0 || index >= itemsCost.length) {
+ return null;
+ }
+
+ return itemsCost[index];
+ }
+
+ @Override
+ public ItemStack[] getCurrentItemsProgress() {
+ ItemStack[] currentItemsProgress = new ItemStack[itemsCost.length];
+ int index = 0;
+ for (ItemStack item : itemsCost) {
+ ItemStack copy = item.copy();
+ copy.stackSize *= getCurrentStage();
+ currentItemsProgress[index++] = copy;
+ }
+
+ return currentItemsProgress;
+ }
+
+ @Override
+ public ItemStack getCurrentItemProgress(int index) {
+ if (itemsCost == null || index < 0 || index >= itemsCost.length || itemsCost[index] == null) {
+ return null;
+ }
+
+ ItemStack item = itemsCost[index].copy();
+ item.stackSize *= getCurrentStage();
+ return item;
+ }
+
+ @Override
+ public ItemStack[] getTotalItemsCost() {
+ ItemStack[] totalItemsCost = new ItemStack[itemsCost.length];
+ int index = 0;
+ for (ItemStack item : itemsCost) {
+ ItemStack copy = item.copy();
+ copy.stackSize *= getTotalStages();
+ totalItemsCost[index++] = copy;
+ }
+
+ return totalItemsCost;
+ }
+
+ @Override
+ public ItemStack getTotalItemCost(int index) {
+ if (itemsCost == null || index < 0 || index >= itemsCost.length || itemsCost[index] == null) {
+ return null;
+ }
+
+ ItemStack item = itemsCost[index].copy();
+ item.stackSize *= getTotalStages();
+ return item;
+ }
+
+ @Override
+ public FluidStack[] getFluidsCostPerStage() {
+ return fluidsCost;
+ }
+
+ @Override
+ public FluidStack getFluidCostPerStage(int index) {
+ if (fluidsCost == null || index < 0 || index >= fluidsCost.length) {
+ return null;
+ }
+
+ return fluidsCost[index];
+ }
+
+ @Override
+ public FluidStack[] getCurrentFluidsProgress() {
+ if (fluidsCost == null) {
+ return null;
+ }
+
+ FluidStack[] currentFluidsProgress = new FluidStack[fluidsCost.length];
+ int index = 0;
+ for (FluidStack fluid : fluidsCost) {
+ FluidStack copy = fluid.copy();
+ copy.amount *= getCurrentStage();
+ currentFluidsProgress[index++] = copy;
+ }
+
+ return currentFluidsProgress;
+ }
+
+ @Override
+ public FluidStack getCurrentFluidProgress(int index) {
+ if (fluidsCost == null || index < 0 || index >= fluidsCost.length || fluidsCost[index] == null) {
+ return null;
+ }
+
+ FluidStack fluid = fluidsCost[index].copy();
+ fluid.amount *= getCurrentStage();
+ return fluid;
+ }
+
+ @Override
+ public FluidStack[] getTotalFluidsCost() {
+ if (fluidsCost == null) {
+ return null;
+ }
+
+ FluidStack[] totalFluidsCost = new FluidStack[fluidsCost.length];
+ int index = 0;
+ for (FluidStack fluid : fluidsCost) {
+ FluidStack copy = fluid.copy();
+ copy.amount *= getTotalStages();
+ totalFluidsCost[index++] = copy;
+ }
+
+ return totalFluidsCost;
+ }
+
+ @Override
+ public FluidStack getTotalFluidCost(int index) {
+ if (fluidsCost == null || index < 0 || index >= fluidsCost.length || fluidsCost[index] == null) {
+ return null;
+ }
+
+ FluidStack fluid = fluidsCost[index].copy();
+ fluid.amount *= getTotalStages();
+ return fluid;
+ }
+
+ @Override
+ public int getTotalStages() {
+ return totalStages;
+ }
+
+ @Override
+ public int getUpgradeBuildTime() {
+ return buildTime;
+ }
+
+ @Override
+ public int getCurrentStage() {
+ return currentStage;
+ }
+
+ @Override
+ public float getCurrentProgress() {
+ return currentStage / totalStages * 100.0f;
+ }
+
+ @Override
+ public long getVoltage() {
+ return voltage;
+ }
+
+ @Override
+ public UpgradeStatus getStatus() {
+ if (requirements == null) {
+ return UpgradeStatus.Unlocked;
+ }
+
+ if (isFinished()) {
+ return UpgradeStatus.Finished;
+ }
+ return UpgradeStatus.Locked;
+ }
+
+ @Override
+ public SP_Requirements getUpgradeRequirements() {
+ return requirements;
+ }
+
+ @Override
+ public ISpaceProject getParentProject() {
+ return projectBelongingTo;
+ }
+
+ // #endregion
+
+ // #region Setter/Builder
+
+ public SP_Upgrade() {}
+
+ public SP_Upgrade setUpgradeName(String upgradeName) {
+ name = upgradeName;
+ return this;
+ }
+
+ public SP_Upgrade setUpgradeUnlocalizedName(String upgradeUnlocalizedName) {
+ unlocalizedName = upgradeUnlocalizedName;
+ return this;
+ }
+
+ public SP_Upgrade setUpgradeItemsCost(ItemStack... upgradeItemsCost) {
+ itemsCost = upgradeItemsCost;
+ return this;
+ }
+
+ public SP_Upgrade setUpgradeFluidsCost(FluidStack... upgradeFluidsCost) {
+ fluidsCost = upgradeFluidsCost;
+ return this;
+ }
+
+ public SP_Upgrade setUpgradeRequirements(SP_Requirements upgradeRequirements) {
+ requirements = upgradeRequirements;
+ return this;
+ }
+
+ public SP_Upgrade setUpgradeTotalStages(int upgradeTotalStages) {
+ totalStages = upgradeTotalStages;
+ return this;
+ }
+
+ public SP_Upgrade setUpgradeBuildTime(int upgradeBuildTime) {
+ buildTime = upgradeBuildTime;
+ return this;
+ }
+
+ public SP_Upgrade setUpgradeVoltage(long upgradeVoltage) {
+ voltage = upgradeVoltage;
+ return this;
+ }
+
+ @Override
+ public void setUpgradeProject(ISpaceProject project) {
+ projectBelongingTo = project;
+ }
+
+ @Override
+ public void setUpgradeCurrentStage(int stage) {
+ currentStage = stage;
+ }
+
+ // #endregion
+
+ // #region Other
+
+ @Override
+ public boolean meetsRequirements(UUID aTeam) {
+ if (requirements == null) {
+ return true;
+ }
+
+ if (requirements.getBodyType() != null && !requirements.getBodyType()
+ .equals(SpaceBodyType.NONE)) {
+ if (!requirements.getBodyType()
+ .equals(
+ projectBelongingTo.getProjectLocation()
+ .getType())) {
+ return false;
+ }
+ }
+
+ if (requirements.getStarType() != null) {
+ if (!requirements.getStarType()
+ .equals(
+ projectBelongingTo.getProjectLocation()
+ .getStarType())) {
+ return false;
+ }
+ }
+
+ if (requirements.getProjects() != null) {
+ for (ISpaceProject tProject : requirements.getProjects()) {
+ if (!SpaceProjectManager.teamHasProject(aTeam, tProject)) {
+ return false;
+ }
+ }
+ }
+
+ if (requirements.getUpgrades() != null) {
+ for (ISP_Upgrade upgrade : requirements.getUpgrades()) {
+ if (!projectBelongingTo.hasUpgrade(upgrade.getUpgradeName())) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public SP_Upgrade copy() {
+ return new SP_Upgrade().setUpgradeName(name)
+ .setUpgradeUnlocalizedName(unlocalizedName)
+ .setUpgradeBuildTime(buildTime)
+ .setUpgradeFluidsCost(fluidsCost)
+ .setUpgradeItemsCost(itemsCost)
+ .setUpgradeRequirements(requirements)
+ .setUpgradeTotalStages(totalStages)
+ .setUpgradeVoltage(voltage);
+ }
+
+ @Override
+ public void goToNextStage() {
+ currentStage++;
+ if (isFinished()) {
+ projectBelongingTo.setBuiltUpgrade(this);
+ }
+ }
+
+ @Override
+ public boolean isFinished() {
+ return currentStage == totalStages;
+ }
+
+ // #endregion
+
+}
diff --git a/src/main/java/gregtech/common/misc/spaceprojects/base/SpaceProject.java b/src/main/java/gregtech/common/misc/spaceprojects/base/SpaceProject.java
new file mode 100644
index 0000000000..201b7c27a9
--- /dev/null
+++ b/src/main/java/gregtech/common/misc/spaceprojects/base/SpaceProject.java
@@ -0,0 +1,451 @@
+package gregtech.common.misc.spaceprojects.base;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.StatCollector;
+import net.minecraftforge.fluids.FluidStack;
+
+import com.gtnewhorizons.modularui.api.drawable.UITexture;
+
+import gregtech.common.misc.spaceprojects.SpaceProjectManager;
+import gregtech.common.misc.spaceprojects.interfaces.ISpaceBody;
+import gregtech.common.misc.spaceprojects.interfaces.ISpaceProject;
+
+/**
+ * @author BlueWeabo
+ */
+public class SpaceProject implements ISpaceProject {
+
+ // #region Variables
+
+ protected String name;
+ protected String unlocalizedName;
+ protected long voltage;
+ protected int buildTime;
+ protected int projectTier;
+ protected int currentStage;
+ protected int totalStage;
+ protected Map<String, ISP_Upgrade> upgradesAvailable = new HashMap<>();
+ protected Map<String, ISP_Upgrade> upgradesInstalled = new HashMap<>();
+ protected ISP_Requirements requirements;
+ protected ISP_Upgrade currentUpgrade;
+ protected ItemStack[] itemsCost;
+ protected FluidStack[] fluidsCost;
+ protected ISpaceBody location;
+ protected UITexture texture;
+
+ // #endregion
+
+ // #region Getters
+
+ @Override
+ public String getProjectName() {
+ return name;
+ }
+
+ @Override
+ public String getUnlocalizedName() {
+ return unlocalizedName;
+ }
+
+ public String getLocalizedName() {
+ return StatCollector.translateToLocal(unlocalizedName);
+ }
+
+ @Override
+ public long getProjectVoltage() {
+ return voltage;
+ }
+
+ @Override
+ public int getProjectBuildTime() {
+ return buildTime;
+ }
+
+ @Override
+ public float getProjectCurrentProgress() {
+ return currentStage / totalStage * 100.0f;
+ }
+
+ @Override
+ public int getProjectTier() {
+ return projectTier;
+ }
+
+ @Override
+ public int getCurrentStage() {
+ return currentStage;
+ }
+
+ @Override
+ public int getTotalStages() {
+ return totalStage;
+ }
+
+ @Override
+ public Collection<ISP_Upgrade> getAllUpgrades() {
+ return upgradesAvailable.values();
+ }
+
+ @Override
+ public Map<String, ISP_Upgrade> getUpgradesBuiltMap() {
+ return upgradesInstalled;
+ }
+
+ @Override
+ public Collection<ISP_Upgrade> getAllBuiltUpgrades() {
+ return upgradesInstalled.values();
+ }
+
+ @Override
+ public ISP_Upgrade getUpgrade(String upgradeName) {
+ return upgradesAvailable.get(upgradeName);
+ }
+
+ @Override
+ public ItemStack[] getItemsCostPerStage() {
+ return itemsCost;
+ }
+
+ @Override
+ public ItemStack getItemCostPerStage(int index) {
+ if (itemsCost == null || index < 0 || index >= itemsCost.length) {
+ return null;
+ }
+
+ return itemsCost[index];
+ }
+
+ @Override
+ public ItemStack[] getCurrentItemsProgress() {
+ ItemStack[] currentItemsProgress = new ItemStack[itemsCost.length];
+ int index = 0;
+ for (ItemStack item : itemsCost) {
+ if (item == null) {
+ currentItemsProgress[index++] = null;
+ continue;
+ }
+ ItemStack copy = item.copy();
+ copy.stackSize *= getCurrentStage();
+ currentItemsProgress[index++] = copy;
+ }
+
+ return currentItemsProgress;
+ }
+
+ @Override
+ public ItemStack getCurrentItemProgress(int index) {
+ if (itemsCost == null || index < 0 || index >= itemsCost.length || itemsCost[index] == null) {
+ return null;
+ }
+
+ ItemStack item = itemsCost[index].copy();
+ item.stackSize *= getCurrentStage();
+ return item;
+ }
+
+ @Override
+ public ItemStack[] getTotalItemsCost() {
+ ItemStack[] totalItemsCost = new ItemStack[itemsCost.length];
+ int index = 0;
+ for (ItemStack item : itemsCost) {
+ if (item == null) {
+ totalItemsCost[index++] = null;
+ continue;
+ }
+ ItemStack copy = item.copy();
+ copy.stackSize *= getTotalStages();
+ totalItemsCost[index++] = copy;
+ }
+
+ return totalItemsCost;
+ }
+
+ @Override
+ public ItemStack getTotalItemCost(int index) {
+ if (itemsCost == null || index < 0 || index >= itemsCost.length || itemsCost[index] == null) {
+ return null;
+ }
+
+ ItemStack item = itemsCost[index].copy();
+ item.stackSize *= getTotalStages();
+ return item;
+ }
+
+ @Override
+ public FluidStack[] getFluidsCostPerStage() {
+ return fluidsCost;
+ }
+
+ @Override
+ public FluidStack getFluidCostPerStage(int index) {
+ if (fluidsCost == null || index < 0 || index >= fluidsCost.length || fluidsCost[index] == null) {
+ return null;
+ }
+
+ return fluidsCost[index];
+ }
+
+ @Override
+ public FluidStack[] getCurrentFluidsProgress() {
+ if (fluidsCost == null) {
+ return null;
+ }
+
+ FluidStack[] currentFluidsProgress = new FluidStack[fluidsCost.length];
+ int index = 0;
+ for (FluidStack fluid : fluidsCost) {
+ if (fluid == null) {
+ currentFluidsProgress[index++] = null;
+ continue;
+ }
+ FluidStack copy = fluid.copy();
+ copy.amount *= getCurrentStage();
+ currentFluidsProgress[index++] = copy;
+ }
+
+ return currentFluidsProgress;
+ }
+
+ @Override
+ public FluidStack getCurrentFluidProgress(int index) {
+ if (fluidsCost == null || index < 0 || index >= fluidsCost.length || fluidsCost[index] == null) {
+ return null;
+ }
+
+ FluidStack fluid = fluidsCost[index].copy();
+ fluid.amount *= getCurrentStage();
+ return fluid;
+ }
+
+ @Override
+ public FluidStack[] getTotalFluidsCost() {
+ if (fluidsCost == null) {
+ return null;
+ }
+
+ FluidStack[] totalFluidsCost = new FluidStack[fluidsCost.length];
+ int index = 0;
+ for (FluidStack fluid : fluidsCost) {
+ if (fluid == null) {
+ totalFluidsCost[index++] = null;
+ continue;
+ }
+ FluidStack copy = fluid.copy();
+ copy.amount *= getTotalStages();
+ totalFluidsCost[index++] = copy;
+ }
+
+ return totalFluidsCost;
+ }
+
+ @Override
+ public FluidStack getTotalFluidCost(int index) {
+ if (fluidsCost == null || index < 0 || index >= fluidsCost.length) {
+ return null;
+ }
+
+ FluidStack fluid = fluidsCost[index].copy();
+ fluid.amount *= getTotalStages();
+ return fluid;
+ }
+
+ @Override
+ public ISP_Upgrade getUpgradeBeingBuilt() {
+ return currentUpgrade;
+ }
+
+ @Override
+ public ISpaceBody getProjectLocation() {
+ return location;
+ }
+
+ @Override
+ public UITexture getTexture() {
+ return texture;
+ }
+
+ // #endregion
+
+ // #region Setter/Builder
+
+ public SpaceProject setProjectName(String spaceProjectName) {
+ name = spaceProjectName;
+ return this;
+ }
+
+ public SpaceProject setProjectUnlocalizedName(String spaceProjectUnlocalizedName) {
+ unlocalizedName = spaceProjectUnlocalizedName;
+ return this;
+ }
+
+ public SpaceProject setProjectVoltage(long spaceProjectVoltage) {
+ voltage = spaceProjectVoltage;
+ return this;
+ }
+
+ public SpaceProject setProjectBuildTime(int spaceProjectBuildTime) {
+ buildTime = spaceProjectBuildTime;
+ return this;
+ }
+
+ public SpaceProject setProjectStages(int spaceProjectTotalStages) {
+ totalStage = spaceProjectTotalStages;
+ return this;
+ }
+
+ public SpaceProject setProjectItemsCost(ItemStack... spaceProjectItemsCost) {
+ itemsCost = spaceProjectItemsCost;
+ return this;
+ }
+
+ public SpaceProject setProjectFluidsCost(FluidStack... spaceProjectFluidsCost) {
+ fluidsCost = spaceProjectFluidsCost;
+ return this;
+ }
+
+ public SpaceProject setProjectUpgrades(ISP_Upgrade... spaceProjectUpgrades) {
+ for (ISP_Upgrade upgrade : spaceProjectUpgrades) {
+ upgrade.setUpgradeProject(this);
+ upgradesAvailable.put(upgrade.getUpgradeName(), upgrade);
+ }
+ return this;
+ }
+
+ public SpaceProject setProjectTexture(UITexture projectTexture) {
+ texture = projectTexture;
+ return this;
+ }
+
+ public SpaceProject setProjectRequirements(ISP_Requirements projectRequirements) {
+ requirements = projectRequirements;
+ return this;
+ }
+
+ @Override
+ public void setCurrentUpgradeBeingBuilt(ISP_Upgrade newCurrentUpgrade) {
+ if (newCurrentUpgrade == null) {
+ return;
+ }
+
+ if (totalStage == currentStage) {
+ currentUpgrade = newCurrentUpgrade.copy();
+ currentUpgrade.setUpgradeProject(this);
+ }
+ }
+
+ @Override
+ public void setProjectCurrentStage(int newCurrentStage) {
+ currentStage = newCurrentStage;
+ }
+
+ @Override
+ public void setProjectLocation(ISpaceBody newLocation) {
+ location = newLocation;
+ }
+
+ @Override
+ public void setBuiltUpgrade(ISP_Upgrade... upgrades) {
+ if (upgrades == null) {
+ return;
+ }
+
+ for (ISP_Upgrade upgrade : upgrades) {
+ if (upgrade.equals(currentUpgrade)) {
+ currentUpgrade = null;
+ }
+ upgradesInstalled.put(upgrade.getUpgradeName(), upgrade);
+ }
+ }
+
+ // #endregion
+
+ // #region Other
+
+ @Override
+ public ISpaceProject copy() {
+ SpaceProject copy = new SpaceProject().setProjectName(name)
+ .setProjectUnlocalizedName(unlocalizedName)
+ .setProjectVoltage(voltage)
+ .setProjectBuildTime(buildTime)
+ .setProjectItemsCost(itemsCost)
+ .setProjectFluidsCost(fluidsCost)
+ .setProjectStages(totalStage)
+ .setProjectTexture(texture)
+ .setProjectRequirements(requirements);
+ if (upgradesAvailable != null) {
+ ISP_Upgrade[] upgrades = new SP_Upgrade[upgradesAvailable.size()];
+ int index = 0;
+ for (ISP_Upgrade upgrade : upgradesAvailable.values()) {
+ upgrades[index++] = upgrade.copy();
+ }
+ copy.setProjectUpgrades(upgrades);
+ }
+ return copy;
+ }
+
+ @Override
+ public void goToNextStage() {
+ currentStage++;
+ }
+
+ @Override
+ public boolean meetsRequirements(UUID team) {
+ return meetsRequirements(team, true);
+ }
+
+ @Override
+ public boolean meetsRequirements(UUID team, boolean checkLocation) {
+ if (requirements == null) {
+ return true;
+ }
+
+ if (requirements.getBodyType() != null && checkLocation) {
+ if (!requirements.getBodyType()
+ .equals(location.getType())) {
+ return false;
+ }
+ }
+
+ if (requirements.getStarType() != null && checkLocation) {
+ if (!requirements.getStarType()
+ .equals(location.getStarType())) {
+ return false;
+ }
+ }
+
+ if (requirements.getProjects() != null) {
+ for (ISpaceProject project : requirements.getProjects()) {
+ if (!SpaceProjectManager.teamHasProject(team, project)) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof SpaceProject)) {
+ return false;
+ }
+ return getProjectName().equals(((SpaceProject) obj).getProjectName());
+ }
+
+ @Override
+ public boolean isFinished() {
+ return currentStage == totalStage;
+ }
+
+ @Override
+ public boolean hasUpgrade(String upgradeName) {
+ return upgradesInstalled.containsKey(upgradeName);
+ }
+
+ // #endregion
+}
diff --git a/src/main/java/gregtech/common/misc/spaceprojects/commands/SPM_Command.java b/src/main/java/gregtech/common/misc/spaceprojects/commands/SPM_Command.java
new file mode 100644
index 0000000000..896c7e1052
--- /dev/null
+++ b/src/main/java/gregtech/common/misc/spaceprojects/commands/SPM_Command.java
@@ -0,0 +1,288 @@
+package gregtech.common.misc.spaceprojects.commands;
+
+import static gregtech.common.misc.spaceprojects.SpaceProjectManager.getLocation;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+import net.minecraft.command.CommandBase;
+import net.minecraft.command.ICommandSender;
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.util.ChatComponentText;
+
+import gregtech.common.misc.spaceprojects.SpaceProjectManager;
+import gregtech.common.misc.spaceprojects.SpaceProjectWorldSavedData;
+import gregtech.common.misc.spaceprojects.interfaces.ISpaceProject;
+
+/**
+ * @author BlueWeabo
+ */
+public class SPM_Command extends CommandBase {
+
+ private static final String RESET = "reset";
+ private static final String UNLOCK = "unlock";
+ private static final String UNLOCK_UPGRADE = "unlock_upgrade";
+ private static final String LOCK = "lock";
+ private static final String LIST = "list";
+ private static final String ALL = "-all";
+ private static final String AVAILABLE = "-available";
+ private static final String UNLOCKED = "-unlocked";
+ private static final String COPY = "copy";
+
+ @Override
+ public String getCommandName() {
+ return "spm";
+ }
+
+ @Override
+ public int getRequiredPermissionLevel() {
+ return 0;
+ }
+
+ @Override
+ public String getCommandUsage(ICommandSender sender) {
+ return "/" + this.getCommandName() + " <subCommand>. Available subCommands: reset, unlock, lock, list, copy";
+ }
+
+ @Override
+ public void processCommand(ICommandSender sender, String[] arguments) {
+ if (arguments.length < 1) {
+ printHelp(sender);
+ return;
+ }
+ switch (arguments[0]) {
+ case RESET:
+ if (!sender.canCommandSenderUseCommand(4, getCommandName())) {
+ sender.addChatMessage(
+ new ChatComponentText("You don't have the permissions to execute this command"));
+ return;
+ }
+ processReset(sender, arguments.length >= 2 ? arguments[1] : sender.getCommandSenderName());
+ break;
+ case UNLOCK:
+ if (!sender.canCommandSenderUseCommand(4, getCommandName())) {
+ sender.addChatMessage(
+ new ChatComponentText("You don't have the permissions to execute this command"));
+ return;
+ }
+ if (arguments.length < 3) {
+ sender.addChatMessage(
+ new ChatComponentText("Not enough arguments. Needs to mention a project and a location"));
+ return;
+ }
+ processUnlock(
+ sender,
+ arguments[1],
+ arguments[2],
+ arguments.length >= 4 ? arguments[3] : sender.getCommandSenderName());
+ break;
+ case UNLOCK_UPGRADE:
+ if (!sender.canCommandSenderUseCommand(4, getCommandName())) {
+ sender.addChatMessage(
+ new ChatComponentText("You don't have the permissions to execute this command"));
+ return;
+ }
+ if (arguments.length < 4) {
+ sender.addChatMessage(
+ new ChatComponentText(
+ "Not enough arguments. Needs to mention a project a location and an upgrade name"));
+ return;
+ }
+ processUnlock(
+ sender,
+ arguments[1],
+ arguments[2],
+ arguments[3],
+ arguments.length >= 5 ? arguments[4] : sender.getCommandSenderName());
+ break;
+ case LOCK:
+ if (!sender.canCommandSenderUseCommand(4, getCommandName())) {
+ sender.addChatMessage(
+ new ChatComponentText("You don't have the permissions to execute this command"));
+ return;
+ }
+ if (arguments.length < 3) {
+ sender.addChatMessage(
+ new ChatComponentText("Not enough arguments. Needs to mention a project and a location"));
+ return;
+ }
+ processLock(
+ sender,
+ arguments[1],
+ arguments[2],
+ arguments.length >= 4 ? arguments[3] : sender.getCommandSenderName());
+ case LIST:
+ if (arguments.length < 2) {
+ sender.addChatMessage(
+ new ChatComponentText(
+ "No Argument for list subCommand. Usage /spm list -all, -available or -unlocked"));
+ return;
+ }
+ processList(sender, arguments[1], arguments.length >= 3 ? arguments[2] : sender.getCommandSenderName());
+ break;
+ case COPY:
+ if (!sender.canCommandSenderUseCommand(4, getCommandName())) {
+ sender.addChatMessage(
+ new ChatComponentText("You don't have the permissions to execute this command"));
+ return;
+ }
+ if (arguments.length < 3) {
+ sender.addChatMessage(new ChatComponentText("Not enough arguments. Needs to mention 2 players"));
+ return;
+ }
+ processCopy(sender, arguments[1], arguments[2]);
+ break;
+ }
+ }
+
+ @Override
+ public List<String> addTabCompletionOptions(ICommandSender sender, String[] arguments) {
+ List<String> autoComplete = new ArrayList<>();
+ String filter = arguments.length == 0 ? "" : arguments[0].trim();
+ switch (arguments.length) {
+ case 1 -> autoComplete.addAll(Arrays.asList(getSubCommands()));
+ case 2 -> {
+ filter = arguments[1].trim();
+ if (arguments[0].equals(LIST)) {
+ autoComplete.addAll(Arrays.asList(getListArguments()));
+ } else if (arguments[0].equals(COPY) || arguments[0].equals(RESET)) {
+ autoComplete.addAll(Arrays.asList(getPlayers()));
+ } else {
+ autoComplete.addAll(Arrays.asList(getProjects()));
+ }
+ }
+ case 3 -> {
+ filter = arguments[2].trim();
+ if (arguments[1].equals(ALL)) {} else if (arguments[0].equals(LIST)) {
+ autoComplete.addAll(Arrays.asList(getPlayers()));
+ } else {
+ autoComplete.addAll(Arrays.asList(getLocations()));
+ }
+ }
+ case 4 -> {
+ filter = arguments[3].trim();
+ if (arguments[0].equals(UNLOCK_UPGRADE)) {
+ ISpaceProject project = SpaceProjectManager.getProject(arguments[2]);
+ if (project != null) {
+ autoComplete.addAll(
+ project.getAllUpgrades()
+ .stream()
+ .map(ISpaceProject.ISP_Upgrade::getUnlocalizedName)
+ .collect(Collectors.toList()));
+ }
+ } else {
+ autoComplete.addAll(Arrays.asList(getPlayers()));
+ }
+ }
+ }
+ String finalFilter = filter;
+ return autoComplete.stream()
+ .filter(s -> finalFilter.isEmpty() || s.startsWith(finalFilter))
+ .collect(Collectors.toList());
+ }
+
+ private String[] getPlayers() {
+ return MinecraftServer.getServer()
+ .getAllUsernames();
+ }
+
+ private String[] getLocations() {
+ return SpaceProjectManager.getLocationNames()
+ .toArray(new String[0]);
+ }
+
+ private String[] getProjects() {
+ return SpaceProjectManager.getProjectsMap()
+ .keySet()
+ .toArray(new String[0]);
+ }
+
+ private String[] getSubCommands() {
+ return new String[] { RESET, COPY, UNLOCK, UNLOCK_UPGRADE, LOCK, LIST };
+ }
+
+ private String[] getListArguments() {
+ return new String[] { ALL, AVAILABLE, UNLOCKED };
+ }
+
+ private void processReset(ICommandSender sender, String playerName) {
+ UUID tID = SpaceProjectManager.getPlayerUUIDFromName(playerName);
+ SpaceProjectManager.spaceTeamProjects.put(tID, null);
+ SpaceProjectWorldSavedData.INSTANCE.markDirty();
+ sender.addChatMessage(new ChatComponentText("Cleared away map"));
+ }
+
+ private void processLock(ICommandSender sender, String projectName, String location, String playerName) {
+ UUID tID = SpaceProjectManager.getPlayerUUIDFromName(playerName);
+ SpaceProjectManager.addTeamProject(tID, getLocation(location), projectName, null);
+ sender.addChatMessage(new ChatComponentText("Project locked"));
+ }
+
+ private void processUnlock(ICommandSender sender, String projectName, String location, String playerName) {
+ UUID tID = SpaceProjectManager.getPlayerUUIDFromName(playerName);
+ ISpaceProject tProject = SpaceProjectManager.getTeamProjectOrCopy(tID, projectName, getLocation(location));
+ if (tProject != null) {
+ tProject.setProjectCurrentStage(tProject.getTotalStages());
+ SpaceProjectManager.addTeamProject(tID, getLocation(location), projectName, tProject);
+ sender.addChatMessage(new ChatComponentText("Project unlocked"));
+ } else {
+ sender.addChatMessage(new ChatComponentText("Incorrect internal project name. Try again"));
+ }
+ }
+
+ private void processUnlock(ICommandSender sender, String projectName, String location, String upgradeName,
+ String playerName) {
+ UUID tID = SpaceProjectManager.getPlayerUUIDFromName(playerName);
+ ISpaceProject tProject = SpaceProjectManager.getTeamProjectOrCopy(tID, projectName, getLocation(location));
+ if (tProject != null) {
+ ISpaceProject.ISP_Upgrade upgrade = tProject.getUpgrade(upgradeName);
+ if (upgrade == null) {
+ sender.addChatMessage(new ChatComponentText("Incorrect internal project upgrade name. Try again"));
+ return;
+ }
+ if (!tProject.isFinished()) {
+ tProject.setProjectCurrentStage(tProject.getTotalStages());
+ SpaceProjectManager.addTeamProject(tID, getLocation(location), projectName, tProject);
+ }
+ tProject.setBuiltUpgrade(upgrade);
+ sender.addChatMessage(new ChatComponentText("Project Upgrade unlocked"));
+ } else {
+ sender.addChatMessage(new ChatComponentText("Incorrect internal project name. Try again"));
+ }
+ }
+
+ private void processList(ICommandSender sender, String argument, String playerName) {
+ UUID tID = SpaceProjectManager.getPlayerUUIDFromName(playerName);
+ switch (argument) {
+ case ALL -> {
+ for (String project : SpaceProjectManager.getProjectsMap()
+ .keySet()) {
+ sender.addChatMessage(new ChatComponentText(project));
+ }
+ }
+ case AVAILABLE -> {
+ for (ISpaceProject project : SpaceProjectManager.getAllProjects()) {
+ if (project.meetsRequirements(tID, false)) {
+ sender.addChatMessage(new ChatComponentText(project.getProjectName()));
+ }
+ }
+ }
+ case UNLOCKED -> {
+ for (ISpaceProject project : SpaceProjectManager.getTeamSpaceProjects(tID)) {
+ sender.addChatMessage(new ChatComponentText(project.getProjectName()));
+ }
+ }
+ }
+ }
+
+ private void processCopy(ICommandSender sender, String playerToCopyFrom, String playerCopyingTo) {
+ // This will take a while
+ }
+
+ private void printHelp(ICommandSender sender) {
+
+ }
+}
diff --git a/src/main/java/gregtech/common/misc/spaceprojects/commands/SP_Command.java b/src/main/java/gregtech/common/misc/spaceprojects/commands/SP_Command.java
new file mode 100644
index 0000000000..3c4ad00932
--- /dev/null
+++ b/src/main/java/gregtech/common/misc/spaceprojects/commands/SP_Command.java
@@ -0,0 +1,166 @@
+package gregtech.common.misc.spaceprojects.commands;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+import java.util.WeakHashMap;
+import java.util.stream.Collectors;
+
+import net.minecraft.command.CommandBase;
+import net.minecraft.command.ICommandSender;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.util.EnumChatFormatting;
+
+import org.apache.commons.lang3.tuple.Pair;
+
+import gregtech.api.util.GT_Utility;
+import gregtech.common.misc.spaceprojects.SpaceProjectManager;
+
+/**
+ * @author BlueWeabo
+ */
+public class SP_Command extends CommandBase {
+
+ private static final Set<Pair<EntityPlayerMP, EntityPlayerMP>> invite = Collections
+ .newSetFromMap(new WeakHashMap<>());
+ private static final Set<EntityPlayerMP> confirm = Collections.newSetFromMap(new WeakHashMap<>());
+
+ private static final String INVITE = "invite";
+ private static final String ACCEPT = "accept";
+ private static final String LEAVE = "leave";
+ private static final String CONFIRM = "confirm";
+
+ @Override
+ public String getCommandName() {
+ return "sp";
+ }
+
+ @Override
+ public int getRequiredPermissionLevel() {
+ return 0;
+ }
+
+ @Override
+ public String getCommandUsage(ICommandSender sender) {
+ return "/" + getCommandName() + "<subCommand> [PlayerName]";
+ }
+
+ @Override
+ public void processCommand(ICommandSender sender, String[] arguments) {
+ if (arguments.length < 1) {
+ return;
+ }
+ switch (arguments[0]) {
+ case INVITE -> {
+ if (arguments.length < 2) {
+ return;
+ }
+ processInvite(sender, arguments[1]);
+ }
+ case ACCEPT -> {
+ if (arguments.length < 2) {
+ return;
+ }
+ processAccept(sender, arguments[1]);
+ }
+ case LEAVE -> processLeave(sender);
+ case CONFIRM -> processConfirm(sender);
+ }
+ }
+
+ private void processInvite(ICommandSender sender, String playerInvited) {
+ EntityPlayerMP teamLeader = getCommandSenderAsPlayer(sender);
+ EntityPlayerMP teamMember = getPlayer(sender, playerInvited);
+ invite.add(Pair.of(teamMember, teamLeader));
+ String message = EnumChatFormatting.GOLD + teamLeader.getCommandSenderName()
+ + EnumChatFormatting.RESET
+ + " has sent you an invite to join their team. Accept it with"
+ + EnumChatFormatting.GOLD
+ + " /sp accept "
+ + teamLeader.getCommandSenderName();
+ GT_Utility.sendChatToPlayer(teamMember, message);
+ }
+
+ private void processAccept(ICommandSender sender, String playerInviter) {
+ EntityPlayerMP teamMember = getCommandSenderAsPlayer(sender);
+ EntityPlayerMP teamLeader = getPlayer(sender, playerInviter);
+ if (invite.contains(Pair.of(teamMember, teamLeader))) {
+ String message = EnumChatFormatting.GOLD + teamMember.getCommandSenderName()
+ + EnumChatFormatting.RESET
+ + " has accepted the invite.";
+ SpaceProjectManager.putInTeam(teamMember.getUniqueID(), teamLeader.getUniqueID());
+ GT_Utility.sendChatToPlayer(teamLeader, message);
+ invite.remove(Pair.of(teamMember, teamLeader));
+ }
+ }
+
+ private void processLeave(ICommandSender sender) {
+ EntityPlayerMP player = getCommandSenderAsPlayer(sender);
+ String message = "Are you sure you want to leave the team. You will lose all progress. Use "
+ + EnumChatFormatting.GOLD
+ + "/sp confirm"
+ + EnumChatFormatting.RESET
+ + " to confirm this. This does nothing if you are the team leader.";
+ GT_Utility.sendChatToPlayer(player, message);
+ confirm.add(player);
+ }
+
+ private void processConfirm(ICommandSender sender) {
+ EntityPlayerMP player = getCommandSenderAsPlayer(sender);
+ if (confirm.contains(player)) {
+ String message = "Successfully left the team.";
+ SpaceProjectManager.putInTeam(player.getUniqueID(), player.getUniqueID());
+ GT_Utility.sendChatToPlayer(player, message);
+ confirm.remove(player);
+ }
+ }
+
+ @Override
+ public List<String> addTabCompletionOptions(ICommandSender sender, String[] arguments) {
+ List<String> autoComplete = new ArrayList<>();
+ String filter = arguments.length == 0 ? "" : arguments[0].trim();
+ switch (arguments.length) {
+ case 1 -> autoComplete.addAll(Arrays.asList(getSubCommands()));
+ case 2 -> {
+ filter = arguments[1].trim();
+ if (arguments[0].equals(INVITE)) {
+ autoComplete.addAll(Arrays.asList(getPlayers()));
+ break;
+ }
+
+ if (arguments[0].equals(CONFIRM)) {
+ Optional<Pair<EntityPlayerMP, EntityPlayerMP>> pairOpt = invite.stream()
+ .filter(
+ (e) -> e.getKey()
+ .getUniqueID() == getCommandSenderAsPlayer(sender).getUniqueID())
+ .findFirst();
+ if (pairOpt.isPresent()) {
+ autoComplete.add(
+ SpaceProjectManager.getPlayerNameFromUUID(
+ pairOpt.get()
+ .getRight()
+ .getUniqueID()));
+ }
+ }
+ }
+ }
+ String finalFilter = filter;
+ return autoComplete.stream()
+ .filter(s -> finalFilter.isEmpty() || s.startsWith(finalFilter))
+ .collect(Collectors.toList());
+ }
+
+ private String[] getPlayers() {
+ return MinecraftServer.getServer()
+ .getAllUsernames();
+ }
+
+ private String[] getSubCommands() {
+ return new String[] { INVITE, ACCEPT, LEAVE, CONFIRM };
+ }
+
+}
diff --git a/src/main/java/gregtech/common/misc/spaceprojects/enums/JsonVariables.java b/src/main/java/gregtech/common/misc/spaceprojects/enums/JsonVariables.java
new file mode 100644
index 0000000000..665f15af74
--- /dev/null
+++ b/src/main/java/gregtech/common/misc/spaceprojects/enums/JsonVariables.java
@@ -0,0 +1,22 @@
+package gregtech.common.misc.spaceprojects.enums;
+
+public class JsonVariables {
+
+ public static final String PAIR_LEFT = "pairLeft";
+ public static final String PAIR_RIGHT = "pairRight";
+
+ public static final String MAP_UUID = "mapUUID";
+ public static final String MAP_MAP = "mapMap";
+ public static final String MAP_PAIR = "mapPair";
+ public static final String MAP_PROJECT = "mapProject";
+
+ public static final String PROJECT_NAME = "projectName";
+ public static final String PROJECT_CURRENT_STAGE = "projectCurrentStage";
+ public static final String PROJECT_UPGRADES_BUILT = "projectUpgradesBuilt";
+ public static final String PROJECT_LOCATION = "projectLocation";
+ public static final String PROJECT_CURRENT_UPGRADE = "projectCurrentUpgrade";
+
+ public static final String UPGRADE_NAME = "upgradeName";
+ public static final String UPGRADE_CURRENT_STAGE = "upgradeCurrentStage";
+ public static final String UPGRADE_PROJECT_PARENT = "upgradeProjectParent";
+}
diff --git a/src/main/java/gregtech/common/misc/spaceprojects/enums/SolarSystem.java b/src/main/java/gregtech/common/misc/spaceprojects/enums/SolarSystem.java
new file mode 100644
index 0000000000..70dee3269d
--- /dev/null
+++ b/src/main/java/gregtech/common/misc/spaceprojects/enums/SolarSystem.java
@@ -0,0 +1,104 @@
+package gregtech.common.misc.spaceprojects.enums;
+
+import static gregtech.api.enums.Mods.GregTech;
+import static gregtech.common.misc.spaceprojects.enums.SpaceBodyType.AsteroidBelt;
+import static gregtech.common.misc.spaceprojects.enums.SpaceBodyType.DwarfPlanet;
+import static gregtech.common.misc.spaceprojects.enums.SpaceBodyType.GasGiant;
+import static gregtech.common.misc.spaceprojects.enums.SpaceBodyType.IceGiant;
+import static gregtech.common.misc.spaceprojects.enums.SpaceBodyType.NaturalSatellite;
+import static gregtech.common.misc.spaceprojects.enums.SpaceBodyType.Planet;
+import static gregtech.common.misc.spaceprojects.enums.SpaceBodyType.Star;
+import static gregtech.common.misc.spaceprojects.enums.StarType.GClass;
+import static gregtech.common.misc.spaceprojects.enums.StarType.NotAStar;
+
+import com.gtnewhorizons.modularui.api.drawable.UITexture;
+
+import gregtech.common.misc.spaceprojects.SpaceProjectManager;
+import gregtech.common.misc.spaceprojects.interfaces.ISpaceBody;
+
+/**
+ * An enum of all space bodies in the Sol Solar System. Or to be exact the more important ones
+ *
+ * @author BlueWeabo
+ */
+public enum SolarSystem implements ISpaceBody {
+
+ Sol(Star, GClass),
+ Overworld(Planet),
+ Moon(NaturalSatellite),
+ Mars(Planet),
+ Deimos(NaturalSatellite),
+ Phobos(NaturalSatellite),
+ Mercury(Planet),
+ Venus(Planet),
+ Jupiter(GasGiant),
+ Io(NaturalSatellite),
+ Ganymede(NaturalSatellite),
+ Europa(NaturalSatellite),
+ Callisto(NaturalSatellite),
+ Saturn(GasGiant),
+ Mimas(NaturalSatellite),
+ Enceladus(NaturalSatellite),
+ Tethys(NaturalSatellite),
+ Rhea(NaturalSatellite),
+ Titan(NaturalSatellite),
+ Hyperion(NaturalSatellite),
+ Iapetus(NaturalSatellite),
+ Phoebe(NaturalSatellite),
+ Uranus(IceGiant),
+ Miranda(NaturalSatellite),
+ Ariel(NaturalSatellite),
+ Umbriel(NaturalSatellite),
+ Titania(NaturalSatellite),
+ Oberon(NaturalSatellite),
+ Neptune(IceGiant),
+ Proteus(NaturalSatellite),
+ Triton(NaturalSatellite),
+ Nereid(NaturalSatellite),
+ Ceres(DwarfPlanet),
+ Pluto(DwarfPlanet),
+ Arrokoth(DwarfPlanet),
+ MakeMake(DwarfPlanet),
+ KuiperBelt(AsteroidBelt),
+ NONE(SpaceBodyType.NONE);
+
+ private final SpaceBodyType spaceBody;
+ private final StarType star;
+ private final UITexture texture;
+
+ SolarSystem(SpaceBodyType aType) {
+ this(aType, NotAStar);
+ }
+
+ SolarSystem(SpaceBodyType aType, StarType aStarType) {
+ star = aStarType;
+ spaceBody = aType;
+ texture = UITexture.fullImage(GregTech.ID, "solarsystem/" + getName());
+ SpaceProjectManager.addLocation(this);
+ }
+
+ @Override
+ public StarType getStarType() {
+ return star;
+ }
+
+ @Override
+ public SpaceBodyType getType() {
+ return spaceBody;
+ }
+
+ @Override
+ public String getName() {
+ return name();
+ }
+
+ @Override
+ public UITexture getTexture() {
+ return texture;
+ }
+
+ @Override
+ public String getUnlocalizedName() {
+ return "gt.solar.system." + getName().toLowerCase();
+ }
+}
diff --git a/src/main/java/gregtech/common/misc/spaceprojects/enums/SpaceBodyType.java b/src/main/java/gregtech/common/misc/spaceprojects/enums/SpaceBodyType.java
new file mode 100644
index 0000000000..8ca8b663da
--- /dev/null
+++ b/src/main/java/gregtech/common/misc/spaceprojects/enums/SpaceBodyType.java
@@ -0,0 +1,17 @@
+package gregtech.common.misc.spaceprojects.enums;
+
+/**
+ * @author BlueWeabo
+ */
+public enum SpaceBodyType {
+ Star,
+ NeutronStar,
+ Planet,
+ NaturalSatellite,
+ AsteroidBelt,
+ BlackHole,
+ GasGiant,
+ DwarfPlanet,
+ IceGiant,
+ NONE
+}
diff --git a/src/main/java/gregtech/common/misc/spaceprojects/enums/StarType.java b/src/main/java/gregtech/common/misc/spaceprojects/enums/StarType.java
new file mode 100644
index 0000000000..7585c95aa0
--- /dev/null
+++ b/src/main/java/gregtech/common/misc/spaceprojects/enums/StarType.java
@@ -0,0 +1,32 @@
+package gregtech.common.misc.spaceprojects.enums;
+
+/**
+ * @author BlueWeabo
+ */
+public enum StarType {
+
+ OClass(30000, 100),
+ BClass(10000, 20),
+ AClass(20, 5),
+ FClass(4, 2),
+ GClass(1, 1),
+ KClass(0.4, 0.5f),
+ MClass(0.08, 0.1f),
+ NotAStar(0, 0);
+
+ private final double solarLuminosity;
+ private final float costMultiplier;
+
+ StarType(double solarLuminosity, float costMultiplier) {
+ this.solarLuminosity = solarLuminosity;
+ this.costMultiplier = costMultiplier;
+ }
+
+ public double getSolarLuminosity() {
+ return solarLuminosity;
+ }
+
+ public float getCostMultiplier() {
+ return costMultiplier;
+ }
+}
diff --git a/src/main/java/gregtech/common/misc/spaceprojects/enums/UpgradeStatus.java b/src/main/java/gregtech/common/misc/spaceprojects/enums/UpgradeStatus.java
new file mode 100644
index 0000000000..3e662720ac
--- /dev/null
+++ b/src/main/java/gregtech/common/misc/spaceprojects/enums/UpgradeStatus.java
@@ -0,0 +1,11 @@
+package gregtech.common.misc.spaceprojects.enums;
+
+/**
+ * @author BlueWeabo
+ */
+public enum UpgradeStatus {
+ Locked,
+ Unlocked,
+ InProgress,
+ Finished
+}
diff --git a/src/main/java/gregtech/common/misc/spaceprojects/interfaces/ISpaceBody.java b/src/main/java/gregtech/common/misc/spaceprojects/interfaces/ISpaceBody.java
new file mode 100644
index 0000000000..79eba4c968
--- /dev/null
+++ b/src/main/java/gregtech/common/misc/spaceprojects/interfaces/ISpaceBody.java
@@ -0,0 +1,37 @@
+package gregtech.common.misc.spaceprojects.interfaces;
+
+import com.gtnewhorizons.modularui.api.drawable.UITexture;
+
+import gregtech.common.misc.spaceprojects.enums.SpaceBodyType;
+import gregtech.common.misc.spaceprojects.enums.StarType;
+
+/**
+ * @author BlueWeabo
+ */
+public interface ISpaceBody {
+
+ /**
+ * @return The star type of the space body, if its a star
+ */
+ StarType getStarType();
+
+ /**
+ * @return The type of space body it is
+ */
+ SpaceBodyType getType();
+
+ /**
+ * @return The internal name of the space body
+ */
+ String getName();
+
+ /**
+ * @return The texture of the space body used for UI
+ */
+ UITexture getTexture();
+
+ /**
+ * @return The Unlocalized name for this body
+ */
+ String getUnlocalizedName();
+}
diff --git a/src/main/java/gregtech/common/misc/spaceprojects/interfaces/ISpaceProject.java b/src/main/java/gregtech/common/misc/spaceprojects/interfaces/ISpaceProject.java
new file mode 100644
index 0000000000..51ae03ff30
--- /dev/null
+++ b/src/main/java/gregtech/common/misc/spaceprojects/interfaces/ISpaceProject.java
@@ -0,0 +1,430 @@
+package gregtech.common.misc.spaceprojects.interfaces;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.fluids.FluidStack;
+
+import com.gtnewhorizons.modularui.api.drawable.UITexture;
+
+import gregtech.common.misc.spaceprojects.enums.SpaceBodyType;
+import gregtech.common.misc.spaceprojects.enums.StarType;
+import gregtech.common.misc.spaceprojects.enums.UpgradeStatus;
+
+/**
+ * @author BlueWeabo
+ */
+public interface ISpaceProject {
+
+ /**
+ * @return the internal name of the project.
+ */
+ String getProjectName();
+
+ /**
+ * @return Unlocalized name of the project.
+ */
+ String getUnlocalizedName();
+
+ /**
+ * @return Localized name of the project using StatCollect#translateToLocal.
+ */
+ String getLocalizedName();
+
+ /**
+ * @return The voltage the project requires to be built at. Used by the project manager.
+ */
+ long getProjectVoltage();
+
+ /**
+ * @return The duration it takes to build out one(1) stage of the project. The time returned is in ticks
+ */
+ int getProjectBuildTime();
+
+ /**
+ * @return The Current Progress of the project in percentage form. 1 being 100% and 0 being 0%.
+ */
+ float getProjectCurrentProgress();
+
+ /**
+ * @return Currently unused, but this is the project's tier. Will be used to determine the min-tier motors needed on
+ * the Space Elevator
+ */
+ int getProjectTier();
+
+ /**
+ * @return The Current stage of the project
+ */
+ int getCurrentStage();
+
+ /**
+ * @return The Total amount of stages the project has
+ */
+ int getTotalStages();
+
+ /**
+ * @return a Collection of all upgrades the project has
+ */
+ Collection<ISP_Upgrade> getAllUpgrades();
+
+ /**
+ * @return a Map of all upgrades that have been built.
+ */
+ Map<String, ISP_Upgrade> getUpgradesBuiltMap();
+
+ /**
+ * @return all built upgrades
+ */
+ Collection<ISP_Upgrade> getAllBuiltUpgrades();
+
+ /**
+ * @param upgradeName The name of the upgrade wanted
+ * @return The upgrade with the appropriate name found in the available upgrades for the project
+ */
+ ISP_Upgrade getUpgrade(String upgradeName);
+
+ /**
+ * @return The Items cost required per stage in an array form. Used for making the recipe.
+ */
+ ItemStack[] getItemsCostPerStage();
+
+ /**
+ * @param index Index at which the itemstack is found at
+ * @return an item's cost at the appropriate index. Null otherwise if it goes above the index or there are no item
+ * costs
+ */
+ ItemStack getItemCostPerStage(int index);
+
+ /**
+ * @return The Items current progress in an array form.
+ */
+ ItemStack[] getCurrentItemsProgress();
+
+ /**
+ * @param index Index at which the itemstack is found at
+ * @return an item's current progress at the appropriate index. Null otherwise if it goes above the index or there
+ * are no item costs
+ */
+ ItemStack getCurrentItemProgress(int index);
+
+ /**
+ * @return The items total cost required in an array form.
+ */
+ ItemStack[] getTotalItemsCost();
+
+ /**
+ * @param index Index at which the itemstack is found at
+ * @return an item's total cost at the appropriate index. Null otherwise if it goes above the index or there are no
+ * item costs
+ */
+ ItemStack getTotalItemCost(int index);
+
+ /**
+ * @return The fluids cost required per stage in an array form. Used for making the recipe.
+ */
+ FluidStack[] getFluidsCostPerStage();
+
+ /**
+ * @param index Index at which the fluidstack is found at
+ * @return a fluid's cost at the appropriate index. Null otherwise if it goes above the index or there are no fluid
+ * costs
+ */
+ FluidStack getFluidCostPerStage(int index);
+
+ /**
+ * @return The fluids current progress in an array form. Null if there are no fluid costs
+ */
+ FluidStack[] getCurrentFluidsProgress();
+
+ /**
+ * @param index Index at which the fluidstack is found at
+ * @return a fluid's current progress at the appropriate index. Null otherwise if it goes above the index or there
+ * are no fluid costs
+ */
+ FluidStack getCurrentFluidProgress(int index);
+
+ /**
+ * @return The fluids total cost required in an array form. Null if there are no fluid costs
+ */
+ FluidStack[] getTotalFluidsCost();
+
+ /**
+ * @param index Index at which the fluidstack is found at
+ * @return a fluid's total cost at the appropriate index. Null otherwise if it goes above the index or there are no
+ * fluid costs
+ */
+ FluidStack getTotalFluidCost(int index);
+
+ /**
+ * @return The current upgrade for this project, which is being built
+ */
+ ISP_Upgrade getUpgradeBeingBuilt();
+
+ /**
+ * @return The location of the project
+ */
+ ISpaceBody getProjectLocation();
+
+ /**
+ * @return The texture used in GUIs for the project
+ */
+ UITexture getTexture();
+
+ /**
+ * Sets the current stage of the project
+ */
+ void setProjectCurrentStage(int stage);
+
+ /**
+ * Sets the current upgrade, which needs to be built
+ */
+ void setCurrentUpgradeBeingBuilt(ISP_Upgrade upgrade);
+
+ /**
+ * Sets the project's location when it starts being built
+ */
+ void setProjectLocation(ISpaceBody newLocation);
+
+ /**
+ * Sets the project's upgrades, which have been built
+ */
+ void setBuiltUpgrade(ISP_Upgrade... upgrades);
+
+ /**
+ * Goes to the next stage of the project
+ */
+ void goToNextStage();
+
+ /**
+ * Creates a copy of the space project
+ */
+ ISpaceProject copy();
+
+ /**
+ * Checks if the project meets all requirements with its current location
+ *
+ * @param team Team wanting said project and checking their projects
+ * @return true if all requirements met, false otherwise
+ */
+ boolean meetsRequirements(UUID team);
+
+ /**
+ * Checks if the project meets requirements if it requires other projects, unless {@code checkLocation} is true,
+ * then it also checks for the location
+ *
+ * @param team Team wanting said project and checking their projects
+ * @param checkLocation If the location position should be checked
+ * @return true if all requirements met, false otherwise
+ */
+ boolean meetsRequirements(UUID team, boolean checkLocation);
+
+ /**
+ * Checks if the projects is finished
+ */
+ boolean isFinished();
+
+ /**
+ * Checks if the project has a certain upgrade installed or not
+ *
+ * @param upgradeName Upgrade being searched for
+ * @return True if that upgrade has been installed, false otherwise
+ */
+ boolean hasUpgrade(String upgradeName);
+
+ /**
+ * @author BlueWeabo
+ */
+ interface ISP_Upgrade {
+
+ /**
+ * @return internal name of the upgrade
+ */
+ String getUpgradeName();
+
+ /**
+ * @return unlocalized name of the upgrade
+ */
+ String getUnlocalizedName();
+
+ /**
+ * @return localized name of the upgrade
+ */
+ String getLocalizedName();
+
+ /**
+ * @return The Items cost required per stage in an array form. Used for making the recipe.
+ */
+ ItemStack[] getItemsCostPerStage();
+
+ /**
+ * @param index Index at which the itemstack is found at
+ * @return an item's cost at the appropriate index. Null otherwise if it goes above the index or there are no
+ * item costs
+ */
+ ItemStack getItemCostPerStage(int index);
+
+ /**
+ * @return The Items current progress in an array form.
+ */
+ ItemStack[] getCurrentItemsProgress();
+
+ /**
+ * @param index Index at which the itemstack is found at
+ * @return an item's current progress at the appropriate index. Null otherwise if it goes above the index or
+ * there are no item costs
+ */
+ ItemStack getCurrentItemProgress(int index);
+
+ /**
+ * @return The items total cost required in an array form.
+ */
+ ItemStack[] getTotalItemsCost();
+
+ /**
+ * @param index Index at which the itemstack is found at
+ * @return an item's total cost at the appropriate index. Null otherwise if it goes above the index or there are
+ * no item costs
+ */
+ ItemStack getTotalItemCost(int index);
+
+ /**
+ * @return The fluids cost required per stage in an array form. Used for making the recipe.
+ */
+ FluidStack[] getFluidsCostPerStage();
+
+ /**
+ * @param index Index at which the fluidstack is found at
+ * @return a fluid's cost at the appropriate index. Null otherwise if it goes above the index or there are no
+ * fluid costs
+ */
+ FluidStack getFluidCostPerStage(int index);
+
+ /**
+ * @return The fluids current progress in an array form. Null if there are no fluid costs
+ */
+ FluidStack[] getCurrentFluidsProgress();
+
+ /**
+ * @param index Index at which the fluidstack is found at
+ * @return a fluid's current progress at the appropriate index. Null otherwise if it goes above the index or
+ * there are no fluid costs
+ */
+ FluidStack getCurrentFluidProgress(int index);
+
+ /**
+ * @return The fluids total cost required in an array form. Null if there are no fluid costs
+ */
+ FluidStack[] getTotalFluidsCost();
+
+ /**
+ * @param index Index at which the fluidstack is found at
+ * @return a fluid's total cost at the appropriate index. Null otherwise if it goes above the index or there are
+ * no fluid costs
+ */
+ FluidStack getTotalFluidCost(int index);
+
+ /**
+ * @return the total stages an upgrade has
+ */
+ int getTotalStages();
+
+ /**
+ * @return the build time for the upgrade to go to its next stage
+ */
+ int getUpgradeBuildTime();
+
+ /**
+ * @return current stage of the upgrade
+ */
+ int getCurrentStage();
+
+ /**
+ * @return The Current Progress of the upgrade in percentage form. 1 being 100% and 0 being 0%.
+ */
+ float getCurrentProgress();
+
+ /**
+ * @return The voltage at which the upgrade requires to be build at.
+ */
+ long getVoltage();
+
+ /**
+ * Unused, unsure if it will get a sure
+ */
+ UpgradeStatus getStatus();
+
+ /**
+ * @return the requirements the upgrade has
+ */
+ ISP_Requirements getUpgradeRequirements();
+
+ /**
+ * @return the parent project, which the upgrade belongs to
+ */
+ ISpaceProject getParentProject();
+
+ /**
+ * @param project The project the upgrade belongs to
+ */
+ void setUpgradeProject(ISpaceProject project);
+
+ /**
+ * Sets the current stage of the upgrade
+ *
+ * @param stage the stage to set
+ */
+ void setUpgradeCurrentStage(int stage);
+
+ /**
+ * Checks if the team has met all requirements to be able to build said upgrade
+ *
+ * @param team The one starting the upgrade
+ * @return true if all requirements are met, false otherwise
+ */
+ boolean meetsRequirements(UUID team);
+
+ /**
+ * Creates a copy of the upgrade
+ */
+ ISP_Upgrade copy();
+
+ /**
+ * Goes to the next stage of the upgrade
+ */
+ void goToNextStage();
+
+ /**
+ * @return true if the upgrade has finished all of its stages, false otherwise
+ */
+ boolean isFinished();
+ }
+
+ /**
+ * @author BlueWeabo
+ */
+ interface ISP_Requirements {
+
+ /**
+ * @return Space Body Type required by the project/upgrade
+ */
+ SpaceBodyType getBodyType();
+
+ /**
+ * @return Star Type required by the project/upgrade
+ */
+ StarType getStarType();
+
+ /**
+ * @return a list of all project required for the team to have to unlock it
+ */
+ List<ISpaceProject> getProjects();
+
+ /**
+ * @return a list of all upgrades an upgrade can have as required.
+ */
+ List<ISP_Upgrade> getUpgrades();
+ }
+}
diff --git a/src/main/java/gregtech/common/net/MessageSetFlaskCapacity.java b/src/main/java/gregtech/common/net/MessageSetFlaskCapacity.java
new file mode 100644
index 0000000000..6c51663c47
--- /dev/null
+++ b/src/main/java/gregtech/common/net/MessageSetFlaskCapacity.java
@@ -0,0 +1,67 @@
+package gregtech.common.net;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.world.IBlockAccess;
+import net.minecraft.world.World;
+import net.minecraftforge.common.DimensionManager;
+
+import com.google.common.io.ByteArrayDataInput;
+
+import gregtech.api.net.GT_Packet_New;
+import gregtech.common.items.GT_VolumetricFlask;
+import io.netty.buffer.ByteBuf;
+
+@Deprecated
+public final class MessageSetFlaskCapacity extends GT_Packet_New {
+
+ private int capacity, dimID, playerID;
+
+ public MessageSetFlaskCapacity() {
+ super(true);
+ }
+
+ public MessageSetFlaskCapacity(int capacity, int dimID, int playerID) {
+ super(false);
+ this.capacity = capacity;
+ this.dimID = dimID;
+ this.playerID = playerID;
+ }
+
+ public MessageSetFlaskCapacity(int capacity, EntityPlayer p) {
+ super(false);
+ this.capacity = capacity;
+ this.dimID = p.worldObj.provider.dimensionId;
+ this.playerID = p.getEntityId();
+ }
+
+ @Override
+ public byte getPacketID() {
+ return 5;
+ }
+
+ @Override
+ public void encode(ByteBuf aOut) {
+ aOut.writeInt(capacity);
+ aOut.writeInt(dimID);
+ aOut.writeInt(playerID);
+ }
+
+ @Override
+ public GT_Packet_New decode(ByteArrayDataInput aData) {
+ return new MessageSetFlaskCapacity(aData.readInt(), aData.readInt(), aData.readInt());
+ }
+
+ @Override
+ public void process(IBlockAccess aWorld) {
+ World w = DimensionManager.getWorld(dimID);
+ if (w != null && w.getEntityByID(playerID) instanceof EntityPlayer) {
+ ItemStack stack = ((EntityPlayer) w.getEntityByID(playerID)).getHeldItem();
+ if ((stack != null) && (stack.stackSize > 0)) {
+ Item item = stack.getItem();
+ if ((item instanceof GT_VolumetricFlask)) ((GT_VolumetricFlask) item).setCapacity(stack, capacity);
+ }
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/redstonecircuits/GT_Circuit_BasicLogic.java b/src/main/java/gregtech/common/redstonecircuits/GT_Circuit_BasicLogic.java
new file mode 100644
index 0000000000..34093a95de
--- /dev/null
+++ b/src/main/java/gregtech/common/redstonecircuits/GT_Circuit_BasicLogic.java
@@ -0,0 +1,137 @@
+package gregtech.common.redstonecircuits;
+
+import gregtech.api.interfaces.IRedstoneCircuitBlock;
+import gregtech.api.util.GT_CircuitryBehavior;
+
+public class GT_Circuit_BasicLogic extends GT_CircuitryBehavior {
+
+ public GT_Circuit_BasicLogic(int aIndex) {
+ super(aIndex);
+ }
+
+ @Override
+ public void initParameters(int[] aCircuitData, IRedstoneCircuitBlock aRedstoneCircuitBlock) {
+ aCircuitData[0] = 0;
+ }
+
+ @Override
+ public void validateParameters(int[] aCircuitData, IRedstoneCircuitBlock aRedstoneCircuitBlock) {
+ if (aCircuitData[0] < 0) {
+ aCircuitData[0] = 0;
+ }
+ if (aCircuitData[0] > 13) {
+ aCircuitData[0] = 13;
+ }
+ }
+
+ @Override
+ public void onTick(int[] aCircuitData, IRedstoneCircuitBlock aRedstoneCircuitBlock) {
+ if (aCircuitData[0] < 2) {
+ aRedstoneCircuitBlock.setRedstone(
+ (byte) (aCircuitData[0] % 2 == (getAnyRedstone(aRedstoneCircuitBlock) ? 0 : 1) ? 15 : 0),
+ aRedstoneCircuitBlock.getOutputFacing());
+ } else if (aCircuitData[0] < 4) {
+ aRedstoneCircuitBlock.setRedstone(
+ (byte) (aCircuitData[0] % 2 == (getOneRedstone(aRedstoneCircuitBlock) ? 0 : 1) ? 15 : 0),
+ aRedstoneCircuitBlock.getOutputFacing());
+ } else if (aCircuitData[0] < 6) {
+ aRedstoneCircuitBlock.setRedstone(
+ (byte) (aCircuitData[0] % 2 == (getAllRedstone(aRedstoneCircuitBlock) ? 0 : 1) ? 15 : 0),
+ aRedstoneCircuitBlock.getOutputFacing());
+ } else if (aCircuitData[0] < 7) {
+ aRedstoneCircuitBlock.setRedstone(
+ (byte) (15 - getStrongestRedstone(aRedstoneCircuitBlock)),
+ aRedstoneCircuitBlock.getOutputFacing());
+ } else if (aCircuitData[0] < 9) {
+ aRedstoneCircuitBlock.setRedstone(
+ (byte) ((aCircuitData[0] % 2 == 0 ? 15 : 0)
+ ^ (getStrongestRedstone(aRedstoneCircuitBlock) | getWeakestRedstone(aRedstoneCircuitBlock))),
+ aRedstoneCircuitBlock.getOutputFacing());
+ } else if (aCircuitData[0] < 11) {
+ aRedstoneCircuitBlock.setRedstone(
+ (byte) ((aCircuitData[0] % 2 == 0 ? 15 : 0) ^ getStrongestRedstone(aRedstoneCircuitBlock)
+ ^ getWeakestRedstone(aRedstoneCircuitBlock)),
+ aRedstoneCircuitBlock.getOutputFacing());
+ } else if (aCircuitData[0] < 13) {
+ aRedstoneCircuitBlock.setRedstone(
+ (byte) ((aCircuitData[0] % 2 == 0 ? 15 : 0)
+ ^ getStrongestRedstone(aRedstoneCircuitBlock) & getWeakestRedstone(aRedstoneCircuitBlock)),
+ aRedstoneCircuitBlock.getOutputFacing());
+ } else if (aCircuitData[0] < 14) {
+ aRedstoneCircuitBlock.setRedstone(
+ (byte) (getStrongestRedstone(aRedstoneCircuitBlock) ^ 0xF),
+ aRedstoneCircuitBlock.getOutputFacing());
+ }
+ }
+
+ @Override
+ public String getName() {
+ return "Basic Logic";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Regular Logic Gates";
+ }
+
+ @Override
+ public String getDataDescription(int[] aCircuitData, int aCircuitDataIndex) {
+ if (aCircuitDataIndex == 0) {
+ switch (aCircuitData[0]) {
+ case 0 -> {
+ return "OR";
+ }
+ case 1 -> {
+ return "NOR";
+ }
+ case 2 -> {
+ return "XOR";
+ }
+ case 3 -> {
+ return "XNOR";
+ }
+ case 4 -> {
+ return "AND";
+ }
+ case 5 -> {
+ return "NAND";
+ }
+ case 6 -> {
+ return "INVERT";
+ }
+ case 7 -> {
+ return "BIT_OR";
+ }
+ case 8 -> {
+ return "BIT_NOR";
+ }
+ case 9 -> {
+ return "BIT_XOR";
+ }
+ case 10 -> {
+ return "BIT_XNOR";
+ }
+ case 11 -> {
+ return "BIT_AND";
+ }
+ case 12 -> {
+ return "BIT_NAND";
+ }
+ case 13 -> {
+ return "BIT_INVERT";
+ }
+ }
+ }
+ return "";
+ }
+
+ @Override
+ public boolean displayItemStack(int[] aCircuitData, IRedstoneCircuitBlock aRedstoneCircuitBlock, int aIndex) {
+ return false;
+ }
+
+ @Override
+ public String getDataDisplay(int[] aCircuitData, int aCircuitDataIndex) {
+ return "";
+ }
+}
diff --git a/src/main/java/gregtech/common/redstonecircuits/GT_Circuit_BitAnd.java b/src/main/java/gregtech/common/redstonecircuits/GT_Circuit_BitAnd.java
new file mode 100644
index 0000000000..f5f83a7e10
--- /dev/null
+++ b/src/main/java/gregtech/common/redstonecircuits/GT_Circuit_BitAnd.java
@@ -0,0 +1,81 @@
+package gregtech.common.redstonecircuits;
+
+import gregtech.api.interfaces.IRedstoneCircuitBlock;
+import gregtech.api.util.GT_CircuitryBehavior;
+
+public class GT_Circuit_BitAnd extends GT_CircuitryBehavior {
+
+ public GT_Circuit_BitAnd(int aIndex) {
+ super(aIndex);
+ }
+
+ @Override
+ public void initParameters(int[] aCircuitData, IRedstoneCircuitBlock aRedstoneCircuitBlock) {
+ aCircuitData[0] = 0;
+ aCircuitData[1] = 0;
+ aCircuitData[2] = 0;
+ aCircuitData[3] = 0;
+ }
+
+ @Override
+ public void validateParameters(int[] aCircuitData, IRedstoneCircuitBlock aRedstoneCircuitBlock) {
+ if (aCircuitData[0] < 0) {
+ aCircuitData[0] = 0;
+ }
+ if (aCircuitData[1] < 0) {
+ aCircuitData[1] = 0;
+ }
+ if (aCircuitData[2] < 0) {
+ aCircuitData[2] = 0;
+ }
+ if (aCircuitData[3] < 0) {
+ aCircuitData[3] = 0;
+ }
+ if (aCircuitData[0] > 1) {
+ aCircuitData[0] = 1;
+ }
+ if (aCircuitData[1] > 1) {
+ aCircuitData[1] = 1;
+ }
+ if (aCircuitData[2] > 1) {
+ aCircuitData[2] = 1;
+ }
+ if (aCircuitData[3] > 1) {
+ aCircuitData[3] = 1;
+ }
+ }
+
+ @Override
+ public void onTick(int[] aCircuitData, IRedstoneCircuitBlock aRedstoneCircuitBlock) {
+ aRedstoneCircuitBlock.setRedstone(
+ (byte) ((getStrongestRedstone(aRedstoneCircuitBlock)
+ & (aCircuitData[0] | aCircuitData[1] << 1 | aCircuitData[2] << 2 | aCircuitData[3] << 3)) != 0 ? 15
+ : 0),
+ aRedstoneCircuitBlock.getOutputFacing());
+ }
+
+ @Override
+ public String getName() {
+ return "Hardcode Bit-AND";
+ }
+
+ @Override
+ public String getDescription() {
+ return "( signal & this ) != 0";
+ }
+
+ @Override
+ public String getDataDescription(int[] aCircuitData, int aCircuitDataIndex) {
+ return "Bit " + aCircuitDataIndex + ":";
+ }
+
+ @Override
+ public boolean displayItemStack(int[] aCircuitData, IRedstoneCircuitBlock aRedstoneCircuitBlock, int aIndex) {
+ return false;
+ }
+
+ @Override
+ public String getDataDisplay(int[] aCircuitData, int aCircuitDataIndex) {
+ return aCircuitData[aCircuitDataIndex] == 0 ? "OFF" : "ON";
+ }
+}
diff --git a/src/main/java/gregtech/common/redstonecircuits/GT_Circuit_CombinationLock.java b/src/main/java/gregtech/common/redstonecircuits/GT_Circuit_CombinationLock.java
new file mode 100644
index 0000000000..67d8527606
--- /dev/null
+++ b/src/main/java/gregtech/common/redstonecircuits/GT_Circuit_CombinationLock.java
@@ -0,0 +1,109 @@
+package gregtech.common.redstonecircuits;
+
+import gregtech.api.interfaces.IRedstoneCircuitBlock;
+import gregtech.api.util.GT_CircuitryBehavior;
+
+public class GT_Circuit_CombinationLock extends GT_CircuitryBehavior {
+
+ public GT_Circuit_CombinationLock(int aIndex) {
+ super(aIndex);
+ }
+
+ @Override
+ public void initParameters(int[] aCircuitData, IRedstoneCircuitBlock aRedstoneCircuitBlock) {
+ aCircuitData[0] = 1;
+ aCircuitData[1] = 0;
+ aCircuitData[2] = 0;
+ aCircuitData[3] = 0;
+ aCircuitData[4] = 0;
+ aCircuitData[5] = 0;
+ }
+
+ @Override
+ public void validateParameters(int[] aCircuitData, IRedstoneCircuitBlock aRedstoneCircuitBlock) {
+ if (aCircuitData[0] < 1) {
+ aCircuitData[0] = 1;
+ }
+ if (aCircuitData[1] < 0) {
+ aCircuitData[1] = 0;
+ }
+ if (aCircuitData[2] < 0) {
+ aCircuitData[2] = 0;
+ }
+ if (aCircuitData[3] < 0) {
+ aCircuitData[3] = 0;
+ }
+ if (aCircuitData[0] > 15) {
+ aCircuitData[0] = 15;
+ }
+ if (aCircuitData[1] > 15) {
+ aCircuitData[1] = 15;
+ }
+ if (aCircuitData[2] > 15) {
+ aCircuitData[2] = 15;
+ }
+ if (aCircuitData[3] > 15) {
+ aCircuitData[3] = 15;
+ }
+ if (aCircuitData[4] < 0) {
+ aCircuitData[4] = 0;
+ }
+ if (aCircuitData[4] > 3) {
+ aCircuitData[4] = 3;
+ }
+ if (aCircuitData[5] < 0) {
+ aCircuitData[5] = 0;
+ }
+ }
+
+ @Override
+ public void onTick(int[] aCircuitData, IRedstoneCircuitBlock aRedstoneCircuitBlock) {
+ while ((aCircuitData[aCircuitData[4]] == 0) && (aCircuitData[4] < 4)) {
+ aCircuitData[4] += 1;
+ }
+ if (aCircuitData[4] < 4) {
+ int tRedstone = getStrongestRedstone(aRedstoneCircuitBlock);
+ if (tRedstone > 0) {
+ if (aCircuitData[5] == 0) {
+ if (tRedstone == aCircuitData[aCircuitData[4]]) {
+ aCircuitData[4] += 1;
+ } else {
+ aCircuitData[4] = 0;
+ }
+ }
+ aCircuitData[5] = 1;
+ } else {
+ aCircuitData[5] = 0;
+ }
+ aRedstoneCircuitBlock.setRedstone((byte) 0, aRedstoneCircuitBlock.getOutputFacing());
+ } else {
+ aRedstoneCircuitBlock.setRedstone((byte) 15, aRedstoneCircuitBlock.getOutputFacing());
+ aCircuitData[4] = 0;
+ }
+ }
+
+ @Override
+ public String getName() {
+ return "Combination Lock";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Checks Combinations";
+ }
+
+ @Override
+ public String getDataDescription(int[] aCircuitData, int aCircuitDataIndex) {
+ return "Power " + aCircuitDataIndex;
+ }
+
+ @Override
+ public boolean displayItemStack(int[] aCircuitData, IRedstoneCircuitBlock aRedstoneCircuitBlock, int aIndex) {
+ return false;
+ }
+
+ @Override
+ public String getDataDisplay(int[] aCircuitData, int aCircuitDataIndex) {
+ return null;
+ }
+}
diff --git a/src/main/java/gregtech/common/redstonecircuits/GT_Circuit_Equals.java b/src/main/java/gregtech/common/redstonecircuits/GT_Circuit_Equals.java
new file mode 100644
index 0000000000..9e9af183e8
--- /dev/null
+++ b/src/main/java/gregtech/common/redstonecircuits/GT_Circuit_Equals.java
@@ -0,0 +1,73 @@
+package gregtech.common.redstonecircuits;
+
+import gregtech.api.interfaces.IRedstoneCircuitBlock;
+import gregtech.api.util.GT_CircuitryBehavior;
+
+public class GT_Circuit_Equals extends GT_CircuitryBehavior {
+
+ public GT_Circuit_Equals(int aIndex) {
+ super(aIndex);
+ }
+
+ @Override
+ public void initParameters(int[] aCircuitData, IRedstoneCircuitBlock aRedstoneCircuitBlock) {
+ aCircuitData[0] = 0;
+ aCircuitData[1] = 0;
+ }
+
+ @Override
+ public void validateParameters(int[] aCircuitData, IRedstoneCircuitBlock aRedstoneCircuitBlock) {
+ if (aCircuitData[0] < 0) {
+ aCircuitData[0] = 0;
+ }
+ if (aCircuitData[0] > 15) {
+ aCircuitData[0] = 15;
+ }
+ if (aCircuitData[1] < 0) {
+ aCircuitData[3] = 0;
+ }
+ if (aCircuitData[1] > 1) {
+ aCircuitData[3] = 1;
+ }
+ }
+
+ @Override
+ public void onTick(int[] aCircuitData, IRedstoneCircuitBlock aRedstoneCircuitBlock) {
+ aRedstoneCircuitBlock.setRedstone(
+ ((byte) (((aCircuitData[1] != 0) == (getStrongestRedstone(aRedstoneCircuitBlock) == aCircuitData[0])) ? 0
+ : 15)),
+ aRedstoneCircuitBlock.getOutputFacing());
+ }
+
+ @Override
+ public String getName() {
+ return "Equals";
+ }
+
+ @Override
+ public String getDescription() {
+ return "signal == this";
+ }
+
+ @Override
+ public String getDataDescription(int[] aCircuitData, int aCircuitDataIndex) {
+ return switch (aCircuitDataIndex) {
+ case 0 -> "Signal";
+ case 1 -> aCircuitData[1] == 0 ? "Equal" : "Unequal";
+ default -> "";
+ };
+ }
+
+ @Override
+ public boolean displayItemStack(int[] aCircuitData, IRedstoneCircuitBlock aRedstoneCircuitBlock, int aIndex) {
+ return false;
+ }
+
+ @Override
+ public String getDataDisplay(int[] aCircuitData, int aCircuitDataIndex) {
+ if (aCircuitDataIndex > 0) {
+ return "";
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/gregtech/common/redstonecircuits/GT_Circuit_Pulser.java b/src/main/java/gregtech/common/redstonecircuits/GT_Circuit_Pulser.java
new file mode 100644
index 0000000000..c54d0be060
--- /dev/null
+++ b/src/main/java/gregtech/common/redstonecircuits/GT_Circuit_Pulser.java
@@ -0,0 +1,92 @@
+package gregtech.common.redstonecircuits;
+
+import gregtech.api.interfaces.IRedstoneCircuitBlock;
+import gregtech.api.util.GT_CircuitryBehavior;
+
+public class GT_Circuit_Pulser extends GT_CircuitryBehavior {
+
+ public GT_Circuit_Pulser(int aIndex) {
+ super(aIndex);
+ }
+
+ @Override
+ public void initParameters(int[] aCircuitData, IRedstoneCircuitBlock aRedstoneCircuitBlock) {
+ aCircuitData[0] = 1;
+ aCircuitData[1] = 16;
+ aCircuitData[4] = 0;
+ }
+
+ @Override
+ public void validateParameters(int[] aCircuitData, IRedstoneCircuitBlock aRedstoneCircuitBlock) {
+ if (aCircuitData[0] < 1) {
+ aCircuitData[0] = 1;
+ }
+ if (aCircuitData[1] < 0) {
+ aCircuitData[1] = 0;
+ }
+ if (aCircuitData[1] > 16) {
+ aCircuitData[1] = 16;
+ }
+ if (aCircuitData[4] < 0) {
+ aCircuitData[4] = 0;
+ }
+ }
+
+ @Override
+ public void onTick(int[] aCircuitData, IRedstoneCircuitBlock aRedstoneCircuitBlock) {
+ byte redstoneSignal = aCircuitData[1] == 0 ? getWeakestNonZeroRedstone(aRedstoneCircuitBlock)
+ : getStrongestRedstone(aRedstoneCircuitBlock);
+ if (aCircuitData[4] == 0) {
+ aCircuitData[5] = redstoneSignal;
+ }
+ if ((redstoneSignal > 0) || (aCircuitData[4] > 0)) {
+ int index = 4;
+ int tmp42_41 = aCircuitData[index];
+ aCircuitData[index] = (tmp42_41 + 1);
+ if ((tmp42_41 >= aCircuitData[0]) && (redstoneSignal <= 0)) {
+ aCircuitData[4] = 0;
+ }
+ }
+ aRedstoneCircuitBlock.setRedstone(
+ (aCircuitData[4] > 0) && (aCircuitData[4] <= aCircuitData[0]) ? (byte) aCircuitData[1]
+ : (aCircuitData[1] <= 0) || (aCircuitData[1] > 15) ? (byte) aCircuitData[5] : 0,
+ aRedstoneCircuitBlock.getOutputFacing());
+ }
+
+ @Override
+ public String getName() {
+ return "Pulser";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Limits&Enlengths";
+ }
+
+ @Override
+ public String getDataDescription(int[] aCircuitData, int aCircuitDataIndex) {
+ return switch (aCircuitDataIndex) {
+ case 0 -> "Length";
+ case 1 -> "RS Out";
+ default -> "";
+ };
+ }
+
+ @Override
+ public boolean displayItemStack(int[] aCircuitData, IRedstoneCircuitBlock aRedstoneCircuitBlock, int aIndex) {
+ return false;
+ }
+
+ @Override
+ public String getDataDisplay(int[] aCircuitData, int aCircuitDataIndex) {
+ if (aCircuitDataIndex == 1) {
+ if (aCircuitData[aCircuitDataIndex] == 16) {
+ return "HIGHEST";
+ }
+ if (aCircuitData[aCircuitDataIndex] == 0) {
+ return "LOWEST";
+ }
+ }
+ return aCircuitDataIndex > 1 ? "" : null;
+ }
+}
diff --git a/src/main/java/gregtech/common/redstonecircuits/GT_Circuit_Randomizer.java b/src/main/java/gregtech/common/redstonecircuits/GT_Circuit_Randomizer.java
new file mode 100644
index 0000000000..336bf9928d
--- /dev/null
+++ b/src/main/java/gregtech/common/redstonecircuits/GT_Circuit_Randomizer.java
@@ -0,0 +1,86 @@
+package gregtech.common.redstonecircuits;
+
+import gregtech.api.interfaces.IRedstoneCircuitBlock;
+import gregtech.api.util.GT_CircuitryBehavior;
+
+public class GT_Circuit_Randomizer extends GT_CircuitryBehavior {
+
+ public GT_Circuit_Randomizer(int aIndex) {
+ super(aIndex);
+ }
+
+ @Override
+ public void initParameters(int[] aCircuitData, IRedstoneCircuitBlock aRedstoneCircuitBlock) {
+ aCircuitData[0] = 1;
+ aCircuitData[4] = 0;
+ }
+
+ @Override
+ public void validateParameters(int[] aCircuitData, IRedstoneCircuitBlock aRedstoneCircuitBlock) {
+ if (aCircuitData[0] < 1) {
+ aCircuitData[0] = 1;
+ }
+ if (aCircuitData[3] < 0) {
+ aCircuitData[3] = 0;
+ }
+ if (aCircuitData[3] > 1) {
+ aCircuitData[3] = 1;
+ }
+ if (aCircuitData[4] < 0) {
+ aCircuitData[4] = 0;
+ }
+ }
+
+ @Override
+ public void onTick(int[] aCircuitData, IRedstoneCircuitBlock aRedstoneCircuitBlock) {
+ if (aCircuitData[3] == 1) {
+ if (getAnyRedstone(aRedstoneCircuitBlock)) {
+ aCircuitData[4] += 1;
+ } else {
+ aCircuitData[4] = 0;
+ }
+ } else if (getAnyRedstone(aRedstoneCircuitBlock)) {
+ aCircuitData[4] = 0;
+ } else {
+ aCircuitData[4] += 1;
+ }
+ if (aCircuitData[4] >= aCircuitData[0]) {
+ aCircuitData[4] = 0;
+ aRedstoneCircuitBlock
+ .setRedstone((byte) aRedstoneCircuitBlock.getRandom(16), aRedstoneCircuitBlock.getOutputFacing());
+ }
+ }
+
+ @Override
+ public String getName() {
+ return "Randomizer";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Randomizes Redstone";
+ }
+
+ @Override
+ public String getDataDescription(int[] aCircuitData, int aCircuitDataIndex) {
+ return switch (aCircuitDataIndex) {
+ case 0 -> "Delay";
+ case 3 -> aCircuitData[aCircuitDataIndex] == 1 ? "RS => ON" : "RS => OFF";
+ case 4 -> "Status";
+ default -> "";
+ };
+ }
+
+ @Override
+ public boolean displayItemStack(int[] aCircuitData, IRedstoneCircuitBlock aRedstoneCircuitBlock, int aIndex) {
+ return false;
+ }
+
+ @Override
+ public String getDataDisplay(int[] aCircuitData, int aCircuitDataIndex) {
+ if (aCircuitDataIndex != 0) {
+ return "";
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/gregtech/common/redstonecircuits/GT_Circuit_RedstoneMeter.java b/src/main/java/gregtech/common/redstonecircuits/GT_Circuit_RedstoneMeter.java
new file mode 100644
index 0000000000..4db261fcf0
--- /dev/null
+++ b/src/main/java/gregtech/common/redstonecircuits/GT_Circuit_RedstoneMeter.java
@@ -0,0 +1,94 @@
+package gregtech.common.redstonecircuits;
+
+import gregtech.api.interfaces.IRedstoneCircuitBlock;
+import gregtech.api.util.GT_CircuitryBehavior;
+
+public class GT_Circuit_RedstoneMeter extends GT_CircuitryBehavior {
+
+ public GT_Circuit_RedstoneMeter(int aIndex) {
+ super(aIndex);
+ }
+
+ @Override
+ public void initParameters(int[] aCircuitData, IRedstoneCircuitBlock aRedstoneCircuitBlock) {
+ aCircuitData[0] = 1;
+ aCircuitData[1] = 15;
+ aCircuitData[2] = 0;
+ aCircuitData[3] = 15;
+ }
+
+ @Override
+ public void validateParameters(int[] aCircuitData, IRedstoneCircuitBlock aRedstoneCircuitBlock) {
+ if (aCircuitData[0] < 0) {
+ aCircuitData[0] = 0;
+ }
+ if (aCircuitData[0] > 15) {
+ aCircuitData[0] = 15;
+ }
+ if (aCircuitData[1] < 0) {
+ aCircuitData[1] = 0;
+ }
+ if (aCircuitData[1] > 15) {
+ aCircuitData[1] = 15;
+ }
+ if (aCircuitData[1] < aCircuitData[0]) {
+ aCircuitData[1] = aCircuitData[0];
+ }
+ if (aCircuitData[2] < 0) {
+ aCircuitData[2] = 0;
+ }
+ if (aCircuitData[2] > 1) {
+ aCircuitData[2] = 1;
+ }
+ if (aCircuitData[3] < 0) {
+ aCircuitData[3] = 0;
+ }
+ if (aCircuitData[3] > 15) {
+ aCircuitData[3] = 15;
+ }
+ }
+
+ @Override
+ public void onTick(int[] aCircuitData, IRedstoneCircuitBlock aRedstoneCircuitBlock) {
+ byte tRedstone = getStrongestRedstone(aRedstoneCircuitBlock);
+ aRedstoneCircuitBlock
+ .setRedstone(
+ ((tRedstone >= aCircuitData[0]) && (tRedstone <= aCircuitData[1]) ? 1 : 0)
+ != (aCircuitData[2] != 0 ? 1 : 0) ? (byte) aCircuitData[3] : 0,
+ aRedstoneCircuitBlock.getOutputFacing());
+ }
+
+ @Override
+ public String getName() {
+ return "Redstone Meter";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Checks Boundaries";
+ }
+
+ @Override
+ public String getDataDescription(int[] aCircuitData, int aCircuitDataIndex) {
+ return switch (aCircuitDataIndex) {
+ case 0 -> "Lower";
+ case 1 -> "Upper";
+ case 2 -> "Invert:";
+ case 3 -> "RS Out:";
+ default -> "";
+ };
+ }
+
+ @Override
+ public boolean displayItemStack(int[] aCircuitData, IRedstoneCircuitBlock aRedstoneCircuitBlock, int aIndex) {
+ return false;
+ }
+
+ @Override
+ public String getDataDisplay(int[] aCircuitData, int aCircuitDataIndex) {
+ if (aCircuitDataIndex == 2) {
+ return aCircuitData[2] == 0 ? "OFF" : "ON";
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/gregtech/common/redstonecircuits/GT_Circuit_Repeater.java b/src/main/java/gregtech/common/redstonecircuits/GT_Circuit_Repeater.java
new file mode 100644
index 0000000000..b96762d73b
--- /dev/null
+++ b/src/main/java/gregtech/common/redstonecircuits/GT_Circuit_Repeater.java
@@ -0,0 +1,86 @@
+package gregtech.common.redstonecircuits;
+
+import gregtech.api.interfaces.IRedstoneCircuitBlock;
+import gregtech.api.util.GT_CircuitryBehavior;
+
+public class GT_Circuit_Repeater extends GT_CircuitryBehavior {
+
+ public GT_Circuit_Repeater(int aIndex) {
+ super(aIndex);
+ }
+
+ @Override
+ public void initParameters(int[] aCircuitData, IRedstoneCircuitBlock aRedstoneCircuitBlock) {
+ aCircuitData[0] = 1;
+ aCircuitData[4] = 0;
+ aCircuitData[5] = -1;
+ }
+
+ @Override
+ public void validateParameters(int[] aCircuitData, IRedstoneCircuitBlock aRedstoneCircuitBlock) {
+ if (aCircuitData[0] < 1) {
+ aCircuitData[0] = 1;
+ }
+ if (aCircuitData[4] < 0) {
+ aCircuitData[4] = 0;
+ }
+ if (aCircuitData[5] < -1) {
+ aCircuitData[5] = -1;
+ }
+ }
+
+ @Override
+ public void onTick(int[] aCircuitData, IRedstoneCircuitBlock aRedstoneCircuitBlock) {
+ if (getAnyRedstone(aRedstoneCircuitBlock)) {
+ aCircuitData[4] += 1;
+ if (aCircuitData[5] < 0) {
+ aCircuitData[5] = 0;
+ }
+ }
+ if ((aCircuitData[5] >= 0) && (aCircuitData[5] < aCircuitData[0])) {
+ aCircuitData[5] += 1;
+ }
+ if (aCircuitData[4] > 0) {
+ if (aCircuitData[5] >= aCircuitData[0]) {
+ aCircuitData[4] -= 1;
+ aRedstoneCircuitBlock.setRedstone((byte) 15, aRedstoneCircuitBlock.getOutputFacing());
+ } else {
+ aRedstoneCircuitBlock.setRedstone((byte) 0, aRedstoneCircuitBlock.getOutputFacing());
+ }
+ } else {
+ aRedstoneCircuitBlock.setRedstone((byte) 0, aRedstoneCircuitBlock.getOutputFacing());
+ aCircuitData[5] = -1;
+ }
+ }
+
+ @Override
+ public String getName() {
+ return "Repeater";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Delays RS-Signal";
+ }
+
+ @Override
+ public String getDataDescription(int[] aCircuitData, int aCircuitDataIndex) {
+ if (aCircuitDataIndex == 0) {
+ return "Delay";
+ }
+ return "";
+ }
+
+ @Override
+ public boolean displayItemStack(int[] aCircuitData, IRedstoneCircuitBlock aRedstoneCircuitBlock, int aIndex) {
+ return false;
+ }
+
+ @Override
+ public String getDataDisplay(int[] aCircuitData, int aCircuitDataIndex) {
+ if (aCircuitDataIndex > 0) {
+ return "";
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/gregtech/common/redstonecircuits/GT_Circuit_Timer.java b/src/main/java/gregtech/common/redstonecircuits/GT_Circuit_Timer.java
new file mode 100644
index 0000000000..026c83dfbc
--- /dev/null
+++ b/src/main/java/gregtech/common/redstonecircuits/GT_Circuit_Timer.java
@@ -0,0 +1,108 @@
+package gregtech.common.redstonecircuits;
+
+import gregtech.api.interfaces.IRedstoneCircuitBlock;
+import gregtech.api.util.GT_CircuitryBehavior;
+
+public class GT_Circuit_Timer extends GT_CircuitryBehavior {
+
+ public GT_Circuit_Timer(int aIndex) {
+ super(aIndex);
+ }
+
+ @Override
+ public void initParameters(int[] aCircuitData, IRedstoneCircuitBlock aRedstoneCircuitBlock) {
+ aCircuitData[0] = 2;
+ aCircuitData[1] = 1;
+ aCircuitData[2] = 2;
+ aCircuitData[4] = 0;
+ }
+
+ @Override
+ public void validateParameters(int[] aCircuitData, IRedstoneCircuitBlock aRedstoneCircuitBlock) {
+ if (aCircuitData[0] < 2) {
+ aCircuitData[0] = 2;
+ }
+ if (aCircuitData[1] < 1) {
+ aCircuitData[1] = 1;
+ }
+ if (aCircuitData[2] < 2) {
+ aCircuitData[2] = 2;
+ }
+ if (aCircuitData[3] < 0) {
+ aCircuitData[3] = 0;
+ }
+ if (aCircuitData[3] > 1) {
+ aCircuitData[3] = 1;
+ }
+ if (aCircuitData[4] < 0) {
+ aCircuitData[4] = 0;
+ }
+ }
+
+ @Override
+ public void onTick(int[] aCircuitData, IRedstoneCircuitBlock aRedstoneCircuitBlock) {
+ if (aCircuitData[3] == 1) {
+ if (getAnyRedstone(aRedstoneCircuitBlock)) {
+ aCircuitData[4] += 1;
+ } else {
+ aCircuitData[4] = 0;
+ }
+ } else if (getAnyRedstone(aRedstoneCircuitBlock)) {
+ aCircuitData[4] = 0;
+ } else {
+ aCircuitData[4] += 1;
+ }
+ if (aCircuitData[4] >= aCircuitData[0]) {
+ if (aCircuitData[1] > 1) {
+ if (aCircuitData[4] >= aCircuitData[0] + (aCircuitData[1] - 1) * aCircuitData[2]) {
+ aRedstoneCircuitBlock.setRedstone((byte) 15, aRedstoneCircuitBlock.getOutputFacing());
+ aCircuitData[4] = 0;
+ } else {
+ aRedstoneCircuitBlock.setRedstone(
+ (byte) ((aCircuitData[4] - aCircuitData[0]) % aCircuitData[2] == 0 ? 15 : 0),
+ aRedstoneCircuitBlock.getOutputFacing());
+ }
+ } else {
+ aRedstoneCircuitBlock.setRedstone((byte) 15, aRedstoneCircuitBlock.getOutputFacing());
+ aCircuitData[4] = 0;
+ }
+ } else {
+ aRedstoneCircuitBlock.setRedstone((byte) 0, aRedstoneCircuitBlock.getOutputFacing());
+ }
+ }
+
+ @Override
+ public String getName() {
+ return "Timer";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Pulses Redstone";
+ }
+
+ @Override
+ public String getDataDescription(int[] aCircuitData, int aCircuitDataIndex) {
+ return switch (aCircuitDataIndex) {
+ case 0 -> "Delay";
+ case 1 -> "Pulses";
+ case 2 -> "Length";
+ case 3 -> aCircuitData[aCircuitDataIndex] == 1 ? "RS => ON" : "RS => OFF";
+ case 4 -> "Time";
+ default -> "";
+ };
+ }
+
+ @Override
+ public boolean displayItemStack(int[] aCircuitData, IRedstoneCircuitBlock aRedstoneCircuitBlock, int aIndex) {
+ return false;
+ }
+
+ @Override
+ public String getDataDisplay(int[] aCircuitData, int aCircuitDataIndex) {
+ if (aCircuitDataIndex == 3) {
+ return "";
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/gregtech/common/render/GT_CapeRenderer.java b/src/main/java/gregtech/common/render/GT_CapeRenderer.java
new file mode 100644
index 0000000000..ec9ef2880c
--- /dev/null
+++ b/src/main/java/gregtech/common/render/GT_CapeRenderer.java
@@ -0,0 +1,148 @@
+package gregtech.common.render;
+
+import java.util.Collection;
+
+import net.minecraft.client.entity.AbstractClientPlayer;
+import net.minecraft.client.model.ModelBiped;
+import net.minecraft.client.renderer.entity.RenderManager;
+import net.minecraft.client.renderer.entity.RenderPlayer;
+import net.minecraft.potion.Potion;
+import net.minecraft.util.MathHelper;
+import net.minecraft.util.ResourceLocation;
+import net.minecraftforge.client.event.RenderPlayerEvent;
+
+import org.lwjgl.opengl.GL11;
+
+import gregtech.api.enums.GT_Values;
+import gregtech.api.util.GT_Log;
+import gregtech.api.util.GT_Utility;
+
+public class GT_CapeRenderer extends RenderPlayer {
+
+ private final ResourceLocation[] mCapes = { new ResourceLocation("gregtech:textures/BrainTechCape.png"),
+ new ResourceLocation("gregtech:textures/GregTechCape.png"),
+ new ResourceLocation("gregtech:textures/MrBrainCape.png"),
+ new ResourceLocation("gregtech:textures/GregoriusCape.png"),
+ new ResourceLocation("gregtech:textures/DonorCape.png"), new ResourceLocation("gregtech:textures/DevCape.png"),
+ new ResourceLocation("gregtech:textures/Steam.png"), new ResourceLocation("gregtech:textures/Titanium.png"),
+ new ResourceLocation("gregtech:textures/Neutronium.png"),
+ new ResourceLocation("gregtech:textures/Stargate.png") };
+ private final Collection<String> mCapeList;
+
+ public GT_CapeRenderer(Collection<String> aCapeList) {
+ this.mCapeList = aCapeList;
+ setRenderManager(RenderManager.instance);
+ }
+
+ public void receiveRenderSpecialsEvent(RenderPlayerEvent.Specials.Pre aEvent) {
+ AbstractClientPlayer aPlayer = (AbstractClientPlayer) aEvent.entityPlayer;
+ if (GT_Utility.getFullInvisibility(aPlayer)) {
+ aEvent.setCanceled(true);
+ return;
+ }
+ float aPartialTicks = aEvent.partialRenderTick;
+ if (aPlayer.isInvisible()) {
+ return;
+ }
+ if (GT_Utility.getPotion(aPlayer, Potion.invisibility.id)) {
+ return;
+ }
+ try {
+ ResourceLocation tResource = aPlayer.getLocationCape();
+ if (aPlayer.getDisplayName()
+ .equalsIgnoreCase("Friedi4321")) {
+ tResource = this.mCapes[0];
+ }
+ if (this.mCapeList.contains(
+ aPlayer.getDisplayName()
+ .toLowerCase())) {
+ tResource = this.mCapes[1];
+ }
+ if (aPlayer.getDisplayName()
+ .equalsIgnoreCase("Mr_Brain")) {
+ tResource = this.mCapes[2];
+ }
+ if (aPlayer.getDisplayName()
+ .equalsIgnoreCase("GregoriusT")) {
+ tResource = this.mCapes[3];
+ }
+ if (this.mCapeList.contains(
+ aPlayer.getDisplayName()
+ .toLowerCase() + ":capedonor")) {
+ tResource = this.mCapes[4];
+ }
+ if (this.mCapeList.contains(
+ aPlayer.getDisplayName()
+ .toLowerCase() + ":capedev")) {
+ tResource = this.mCapes[5];
+ }
+ if (this.mCapeList.contains(
+ aPlayer.getDisplayName()
+ .toLowerCase() + ":cape_steam")) {
+ tResource = this.mCapes[6];
+ }
+ if (this.mCapeList.contains(
+ aPlayer.getDisplayName()
+ .toLowerCase() + ":cape_titanium")) {
+ tResource = this.mCapes[7];
+ }
+ if (this.mCapeList.contains(
+ aPlayer.getDisplayName()
+ .toLowerCase() + ":cape_neutronium")) {
+ tResource = this.mCapes[8];
+ }
+ if (this.mCapeList.contains(
+ aPlayer.getDisplayName()
+ .toLowerCase() + ":cape_stargate")) {
+ tResource = this.mCapes[9];
+ }
+
+ if ((tResource != null) && (!aPlayer.getHideCape())) {
+ bindTexture(tResource);
+ GL11.glPushMatrix();
+ GL11.glTranslatef(0.0F, 0.0F, 0.125F);
+ double d0 = aPlayer.field_71091_bM + (aPlayer.field_71094_bP - aPlayer.field_71091_bM) * aPartialTicks
+ - (aPlayer.prevPosX + (aPlayer.posX - aPlayer.prevPosX) * aPartialTicks);
+ double d1 = aPlayer.field_71096_bN + (aPlayer.field_71095_bQ - aPlayer.field_71096_bN) * aPartialTicks
+ - (aPlayer.prevPosY + (aPlayer.posY - aPlayer.prevPosY) * aPartialTicks);
+ double d2 = aPlayer.field_71097_bO + (aPlayer.field_71085_bR - aPlayer.field_71097_bO) * aPartialTicks
+ - (aPlayer.prevPosZ + (aPlayer.posZ - aPlayer.prevPosZ) * aPartialTicks);
+ float f6 = aPlayer.prevRenderYawOffset
+ + (aPlayer.renderYawOffset - aPlayer.prevRenderYawOffset) * aPartialTicks;
+ double d3 = MathHelper.sin(f6 * (float) Math.PI / 180.0F);
+ double d4 = -MathHelper.cos(f6 * (float) Math.PI / 180.0F);
+ float f7 = (float) d1 * 10.0F;
+ float f8 = (float) (d0 * d3 + d2 * d4) * 100.0F;
+ float f9 = (float) (d0 * d4 - d2 * d3) * 100.0F;
+ if (f7 < -6.0F) {
+ f7 = -6.0F;
+ }
+ if (f7 > 32.0F) {
+ f7 = 32.0F;
+ }
+ if (f8 < 0.0F) {
+ f8 = 0.0F;
+ }
+ float f10 = aPlayer.prevCameraYaw + (aPlayer.cameraYaw - aPlayer.prevCameraYaw) * aPartialTicks;
+ f7 += MathHelper.sin(
+ (aPlayer.prevDistanceWalkedModified
+ + (aPlayer.distanceWalkedModified - aPlayer.prevDistanceWalkedModified) * aPartialTicks) * 6.0F)
+ * 32.0F
+ * f10;
+ if (aPlayer.isSneaking()) {
+ f7 += 25.0F;
+ }
+ GL11.glRotatef(6.0F + f8 / 2.0F + f7, 1.0F, 0.0F, 0.0F);
+ GL11.glRotatef(f9 / 2.0F, 0.0F, 0.0F, 1.0F);
+ GL11.glRotatef(-f9 / 2.0F, 0.0F, 1.0F, 0.0F);
+ GL11.glRotatef(180.0F, 0.0F, 1.0F, 0.0F);
+ ((ModelBiped) this.mainModel).renderCloak(0.0625F);
+ GL11.glPopMatrix();
+ }
+ } catch (Throwable e) {
+ if (GT_Values.D1) {
+ e.printStackTrace(GT_Log.err);
+ }
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/render/GT_CopiedBlockTexture.java b/src/main/java/gregtech/common/render/GT_CopiedBlockTexture.java
new file mode 100644
index 0000000000..937c1a994f
--- /dev/null
+++ b/src/main/java/gregtech/common/render/GT_CopiedBlockTexture.java
@@ -0,0 +1,112 @@
+package gregtech.common.render;
+
+import net.minecraft.block.Block;
+import net.minecraft.client.renderer.RenderBlocks;
+import net.minecraft.util.IIcon;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.interfaces.IBlockContainer;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.util.LightingHelper;
+
+public class GT_CopiedBlockTexture extends GT_TextureBase implements ITexture, IBlockContainer {
+
+ private final Block mBlock;
+ private final byte mSide, mMeta;
+
+ protected GT_CopiedBlockTexture(Block aBlock, int ordinalSide, int aMeta, short[] aRGBa, boolean allowAlpha) {
+ if (aRGBa.length != 4) throw new IllegalArgumentException("RGBa doesn't have 4 Values @ GT_CopiedBlockTexture");
+ mBlock = aBlock;
+ mSide = (byte) ordinalSide;
+ mMeta = (byte) aMeta;
+ }
+
+ @Override
+ public boolean isOldTexture() {
+ return false;
+ }
+
+ private IIcon getIcon(int ordinalSide) {
+ if (mSide == 6) return mBlock.getIcon(ordinalSide, mMeta);
+ return mBlock.getIcon(mSide, mMeta);
+ }
+
+ @Override
+ public void renderXPos(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
+ final IIcon aIcon = getIcon(ForgeDirection.EAST.ordinal());
+ aRenderer.field_152631_f = true;
+ startDrawingQuads(aRenderer, 1.0f, 0.0f, 0.0f);
+ new LightingHelper(aRenderer).setupLightingXPos(aBlock, aX, aY, aZ)
+ .setupColor(ForgeDirection.EAST, 0xffffff);
+ aRenderer.renderFaceXPos(aBlock, aX, aY, aZ, aIcon);
+ draw(aRenderer);
+ aRenderer.field_152631_f = false;
+ }
+
+ @Override
+ public void renderXNeg(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
+ startDrawingQuads(aRenderer, -1.0f, 0.0f, 0.0f);
+ final IIcon aIcon = getIcon(ForgeDirection.WEST.ordinal());
+ new LightingHelper(aRenderer).setupLightingXNeg(aBlock, aX, aY, aZ)
+ .setupColor(ForgeDirection.WEST, 0xffffff);
+ aRenderer.renderFaceXNeg(aBlock, aX, aY, aZ, aIcon);
+ draw(aRenderer);
+ }
+
+ @Override
+ public void renderYPos(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
+ startDrawingQuads(aRenderer, 0.0f, 1.0f, 0.0f);
+ final IIcon aIcon = getIcon(ForgeDirection.UP.ordinal());
+ new LightingHelper(aRenderer).setupLightingYPos(aBlock, aX, aY, aZ)
+ .setupColor(ForgeDirection.UP, 0xffffff);
+ aRenderer.renderFaceYPos(aBlock, aX, aY, aZ, aIcon);
+ draw(aRenderer);
+ }
+
+ @Override
+ public void renderYNeg(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
+ startDrawingQuads(aRenderer, 0.0f, -1.0f, 0.0f);
+ final IIcon aIcon = getIcon(ForgeDirection.DOWN.ordinal());
+ new LightingHelper(aRenderer).setupLightingYNeg(aBlock, aX, aY, aZ)
+ .setupColor(ForgeDirection.DOWN, 0xffffff);
+ aRenderer.renderFaceYNeg(aBlock, aX, aY, aZ, aIcon);
+ draw(aRenderer);
+ }
+
+ @Override
+ public void renderZPos(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
+ startDrawingQuads(aRenderer, 0.0f, 0.0f, 1.0f);
+ final IIcon aIcon = getIcon(ForgeDirection.SOUTH.ordinal());
+ new LightingHelper(aRenderer).setupLightingZPos(aBlock, aX, aY, aZ)
+ .setupColor(ForgeDirection.SOUTH, 0xffffff);
+ aRenderer.renderFaceZPos(aBlock, aX, aY, aZ, aIcon);
+ draw(aRenderer);
+ }
+
+ @Override
+ public void renderZNeg(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
+ startDrawingQuads(aRenderer, 0.0f, 0.0f, -1.0f);
+ final IIcon aIcon = getIcon(ForgeDirection.NORTH.ordinal());
+ aRenderer.field_152631_f = true;
+ new LightingHelper(aRenderer).setupLightingZNeg(aBlock, aX, aY, aZ)
+ .setupColor(ForgeDirection.NORTH, 0xffffff);
+ aRenderer.renderFaceZNeg(aBlock, aX, aY, aZ, aIcon);
+ draw(aRenderer);
+ aRenderer.field_152631_f = false;
+ }
+
+ @Override
+ public boolean isValidTexture() {
+ return mBlock != null;
+ }
+
+ @Override
+ public Block getBlock() {
+ return mBlock;
+ }
+
+ @Override
+ public byte getMeta() {
+ return mMeta;
+ }
+}
diff --git a/src/main/java/gregtech/common/render/GT_CopiedCTMBlockTexture.java b/src/main/java/gregtech/common/render/GT_CopiedCTMBlockTexture.java
new file mode 100644
index 0000000000..17fa9ac8ff
--- /dev/null
+++ b/src/main/java/gregtech/common/render/GT_CopiedCTMBlockTexture.java
@@ -0,0 +1,118 @@
+package gregtech.common.render;
+
+import net.minecraft.block.Block;
+import net.minecraft.client.renderer.RenderBlocks;
+import net.minecraft.util.IIcon;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.interfaces.IBlockContainer;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.util.GT_RenderingWorld;
+import gregtech.api.util.LightingHelper;
+
+class GT_CopiedCTMBlockTexture extends GT_TextureBase implements ITexture, IBlockContainer {
+
+ private final Block mBlock;
+ private final byte mSide, mMeta;
+
+ GT_CopiedCTMBlockTexture(Block aBlock, int ordinalSide, int aMeta, short[] aRGBa, boolean allowAlpha) {
+ if (aRGBa.length != 4)
+ throw new IllegalArgumentException("RGBa doesn't have 4 Values @ GT_CopiedCTMBlockTexture");
+ mBlock = aBlock;
+ mSide = (byte) ordinalSide;
+ mMeta = (byte) aMeta;
+ }
+
+ @Override
+ public boolean isOldTexture() {
+ return false;
+ }
+
+ private IIcon getIcon(int ordinalSide, int aX, int aY, int aZ, RenderBlocks aRenderer) {
+ final int tSide = mSide == 6 ? ordinalSide : mSide;
+ return mBlock.getIcon(getBlockAccess(aRenderer), aX, aY, aZ, tSide);
+ }
+
+ private GT_RenderingWorld getBlockAccess(RenderBlocks aRenderer) {
+ return GT_RenderingWorld.getInstance(aRenderer.blockAccess);
+ }
+
+ @Override
+ public void renderXPos(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
+ final IIcon aIcon = getIcon(ForgeDirection.EAST.ordinal(), aX, aY, aZ, aRenderer);
+ aRenderer.field_152631_f = true;
+ startDrawingQuads(aRenderer, 1.0f, 0.0f, 0.0f);
+ new LightingHelper(aRenderer).setupLightingXPos(aBlock, aX, aY, aZ)
+ .setupColor(ForgeDirection.EAST, mBlock.colorMultiplier(getBlockAccess(aRenderer), aX, aY, aZ));
+ aRenderer.renderFaceXPos(aBlock, aX, aY, aZ, aIcon);
+ draw(aRenderer);
+ aRenderer.field_152631_f = false;
+ }
+
+ @Override
+ public void renderXNeg(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
+ startDrawingQuads(aRenderer, -1.0f, 0.0f, 0.0f);
+ final IIcon aIcon = getIcon(ForgeDirection.WEST.ordinal(), aX, aY, aZ, aRenderer);
+ new LightingHelper(aRenderer).setupLightingXNeg(aBlock, aX, aY, aZ)
+ .setupColor(ForgeDirection.WEST, mBlock.colorMultiplier(getBlockAccess(aRenderer), aX, aY, aZ));
+ aRenderer.renderFaceXNeg(aBlock, aX, aY, aZ, aIcon);
+ draw(aRenderer);
+ }
+
+ @Override
+ public void renderYPos(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
+ startDrawingQuads(aRenderer, 0.0f, 1.0f, 0.0f);
+ final IIcon aIcon = getIcon(ForgeDirection.UP.ordinal(), aX, aY, aZ, aRenderer);
+ new LightingHelper(aRenderer).setupLightingYPos(aBlock, aX, aY, aZ)
+ .setupColor(ForgeDirection.UP, mBlock.colorMultiplier(getBlockAccess(aRenderer), aX, aY, aZ));
+ aRenderer.renderFaceYPos(aBlock, aX, aY, aZ, aIcon);
+ draw(aRenderer);
+ }
+
+ @Override
+ public void renderYNeg(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
+ startDrawingQuads(aRenderer, 0.0f, -1.0f, 0.0f);
+ final IIcon aIcon = getIcon(ForgeDirection.DOWN.ordinal(), aX, aY, aZ, aRenderer);
+ new LightingHelper(aRenderer).setupLightingYNeg(aBlock, aX, aY, aZ)
+ .setupColor(ForgeDirection.DOWN, mBlock.colorMultiplier(getBlockAccess(aRenderer), aX, aY, aZ));
+ aRenderer.renderFaceYNeg(aBlock, aX, aY, aZ, aIcon);
+ draw(aRenderer);
+ }
+
+ @Override
+ public void renderZPos(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
+ startDrawingQuads(aRenderer, 0.0f, 0.0f, 1.0f);
+ final IIcon aIcon = getIcon(ForgeDirection.SOUTH.ordinal(), aX, aY, aZ, aRenderer);
+ new LightingHelper(aRenderer).setupLightingZPos(aBlock, aX, aY, aZ)
+ .setupColor(ForgeDirection.SOUTH, mBlock.colorMultiplier(getBlockAccess(aRenderer), aX, aY, aZ));
+ aRenderer.renderFaceZPos(aBlock, aX, aY, aZ, aIcon);
+ draw(aRenderer);
+ }
+
+ @Override
+ public void renderZNeg(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
+ startDrawingQuads(aRenderer, 0.0f, 0.0f, -1.0f);
+ final IIcon aIcon = getIcon(ForgeDirection.NORTH.ordinal(), aX, aY, aZ, aRenderer);
+ aRenderer.field_152631_f = true;
+ new LightingHelper(aRenderer).setupLightingZNeg(aBlock, aX, aY, aZ)
+ .setupColor(ForgeDirection.NORTH, mBlock.colorMultiplier(getBlockAccess(aRenderer), aX, aY, aZ));
+ aRenderer.renderFaceZNeg(aBlock, aX, aY, aZ, aIcon);
+ draw(aRenderer);
+ aRenderer.field_152631_f = false;
+ }
+
+ @Override
+ public boolean isValidTexture() {
+ return mBlock != null;
+ }
+
+ @Override
+ public Block getBlock() {
+ return mBlock;
+ }
+
+ @Override
+ public byte getMeta() {
+ return mMeta;
+ }
+}
diff --git a/src/main/java/gregtech/common/render/GT_FlaskRenderer.java b/src/main/java/gregtech/common/render/GT_FlaskRenderer.java
new file mode 100644
index 0000000000..addcb1cf70
--- /dev/null
+++ b/src/main/java/gregtech/common/render/GT_FlaskRenderer.java
@@ -0,0 +1,71 @@
+package gregtech.common.render;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.texture.TextureMap;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.IIcon;
+import net.minecraftforge.client.IItemRenderer;
+import net.minecraftforge.client.MinecraftForgeClient;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidStack;
+
+import org.lwjgl.opengl.GL11;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.api.enums.ItemList;
+import gregtech.common.items.GT_VolumetricFlask;
+
+@SideOnly(Side.CLIENT)
+public final class GT_FlaskRenderer implements IItemRenderer {
+
+ public GT_FlaskRenderer() {
+ MinecraftForgeClient.registerItemRenderer(ItemList.VOLUMETRIC_FLASK.getItem(), this);
+ }
+
+ @Override
+ public boolean handleRenderType(ItemStack item, ItemRenderType type) {
+ return type != ItemRenderType.FIRST_PERSON_MAP;
+ }
+
+ @Override
+ public boolean shouldUseRenderHelper(ItemRenderType type, ItemStack item, ItemRendererHelper helper) {
+ return type == ItemRenderType.ENTITY && helper == ItemRendererHelper.ENTITY_BOBBING
+ || (helper == ItemRendererHelper.ENTITY_ROTATION && Minecraft.getMinecraft().gameSettings.fancyGraphics);
+ }
+
+ @Override
+ public void renderItem(ItemRenderType type, ItemStack item, Object... data) {
+ GT_VolumetricFlask cell = (GT_VolumetricFlask) item.getItem();
+ IIcon icon = item.getIconIndex();
+ GL11.glEnable(GL11.GL_BLEND);
+ GL11.glEnable(GL11.GL_ALPHA_TEST);
+ GT_RenderUtil.applyStandardItemTransform(type);
+
+ FluidStack fs = cell != null ? cell.getFluid(item) : null;
+ if (fs != null) {
+ IIcon iconWindow = cell.iconWindow;
+ Fluid fluid = fs.getFluid();
+ IIcon fluidIcon = fluid.getIcon(fs);
+ int fluidColor = fluid.getColor(fs);
+
+ Minecraft.getMinecraft().renderEngine.bindTexture(TextureMap.locationItemsTexture);
+ GL11.glBlendFunc(GL11.GL_ZERO, GL11.GL_ONE);
+ GT_RenderUtil.renderItem(type, iconWindow);
+
+ Minecraft.getMinecraft().renderEngine.bindTexture(TextureMap.locationBlocksTexture);
+ GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ GL11.glDepthFunc(GL11.GL_EQUAL);
+ GL11.glColor3ub((byte) (fluidColor >> 16), (byte) (fluidColor >> 8), (byte) fluidColor);
+ GT_RenderUtil.renderItem(type, fluidIcon);
+ GL11.glColor3ub((byte) -1, (byte) -1, (byte) -1);
+ GL11.glDepthFunc(GL11.GL_LEQUAL);
+ }
+
+ Minecraft.getMinecraft().renderEngine.bindTexture(TextureMap.locationItemsTexture);
+ GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ GT_RenderUtil.renderItem(type, icon);
+ GL11.glDisable(GL11.GL_ALPHA_TEST);
+ GL11.glDisable(GL11.GL_BLEND);
+ }
+}
diff --git a/src/main/java/gregtech/common/render/GT_FluidDisplayStackRenderer.java b/src/main/java/gregtech/common/render/GT_FluidDisplayStackRenderer.java
new file mode 100644
index 0000000000..9a35f6bc57
--- /dev/null
+++ b/src/main/java/gregtech/common/render/GT_FluidDisplayStackRenderer.java
@@ -0,0 +1,98 @@
+package gregtech.common.render;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.renderer.OpenGlHelper;
+import net.minecraft.client.renderer.Tessellator;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.IIcon;
+import net.minecraftforge.client.IItemRenderer;
+import net.minecraftforge.client.MinecraftForgeClient;
+
+import org.lwjgl.opengl.GL11;
+
+import appeng.util.ReadableNumberConverter;
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Materials;
+import gregtech.common.items.GT_FluidDisplayItem;
+
+@SideOnly(Side.CLIENT)
+public class GT_FluidDisplayStackRenderer implements IItemRenderer {
+
+ public GT_FluidDisplayStackRenderer() {
+ MinecraftForgeClient.registerItemRenderer(ItemList.Display_Fluid.getItem(), this);
+ }
+
+ @Override
+ public boolean handleRenderType(ItemStack item, ItemRenderType type) {
+ if (!item.hasTagCompound()) return false;
+ return type == ItemRenderType.INVENTORY;
+ }
+
+ @Override
+ public boolean shouldUseRenderHelper(ItemRenderType type, ItemStack item, ItemRendererHelper helper) {
+ // not sure what this does.
+ return false;
+ }
+
+ @Override
+ public void renderItem(ItemRenderType type, ItemStack item, Object... data) {
+ if (item == null || item.getItem() == null || !(item.getItem() instanceof GT_FluidDisplayItem)) return;
+
+ OpenGlHelper.glBlendFunc(770, 771, 1, 0);
+ GL11.glEnable(GL11.GL_BLEND);
+ GL11.glEnable(GL11.GL_ALPHA_TEST);
+
+ Materials associatedFluidMaterial = Materials.get(item.stackTagCompound.getString("mFluidMaterialName"));
+ if (associatedFluidMaterial.renderer == null
+ || !associatedFluidMaterial.renderer.renderFluidDisplayItem(type, item, data)) {
+ IIcon icon = item.getItem()
+ .getIconFromDamage(item.getItemDamage());
+ Tessellator tess = Tessellator.instance;
+ tess.startDrawingQuads();
+ // draw a simple rectangle for the inventory icon
+ final float x_min = icon.getMinU();
+ final float x_max = icon.getMaxU();
+ final float y_min = icon.getMinV();
+ final float y_max = icon.getMaxV();
+ tess.addVertexWithUV(0, 16, 0, x_min, y_max);
+ tess.addVertexWithUV(16, 16, 0, x_max, y_max);
+ tess.addVertexWithUV(16, 0, 0, x_max, y_min);
+ tess.addVertexWithUV(0, 0, 0, x_min, y_min);
+ tess.draw();
+ }
+
+ if (item.getTagCompound() == null) {
+ GL11.glDisable(GL11.GL_BLEND);
+ GL11.glDisable(GL11.GL_ALPHA_TEST);
+ return;
+ }
+
+ // Render Fluid amount text
+ long fluidAmount = item.getTagCompound()
+ .getLong("mFluidDisplayAmount");
+ if (fluidAmount > 0L && !item.getTagCompound()
+ .getBoolean("mHideStackSize")) {
+ String amountString;
+
+ if (fluidAmount < 10_000) {
+ amountString = "" + fluidAmount + "L";
+ } else {
+ amountString = ReadableNumberConverter.INSTANCE.toWideReadableForm(fluidAmount) + "L";
+ }
+
+ FontRenderer fontRender = Minecraft.getMinecraft().fontRenderer;
+ float smallTextScale = fontRender.getUnicodeFlag() ? 3F / 4F : 1F / 2F;
+ GL11.glDisable(GL11.GL_BLEND);
+ GL11.glPushMatrix();
+ GL11.glScalef(smallTextScale, smallTextScale, 1.0f);
+
+ fontRender
+ .drawString(amountString, 0, (int) (16 / smallTextScale) - fontRender.FONT_HEIGHT + 1, 0xFFFFFF, true);
+ GL11.glPopMatrix();
+ GL11.glDisable(GL11.GL_ALPHA_TEST);
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/render/GT_IconFlipped.java b/src/main/java/gregtech/common/render/GT_IconFlipped.java
new file mode 100644
index 0000000000..8258e74ffa
--- /dev/null
+++ b/src/main/java/gregtech/common/render/GT_IconFlipped.java
@@ -0,0 +1,91 @@
+package gregtech.common.render;
+
+import net.minecraft.util.IIcon;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+
+@SideOnly(Side.CLIENT)
+public class GT_IconFlipped implements IIcon {
+
+ private final IIcon baseIcon;
+ private final boolean flipU;
+ private final boolean flipV;
+
+ public GT_IconFlipped(IIcon baseIcon, boolean flipU, boolean flipV) {
+ this.baseIcon = baseIcon;
+ this.flipU = flipU;
+ this.flipV = flipV;
+ }
+
+ /**
+ * Returns the width of the icon, in pixels.
+ */
+ @Override
+ public int getIconWidth() {
+ return this.baseIcon.getIconWidth();
+ }
+
+ /**
+ * Returns the height of the icon, in pixels.
+ */
+ @Override
+ public int getIconHeight() {
+ return this.baseIcon.getIconHeight();
+ }
+
+ /**
+ * Returns the minimum U coordinate to use when rendering with this icon.
+ */
+ @Override
+ public float getMinU() {
+ return this.flipU ? this.baseIcon.getMaxU() : this.baseIcon.getMinU();
+ }
+
+ /**
+ * Returns the maximum U coordinate to use when rendering with this icon.
+ */
+ @Override
+ public float getMaxU() {
+ return this.flipU ? this.baseIcon.getMinU() : this.baseIcon.getMaxU();
+ }
+
+ /**
+ * Gets a U coordinate on the icon. 0 returns uMin and 16 returns uMax. Other arguments return in-between values.
+ */
+ @Override
+ public float getInterpolatedU(double p_94214_1_) {
+ final float f = this.getMaxU() - this.getMinU();
+ return this.getMinU() + f * ((float) p_94214_1_ / 16.0F);
+ }
+
+ /**
+ * Returns the minimum V coordinate to use when rendering with this icon.
+ */
+ @Override
+ public float getMinV() {
+ return this.flipV ? this.baseIcon.getMaxV() : this.baseIcon.getMinV();
+ }
+
+ /**
+ * Returns the maximum V coordinate to use when rendering with this icon.
+ */
+ @Override
+ public float getMaxV() {
+ return this.flipV ? this.baseIcon.getMinV() : this.baseIcon.getMaxV();
+ }
+
+ /**
+ * Gets a V coordinate on the icon. 0 returns vMin and 16 returns vMax. Other arguments return in-between values.
+ */
+ @Override
+ public float getInterpolatedV(double p_94207_1_) {
+ final float f = this.getMaxV() - this.getMinV();
+ return this.getMinV() + f * ((float) p_94207_1_ / 16.0F);
+ }
+
+ @Override
+ public String getIconName() {
+ return this.baseIcon.getIconName();
+ }
+}
diff --git a/src/main/java/gregtech/common/render/GT_MetaGenerated_Tool_Renderer.java b/src/main/java/gregtech/common/render/GT_MetaGenerated_Tool_Renderer.java
new file mode 100644
index 0000000000..96285a3fc1
--- /dev/null
+++ b/src/main/java/gregtech/common/render/GT_MetaGenerated_Tool_Renderer.java
@@ -0,0 +1,130 @@
+package gregtech.common.render;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.IIcon;
+import net.minecraftforge.client.IItemRenderer;
+import net.minecraftforge.client.MinecraftForgeClient;
+
+import org.lwjgl.opengl.GL11;
+
+import gregtech.GT_Mod;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.interfaces.IToolStats;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+
+public class GT_MetaGenerated_Tool_Renderer implements IItemRenderer {
+
+ public GT_MetaGenerated_Tool_Renderer() {
+ for (GT_MetaGenerated_Tool tItem : GT_MetaGenerated_Tool.sInstances.values()) {
+ if (tItem != null) {
+ MinecraftForgeClient.registerItemRenderer(tItem, this);
+ }
+ }
+ }
+
+ @Override
+ public boolean handleRenderType(ItemStack stack, ItemRenderType type) {
+ return (type == ItemRenderType.EQUIPPED_FIRST_PERSON) || (type == ItemRenderType.INVENTORY)
+ || (type == ItemRenderType.EQUIPPED)
+ || (type == ItemRenderType.ENTITY);
+ }
+
+ @Override
+ public boolean shouldUseRenderHelper(ItemRenderType type, ItemStack stack, ItemRendererHelper helper) {
+ return type == ItemRenderType.ENTITY && helper == ItemRendererHelper.ENTITY_BOBBING
+ || (helper == ItemRendererHelper.ENTITY_ROTATION && Minecraft.getMinecraft().gameSettings.fancyGraphics);
+ }
+
+ @Override
+ public void renderItem(ItemRenderType type, ItemStack stack, Object... data) {
+ GT_MetaGenerated_Tool item = (GT_MetaGenerated_Tool) stack.getItem();
+ GL11.glEnable(GL11.GL_BLEND);
+ GT_RenderUtil.applyStandardItemTransform(type);
+ GL11.glColor3f(1.0F, 1.0F, 1.0F);
+
+ IToolStats toolStats = item != null ? item.getToolStats(stack) : null;
+ if (toolStats != null) {
+ renderToolPart(type, stack, toolStats, false);
+ renderToolPart(type, stack, toolStats, true);
+
+ if ((type == ItemRenderType.INVENTORY)
+ && (GT_MetaGenerated_Tool.getPrimaryMaterial(stack) != Materials._NULL)) {
+ if (GT_Mod.gregtechproxy.mRenderItemDurabilityBar) {
+ IIconContainer iconContainer;
+ long damage = GT_MetaGenerated_Tool.getToolDamage(stack);
+ long maxDamage = GT_MetaGenerated_Tool.getToolMaxDamage(stack);
+ if (damage <= 0L) {
+ iconContainer = Textures.ItemIcons.DURABILITY_BAR[8];
+ } else if (damage >= maxDamage) {
+ iconContainer = Textures.ItemIcons.DURABILITY_BAR[0];
+ } else {
+ iconContainer = Textures.ItemIcons.DURABILITY_BAR[((int) Math
+ .max(0L, Math.min(7L, (maxDamage - damage) * 8L / maxDamage)))];
+ }
+ renderIcon(iconContainer);
+ }
+
+ if (GT_Mod.gregtechproxy.mRenderItemChargeBar) {
+ IIconContainer iconContainer;
+ Long[] stats = item.getElectricStats(stack);
+ if ((stats != null) && (stats[3] < 0L)) {
+ long tCharge = item.getRealCharge(stack);
+ if (tCharge <= 0L) {
+ iconContainer = Textures.ItemIcons.ENERGY_BAR[0];
+ } else if (tCharge >= stats[0]) {
+ iconContainer = Textures.ItemIcons.ENERGY_BAR[8];
+ } else {
+ iconContainer = Textures.ItemIcons.ENERGY_BAR[(7
+ - (int) Math.max(0L, Math.min(6L, (stats[0] - tCharge) * 7L / stats[0])))];
+ }
+ } else {
+ iconContainer = null;
+ }
+ renderIcon(iconContainer);
+ }
+ }
+ }
+ GL11.glDisable(GL11.GL_BLEND);
+ }
+
+ private void renderIcon(IIconContainer iconContainer) {
+ if (iconContainer != null) {
+ IIcon icon = iconContainer.getIcon();
+ IIcon overlay = iconContainer.getOverlayIcon();
+ if (icon != null) {
+ Minecraft.getMinecraft().renderEngine.bindTexture(iconContainer.getTextureFile());
+ GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ GT_RenderUtil.renderItemIcon(icon, 16.0D, 0.001D, 0.0F, 0.0F, -1.0F);
+ }
+ if (overlay != null) {
+ Minecraft.getMinecraft().renderEngine.bindTexture(iconContainer.getTextureFile());
+ GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ GT_RenderUtil.renderItemIcon(overlay, 16.0D, 0.001D, 0.0F, 0.0F, -1.0F);
+ }
+ }
+ }
+
+ private static void renderToolPart(ItemRenderType type, ItemStack stack, IToolStats toolStats, boolean isToolHead) {
+ IIconContainer iconContainer = toolStats.getIcon(isToolHead, stack);
+ if (iconContainer != null) {
+ IIcon icon = iconContainer.getIcon();
+ IIcon overlay = iconContainer.getOverlayIcon();
+ if (icon != null) {
+ Minecraft.getMinecraft().renderEngine.bindTexture(iconContainer.getTextureFile());
+ GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ short[] modulation = toolStats.getRGBa(isToolHead, stack);
+ GL11.glColor3f(modulation[0] / 255.0F, modulation[1] / 255.0F, modulation[2] / 255.0F);
+ GT_RenderUtil.renderItem(type, icon);
+ GL11.glColor3f(1.0F, 1.0F, 1.0F);
+ }
+ if (overlay != null) {
+ Minecraft.getMinecraft().renderEngine.bindTexture(iconContainer.getTextureFile());
+ GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ GT_RenderUtil.renderItem(type, overlay);
+ }
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/render/GT_MultiTexture.java b/src/main/java/gregtech/common/render/GT_MultiTexture.java
new file mode 100644
index 0000000000..d3cff271cb
--- /dev/null
+++ b/src/main/java/gregtech/common/render/GT_MultiTexture.java
@@ -0,0 +1,69 @@
+package gregtech.common.render;
+
+import net.minecraft.block.Block;
+import net.minecraft.client.renderer.RenderBlocks;
+
+import gregtech.GT_Mod;
+import gregtech.api.interfaces.ITexture;
+
+/**
+ * <p>
+ * Lets Multiple ITextures Render overlay over each other.<
+ * </p>
+ * <p>
+ * I should have done this much earlier...
+ * </p>
+ */
+public class GT_MultiTexture extends GT_TextureBase implements ITexture {
+
+ protected final ITexture[] mTextures;
+
+ public static GT_MultiTexture get(ITexture... aTextures) {
+ return GT_Mod.instance.isClientSide() ? new GT_MultiTexture(aTextures) : null;
+ }
+
+ protected GT_MultiTexture(ITexture... aTextures) {
+ mTextures = aTextures;
+ }
+
+ @Override
+ public void renderXPos(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
+ for (ITexture tTexture : mTextures)
+ if (tTexture != null && tTexture.isValidTexture()) tTexture.renderXPos(aRenderer, aBlock, aX, aY, aZ);
+ }
+
+ @Override
+ public void renderXNeg(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
+ for (ITexture tTexture : mTextures)
+ if (tTexture != null && tTexture.isValidTexture()) tTexture.renderXNeg(aRenderer, aBlock, aX, aY, aZ);
+ }
+
+ @Override
+ public void renderYPos(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
+ for (ITexture tTexture : mTextures)
+ if (tTexture != null && tTexture.isValidTexture()) tTexture.renderYPos(aRenderer, aBlock, aX, aY, aZ);
+ }
+
+ @Override
+ public void renderYNeg(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
+ for (ITexture tTexture : mTextures)
+ if (tTexture != null && tTexture.isValidTexture()) tTexture.renderYNeg(aRenderer, aBlock, aX, aY, aZ);
+ }
+
+ @Override
+ public void renderZPos(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
+ for (ITexture tTexture : mTextures)
+ if (tTexture != null && tTexture.isValidTexture()) tTexture.renderZPos(aRenderer, aBlock, aX, aY, aZ);
+ }
+
+ @Override
+ public void renderZNeg(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
+ for (ITexture tTexture : mTextures)
+ if (tTexture != null && tTexture.isValidTexture()) tTexture.renderZNeg(aRenderer, aBlock, aX, aY, aZ);
+ }
+
+ @Override
+ public boolean isValidTexture() {
+ return true;
+ }
+}
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_PollutionRenderer.java b/src/main/java/gregtech/common/render/GT_PollutionRenderer.java
new file mode 100644
index 0000000000..ee87b2b5d1
--- /dev/null
+++ b/src/main/java/gregtech/common/render/GT_PollutionRenderer.java
@@ -0,0 +1,251 @@
+package gregtech.common.render;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.material.Material;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.entity.EntityClientPlayerMP;
+import net.minecraft.client.particle.EntityFX;
+import net.minecraft.client.renderer.OpenGlHelper;
+import net.minecraft.potion.Potion;
+import net.minecraft.util.MathHelper;
+import net.minecraft.world.ChunkCoordIntPair;
+import net.minecraft.world.World;
+import net.minecraftforge.client.event.EntityViewRenderEvent;
+import net.minecraftforge.event.world.WorldEvent;
+
+import org.lwjgl.opengl.GL11;
+
+import cpw.mods.fml.common.FMLCommonHandler;
+import cpw.mods.fml.common.eventhandler.EventPriority;
+import cpw.mods.fml.common.eventhandler.SubscribeEvent;
+import cpw.mods.fml.common.gameevent.TickEvent;
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.GT_Mod;
+import gregtech.common.entities.GT_EntityFXPollution;
+import gregtech.common.misc.GT_ClientPollutionMap;
+
+@SideOnly(Side.CLIENT)
+public class GT_PollutionRenderer {
+
+ private static GT_ClientPollutionMap pollutionMap;
+ private static int playerPollution = 0;
+
+ private static final boolean DEBUG = false;
+
+ // PARTICLES_POLLUTION_START + PARTICLES_POLLUTION_END -> Max Particles
+ private static final int PARTICLES_MAX_NUM = 100;
+ private static final int PARTICLES_POLLUTION_START = 400000;
+ private static final int PARTICLES_POLLUTION_END = 3500000;
+
+ private static final int FOG_START_AT_POLLUTION = 400000;
+ private static final int FOG_MAX_AT_POLLUTION = 7000000;
+ // jump from linear to exponential fog. x*FOG_MAX_AT_POLLUTION+FOG_START_AT_POLLUTION
+ private static final double FOG_START_EXP_RATIO = 0.02D;
+
+ private static final float[] fogColor = { 0.3f, 0.25f, 0.1f };
+ private static final short[] grassColor = { 230, 180, 40 };
+ private static final short[] leavesColor = { 160, 80, 15 };
+ private static final short[] liquidColor = { 160, 200, 10 };
+ private static final short[] foliageColor = { 160, 80, 15 };
+
+ // TODO need to soft update some blocks, grass and leaves does more often than liquid it looks like.
+
+ public GT_PollutionRenderer() {
+ pollutionMap = new GT_ClientPollutionMap();
+ }
+
+ public void preLoad() {
+ net.minecraftforge.common.MinecraftForge.EVENT_BUS.register(this);
+ FMLCommonHandler.instance()
+ .bus()
+ .register(this);
+ }
+
+ public void processPacket(ChunkCoordIntPair chunk, int pollution) {
+ pollutionMap.addChunkPollution(chunk.chunkXPos, chunk.chunkZPos, pollution);
+ }
+
+ @SubscribeEvent(priority = EventPriority.HIGH)
+ public void enteredWorld(WorldEvent.Load event) {
+ EntityClientPlayerMP p = Minecraft.getMinecraft().thePlayer;
+ if (!event.world.isRemote || p == null) return;
+ pollutionMap.reset();
+ }
+
+ private static int color(int color, int pollution, int low, float high, short[] colors) {
+ if (pollution < low) return color;
+
+ int r = (color >> 16) & 0xFF;
+ int g = (color >> 8) & 0xFF;
+ int b = color & 0xFF;
+ float p = (pollution - low) / high;
+ if (p > 1) p = 1;
+ float pi = 1 - p;
+
+ r = ((int) (r * pi + p * colors[0])) & 0xFF;
+ g = ((int) (g * pi + p * colors[1])) & 0xFF;
+ b = ((int) (b * pi + p * colors[2])) & 0xFF;
+
+ return (r & 0xFF) << 16 | (g & 0xFF) << 8 | b & 0xFF;
+ }
+
+ // Methods for hodgepodge to color grass / foliage blocks etc.
+ public static int colorGrass(int oColor, int x, int z) {
+ return color(oColor, pollutionMap.getPollution(x, z) / 1000, 350, 600, grassColor);
+ }
+
+ public static int colorLeaves(int oColor, int x, int z) {
+ return color(oColor, pollutionMap.getPollution(x, z) / 1000, 300, 500, leavesColor);
+ }
+
+ public static int colorLiquid(int oColor, int x, int z) {
+ return color(oColor, pollutionMap.getPollution(x, z) / 1000, 300, 500, liquidColor);
+ }
+
+ public static int colorFoliage(int oColor, int x, int z) {
+ return color(oColor, pollutionMap.getPollution(x, z) / 1000, 300, 500, foliageColor);
+ }
+
+ public static int getKnownPollution(int x, int z) {
+ return pollutionMap.getPollution(x, z);
+ }
+
+ @SubscribeEvent(priority = EventPriority.LOW)
+ public void manipulateColor(EntityViewRenderEvent.FogColors event) {
+ if (!DEBUG && Minecraft.getMinecraft().thePlayer.capabilities.isCreativeMode) return;
+
+ if (event.block.getMaterial() == Material.water || event.block.getMaterial() == Material.lava) return;
+
+ float x = fogIntensityLastTick > 1 ? 1F : (float) fogIntensityLastTick;
+ float xi = 1 - x;
+
+ event.red = xi * event.red + x * fogColor[0];
+ event.green = xi * event.green + x * fogColor[1];
+ event.blue = xi * event.blue + x * fogColor[2];
+ }
+
+ private static final int END_MAX_DISTANCE = 192 - 1;
+ private static double fogIntensityLastTick = 0;
+
+ @SubscribeEvent(priority = EventPriority.LOWEST)
+ public void renderGTPollutionFog(EntityViewRenderEvent.RenderFogEvent event) {
+ if (!GT_Mod.gregtechproxy.mRenderPollutionFog) return;
+
+ if ((!DEBUG && Minecraft.getMinecraft().thePlayer.capabilities.isCreativeMode)
+ || (fogIntensityLastTick <= 0 && fogIntensityLastTick >= FOG_START_EXP_RATIO)) return;
+
+ if (event.fogMode == 0) {
+ double v = 1 - fogIntensityLastTick / FOG_START_EXP_RATIO;
+ // trying to smooth out jump from linear to exponential
+ GL11.glFogi(GL11.GL_FOG_MODE, GL11.GL_LINEAR);
+ GL11.glFogf(GL11.GL_FOG_START, (float) ((END_MAX_DISTANCE - 20) * 0.75F * v + 20));
+ GL11.glFogf(GL11.GL_FOG_END, (float) (END_MAX_DISTANCE * (0.75F + v * 0.25F)));
+ }
+ // else if ( event.fogMode < 0) { }
+ }
+
+ @SubscribeEvent(priority = EventPriority.LOWEST)
+ public void renderGTPollutionFog(EntityViewRenderEvent.FogDensity event) {
+ if (!GT_Mod.gregtechproxy.mRenderPollutionFog) return;
+
+ if (!DEBUG && Minecraft.getMinecraft().thePlayer.capabilities.isCreativeMode) return;
+
+ if (event.entity.isPotionActive(Potion.blindness) || (fogIntensityLastTick < FOG_START_EXP_RATIO)
+ || event.block.getMaterial() == Material.water
+ || event.block.getMaterial() == Material.lava) return;
+
+ GL11.glFogi(GL11.GL_FOG_MODE, GL11.GL_EXP2);
+ event.density = (float) Math.pow(fogIntensityLastTick - FOG_START_EXP_RATIO, .75F) / 5 + 0.01F;
+ event.setCanceled(true);
+ }
+
+ private double lastUpdate = 0;
+
+ @SubscribeEvent(priority = EventPriority.HIGHEST)
+ public void onRenderTick(TickEvent.RenderTickEvent event) {
+ Minecraft mc = Minecraft.getMinecraft();
+ if (mc == null) return;
+ EntityClientPlayerMP player = mc.thePlayer;
+ if (player == null) return;
+
+ if (event.phase == TickEvent.Phase.START) {
+ if (event.renderTickTime < lastUpdate) lastUpdate = lastUpdate - 1;
+ float step = (float) ((event.renderTickTime - lastUpdate) / 50);
+ lastUpdate = event.renderTickTime;
+
+ float fogIntensity = (playerPollution - FOG_START_AT_POLLUTION) / (float) FOG_MAX_AT_POLLUTION;
+ if (fogIntensity > 1) fogIntensity = 1;
+ else if (fogIntensity < 0) fogIntensity = 0;
+
+ double e = fogIntensity - fogIntensityLastTick;
+ if (e != 0) {
+ if (e > 0.2) e = 0.2D;
+ else if (e < -0.5) e = -0.5D;
+
+ if (e > 0.001D || e < -0.001D) fogIntensityLastTick += step * e;
+ else fogIntensityLastTick = fogIntensity;
+ }
+ } else if (DEBUG) {
+ drawPollution("Intensity: " + (fogIntensityLastTick * 10000), 0);
+ drawPollution(
+ "Pollution: " + pollutionMap.getPollution(
+ Minecraft.getMinecraft().thePlayer.lastTickPosX,
+ Minecraft.getMinecraft().thePlayer.lastTickPosZ),
+ 20);
+ drawPollution(
+ "Density: "
+ + ((float) (Math.pow(fogIntensityLastTick - FOG_START_EXP_RATIO, .75F) / 5 + 0.01F) * 10000),
+ 40);
+ }
+ }
+
+ // Adding dirt particles in the air
+ @SubscribeEvent(priority = EventPriority.HIGHEST)
+ public void onClientTick(TickEvent.ClientTickEvent event) {
+ if (!GT_Mod.gregtechproxy.mRenderDirtParticles) return;
+ Minecraft mc = Minecraft.getMinecraft();
+ if (mc == null) return;
+ EntityClientPlayerMP player = mc.thePlayer;
+ if (player == null || (player.capabilities.isCreativeMode && !DEBUG)) return;
+
+ World w = player.worldObj;
+ playerPollution = pollutionMap.getPollution(player.lastTickPosX, player.lastTickPosZ);
+
+ float intensity = ((float) playerPollution - PARTICLES_POLLUTION_START) / PARTICLES_POLLUTION_END;
+ if (intensity < 0) return;
+ else if (intensity > 1) intensity = 1;
+ else intensity *= intensity;
+
+ int x = MathHelper.floor_double(player.posX);
+ int y = MathHelper.floor_double(player.posY);
+ int z = MathHelper.floor_double(player.posZ);
+
+ int numParticles = Math.round(intensity * PARTICLES_MAX_NUM);
+
+ for (int l = 0; l < numParticles; ++l) {
+ int i1 = x + w.rand.nextInt(16) - w.rand.nextInt(16);
+ int j1 = y + w.rand.nextInt(16) - w.rand.nextInt(16);
+ int k1 = z + w.rand.nextInt(16) - w.rand.nextInt(16);
+ Block block = w.getBlock(i1, j1, k1);
+
+ if (block.getMaterial() == Material.air) {
+ EntityFX fx = new GT_EntityFXPollution(
+ w,
+ (float) i1 + w.rand.nextFloat(),
+ (float) j1 + w.rand.nextFloat(),
+ (float) k1 + w.rand.nextFloat());
+ mc.effectRenderer.addEffect(fx);
+ }
+ }
+ }
+
+ private void drawPollution(String text, int off) {
+ GL11.glPushMatrix();
+ GL11.glEnable(GL11.GL_BLEND);
+ OpenGlHelper.glBlendFunc(770, 771, 1, 0);
+ Minecraft.getMinecraft().fontRenderer.drawStringWithShadow(text, 0, off, 0xFFFFFFFF);
+ GL11.glDisable(GL11.GL_BLEND);
+ GL11.glPopMatrix();
+ }
+}
diff --git a/src/main/java/gregtech/common/render/GT_RenderDrone.java b/src/main/java/gregtech/common/render/GT_RenderDrone.java
new file mode 100644
index 0000000000..af1336a219
--- /dev/null
+++ b/src/main/java/gregtech/common/render/GT_RenderDrone.java
@@ -0,0 +1,93 @@
+package gregtech.common.render;
+
+import static gregtech.api.enums.Mods.GregTech;
+
+import net.minecraft.client.renderer.OpenGlHelper;
+import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.ResourceLocation;
+import net.minecraftforge.client.model.AdvancedModelLoader;
+import net.minecraftforge.client.model.IModelCustom;
+
+import org.lwjgl.opengl.GL11;
+
+import cpw.mods.fml.client.registry.ClientRegistry;
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.common.tileentities.render.TileDrone;
+
+@SideOnly(Side.CLIENT)
+public class GT_RenderDrone extends TileEntitySpecialRenderer {
+
+ private static final ResourceLocation DroneTexture = new ResourceLocation(GregTech.ID, "textures/model/drone.png");
+ private static final IModelCustom Drone = AdvancedModelLoader
+ .loadModel(new ResourceLocation(GregTech.ID, "textures/model/drone.obj"));
+
+ public GT_RenderDrone() {
+ ClientRegistry.bindTileEntitySpecialRenderer(TileDrone.class, this);
+ }
+
+ @Override
+ public void renderTileEntityAt(TileEntity tile, double x, double y, double z, float timeSinceLastTick) {
+ if (!(tile instanceof TileDrone drone)) return;
+ final float size = 1.0f;
+ GL11.glPushMatrix();
+ GL11.glTranslated(x + 0.5, y + 0.5, z + 0.5);
+ renderDrone(size);
+ renderBlade(drone, size);
+ GL11.glPopMatrix();
+ }
+
+ private void renderDrone(double size) {
+ GL11.glDisable(GL11.GL_LIGHTING);
+ GL11.glDisable(GL11.GL_CULL_FACE);
+ GL11.glEnable(GL11.GL_BLEND);
+ GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ this.bindTexture(DroneTexture);
+ GL11.glScaled(size, size, size);
+ OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f);
+ Drone.renderOnly("drone", "box", "main");
+ GL11.glDisable(GL11.GL_BLEND);
+ GL11.glDepthMask(true);
+ GL11.glEnable(GL11.GL_CULL_FACE);
+ GL11.glEnable(GL11.GL_LIGHTING);
+ }
+
+ private void renderBlade(TileDrone drone, double size) {
+ GL11.glDisable(GL11.GL_LIGHTING);
+ GL11.glDisable(GL11.GL_CULL_FACE);
+ GL11.glEnable(GL11.GL_BLEND);
+ GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ this.bindTexture(DroneTexture);
+ GL11.glScaled(size, size, size);
+ OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f);
+ GL11.glPushMatrix();
+ GL11.glTranslated(-0.7d * size, -1 * size, -0.7 * size);
+ GL11.glRotated(drone.rotation, 0, 1, 0);
+ GL11.glTranslated(0.7d * size, 1 * size, 0.7 * size);
+ Drone.renderOnly("blade2");
+ GL11.glPopMatrix();
+ GL11.glPushMatrix();
+ GL11.glTranslated(-0.7d * size, -1 * size, 0.7 * size);
+ GL11.glRotated(drone.rotation, 0, 1, 0);
+ GL11.glTranslated(0.7d * size, 1 * size, -0.7 * size);
+ Drone.renderOnly("blade3");
+ GL11.glPopMatrix();
+ GL11.glPushMatrix();
+ GL11.glTranslated(0.7d * size, -1 * size, -0.7 * size);
+ GL11.glRotated(drone.rotation, 0, 1, 0);
+ GL11.glTranslated(-0.7d * size, 1 * size, 0.7 * size);
+ Drone.renderOnly("blade1");
+ GL11.glPopMatrix();
+ GL11.glPushMatrix();
+ GL11.glTranslated(0.7d * size, -1 * size, 0.7 * size);
+ GL11.glRotated(drone.rotation, 0, 1, 0);
+ GL11.glTranslated(-0.7d * size, 1 * size, -0.7 * size);
+ Drone.renderOnly("blade4");
+ GL11.glPopMatrix();
+ GL11.glDisable(GL11.GL_BLEND);
+ GL11.glDepthMask(true);
+ GL11.glEnable(GL11.GL_CULL_FACE);
+ GL11.glEnable(GL11.GL_LIGHTING);
+ }
+}
diff --git a/src/main/java/gregtech/common/render/GT_RenderUtil.java b/src/main/java/gregtech/common/render/GT_RenderUtil.java
new file mode 100644
index 0000000000..68195513fe
--- /dev/null
+++ b/src/main/java/gregtech/common/render/GT_RenderUtil.java
@@ -0,0 +1,141 @@
+package gregtech.common.render;
+
+import net.minecraft.block.Block;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.ItemRenderer;
+import net.minecraft.client.renderer.RenderBlocks;
+import net.minecraft.client.renderer.Tessellator;
+import net.minecraft.client.renderer.entity.RenderItem;
+import net.minecraft.client.renderer.entity.RenderManager;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.IIcon;
+import net.minecraftforge.client.IItemRenderer;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import org.lwjgl.opengl.GL11;
+
+import gregtech.api.interfaces.IGT_ItemWithMaterialRenderer;
+
+public class GT_RenderUtil {
+
+ public static void colorGTItem(ItemStack aStack) {
+ if (aStack.getItem() instanceof IGT_ItemWithMaterialRenderer aItem) {
+
+ short[] tModulation = aItem.getRGBa(aStack);
+ GL11.glColor4f(tModulation[0] / 255.0F, tModulation[1] / 255.0F, tModulation[2] / 255.0F, 255.0f);
+ } else {
+ System.out.println("WARNING: " + aStack.getDisplayName() + " does not have an associated GT colour.");
+ }
+ }
+
+ public static void renderBlockIcon(RenderBlocks aRenderer, Block aBlock, double aX, double aY, double aZ,
+ IIcon aIcon, ForgeDirection side) {
+ switch (side) {
+ case DOWN -> aRenderer.renderFaceYNeg(aBlock, aX, aY, aZ, aIcon);
+ case UP -> aRenderer.renderFaceYPos(aBlock, aX, aY, aZ, aIcon);
+ case NORTH -> aRenderer.renderFaceZNeg(aBlock, aX, aY, aZ, aIcon);
+ case SOUTH -> aRenderer.renderFaceZPos(aBlock, aX, aY, aZ, aIcon);
+ case WEST -> aRenderer.renderFaceXNeg(aBlock, aX, aY, aZ, aIcon);
+ case EAST -> aRenderer.renderFaceXPos(aBlock, aX, aY, aZ, aIcon);
+ }
+ }
+
+ public static void renderItemIcon(IIcon icon, double size, double z, float nx, float ny, float nz) {
+ renderItemIcon(icon, 0.0D, 0.0D, size, size, z, nx, ny, nz);
+ }
+
+ public static void renderItemIcon(IIcon icon, double xStart, double yStart, double xEnd, double yEnd, double z,
+ float nx, float ny, float nz) {
+ if (icon == null) {
+ return;
+ }
+ Tessellator.instance.startDrawingQuads();
+ Tessellator.instance.setNormal(nx, ny, nz);
+ if (nz > 0.0F) {
+ Tessellator.instance.addVertexWithUV(xStart, yStart, z, icon.getMinU(), icon.getMinV());
+ Tessellator.instance.addVertexWithUV(xEnd, yStart, z, icon.getMaxU(), icon.getMinV());
+ Tessellator.instance.addVertexWithUV(xEnd, yEnd, z, icon.getMaxU(), icon.getMaxV());
+ Tessellator.instance.addVertexWithUV(xStart, yEnd, z, icon.getMinU(), icon.getMaxV());
+ } else {
+ Tessellator.instance.addVertexWithUV(xStart, yEnd, z, icon.getMinU(), icon.getMaxV());
+ Tessellator.instance.addVertexWithUV(xEnd, yEnd, z, icon.getMaxU(), icon.getMaxV());
+ Tessellator.instance.addVertexWithUV(xEnd, yStart, z, icon.getMaxU(), icon.getMinV());
+ Tessellator.instance.addVertexWithUV(xStart, yStart, z, icon.getMinU(), icon.getMinV());
+ }
+ Tessellator.instance.draw();
+ }
+
+ @SuppressWarnings("RedundantLabeledSwitchRuleCodeBlock")
+ public static void renderItem(IItemRenderer.ItemRenderType type, IIcon icon) {
+ Tessellator tessellator = Tessellator.instance;
+ float maxU = icon.getMaxU();
+ float minV = icon.getMinV();
+ float minU = icon.getMinU();
+ float maxV = icon.getMaxV();
+
+ switch (type) {
+ case ENTITY -> {
+ if (Minecraft.getMinecraft().gameSettings.fancyGraphics) {
+ ItemRenderer.renderItemIn2D(
+ tessellator,
+ maxU,
+ minV,
+ minU,
+ maxV,
+ icon.getIconWidth(),
+ icon.getIconHeight(),
+ 0.0625F);
+ } else {
+ GL11.glPushMatrix();
+
+ if (!RenderItem.renderInFrame) {
+ GL11.glRotatef(180.0F - RenderManager.instance.playerViewY, 0.0F, 1.0F, 0.0F);
+ }
+
+ tessellator.startDrawingQuads();
+ tessellator.setNormal(0.0F, 1.0F, 0.0F);
+ tessellator.addVertexWithUV(0.0F - 0.5F, 0.0F - 0.25F, 0.0D, minU, maxV);
+ tessellator.addVertexWithUV(1.0F - 0.5F, 0.0F - 0.25F, 0.0D, maxU, maxV);
+ tessellator.addVertexWithUV(1.0F - 0.5F, 1.0F - 0.25F, 0.0D, maxU, minV);
+ tessellator.addVertexWithUV(0.0F - 0.5F, 1.0F - 0.25F, 0.0D, minU, minV);
+ tessellator.draw();
+
+ GL11.glPopMatrix();
+ }
+ }
+ case EQUIPPED, EQUIPPED_FIRST_PERSON -> {
+ ItemRenderer.renderItemIn2D(
+ tessellator,
+ maxU,
+ minV,
+ minU,
+ maxV,
+ icon.getIconWidth(),
+ icon.getIconHeight(),
+ 0.0625F);
+ }
+ case INVENTORY -> {
+ renderItemIcon(icon, 16.0D, 0.001, 0.0F, 0.0F, -1.0F);
+ }
+ default -> {}
+ }
+ }
+
+ public static void applyStandardItemTransform(IItemRenderer.ItemRenderType type) {
+ if (type == IItemRenderer.ItemRenderType.ENTITY) {
+ if (RenderItem.renderInFrame) {
+ // Magic numbers calculated from vanilla code
+ GL11.glScalef(1.025641F, 1.025641F, 1.025641F);
+ GL11.glTranslatef(0.0F, -0.05F, 0.0F);
+ }
+
+ if (Minecraft.getMinecraft().gameSettings.fancyGraphics) {
+ if (RenderItem.renderInFrame) {
+ GL11.glRotatef(180.0F, 0.0F, 1.0F, 0.0F);
+ }
+ // Magic numbers calculated from vanilla code
+ GL11.glTranslatef(-0.5F, -0.25F, 0.0421875F);
+ }
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/render/GT_RenderedTexture.java b/src/main/java/gregtech/common/render/GT_RenderedTexture.java
new file mode 100644
index 0000000000..afaf3b290c
--- /dev/null
+++ b/src/main/java/gregtech/common/render/GT_RenderedTexture.java
@@ -0,0 +1,395 @@
+package gregtech.common.render;
+
+import static gregtech.api.util.LightingHelper.MAX_BRIGHTNESS;
+
+import net.minecraft.block.Block;
+import net.minecraft.client.renderer.RenderBlocks;
+import net.minecraft.client.renderer.Tessellator;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.IIcon;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.gtnewhorizon.structurelib.alignment.IAlignment;
+import com.gtnewhorizon.structurelib.alignment.IAlignmentProvider;
+import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
+import com.gtnewhorizon.structurelib.alignment.enumerable.Flip;
+import com.gtnewhorizon.structurelib.alignment.enumerable.Rotation;
+
+import gregtech.GT_Mod;
+import gregtech.api.interfaces.IColorModulationContainer;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.util.LightingHelper;
+
+public class GT_RenderedTexture extends GT_TextureBase implements ITexture, IColorModulationContainer {
+
+ protected final IIconContainer mIconContainer;
+ private final short[] mRGBa;
+ private final boolean glow;
+ private final boolean stdOrient;
+ private final boolean useExtFacing;
+
+ protected GT_RenderedTexture(IIconContainer aIcon, short[] aRGBa, boolean allowAlpha, boolean glow,
+ boolean stdOrient, boolean extFacing) {
+ if (aRGBa.length != 4) throw new IllegalArgumentException("RGBa doesn't have 4 Values @ GT_RenderedTexture");
+ mIconContainer = aIcon;
+ mRGBa = aRGBa;
+ this.glow = glow;
+ this.stdOrient = stdOrient;
+ this.useExtFacing = extFacing;
+ }
+
+ @Override
+ public boolean isOldTexture() {
+ return false;
+ }
+
+ @Override
+ public void renderXPos(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
+ startDrawingQuads(aRenderer, 1.0f, 0.0f, 0.0f);
+ final boolean enableAO = aRenderer.enableAO;
+ final LightingHelper lighting = new LightingHelper(aRenderer);
+ if (glow) {
+ if (!GT_Mod.gregtechproxy.mRenderGlowTextures) {
+ draw(aRenderer);
+ return;
+ }
+ aRenderer.enableAO = false;
+ lighting.setLightnessOverride(1.0F);
+ if (enableAO) lighting.setBrightnessOverride(MAX_BRIGHTNESS);
+ }
+ lighting.setupLightingXPos(aBlock, aX, aY, aZ)
+ .setupColor(ForgeDirection.EAST, mRGBa);
+ final ExtendedFacing rotation = getExtendedFacing(aX, aY, aZ);
+ renderFaceXPos(aRenderer, aX, aY, aZ, mIconContainer.getIcon(), rotation);
+ if (mIconContainer.getOverlayIcon() != null) {
+ lighting.setupColor(ForgeDirection.EAST, 0xffffff);
+ renderFaceXPos(aRenderer, aX, aY, aZ, mIconContainer.getOverlayIcon(), rotation);
+ }
+ aRenderer.enableAO = enableAO;
+ draw(aRenderer);
+ }
+
+ @Override
+ public void renderXNeg(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
+ startDrawingQuads(aRenderer, -1.0f, 0.0f, 0.0f);
+ final boolean enableAO = aRenderer.enableAO;
+ final LightingHelper lighting = new LightingHelper(aRenderer);
+ if (glow) {
+ if (!GT_Mod.gregtechproxy.mRenderGlowTextures) {
+ draw(aRenderer);
+ return;
+ }
+ aRenderer.enableAO = false;
+ lighting.setLightnessOverride(1.0F);
+ lighting.setBrightnessOverride(MAX_BRIGHTNESS);
+ }
+ lighting.setupLightingXNeg(aBlock, aX, aY, aZ)
+ .setupColor(ForgeDirection.WEST, mRGBa);
+ final ExtendedFacing rotation = getExtendedFacing(aX, aY, aZ);
+ renderFaceXNeg(aRenderer, aX, aY, aZ, mIconContainer.getIcon(), rotation);
+ if (mIconContainer.getOverlayIcon() != null) {
+ lighting.setupColor(ForgeDirection.WEST, 0xffffff);
+ renderFaceXNeg(aRenderer, aX, aY, aZ, mIconContainer.getOverlayIcon(), rotation);
+ }
+ aRenderer.enableAO = enableAO;
+ draw(aRenderer);
+ }
+
+ @Override
+ public void renderYPos(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
+ startDrawingQuads(aRenderer, 0.0f, 1.0f, 0.0f);
+ final boolean enableAO = aRenderer.enableAO;
+ final LightingHelper lighting = new LightingHelper(aRenderer);
+ if (glow) {
+ if (!GT_Mod.gregtechproxy.mRenderGlowTextures) {
+ draw(aRenderer);
+ return;
+ }
+ aRenderer.enableAO = false;
+ lighting.setLightnessOverride(1.0F);
+ lighting.setBrightnessOverride(MAX_BRIGHTNESS);
+ }
+ lighting.setupLightingYPos(aBlock, aX, aY, aZ)
+ .setupColor(ForgeDirection.UP, mRGBa);
+ final ExtendedFacing rotation = getExtendedFacing(aX, aY, aZ);
+ renderFaceYPos(aRenderer, aX, aY, aZ, mIconContainer.getIcon(), rotation);
+ if (mIconContainer.getOverlayIcon() != null) {
+ lighting.setupColor(ForgeDirection.UP, 0xffffff);
+ renderFaceYPos(aRenderer, aX, aY, aZ, mIconContainer.getOverlayIcon(), rotation);
+ }
+ aRenderer.enableAO = enableAO;
+ draw(aRenderer);
+ }
+
+ @Override
+ public void renderYNeg(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
+ startDrawingQuads(aRenderer, 0.0f, -1.0f, 0.0f);
+ final boolean enableAO = aRenderer.enableAO;
+ final LightingHelper lighting = new LightingHelper(aRenderer);
+ if (glow) {
+ if (!GT_Mod.gregtechproxy.mRenderGlowTextures) {
+ draw(aRenderer);
+ return;
+ }
+ aRenderer.enableAO = false;
+ lighting.setLightnessOverride(1.0F);
+ lighting.setBrightnessOverride(MAX_BRIGHTNESS);
+ }
+ lighting.setupLightingYNeg(aBlock, aX, aY, aZ)
+ .setupColor(ForgeDirection.DOWN, mRGBa);
+ final ExtendedFacing rotation = getExtendedFacing(aX, aY, aZ);
+ renderFaceYNeg(aRenderer, aX, aY, aZ, mIconContainer.getIcon(), rotation);
+ if (mIconContainer.getOverlayIcon() != null) {
+ Tessellator.instance.setColorRGBA(255, 255, 255, 255);
+ renderFaceYNeg(aRenderer, aX, aY, aZ, mIconContainer.getOverlayIcon(), rotation);
+ }
+ aRenderer.enableAO = enableAO;
+ draw(aRenderer);
+ }
+
+ @Override
+ public void renderZPos(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
+ startDrawingQuads(aRenderer, 0.0f, 0.0f, 1.0f);
+ final boolean enableAO = aRenderer.enableAO;
+ final LightingHelper lighting = new LightingHelper(aRenderer);
+ if (glow) {
+ if (!GT_Mod.gregtechproxy.mRenderGlowTextures) {
+ draw(aRenderer);
+ return;
+ }
+ aRenderer.enableAO = false;
+ lighting.setLightnessOverride(1.0F);
+ lighting.setBrightnessOverride(MAX_BRIGHTNESS);
+ }
+ lighting.setupLightingZPos(aBlock, aX, aY, aZ)
+ .setupColor(ForgeDirection.SOUTH, mRGBa);
+ final ExtendedFacing rotation = getExtendedFacing(aX, aY, aZ);
+ renderFaceZPos(aRenderer, aX, aY, aZ, mIconContainer.getIcon(), rotation);
+ if (mIconContainer.getOverlayIcon() != null) {
+ lighting.setupColor(ForgeDirection.SOUTH, 0xffffff);
+ renderFaceZPos(aRenderer, aX, aY, aZ, mIconContainer.getOverlayIcon(), rotation);
+ }
+ aRenderer.enableAO = enableAO;
+ draw(aRenderer);
+ }
+
+ @Override
+ public void renderZNeg(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
+ startDrawingQuads(aRenderer, 0.0f, 0.0f, -1.0f);
+ final boolean enableAO = aRenderer.enableAO;
+ final LightingHelper lighting = new LightingHelper(aRenderer);
+ if (glow) {
+ if (!GT_Mod.gregtechproxy.mRenderGlowTextures) {
+ draw(aRenderer);
+ return;
+ }
+ aRenderer.enableAO = false;
+ lighting.setLightnessOverride(1.0F);
+ lighting.setBrightnessOverride(MAX_BRIGHTNESS);
+ }
+ lighting.setupLightingZNeg(aBlock, aX, aY, aZ)
+ .setupColor(ForgeDirection.NORTH, mRGBa);
+ final ExtendedFacing rotation = getExtendedFacing(aX, aY, aZ);
+ renderFaceZNeg(aRenderer, aX, aY, aZ, mIconContainer.getIcon(), rotation);
+ if (mIconContainer.getOverlayIcon() != null) {
+ lighting.setupColor(ForgeDirection.NORTH, 0xffffff);
+ renderFaceZNeg(aRenderer, aX, aY, aZ, mIconContainer.getOverlayIcon(), rotation);
+ }
+ aRenderer.enableAO = enableAO;
+ draw(aRenderer);
+ }
+
+ @Override
+ public short[] getRGBA() {
+ return mRGBa;
+ }
+
+ @Override
+ public boolean isValidTexture() {
+ return mIconContainer != null;
+ }
+
+ /**
+ * Renders the given texture to the bottom face of the block. Args: block, x, y, z, texture
+ */
+ protected void renderFaceYNeg(RenderBlocks aRenderer, double x, double y, double z, IIcon icon,
+ ExtendedFacing extendedFacing) {
+
+ switch (useExtFacing ? extendedFacing.getRotation() : Rotation.NORMAL) {
+ case COUNTER_CLOCKWISE -> aRenderer.uvRotateBottom = 2;
+ case CLOCKWISE -> aRenderer.uvRotateBottom = 1;
+ case UPSIDE_DOWN -> aRenderer.uvRotateBottom = 3;
+ default -> aRenderer.uvRotateBottom = 0;
+ }
+
+ final Flip aFlip = extendedFacing.getFlip();
+ aRenderer.renderFaceYNeg(
+ Blocks.air,
+ x,
+ y,
+ z,
+ useExtFacing && GT_Mod.gregtechproxy.mRenderFlippedMachinesFlipped
+ ? new GT_IconFlipped(icon, aFlip.isHorizontallyFlipped() ^ !stdOrient, aFlip.isVerticallyFliped())
+ : new GT_IconFlipped(icon, !stdOrient, false));
+ aRenderer.uvRotateBottom = 0;
+ }
+
+ /**
+ * Renders the given texture to the top face of the block. Args: block, x, y, z, texture
+ */
+ protected void renderFaceYPos(RenderBlocks aRenderer, double x, double y, double z, IIcon icon,
+ ExtendedFacing extendedFacing) {
+
+ switch (useExtFacing ? extendedFacing.getRotation() : Rotation.NORMAL) {
+ case COUNTER_CLOCKWISE -> aRenderer.uvRotateTop = 2;
+ case CLOCKWISE -> aRenderer.uvRotateTop = 1;
+ case UPSIDE_DOWN -> aRenderer.uvRotateTop = 3;
+ default -> aRenderer.uvRotateTop = 0;
+ }
+
+ final Flip aFlip = extendedFacing.getFlip();
+ aRenderer.renderFaceYPos(
+ Blocks.air,
+ x,
+ y,
+ z,
+ useExtFacing && GT_Mod.gregtechproxy.mRenderFlippedMachinesFlipped
+ ? new GT_IconFlipped(icon, aFlip.isHorizontallyFlipped(), aFlip.isVerticallyFliped())
+ : icon);
+ aRenderer.uvRotateTop = 0;
+ }
+
+ /**
+ * Renders the given texture to the north (z-negative) face of the block. Args: block, x, y, z, texture
+ */
+ protected void renderFaceZNeg(RenderBlocks aRenderer, double x, double y, double z, IIcon icon,
+ ExtendedFacing extendedFacing) {
+ aRenderer.field_152631_f = true;
+ // **NOT A BUG**: aRenderer.uvRotateEast REALLY CONTROLS THE ROTATION OF THE NORTH SIDE
+ switch (useExtFacing ? extendedFacing.getRotation() : Rotation.NORMAL) {
+ case COUNTER_CLOCKWISE -> aRenderer.uvRotateEast = 2;
+ case CLOCKWISE -> aRenderer.uvRotateEast = 1;
+ case UPSIDE_DOWN -> aRenderer.uvRotateEast = 3;
+ default -> aRenderer.uvRotateEast = 0;
+ }
+
+ final Flip aFlip = extendedFacing.getFlip();
+ aRenderer.renderFaceZNeg(
+ Blocks.air,
+ x,
+ y,
+ z,
+ useExtFacing && GT_Mod.gregtechproxy.mRenderFlippedMachinesFlipped
+ ? new GT_IconFlipped(icon, aFlip.isHorizontallyFlipped(), aFlip.isVerticallyFliped())
+ : icon);
+ aRenderer.uvRotateEast = 0;
+ aRenderer.field_152631_f = false;
+ }
+
+ /**
+ * Renders the given texture to the south (z-positive) face of the block. Args: block, x, y, z, texture
+ */
+ protected void renderFaceZPos(RenderBlocks aRenderer, double x, double y, double z, IIcon icon,
+ ExtendedFacing extendedFacing) {
+ // **NOT A BUG**: aRenderer.uvRotateWest REALLY CONTROLS THE ROTATION OF THE SOUTH SIDE
+ switch (useExtFacing ? extendedFacing.getRotation() : Rotation.NORMAL) {
+ case COUNTER_CLOCKWISE -> aRenderer.uvRotateWest = 2;
+ case CLOCKWISE -> aRenderer.uvRotateWest = 1;
+ case UPSIDE_DOWN -> aRenderer.uvRotateWest = 3;
+ default -> aRenderer.uvRotateWest = 0;
+ }
+
+ final Flip aFlip = extendedFacing.getFlip();
+ aRenderer.renderFaceZPos(
+ Blocks.air,
+ x,
+ y,
+ z,
+ useExtFacing && GT_Mod.gregtechproxy.mRenderFlippedMachinesFlipped
+ ? new GT_IconFlipped(icon, aFlip.isHorizontallyFlipped(), aFlip.isVerticallyFliped())
+ : icon);
+ aRenderer.uvRotateWest = 0;
+ }
+
+ /**
+ * Renders the given texture to the west (x-negative) face of the block. Args: block, x, y, z, texture
+ */
+ protected void renderFaceXNeg(RenderBlocks aRenderer, double x, double y, double z, IIcon icon,
+ ExtendedFacing extendedFacing) {
+ // **NOT A BUG**: aRenderer.uvRotateNorth REALLY CONTROLS THE ROTATION OF THE WEST SIDE
+ switch (useExtFacing ? extendedFacing.getRotation() : Rotation.NORMAL) {
+ case COUNTER_CLOCKWISE -> aRenderer.uvRotateNorth = 2;
+ case CLOCKWISE -> aRenderer.uvRotateNorth = 1;
+ case UPSIDE_DOWN -> aRenderer.uvRotateNorth = 3;
+ default -> aRenderer.uvRotateNorth = 0;
+ }
+
+ final Flip aFlip = extendedFacing.getFlip();
+ aRenderer.renderFaceXNeg(
+ Blocks.air,
+ x,
+ y,
+ z,
+ useExtFacing && GT_Mod.gregtechproxy.mRenderFlippedMachinesFlipped
+ ? new GT_IconFlipped(icon, aFlip.isHorizontallyFlipped(), aFlip.isVerticallyFliped())
+ : icon);
+ aRenderer.uvRotateNorth = 0;
+ }
+
+ /**
+ * Renders the given texture to the east (x-positive) face of the block. Args: block, x, y, z, texture
+ */
+ protected void renderFaceXPos(RenderBlocks aRenderer, double x, double y, double z, IIcon icon,
+ ExtendedFacing extendedFacing) {
+ aRenderer.field_152631_f = true;
+ // **NOT A BUG**: aRenderer.uvRotateSouth REALLY CONTROLS THE ROTATION OF THE EAST SIDE
+ switch (useExtFacing ? extendedFacing.getRotation() : Rotation.NORMAL) {
+ case COUNTER_CLOCKWISE -> aRenderer.uvRotateSouth = 2;
+ case CLOCKWISE -> aRenderer.uvRotateSouth = 1;
+ case UPSIDE_DOWN -> aRenderer.uvRotateSouth = 3;
+ default -> aRenderer.uvRotateSouth = 0;
+ }
+
+ final Flip aFlip = extendedFacing.getFlip();
+ aRenderer.renderFaceXPos(
+ Blocks.air,
+ x,
+ y,
+ z,
+ useExtFacing && GT_Mod.gregtechproxy.mRenderFlippedMachinesFlipped
+ ? new GT_IconFlipped(icon, aFlip.isHorizontallyFlipped(), aFlip.isVerticallyFliped())
+ : icon);
+ aRenderer.uvRotateSouth = 0;
+ aRenderer.field_152631_f = false;
+ }
+
+ private ExtendedFacing getExtendedFacing(int x, int y, int z) {
+ if (stdOrient) return ExtendedFacing.DEFAULT;
+ final EntityPlayer player = GT_Mod.gregtechproxy.getThePlayer();
+ if (player == null) return ExtendedFacing.DEFAULT;
+ final World w = player.getEntityWorld();
+ if (w == null) return ExtendedFacing.DEFAULT;
+ final TileEntity te = w.getTileEntity(x, y, z);
+ IAlignment alignment = null;
+ if (te instanceof IGregTechTileEntity) {
+ final IMetaTileEntity meta = ((IGregTechTileEntity) te).getMetaTileEntity();
+ if (meta instanceof IAlignmentProvider) {
+ alignment = ((IAlignmentProvider) meta).getAlignment();
+ } else if (meta != null) {
+ return ExtendedFacing.of(
+ meta.getBaseMetaTileEntity()
+ .getFrontFacing());
+ }
+ } else if (te instanceof IAlignmentProvider) {
+ alignment = ((IAlignmentProvider) te).getAlignment();
+ }
+ if (alignment != null) return alignment.getExtendedFacing();
+ return ExtendedFacing.DEFAULT;
+ }
+}
diff --git a/src/main/java/gregtech/common/render/GT_Renderer_Block.java b/src/main/java/gregtech/common/render/GT_Renderer_Block.java
new file mode 100644
index 0000000000..da0d68d555
--- /dev/null
+++ b/src/main/java/gregtech/common/render/GT_Renderer_Block.java
@@ -0,0 +1,747 @@
+package gregtech.common.render;
+
+import static gregtech.api.enums.GT_Values.SIDE_DOWN;
+import static gregtech.api.enums.GT_Values.SIDE_EAST;
+import static gregtech.api.enums.GT_Values.SIDE_NORTH;
+import static gregtech.api.enums.GT_Values.SIDE_SOUTH;
+import static gregtech.api.enums.GT_Values.SIDE_UP;
+import static gregtech.api.enums.GT_Values.SIDE_WEST;
+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;
+import static gregtech.api.interfaces.metatileentity.IConnectable.CONNECTED_SOUTH;
+import static gregtech.api.interfaces.metatileentity.IConnectable.CONNECTED_UP;
+import static gregtech.api.interfaces.metatileentity.IConnectable.CONNECTED_WEST;
+import static gregtech.api.interfaces.metatileentity.IConnectable.HAS_FRESHFOAM;
+import static gregtech.api.interfaces.metatileentity.IConnectable.HAS_HARDENEDFOAM;
+import static gregtech.api.interfaces.metatileentity.IConnectable.NO_CONNECTION;
+import static net.minecraftforge.common.util.ForgeDirection.DOWN;
+import static net.minecraftforge.common.util.ForgeDirection.EAST;
+import static net.minecraftforge.common.util.ForgeDirection.NORTH;
+import static net.minecraftforge.common.util.ForgeDirection.SOUTH;
+import static net.minecraftforge.common.util.ForgeDirection.UP;
+import static net.minecraftforge.common.util.ForgeDirection.VALID_DIRECTIONS;
+import static net.minecraftforge.common.util.ForgeDirection.WEST;
+
+import net.minecraft.block.Block;
+import net.minecraft.client.Minecraft;
+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.tileentity.TileEntity;
+import net.minecraft.world.IBlockAccess;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import org.lwjgl.opengl.GL11;
+
+import com.gtnewhorizons.angelica.api.ThreadSafeISBRH;
+
+import cpw.mods.fml.client.registry.ISimpleBlockRenderingHandler;
+import cpw.mods.fml.client.registry.RenderingRegistry;
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.GT_Mod;
+import gregtech.api.GregTech_API;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IAllSidedTexturedTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.interfaces.tileentity.IPipeRenderedTileEntity;
+import gregtech.api.interfaces.tileentity.ITexturedTileEntity;
+import gregtech.api.metatileentity.MetaPipeEntity;
+import gregtech.api.objects.XSTR;
+import gregtech.common.blocks.GT_Block_Machines;
+import gregtech.common.blocks.GT_Block_Ores_Abstract;
+import gregtech.common.blocks.GT_TileEntity_Ores;
+
+@ThreadSafeISBRH(perThread = true)
+public class GT_Renderer_Block implements ISimpleBlockRenderingHandler {
+
+ public static final float blockMin = 0.0F;
+ public static final float blockMax = 1.0F;
+ private static final float coverThickness = blockMax / 8.0F;
+ private static final float coverInnerMin = blockMin + coverThickness;
+ private static final float coverInnerMax = blockMax - coverThickness;
+
+ @Deprecated
+ public static GT_Renderer_Block INSTANCE;
+ public static int mRenderID;
+
+ public static void register() {
+ mRenderID = RenderingRegistry.getNextAvailableRenderId();
+ INSTANCE = new GT_Renderer_Block();
+ RenderingRegistry.registerBlockHandler(INSTANCE);
+ }
+
+ private final ITexture[][] textureArray = new ITexture[6][];
+
+ public boolean renderStandardBlock(IBlockAccess aWorld, int aX, int aY, int aZ, Block aBlock,
+ RenderBlocks aRenderer) {
+ final TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if (tTileEntity instanceof IPipeRenderedTileEntity pipeRenderedTileEntity) {
+ textureArray[0] = pipeRenderedTileEntity.getTextureCovered(DOWN);
+ textureArray[1] = pipeRenderedTileEntity.getTextureCovered(UP);
+ textureArray[2] = pipeRenderedTileEntity.getTextureCovered(NORTH);
+ textureArray[3] = pipeRenderedTileEntity.getTextureCovered(SOUTH);
+ textureArray[4] = pipeRenderedTileEntity.getTextureCovered(WEST);
+ textureArray[5] = pipeRenderedTileEntity.getTextureCovered(EAST);
+ return renderStandardBlock(aWorld, aX, aY, aZ, aBlock, aRenderer, textureArray);
+ }
+ if (tTileEntity instanceof IAllSidedTexturedTileEntity allSidedTexturedTileEntity) {
+ ITexture[] texture = allSidedTexturedTileEntity.getTexture(aBlock);
+ textureArray[0] = texture;
+ textureArray[1] = texture;
+ textureArray[2] = texture;
+ textureArray[3] = texture;
+ textureArray[4] = texture;
+ textureArray[5] = texture;
+ return renderStandardBlock(aWorld, aX, aY, aZ, aBlock, aRenderer, textureArray);
+ }
+ if (tTileEntity instanceof ITexturedTileEntity texturedTileEntity) {
+ textureArray[0] = texturedTileEntity.getTexture(aBlock, DOWN);
+ textureArray[1] = texturedTileEntity.getTexture(aBlock, UP);
+ textureArray[2] = texturedTileEntity.getTexture(aBlock, NORTH);
+ textureArray[3] = texturedTileEntity.getTexture(aBlock, SOUTH);
+ textureArray[4] = texturedTileEntity.getTexture(aBlock, WEST);
+ textureArray[5] = texturedTileEntity.getTexture(aBlock, EAST);
+ return renderStandardBlock(aWorld, aX, aY, aZ, aBlock, aRenderer, textureArray);
+ }
+ return false;
+ }
+
+ public boolean renderStandardBlock(IBlockAccess aWorld, int aX, int aY, int aZ, Block aBlock,
+ RenderBlocks aRenderer, ITexture[][] aTextures) {
+ aBlock.setBlockBounds(blockMin, blockMin, blockMin, blockMax, blockMax, blockMax);
+ aRenderer.setRenderBoundsFromBlock(aBlock);
+
+ renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, aTextures[SIDE_DOWN], true);
+ renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, aTextures[SIDE_UP], true);
+ renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, aTextures[SIDE_NORTH], true);
+ renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, aTextures[SIDE_SOUTH], true);
+ renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, aTextures[SIDE_WEST], true);
+ renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, aTextures[SIDE_EAST], true);
+ return true;
+ }
+
+ final ITexture[][] tIcons = new ITexture[VALID_DIRECTIONS.length][];
+ final ITexture[][] tCovers = new ITexture[VALID_DIRECTIONS.length][];
+ final boolean[] tIsCovered = new boolean[VALID_DIRECTIONS.length];
+
+ public boolean renderPipeBlock(IBlockAccess aWorld, int aX, int aY, int aZ, Block aBlock,
+ IPipeRenderedTileEntity aTileEntity, RenderBlocks aRenderer) {
+ final byte aConnections = aTileEntity.getConnections();
+ if ((aConnections & (HAS_FRESHFOAM | HAS_HARDENEDFOAM)) != 0) {
+ return renderStandardBlock(aWorld, aX, aY, aZ, aBlock, aRenderer);
+ }
+ final float thickness = aTileEntity.getThickNess();
+ if (thickness >= 0.99F) {
+ return renderStandardBlock(aWorld, aX, aY, aZ, aBlock, aRenderer);
+ }
+ // Range of block occupied by pipe
+ final float pipeMin = (blockMax - thickness) / 2.0F;
+ final float pipeMax = blockMax - pipeMin;
+
+ for (int i = 0; i < VALID_DIRECTIONS.length; i++) {
+ final ForgeDirection iSide = VALID_DIRECTIONS[i];
+ tIsCovered[i] = (aTileEntity.getCoverIDAtSide(iSide) != 0);
+ tCovers[i] = aTileEntity.getTexture(aBlock, iSide);
+ tIcons[i] = aTileEntity.getTextureUncovered(iSide);
+
+ }
+
+ switch (aConnections) {
+ case NO_CONNECTION -> {
+ aBlock.setBlockBounds(pipeMin, pipeMin, pipeMin, pipeMax, pipeMax, pipeMax);
+ aRenderer.setRenderBoundsFromBlock(aBlock);
+ renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_DOWN], false);
+ renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_UP], false);
+ renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_NORTH], false);
+ renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_SOUTH], false);
+ renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_WEST], false);
+ renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_EAST], false);
+ }
+ case CONNECTED_EAST | CONNECTED_WEST -> {
+ // EAST - WEST Pipe Sides
+ aBlock.setBlockBounds(blockMin, pipeMin, pipeMin, blockMax, pipeMax, pipeMax);
+ aRenderer.setRenderBoundsFromBlock(aBlock);
+ renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_DOWN], false);
+ renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_UP], false);
+ renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_NORTH], false);
+ renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_SOUTH], false);
+
+ // EAST - WEST Pipe Ends
+ renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_WEST], false);
+ renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_EAST], false);
+ }
+ case CONNECTED_DOWN | CONNECTED_UP -> {
+ // UP - DOWN Pipe Sides
+ aBlock.setBlockBounds(pipeMin, blockMin, pipeMin, pipeMax, blockMax, pipeMax);
+ aRenderer.setRenderBoundsFromBlock(aBlock);
+ renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_NORTH], false);
+ renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_SOUTH], false);
+ renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_WEST], false);
+ renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_EAST], false);
+
+ // UP - DOWN Pipe Ends
+ renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_DOWN], false);
+ renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_UP], false);
+ }
+ case CONNECTED_NORTH | CONNECTED_SOUTH -> {
+ // NORTH - SOUTH Pipe Sides
+ aBlock.setBlockBounds(pipeMin, pipeMin, blockMin, pipeMax, pipeMax, blockMax);
+ aRenderer.setRenderBoundsFromBlock(aBlock);
+ renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_DOWN], false);
+ renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_UP], false);
+ renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_WEST], false);
+ renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_EAST], false);
+
+ // NORTH - SOUTH Pipe Ends
+ renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_NORTH], false);
+ renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_SOUTH], false);
+ }
+ default -> {
+ if ((aConnections & CONNECTED_WEST) == 0) {
+ aBlock.setBlockBounds(pipeMin, pipeMin, pipeMin, pipeMax, pipeMax, pipeMax);
+ aRenderer.setRenderBoundsFromBlock(aBlock);
+ } else {
+ aBlock.setBlockBounds(blockMin, pipeMin, pipeMin, pipeMin, pipeMax, pipeMax);
+ aRenderer.setRenderBoundsFromBlock(aBlock);
+ renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_DOWN], false);
+ renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_UP], false);
+ renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_NORTH], false);
+ renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_SOUTH], false);
+ }
+ renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_WEST], false);
+ if ((aConnections & CONNECTED_EAST) == 0) {
+ aBlock.setBlockBounds(pipeMin, pipeMin, pipeMin, pipeMax, pipeMax, pipeMax);
+ aRenderer.setRenderBoundsFromBlock(aBlock);
+ } else {
+ aBlock.setBlockBounds(pipeMax, pipeMin, pipeMin, blockMax, pipeMax, pipeMax);
+ aRenderer.setRenderBoundsFromBlock(aBlock);
+ renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_DOWN], false);
+ renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_UP], false);
+ renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_NORTH], false);
+ renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_SOUTH], false);
+ }
+ renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_EAST], false);
+ if ((aConnections & CONNECTED_DOWN) == 0) {
+ aBlock.setBlockBounds(pipeMin, pipeMin, pipeMin, pipeMax, pipeMax, pipeMax);
+ aRenderer.setRenderBoundsFromBlock(aBlock);
+ } else {
+ aBlock.setBlockBounds(pipeMin, blockMin, pipeMin, pipeMax, pipeMin, pipeMax);
+ aRenderer.setRenderBoundsFromBlock(aBlock);
+ renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_NORTH], false);
+ renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_SOUTH], false);
+ renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_WEST], false);
+ renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_EAST], false);
+ }
+ renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_DOWN], false);
+ if ((aConnections & CONNECTED_UP) == 0) {
+ aBlock.setBlockBounds(pipeMin, pipeMin, pipeMin, pipeMax, pipeMax, pipeMax);
+ aRenderer.setRenderBoundsFromBlock(aBlock);
+ } else {
+ aBlock.setBlockBounds(pipeMin, pipeMax, pipeMin, pipeMax, blockMax, pipeMax);
+ aRenderer.setRenderBoundsFromBlock(aBlock);
+ renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_NORTH], false);
+ renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_SOUTH], false);
+ renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_WEST], false);
+ renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_EAST], false);
+ }
+ renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_UP], false);
+ if ((aConnections & CONNECTED_NORTH) == 0) {
+ aBlock.setBlockBounds(pipeMin, pipeMin, pipeMin, pipeMax, pipeMax, pipeMax);
+ aRenderer.setRenderBoundsFromBlock(aBlock);
+ } else {
+ aBlock.setBlockBounds(pipeMin, pipeMin, blockMin, pipeMax, pipeMax, pipeMin);
+ aRenderer.setRenderBoundsFromBlock(aBlock);
+ renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_DOWN], false);
+ renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_UP], false);
+ renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_WEST], false);
+ renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_EAST], false);
+ }
+ renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_NORTH], false);
+ if ((aConnections & CONNECTED_SOUTH) == 0) {
+ aBlock.setBlockBounds(pipeMin, pipeMin, pipeMin, pipeMax, pipeMax, pipeMax);
+ aRenderer.setRenderBoundsFromBlock(aBlock);
+ } else {
+ aBlock.setBlockBounds(pipeMin, pipeMin, pipeMax, pipeMax, pipeMax, blockMax);
+ aRenderer.setRenderBoundsFromBlock(aBlock);
+ renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_DOWN], false);
+ renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_UP], false);
+ renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_WEST], false);
+ renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_EAST], false);
+ }
+ renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tIcons[SIDE_SOUTH], false);
+ }
+ }
+
+ // Render covers on pipes
+ if (tIsCovered[SIDE_DOWN]) {
+ aBlock.setBlockBounds(blockMin, blockMin, blockMin, blockMax, coverInnerMin, blockMax);
+ aRenderer.setRenderBoundsFromBlock(aBlock);
+ if (!tIsCovered[SIDE_NORTH]) {
+ renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_DOWN], false);
+ }
+ if (!tIsCovered[SIDE_SOUTH]) {
+ renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_DOWN], false);
+ }
+ if (!tIsCovered[SIDE_WEST]) {
+ renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_DOWN], false);
+ }
+ if (!tIsCovered[SIDE_EAST]) {
+ renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_DOWN], false);
+ }
+ renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_DOWN], false);
+ if ((aConnections & CONNECTED_DOWN) != 0) {
+ // Split outer face to leave hole for pipe
+ // Lower panel
+ aRenderer.setRenderBounds(blockMin, blockMin, blockMin, blockMax, blockMin, pipeMin);
+ renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_DOWN], false);
+ // Upper panel
+ aRenderer.setRenderBounds(blockMin, blockMin, pipeMax, blockMax, blockMin, blockMax);
+ renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_DOWN], false);
+ // Middle left panel
+ aRenderer.setRenderBounds(blockMin, blockMin, pipeMin, pipeMin, blockMin, pipeMax);
+ renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_DOWN], false);
+ // Middle right panel
+ aRenderer.setRenderBounds(pipeMax, blockMin, pipeMin, blockMax, blockMin, pipeMax);
+ }
+ renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_DOWN], false);
+ }
+
+ if (tIsCovered[SIDE_UP]) {
+ aBlock.setBlockBounds(blockMin, coverInnerMax, blockMin, blockMax, blockMax, blockMax);
+ aRenderer.setRenderBoundsFromBlock(aBlock);
+ if (!tIsCovered[SIDE_NORTH]) {
+ renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_UP], false);
+ }
+ if (!tIsCovered[SIDE_SOUTH]) {
+ renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_UP], false);
+ }
+ if (!tIsCovered[SIDE_WEST]) {
+ renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_UP], false);
+ }
+ if (!tIsCovered[SIDE_EAST]) {
+ renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_UP], false);
+ }
+ renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_UP], false);
+ if ((aConnections & CONNECTED_UP) != 0) {
+ // Split outer face to leave hole for pipe
+ // Lower panel
+ aRenderer.setRenderBounds(blockMin, blockMax, blockMin, blockMax, blockMax, pipeMin);
+ renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_UP], false);
+ // Upper panel
+ aRenderer.setRenderBounds(blockMin, blockMax, pipeMax, blockMax, blockMax, blockMax);
+ renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_UP], false);
+ // Middle left panel
+ aRenderer.setRenderBounds(blockMin, blockMax, pipeMin, pipeMin, blockMax, pipeMax);
+ renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_UP], false);
+ // Middle right panel
+ aRenderer.setRenderBounds(pipeMax, blockMax, pipeMin, blockMax, blockMax, pipeMax);
+ }
+ renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_UP], false);
+ }
+
+ if (tIsCovered[SIDE_NORTH]) {
+ aBlock.setBlockBounds(blockMin, blockMin, blockMin, blockMax, blockMax, coverInnerMin);
+ aRenderer.setRenderBoundsFromBlock(aBlock);
+ if (!tIsCovered[SIDE_DOWN]) {
+ renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_NORTH], false);
+ }
+ if (!tIsCovered[SIDE_UP]) {
+ renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_NORTH], false);
+ }
+ if (!tIsCovered[SIDE_WEST]) {
+ renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_NORTH], false);
+ }
+ if (!tIsCovered[SIDE_EAST]) {
+ renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_NORTH], false);
+ }
+ renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_NORTH], false);
+ if ((aConnections & CONNECTED_NORTH) != 0) {
+ // Split outer face to leave hole for pipe
+ // Lower panel
+ aRenderer.setRenderBounds(blockMin, blockMin, blockMin, blockMax, pipeMin, blockMin);
+ renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_NORTH], false);
+ // Upper panel
+ aRenderer.setRenderBounds(blockMin, pipeMax, blockMin, blockMax, blockMax, blockMin);
+ renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_NORTH], false);
+ // Middle left panel
+ aRenderer.setRenderBounds(blockMin, pipeMin, blockMin, pipeMin, pipeMax, blockMin);
+ renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_NORTH], false);
+ // Middle right panel
+ aRenderer.setRenderBounds(pipeMax, pipeMin, blockMin, blockMax, pipeMax, blockMin);
+ }
+ renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_NORTH], false);
+ }
+
+ if (tIsCovered[SIDE_SOUTH]) {
+ aBlock.setBlockBounds(blockMin, blockMin, coverInnerMax, blockMax, blockMax, blockMax);
+ aRenderer.setRenderBoundsFromBlock(aBlock);
+ if (!tIsCovered[SIDE_DOWN]) {
+ renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_SOUTH], false);
+ }
+ if (!tIsCovered[SIDE_UP]) {
+ renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_SOUTH], false);
+ }
+ if (!tIsCovered[SIDE_WEST]) {
+ renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_SOUTH], false);
+ }
+ if (!tIsCovered[SIDE_EAST]) {
+ renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_SOUTH], false);
+ }
+ renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_SOUTH], false);
+ if ((aConnections & CONNECTED_SOUTH) != 0) {
+ // Split outer face to leave hole for pipe
+ // Lower panel
+ aRenderer.setRenderBounds(blockMin, blockMin, blockMax, blockMax, pipeMin, blockMax);
+ renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_SOUTH], false);
+ // Upper panel
+ aRenderer.setRenderBounds(blockMin, pipeMax, blockMax, blockMax, blockMax, blockMax);
+ renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_SOUTH], false);
+ // Middle left panel
+ aRenderer.setRenderBounds(blockMin, pipeMin, blockMax, pipeMin, pipeMax, blockMax);
+ renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_SOUTH], false);
+ // Middle right panel
+ aRenderer.setRenderBounds(pipeMax, pipeMin, blockMax, blockMax, pipeMax, blockMax);
+ }
+ renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_SOUTH], false);
+ }
+
+ if (tIsCovered[SIDE_WEST]) {
+ aBlock.setBlockBounds(blockMin, blockMin, blockMin, coverInnerMin, blockMax, blockMax);
+ aRenderer.setRenderBoundsFromBlock(aBlock);
+ if (!tIsCovered[SIDE_DOWN]) {
+ renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_WEST], false);
+ }
+ if (!tIsCovered[SIDE_UP]) {
+ renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_WEST], false);
+ }
+ if (!tIsCovered[SIDE_NORTH]) {
+ renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_WEST], false);
+ }
+ if (!tIsCovered[SIDE_SOUTH]) {
+ renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_WEST], false);
+ }
+ renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_WEST], false);
+ if ((aConnections & CONNECTED_WEST) != 0) {
+ // Split outer face to leave hole for pipe
+ // Lower panel
+ aRenderer.setRenderBounds(blockMin, blockMin, blockMin, blockMin, pipeMin, blockMax);
+ renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_WEST], false);
+ // Upper panel
+ aRenderer.setRenderBounds(blockMin, pipeMax, blockMin, blockMin, blockMax, blockMax);
+ renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_WEST], false);
+ // Middle left panel
+ aRenderer.setRenderBounds(blockMin, pipeMin, blockMin, blockMin, pipeMax, pipeMin);
+ renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_WEST], false);
+ // Middle right panel
+ aRenderer.setRenderBounds(blockMin, pipeMin, pipeMax, blockMin, pipeMax, blockMax);
+ }
+ renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_WEST], false);
+ }
+
+ if (tIsCovered[SIDE_EAST]) {
+ aBlock.setBlockBounds(coverInnerMax, blockMin, blockMin, blockMax, blockMax, blockMax);
+ aRenderer.setRenderBoundsFromBlock(aBlock);
+ if (!tIsCovered[SIDE_DOWN]) {
+ renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_EAST], false);
+ }
+ if (!tIsCovered[SIDE_UP]) {
+ renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_EAST], false);
+ }
+ if (!tIsCovered[SIDE_NORTH]) {
+ renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_EAST], false);
+ }
+ if (!tIsCovered[SIDE_SOUTH]) {
+ renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_EAST], false);
+ }
+ renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_EAST], false);
+
+ if ((aConnections & CONNECTED_EAST) != 0) {
+ // Split outer face to leave hole for pipe
+ // Lower panel
+ aRenderer.setRenderBounds(blockMax, blockMin, blockMin, blockMax, pipeMin, blockMax);
+ renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_EAST], false);
+ // Upper panel
+ aRenderer.setRenderBounds(blockMax, pipeMax, blockMin, blockMax, blockMax, blockMax);
+ renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_EAST], false);
+ // Middle left panel
+ aRenderer.setRenderBounds(blockMax, pipeMin, blockMin, blockMax, pipeMax, pipeMin);
+ renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_EAST], false);
+ // Middle right panel
+ aRenderer.setRenderBounds(blockMax, pipeMin, pipeMax, blockMax, pipeMax, blockMax);
+ }
+ renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, tCovers[SIDE_EAST], false);
+ }
+ aBlock.setBlockBounds(blockMin, blockMin, blockMin, blockMax, blockMax, blockMax);
+ aRenderer.setRenderBoundsFromBlock(aBlock);
+
+ return true;
+ }
+
+ @SideOnly(Side.CLIENT)
+ public static void addHitEffects(EffectRenderer effectRenderer, Block block, World world, int x, int y, int z,
+ int ordinalSide) {
+ double rX = x + XSTR.XSTR_INSTANCE.nextDouble() * 0.8 + 0.1;
+ double rY = y + XSTR.XSTR_INSTANCE.nextDouble() * 0.8 + 0.1;
+ double rZ = z + XSTR.XSTR_INSTANCE.nextDouble() * 0.8 + 0.1;
+ if (ordinalSide == 0) {
+ rY = y - 0.1;
+ } else if (ordinalSide == 1) {
+ rY = y + 1.1;
+ } else if (ordinalSide == 2) {
+ rZ = z - 0.1;
+ } else if (ordinalSide == 3) {
+ rZ = z + 1.1;
+ } else if (ordinalSide == 4) {
+ rX = x - 0.1;
+ } else if (ordinalSide == 5) {
+ rX = x + 1.1;
+ }
+ effectRenderer.addEffect(
+ (new EntityDiggingFX(
+ world,
+ rX,
+ rY,
+ rZ,
+ 0.0,
+ 0.0,
+ 0.0,
+ block,
+ block.getDamageValue(world, x, y, z),
+ ordinalSide)).applyColourMultiplier(x, y, z)
+ .multiplyVelocity(0.2F)
+ .multipleParticleScaleBy(0.6F));
+ }
+
+ @SideOnly(Side.CLIENT)
+ public static void addDestroyEffects(EffectRenderer effectRenderer, Block block, World world, int x, int y, int z) {
+ for (int iX = 0; iX < 4; ++iX) {
+ for (int iY = 0; iY < 4; ++iY) {
+ for (int iZ = 0; iZ < 4; ++iZ) {
+ final double bX = x + (iX + 0.5) / 4.0;
+ final double bY = y + (iY + 0.5) / 4.0;
+ final double bZ = z + (iZ + 0.5) / 4.0;
+ effectRenderer.addEffect(
+ (new EntityDiggingFX(
+ world,
+ bX,
+ bY,
+ bZ,
+ bX - x - 0.5,
+ bY - y - 0.5,
+ bZ - z - 0.5,
+ block,
+ block.getDamageValue(world, x, y, z))).applyColourMultiplier(x, y, z));
+ }
+ }
+ }
+ }
+
+ final GT_TileEntity_Ores tTileEntity = new GT_TileEntity_Ores();
+
+ @Override
+ public void renderInventoryBlock(Block aBlock, int aMeta, int aModelID, RenderBlocks aRenderer) {
+ aRenderer.enableAO = false;
+ aRenderer.useInventoryTint = true;
+
+ GL11.glRotatef(90.0F, 0.0F, 1.0F, 0.0F);
+ GL11.glTranslatef(-0.5F, -0.5F, -0.5F);
+ if (aBlock instanceof GT_Block_Ores_Abstract) {
+ tTileEntity.mMetaData = ((short) aMeta);
+
+ aBlock.setBlockBoundsForItemRender();
+ aRenderer.setRenderBoundsFromBlock(aBlock);
+ // spotless:off
+ ITexture[] texture = tTileEntity.getTexture(aBlock);
+ renderNegativeYFacing(null, aRenderer, aBlock, 0, 0, 0, texture, true);
+ renderPositiveYFacing(null, aRenderer, aBlock, 0, 0, 0, texture, true);
+ renderNegativeZFacing(null, aRenderer, aBlock, 0, 0, 0, texture, true);
+ renderPositiveZFacing(null, aRenderer, aBlock, 0, 0, 0, texture, true);
+ renderNegativeXFacing(null, aRenderer, aBlock, 0, 0, 0, texture, true);
+ renderPositiveXFacing(null, aRenderer, aBlock, 0, 0, 0, texture, true);
+ // spotless:on
+ } 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);
+
+ aRenderer.setRenderBoundsFromBlock(aBlock);
+
+ GL11.glTranslatef(0.5F, 0.5F, 0.5F);
+ aRenderer.useInventoryTint = false;
+ }
+
+ private static void renderNormalInventoryMetaTileEntity(Block aBlock, int aMeta, RenderBlocks aRenderer) {
+ if ((aMeta <= 0) || (aMeta >= GregTech_API.METATILEENTITIES.length)) {
+ return;
+ }
+ final IMetaTileEntity tMetaTileEntity = GregTech_API.METATILEENTITIES[aMeta];
+ if (tMetaTileEntity == null) {
+ return;
+ }
+ aBlock.setBlockBoundsForItemRender();
+ aRenderer.setRenderBoundsFromBlock(aBlock);
+
+ final IGregTechTileEntity iGregTechTileEntity = tMetaTileEntity.getBaseMetaTileEntity();
+
+ // spotless:off
+ if ((iGregTechTileEntity instanceof IPipeRenderedTileEntity renderedPipe)
+ && (tMetaTileEntity instanceof MetaPipeEntity pipeEntity)) {
+ final float tThickness = renderedPipe.getThickNess();
+ final float pipeMin = (blockMax - tThickness) / 2.0F;
+ final float pipeMax = blockMax - pipeMin;
+
+ aBlock.setBlockBounds(blockMin, pipeMin, pipeMin, blockMax, pipeMax, pipeMax);
+ aRenderer.setRenderBoundsFromBlock(aBlock);
+ renderNegativeYFacing(null, aRenderer, aBlock, 0, 0, 0, pipeEntity.getTexture(iGregTechTileEntity, DOWN, (CONNECTED_WEST | CONNECTED_EAST), -1, false, false), true);
+ renderPositiveYFacing(null, aRenderer, aBlock, 0, 0, 0, pipeEntity.getTexture(iGregTechTileEntity, UP, (CONNECTED_WEST | CONNECTED_EAST), -1, false, false), true);
+ renderNegativeZFacing(null, aRenderer, aBlock, 0, 0, 0, pipeEntity.getTexture(iGregTechTileEntity, NORTH, (CONNECTED_WEST | CONNECTED_EAST), -1, false, false), true);
+ renderPositiveZFacing(null, aRenderer, aBlock, 0, 0, 0, pipeEntity.getTexture(iGregTechTileEntity, SOUTH, (CONNECTED_WEST | CONNECTED_EAST), -1, false, false), true);
+ renderNegativeXFacing(null, aRenderer, aBlock, 0, 0, 0, pipeEntity.getTexture(iGregTechTileEntity, WEST, (CONNECTED_WEST | CONNECTED_EAST), -1, true, false), true);
+ renderPositiveXFacing(null, aRenderer, aBlock, 0, 0, 0, pipeEntity.getTexture(iGregTechTileEntity, EAST, (CONNECTED_WEST | CONNECTED_EAST), -1, true, false), true);
+ } else {
+ renderNegativeYFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(iGregTechTileEntity, DOWN, WEST, -1, true, false), true);
+ renderPositiveYFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(iGregTechTileEntity, UP, WEST, -1, true, false), true);
+ renderNegativeZFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(iGregTechTileEntity, NORTH, WEST, -1, true, false), true);
+ renderPositiveZFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(iGregTechTileEntity, SOUTH, WEST, -1, true, false), true);
+ renderNegativeXFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(iGregTechTileEntity, WEST, WEST, -1, true, false), true);
+ renderPositiveXFacing(null, aRenderer, aBlock, 0, 0, 0, tMetaTileEntity.getTexture(iGregTechTileEntity, EAST, WEST, -1, true, false), true);
+ }
+ // spotless:on
+ }
+
+ public static void renderNegativeYFacing(IBlockAccess aWorld, RenderBlocks aRenderer, Block aBlock, int aX, int aY,
+ int aZ, ITexture[] aIcon, boolean aFullBlock) {
+ if (aWorld != null) {
+ if ((aFullBlock) && (!aBlock.shouldSideBeRendered(aWorld, aX, aY - 1, aZ, 0))) return;
+ Tessellator.instance
+ .setBrightness(aBlock.getMixedBrightnessForBlock(aWorld, aX, aFullBlock ? aY - 1 : aY, aZ));
+ }
+ if (aIcon == null) return;
+ for (final ITexture iTexture : aIcon) {
+ if (iTexture != null) {
+ iTexture.renderYNeg(aRenderer, aBlock, aX, aY, aZ);
+ }
+ }
+ }
+
+ public static void renderPositiveYFacing(IBlockAccess aWorld, RenderBlocks aRenderer, Block aBlock, int aX, int aY,
+ int aZ, ITexture[] aIcon, boolean aFullBlock) {
+ if (aWorld != null) {
+ if ((aFullBlock) && (!aBlock.shouldSideBeRendered(aWorld, aX, aY + 1, aZ, 1))) return;
+ Tessellator.instance
+ .setBrightness(aBlock.getMixedBrightnessForBlock(aWorld, aX, aFullBlock ? aY + 1 : aY, aZ));
+ }
+ if (aIcon == null) return;
+ for (final ITexture iTexture : aIcon) {
+ if (iTexture != null) {
+ iTexture.renderYPos(aRenderer, aBlock, aX, aY, aZ);
+ }
+ }
+ }
+
+ public static void renderNegativeZFacing(IBlockAccess aWorld, RenderBlocks aRenderer, Block aBlock, int aX, int aY,
+ int aZ, ITexture[] aIcon, boolean aFullBlock) {
+ if (aWorld != null) {
+ if ((aFullBlock) && (!aBlock.shouldSideBeRendered(aWorld, aX, aY, aZ - 1, 2))) return;
+ Tessellator.instance
+ .setBrightness(aBlock.getMixedBrightnessForBlock(aWorld, aX, aY, aFullBlock ? aZ - 1 : aZ));
+ }
+ if (aIcon == null) return;
+ for (final ITexture iTexture : aIcon) {
+ if (iTexture != null) {
+ iTexture.renderZNeg(aRenderer, aBlock, aX, aY, aZ);
+ }
+ }
+ }
+
+ public static void renderPositiveZFacing(IBlockAccess aWorld, RenderBlocks aRenderer, Block aBlock, int aX, int aY,
+ int aZ, ITexture[] aIcon, boolean aFullBlock) {
+ if (aWorld != null) {
+ if ((aFullBlock) && (!aBlock.shouldSideBeRendered(aWorld, aX, aY, aZ + 1, 3))) return;
+ Tessellator.instance
+ .setBrightness(aBlock.getMixedBrightnessForBlock(aWorld, aX, aY, aFullBlock ? aZ + 1 : aZ));
+ }
+ if (aIcon == null) return;
+ for (final ITexture iTexture : aIcon) {
+ if (iTexture != null) {
+ iTexture.renderZPos(aRenderer, aBlock, aX, aY, aZ);
+ }
+ }
+ }
+
+ public static void renderNegativeXFacing(IBlockAccess aWorld, RenderBlocks aRenderer, Block aBlock, int aX, int aY,
+ int aZ, ITexture[] aIcon, boolean aFullBlock) {
+ if (aWorld != null) {
+ if ((aFullBlock) && (!aBlock.shouldSideBeRendered(aWorld, aX - 1, aY, aZ, 4))) return;
+ Tessellator.instance
+ .setBrightness(aBlock.getMixedBrightnessForBlock(aWorld, aFullBlock ? aX - 1 : aX, aY, aZ));
+ }
+ if (aIcon == null) return;
+ for (final ITexture iTexture : aIcon) {
+ if (iTexture != null) {
+ iTexture.renderXNeg(aRenderer, aBlock, aX, aY, aZ);
+ }
+ }
+ }
+
+ public static void renderPositiveXFacing(IBlockAccess aWorld, RenderBlocks aRenderer, Block aBlock, int aX, int aY,
+ int aZ, ITexture[] aIcon, boolean aFullBlock) {
+ if (aWorld != null) {
+ if ((aFullBlock) && (!aBlock.shouldSideBeRendered(aWorld, aX + 1, aY, aZ, 5))) return;
+ Tessellator.instance
+ .setBrightness(aBlock.getMixedBrightnessForBlock(aWorld, aFullBlock ? aX + 1 : aX, aY, aZ));
+ }
+ if (aIcon == null) return;
+ for (final ITexture iTexture : aIcon) {
+ if (iTexture != null) {
+ iTexture.renderXPos(aRenderer, aBlock, aX, aY, aZ);
+ }
+ }
+ }
+
+ @Override
+ public boolean renderWorldBlock(IBlockAccess aWorld, int aX, int aY, int aZ, Block aBlock, int aModelID,
+ RenderBlocks aRenderer) {
+ aRenderer.enableAO = Minecraft.isAmbientOcclusionEnabled() && GT_Mod.gregtechproxy.mRenderTileAmbientOcclusion;
+ aRenderer.useInventoryTint = false;
+
+ final TileEntity tileEntity = aWorld.getTileEntity(aX, aY, aZ);
+ if (tileEntity == null) return false;
+ if (tileEntity instanceof IGregTechTileEntity) {
+ final IMetaTileEntity metaTileEntity;
+ if ((metaTileEntity = ((IGregTechTileEntity) tileEntity).getMetaTileEntity()) != null
+ && metaTileEntity.renderInWorld(aWorld, aX, aY, aZ, aBlock, aRenderer)) {
+ aRenderer.enableAO = false;
+ return true;
+ }
+ }
+ if (tileEntity instanceof IPipeRenderedTileEntity
+ && renderPipeBlock(aWorld, aX, aY, aZ, aBlock, (IPipeRenderedTileEntity) tileEntity, aRenderer)) {
+ aRenderer.enableAO = false;
+ return true;
+ }
+ if (renderStandardBlock(aWorld, aX, aY, aZ, aBlock, aRenderer)) {
+ aRenderer.enableAO = false;
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean shouldRender3DInInventory(int aModel) {
+ return true;
+ }
+
+ @Override
+ public int getRenderId() {
+ return this.mRenderID;
+ }
+}
diff --git a/src/main/java/gregtech/common/render/GT_Renderer_Entity_Arrow.java b/src/main/java/gregtech/common/render/GT_Renderer_Entity_Arrow.java
new file mode 100644
index 0000000000..e72a79514e
--- /dev/null
+++ b/src/main/java/gregtech/common/render/GT_Renderer_Entity_Arrow.java
@@ -0,0 +1,23 @@
+package gregtech.common.render;
+
+import net.minecraft.client.renderer.entity.RenderArrow;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.projectile.EntityArrow;
+import net.minecraft.util.ResourceLocation;
+
+import cpw.mods.fml.client.registry.RenderingRegistry;
+
+public class GT_Renderer_Entity_Arrow extends RenderArrow {
+
+ private final ResourceLocation mTexture;
+
+ public GT_Renderer_Entity_Arrow(Class<? extends EntityArrow> aArrowClass, String aTextureName) {
+ this.mTexture = new ResourceLocation("gregtech:textures/entity/" + aTextureName + ".png");
+ RenderingRegistry.registerEntityRenderingHandler(aArrowClass, this);
+ }
+
+ @Override
+ protected ResourceLocation getEntityTexture(Entity p_110775_1_) {
+ return this.mTexture;
+ }
+}
diff --git a/src/main/java/gregtech/common/render/GT_SidedTexture.java b/src/main/java/gregtech/common/render/GT_SidedTexture.java
new file mode 100644
index 0000000000..7a851fd1e7
--- /dev/null
+++ b/src/main/java/gregtech/common/render/GT_SidedTexture.java
@@ -0,0 +1,78 @@
+package gregtech.common.render;
+
+import net.minecraft.block.Block;
+import net.minecraft.client.renderer.RenderBlocks;
+
+import gregtech.api.interfaces.IColorModulationContainer;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.render.TextureFactory;
+
+public class GT_SidedTexture extends GT_TextureBase implements ITexture, IColorModulationContainer {
+
+ protected final ITexture[] mTextures;
+ /**
+ * DO NOT MANIPULATE THE VALUES INSIDE THIS ARRAY!!!
+ * <p/>
+ * Just set this variable to another different Array instead. Otherwise some colored things will get Problems.
+ */
+ private final short[] mRGBa;
+
+ protected GT_SidedTexture(IIconContainer aIcon0, IIconContainer aIcon1, IIconContainer aIcon2,
+ IIconContainer aIcon3, IIconContainer aIcon4, IIconContainer aIcon5, short[] aRGBa, boolean aAllowAlpha) {
+ if (aRGBa.length != 4) throw new IllegalArgumentException("RGBa doesn't have 4 Values @ GT_RenderedTexture");
+ mTextures = new ITexture[] { TextureFactory.of(aIcon0, aRGBa, aAllowAlpha),
+ TextureFactory.of(aIcon1, aRGBa, aAllowAlpha), TextureFactory.of(aIcon2, aRGBa, aAllowAlpha),
+ TextureFactory.of(aIcon3, aRGBa, aAllowAlpha), TextureFactory.of(aIcon4, aRGBa, aAllowAlpha),
+ TextureFactory.of(aIcon5, aRGBa, aAllowAlpha) };
+ mRGBa = aRGBa;
+ }
+
+ @Override
+ public boolean isOldTexture() {
+ return false;
+ }
+
+ @Override
+ public void renderXPos(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
+ mTextures[5].renderXPos(aRenderer, aBlock, aX, aY, aZ);
+ }
+
+ @Override
+ public void renderXNeg(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
+ mTextures[4].renderXNeg(aRenderer, aBlock, aX, aY, aZ);
+ }
+
+ @Override
+ public void renderYPos(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
+ mTextures[1].renderYPos(aRenderer, aBlock, aX, aY, aZ);
+ }
+
+ @Override
+ public void renderYNeg(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
+ mTextures[0].renderYNeg(aRenderer, aBlock, aX, aY, aZ);
+ }
+
+ @Override
+ public void renderZPos(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
+ mTextures[3].renderZPos(aRenderer, aBlock, aX, aY, aZ);
+ }
+
+ @Override
+ public void renderZNeg(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) {
+ mTextures[2].renderZNeg(aRenderer, aBlock, aX, aY, aZ);
+ }
+
+ @Override
+ public short[] getRGBA() {
+ return mRGBa;
+ }
+
+ @Override
+ public boolean isValidTexture() {
+ for (ITexture renderedTexture : mTextures) {
+ if (!renderedTexture.isValidTexture()) return false;
+ }
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/common/render/GT_TextureBase.java b/src/main/java/gregtech/common/render/GT_TextureBase.java
new file mode 100644
index 0000000000..20188e2e01
--- /dev/null
+++ b/src/main/java/gregtech/common/render/GT_TextureBase.java
@@ -0,0 +1,31 @@
+package gregtech.common.render;
+
+import net.minecraft.client.renderer.RenderBlocks;
+import net.minecraft.client.renderer.Tessellator;
+
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.util.GT_UtilityClient;
+
+public abstract class GT_TextureBase implements ITexture {
+
+ protected boolean isDrawing = false;
+
+ @Override
+ public void startDrawingQuads(RenderBlocks aRenderer, float aNormalX, float aNormalY, float aNormalZ) {
+ if (aRenderer.useInventoryTint && (!isOldTexture() || !GT_UtilityClient.isDrawing(Tessellator.instance))) {
+ // Draw if we're not an old texture OR we are an old texture AND we're not already drawing
+ isDrawing = true;
+ Tessellator.instance.startDrawingQuads();
+ Tessellator.instance.setNormal(aNormalX, aNormalY, aNormalZ);
+ }
+ }
+
+ @Override
+ public void draw(RenderBlocks aRenderer) {
+ if (aRenderer.useInventoryTint && (!isOldTexture() || isDrawing)) {
+ // Draw if we're not an old texture OR we initiated the drawing
+ isDrawing = false;
+ Tessellator.instance.draw();
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/render/GT_TextureBuilder.java b/src/main/java/gregtech/common/render/GT_TextureBuilder.java
new file mode 100644
index 0000000000..af8a590fc1
--- /dev/null
+++ b/src/main/java/gregtech/common/render/GT_TextureBuilder.java
@@ -0,0 +1,151 @@
+package gregtech.common.render;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import net.minecraft.block.Block;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.GT_Mod;
+import gregtech.api.enums.Dyes;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.ITextureBuilder;
+
+@SuppressWarnings({ "unused", "ClassWithTooManyFields" })
+public class GT_TextureBuilder implements ITextureBuilder {
+
+ private final List<IIconContainer> iconContainerList;
+ private final List<ITexture> textureLayers;
+ private Block fromBlock;
+ private int fromMeta;
+ private ForgeDirection fromSide;
+ private short[] rgba;
+ private boolean allowAlpha;
+ private boolean stdOrient;
+ private boolean extFacing;
+ private boolean glow;
+ private Boolean worldCoord = null;
+
+ public GT_TextureBuilder() {
+ textureLayers = new ArrayList<>();
+ iconContainerList = new ArrayList<>();
+ rgba = Dyes._NULL.mRGBa;
+ allowAlpha = true;
+ stdOrient = false;
+ glow = false;
+ }
+
+ @Override
+ public ITextureBuilder setFromBlock(final Block block, final int meta) {
+ this.fromBlock = block;
+ this.fromMeta = meta;
+ this.fromSide = ForgeDirection.UNKNOWN;
+ return this;
+ }
+
+ @Override
+ public ITextureBuilder setFromSide(final ForgeDirection side) {
+ this.fromSide = side;
+ return this;
+ }
+
+ @Override
+ public ITextureBuilder addIcon(final IIconContainer... iconContainers) {
+ this.iconContainerList.addAll(Arrays.asList(iconContainers));
+ return this;
+ }
+
+ @Override
+ public ITextureBuilder setRGBA(final short[] rgba) {
+ this.rgba = rgba;
+ return this;
+ }
+
+ @Override
+ public ITextureBuilder addLayer(final ITexture... iTextures) {
+ this.textureLayers.addAll(Arrays.asList(iTextures));
+ return this;
+ }
+
+ @Override
+ public ITextureBuilder setAllowAlpha(final boolean allowAlpha) {
+ this.allowAlpha = allowAlpha;
+ return this;
+ }
+
+ @Override
+ public ITextureBuilder stdOrient() {
+ this.stdOrient = true;
+ return this;
+ }
+
+ @Override
+ public ITextureBuilder useWorldCoord() {
+ this.worldCoord = true;
+ return this;
+ }
+
+ @Override
+ public ITextureBuilder noWorldCoord() {
+ this.worldCoord = false;
+ return this;
+ }
+
+ @Override
+ public ITextureBuilder extFacing() {
+ this.extFacing = true;
+ return this;
+ }
+
+ @Override
+ public ITextureBuilder glow() {
+ glow = true;
+ return this;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public ITexture build() {
+ if (fromBlock != null) {
+ if (worldCoord == Boolean.TRUE || worldCoord == null && isCTMBlock(fromBlock, fromMeta))
+ return new GT_CopiedCTMBlockTexture(fromBlock, fromSide.ordinal(), fromMeta, rgba, allowAlpha);
+ else return new GT_CopiedBlockTexture(fromBlock, fromSide.ordinal(), fromMeta, rgba, allowAlpha);
+ }
+ if (worldCoord != null) throw new IllegalStateException("worldCoord without from block");
+ if (!textureLayers.isEmpty()) return new GT_MultiTexture(textureLayers.toArray(new ITexture[0]));
+ return switch (iconContainerList.size()) {
+ case 1 -> new GT_RenderedTexture(iconContainerList.get(0), rgba, allowAlpha, glow, stdOrient, extFacing);
+ case 6 -> new GT_SidedTexture(
+ iconContainerList.get(ForgeDirection.DOWN.ordinal()),
+ iconContainerList.get(ForgeDirection.UP.ordinal()),
+ iconContainerList.get(ForgeDirection.NORTH.ordinal()),
+ iconContainerList.get(ForgeDirection.SOUTH.ordinal()),
+ iconContainerList.get(ForgeDirection.WEST.ordinal()),
+ iconContainerList.get(ForgeDirection.EAST.ordinal()),
+ rgba,
+ allowAlpha);
+ default -> throw new IllegalStateException("Invalid sideIconContainer count");
+ };
+ }
+
+ private boolean isCTMBlock(Block fromBlock, int fromMeta) {
+ return GT_Mod.gregtechproxy.mCTMBlockCache
+ .computeIfAbsent(fromBlock, (byte) fromMeta, GT_TextureBuilder::apply);
+ }
+
+ private static Boolean apply(Block b, Byte m) {
+ Class<?> clazz = b.getClass();
+ while (clazz != Block.class) {
+ final String className = clazz.getName();
+ if (GT_Values.mCTMDisabledBlock.contains(className)) return false;
+ if (GT_Values.mCTMEnabledBlock.contains(className)) return true;
+ clazz = clazz.getSuperclass();
+ }
+ return false;
+ }
+}
diff --git a/src/main/java/gregtech/common/render/IRenderedBlock.java b/src/main/java/gregtech/common/render/IRenderedBlock.java
new file mode 100644
index 0000000000..16268de750
--- /dev/null
+++ b/src/main/java/gregtech/common/render/IRenderedBlock.java
@@ -0,0 +1,114 @@
+package gregtech.common.render;
+
+import net.minecraft.block.Block;
+import net.minecraft.client.renderer.RenderBlocks;
+import net.minecraft.item.ItemStack;
+import net.minecraft.world.IBlockAccess;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.ITexture;
+
+public interface IRenderedBlock {
+
+ /** @return the Textures to be rendered */
+ @SideOnly(Side.CLIENT)
+ ITexture[] getTexture(Block aBlock, ForgeDirection side, int aRenderPass, boolean[] aShouldSideBeRendered);
+
+ @SideOnly(Side.CLIENT)
+ ITexture[] getTexture(Block aBlock, ForgeDirection side, boolean isActive, int aRenderPass);
+
+ /** gets the Amount of Render Passes for this TileEntity or similar Handler. Only gets called once per Rendering. */
+ @SideOnly(Side.CLIENT)
+ int getRenderPasses(Block aBlock);
+
+ /** if this uses said Render Pass or if it can be skipped entirely. */
+ @SideOnly(Side.CLIENT)
+ boolean usesRenderPass(int aRenderPass);
+
+ /** sets the Block Size rendered; return false for letting it select the normal Block Bounds. */
+ @SideOnly(Side.CLIENT)
+ boolean setBlockBounds(Block aBlock, int aRenderPass);
+
+ /** returning true stops all the other Rendering from happening. */
+ @SideOnly(Side.CLIENT)
+ default boolean renderItem(Block aBlock, RenderBlocks aRenderer) {
+ return false;
+ }
+
+ /** returning true stops all the other Rendering from happening. */
+ @SideOnly(Side.CLIENT)
+ default boolean renderBlock(Block aBlock, RenderBlocks aRenderer, IBlockAccess aWorld, int aX, int aY, int aZ) {
+ return false;
+ }
+
+ /** if this Block lets the TileEntity or a similar Handler do all the Inventory Render work. */
+ @SideOnly(Side.CLIENT)
+ IRenderedBlock passRenderingToObject(ItemStack aStack);
+
+ /** if this Block lets the TileEntity or a similar Handler do all the World Render work. */
+ @SideOnly(Side.CLIENT)
+ IRenderedBlock passRenderingToObject(IBlockAccess aWorld, int aX, int aY, int aZ);
+
+ class ErrorRenderer implements IRenderedBlockSideCheck, IRenderedBlock {
+
+ public static final ErrorRenderer INSTANCE = new ErrorRenderer();
+ public ITexture[] mErrorTexture = Textures.BlockIcons.ERROR_RENDERING;
+
+ @Override
+ public ITexture[] getTexture(Block aBlock, ForgeDirection side, int aRenderPass,
+ boolean[] aShouldSideBeRendered) {
+ return mErrorTexture;
+ }
+
+ @Override
+ public ITexture[] getTexture(Block aBlock, ForgeDirection side, boolean isActive, int aRenderPass) {
+ return mErrorTexture;
+ }
+
+ @Override
+ public int getRenderPasses(Block aBlock) {
+ return 1;
+ }
+
+ @Override
+ public boolean usesRenderPass(int aRenderPass) {
+ return true;
+ }
+
+ @Override
+ public boolean setBlockBounds(Block aBlock, int aRenderPass) {
+ aBlock.setBlockBounds(-0.25F, -0.25F, -0.25F, 1.25F, 1.25F, 1.25F);
+ return true;
+ }
+
+ @Override
+ public boolean renderFullBlockSide(Block aBlock, RenderBlocks aRenderer, ForgeDirection side) {
+ return true;
+ }
+
+ @Override
+ public IRenderedBlock passRenderingToObject(ItemStack aStack) {
+ return this;
+ }
+
+ @Override
+ public IRenderedBlock passRenderingToObject(IBlockAccess aWorld, int aX, int aY, int aZ) {
+ return this;
+ }
+
+ @Override
+ public boolean renderBlock(Block aBlock, RenderBlocks aRenderer, IBlockAccess aWorld, int aX, int aY, int aZ) {
+ aBlock.setBlockBounds(-0.25F, -0.25F, -0.25F, 1.25F, 1.25F, 1.25F);
+ GT_Renderer_Block.renderNegativeYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, mErrorTexture, false);
+ GT_Renderer_Block.renderPositiveYFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, mErrorTexture, false);
+ GT_Renderer_Block.renderNegativeZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, mErrorTexture, false);
+ GT_Renderer_Block.renderPositiveZFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, mErrorTexture, false);
+ GT_Renderer_Block.renderNegativeXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, mErrorTexture, false);
+ GT_Renderer_Block.renderPositiveXFacing(aWorld, aRenderer, aBlock, aX, aY, aZ, mErrorTexture, false);
+ return true;
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/render/IRenderedBlockSideCheck.java b/src/main/java/gregtech/common/render/IRenderedBlockSideCheck.java
new file mode 100644
index 0000000000..8feb69b2f5
--- /dev/null
+++ b/src/main/java/gregtech/common/render/IRenderedBlockSideCheck.java
@@ -0,0 +1,15 @@
+package gregtech.common.render;
+
+import net.minecraft.block.Block;
+import net.minecraft.client.renderer.RenderBlocks;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+
+public interface IRenderedBlockSideCheck {
+
+ /** returning false stops all the other Rendering from happening on that Side. */
+ @SideOnly(Side.CLIENT)
+ boolean renderFullBlockSide(Block aBlock, RenderBlocks aRenderer, ForgeDirection side);
+}
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/render/items/CosmicNeutroniumRenderer.java b/src/main/java/gregtech/common/render/items/CosmicNeutroniumRenderer.java
new file mode 100644
index 0000000000..acb830de58
--- /dev/null
+++ b/src/main/java/gregtech/common/render/items/CosmicNeutroniumRenderer.java
@@ -0,0 +1,109 @@
+package gregtech.common.render.items;
+
+import static gregtech.common.render.GT_RenderUtil.colorGTItem;
+
+import net.minecraft.client.renderer.Tessellator;
+import net.minecraft.client.renderer.entity.RenderItem;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.IIcon;
+import net.minecraftforge.client.IItemRenderer;
+
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL12;
+
+import com.gtnewhorizons.modularui.api.math.Pos2d;
+
+import gregtech.api.enums.Textures;
+import gregtech.common.render.GT_RenderUtil;
+
+public class CosmicNeutroniumRenderer extends GT_GeneratedMaterial_Renderer {
+
+ // spotless:off
+ private static final Pos2d point0 = new Pos2d(0 - 10, 0 - 10);
+ private static final Pos2d point1 = new Pos2d(17 + 10, 0 - 10);
+ private static final Pos2d point2 = new Pos2d(17 + 10, 17 + 10);
+ private static final Pos2d point3 = new Pos2d(0 - 10, 17 + 10);
+ // spotless:on
+
+ // TODO: Render halo outside of inventory.
+ private void drawHalo(ItemRenderType type) {
+ // Because when this class is instantiated, making this a static field will cause it to set to null.
+ final IIcon haloFuzzy = Textures.ItemIcons.HALO_FUZZY.getIcon();
+
+ if (haloFuzzy == null) {
+ return;
+ }
+
+ markNeedsAnimationUpdate(haloFuzzy);
+ GL11.glPushMatrix();
+
+ // Ideally this magic haloColour number should scale depending on the # of transparent pixels,
+ // but I'm not sure how to determine this with OpenGL.
+ // This is from Avaritia code, but modified to untangle the interfaces.
+ int haloColour = 0x4DFFFFFF;
+ float ca = (float) (haloColour >> 24 & 255) / 255.0F;
+ float cr = (float) (0x99FFFFFF >> 16 & 255) / 255.0F;
+ float cg = (float) (0x99FFFFFF >> 8 & 255) / 255.0F;
+ float cb = (float) (0x99FFFFFF & 255) / 255.0F;
+ GL11.glColor4f(cr, cg, cb, ca);
+
+ // spotless:off
+ // For those following in my footsteps, this may be of use - Colen 25th dec 2022.
+ // http://greyminecraftcoder.blogspot.com/2013/08/the-tessellator.html
+
+ Tessellator t = Tessellator.instance;
+
+ if (type.equals(IItemRenderer.ItemRenderType.INVENTORY)) {
+ t.startDrawingQuads();
+ t.addVertexWithUV(point0.x, point0.y, 0, haloFuzzy.getMinU(), haloFuzzy.getMinV());
+ t.addVertexWithUV(point3.x, point3.y, 0, haloFuzzy.getMinU(), haloFuzzy.getMaxV());
+ t.addVertexWithUV(point2.x, point2.y, 0, haloFuzzy.getMaxU(), haloFuzzy.getMaxV());
+ t.addVertexWithUV(point1.x, point1.y, 0, haloFuzzy.getMaxU(), haloFuzzy.getMinV());
+ t.draw();
+ }
+
+ GL11.glPopMatrix();
+ }
+
+ @Override
+ protected void renderRegularItem(ItemRenderType type, ItemStack item, IIcon icon, boolean shouldModulateColor, int pass, Object... data) {
+ RenderItem r = RenderItem.getInstance();
+
+ GL11.glPushMatrix();
+
+ if (type.equals(IItemRenderer.ItemRenderType.INVENTORY)) {
+ GL11.glEnable(GL11.GL_BLEND);
+ GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ GL11.glDisable(GL11.GL_ALPHA_TEST);
+ GL11.glDisable(GL11.GL_DEPTH_TEST);
+ }
+
+ if (pass == 0) {
+ drawHalo(type);
+ }
+
+ //spotless:on
+ {
+ // Draw actual cosmic Nt item.
+ GL11.glPushMatrix();
+
+ colorGTItem(item);
+
+ if (type.equals(IItemRenderer.ItemRenderType.INVENTORY)) {
+ GT_RenderUtil.renderItemIcon(icon, 16.0D, 0.001D, 0.0F, 0.0F, -1.0F);
+ } else {
+ GL11.glEnable(GL11.GL_DEPTH_TEST);
+ GT_RenderUtil.renderItem(type, icon);
+ }
+ GL11.glPopMatrix();
+ }
+
+ // GL11.glEnable(GL11.GL_ALPHA_TEST);
+ GL11.glEnable(GL12.GL_RESCALE_NORMAL);
+ GL11.glEnable(GL11.GL_DEPTH_TEST);
+
+ r.renderWithColor = true;
+
+ GL11.glPopMatrix();
+ }
+}
diff --git a/src/main/java/gregtech/common/render/items/GT_DataStick_Renderer.java b/src/main/java/gregtech/common/render/items/GT_DataStick_Renderer.java
new file mode 100644
index 0000000000..668b1daa6c
--- /dev/null
+++ b/src/main/java/gregtech/common/render/items/GT_DataStick_Renderer.java
@@ -0,0 +1,42 @@
+package gregtech.common.render.items;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.RenderHelper;
+import net.minecraft.client.renderer.entity.RenderItem;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.client.IItemRenderer;
+
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.opengl.GL11;
+
+import gregtech.api.util.GT_AssemblyLineUtils;
+
+// borrow form ae2
+
+public class GT_DataStick_Renderer implements IItemRenderer {
+
+ private final RenderItem ri = new RenderItem();
+
+ @Override
+ public boolean handleRenderType(ItemStack item, ItemRenderType type) {
+ final boolean isShiftHeld = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT);
+ return type == ItemRenderType.INVENTORY && isShiftHeld;
+ }
+
+ @Override
+ public boolean shouldUseRenderHelper(ItemRenderType type, ItemStack item, ItemRendererHelper helper) {
+ return false;
+ }
+
+ @Override
+ public void renderItem(ItemRenderType type, ItemStack item, Object... data) {
+ final ItemStack is = GT_AssemblyLineUtils.getDataStickOutput(item);
+ final Minecraft mc = Minecraft.getMinecraft();
+
+ GL11.glPushAttrib(GL11.GL_ENABLE_BIT | GL11.GL_COLOR_BUFFER_BIT);
+ RenderHelper.enableGUIStandardItemLighting();
+ this.ri.renderItemAndEffectIntoGUI(mc.fontRenderer, mc.getTextureManager(), is, 0, 0);
+ RenderHelper.disableStandardItemLighting();
+ GL11.glPopAttrib();
+ }
+}
diff --git a/src/main/java/gregtech/common/render/items/GT_GeneratedItem_Renderer.java b/src/main/java/gregtech/common/render/items/GT_GeneratedItem_Renderer.java
new file mode 100644
index 0000000000..84045446c2
--- /dev/null
+++ b/src/main/java/gregtech/common/render/items/GT_GeneratedItem_Renderer.java
@@ -0,0 +1,166 @@
+package gregtech.common.render.items;
+
+import static gregtech.api.enums.ItemList.Large_Fluid_Cell_Aluminium;
+import static gregtech.api.enums.ItemList.Large_Fluid_Cell_Chrome;
+import static gregtech.api.enums.ItemList.Large_Fluid_Cell_Iridium;
+import static gregtech.api.enums.ItemList.Large_Fluid_Cell_Neutronium;
+import static gregtech.api.enums.ItemList.Large_Fluid_Cell_Osmium;
+import static gregtech.api.enums.ItemList.Large_Fluid_Cell_StainlessSteel;
+import static gregtech.api.enums.ItemList.Large_Fluid_Cell_Steel;
+import static gregtech.api.enums.ItemList.Large_Fluid_Cell_Titanium;
+import static gregtech.api.enums.ItemList.Large_Fluid_Cell_TungstenSteel;
+import static gregtech.api.enums.Mods.HodgePodge;
+
+import javax.annotation.Nullable;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.texture.TextureMap;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.IIcon;
+import net.minecraftforge.client.IItemRenderer;
+import net.minecraftforge.fluids.FluidStack;
+
+import org.lwjgl.opengl.GL11;
+
+import com.mitchej123.hodgepodge.textures.IPatchedTextureAtlasSprite;
+
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Textures;
+import gregtech.api.items.GT_MetaGenerated_Item;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.render.GT_RenderUtil;
+import gregtech.loaders.ExtraIcons;
+
+public class GT_GeneratedItem_Renderer implements IItemRenderer {
+
+ @Override
+ public boolean handleRenderType(ItemStack item, ItemRenderType type) {
+ return type == ItemRenderType.EQUIPPED || type == ItemRenderType.EQUIPPED_FIRST_PERSON
+ || type == ItemRenderType.INVENTORY
+ || type == ItemRenderType.ENTITY;
+ }
+
+ @Override
+ public boolean shouldUseRenderHelper(ItemRenderType type, ItemStack item, ItemRendererHelper helper) {
+ return type == ItemRenderType.ENTITY && helper == ItemRendererHelper.ENTITY_BOBBING
+ || (helper == ItemRendererHelper.ENTITY_ROTATION && Minecraft.getMinecraft().gameSettings.fancyGraphics);
+ }
+
+ @Override
+ public void renderItem(ItemRenderType type, ItemStack aStack, Object... data) {
+ short aMetaData = (short) aStack.getItemDamage();
+ if (!(aStack.getItem() instanceof GT_MetaGenerated_Item aItem)) return;
+
+ GL11.glEnable(GL11.GL_BLEND);
+ GL11.glColor3f(1.0F, 1.0F, 1.0F);
+ IIcon tIcon;
+ if (aItem.mIconList[(aMetaData - aItem.mOffset)].length > 1) {
+ Long[] tStats = aItem.mElectricStats.get(aMetaData);
+
+ if ((tStats != null) && (tStats[3] < 0L)) {
+ long tCharge = aItem.getRealCharge(aStack);
+
+ if (tCharge <= 0L) {
+ tIcon = aItem.mIconList[(aMetaData - aItem.mOffset)][1];
+ } else {
+
+ if (tCharge >= tStats[0]) {
+ tIcon = aItem.mIconList[(aMetaData - aItem.mOffset)][8];
+ } else {
+ tIcon = aItem.mIconList[(aMetaData - aItem.mOffset)][(7
+ - (int) Math.max(0L, Math.min(5L, (tStats[0] - tCharge) * 6L / tStats[0])))];
+ }
+ }
+ } else {
+ tIcon = aItem.mIconList[(aMetaData - aItem.mOffset)][0];
+ }
+ } else {
+ tIcon = aItem.mIconList[(aMetaData - aItem.mOffset)][0];
+ }
+
+ if (tIcon == null) tIcon = Textures.ItemIcons.RENDERING_ERROR.getIcon();
+
+ markNeedsAnimationUpdate(tIcon);
+
+ ItemList largeFluidCell = getLargeFluidCell(aStack);
+ if (largeFluidCell != null) {
+ renderLargeFluidCellExtraParts(type, largeFluidCell, aStack);
+ }
+
+ Minecraft.getMinecraft().renderEngine.bindTexture(TextureMap.locationItemsTexture);
+ GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ GT_RenderUtil.renderItem(type, tIcon);
+ GL11.glDisable(GL11.GL_BLEND);
+ }
+
+ @Nullable
+ private static ItemList getLargeFluidCell(ItemStack stack) {
+ if (isSame(Large_Fluid_Cell_Steel, stack)) return Large_Fluid_Cell_Steel;
+ if (isSame(Large_Fluid_Cell_Aluminium, stack)) return Large_Fluid_Cell_Aluminium;
+ if (isSame(Large_Fluid_Cell_TungstenSteel, stack)) return Large_Fluid_Cell_TungstenSteel;
+ if (isSame(Large_Fluid_Cell_StainlessSteel, stack)) return Large_Fluid_Cell_StainlessSteel;
+ if (isSame(Large_Fluid_Cell_Titanium, stack)) return Large_Fluid_Cell_Titanium;
+ if (isSame(Large_Fluid_Cell_Chrome, stack)) return Large_Fluid_Cell_Chrome;
+ if (isSame(Large_Fluid_Cell_Iridium, stack)) return Large_Fluid_Cell_Iridium;
+ if (isSame(Large_Fluid_Cell_Osmium, stack)) return Large_Fluid_Cell_Osmium;
+ if (isSame(Large_Fluid_Cell_Neutronium, stack)) return Large_Fluid_Cell_Neutronium;
+
+ return null;
+ }
+
+ private void renderLargeFluidCellExtraParts(IItemRenderer.ItemRenderType type, ItemList item, ItemStack stack) {
+
+ IIcon inner = switch (item) {
+ case Large_Fluid_Cell_Steel -> ExtraIcons.steelLargeCellInner;
+ case Large_Fluid_Cell_Aluminium -> ExtraIcons.aluminiumLargeCellInner;
+ case Large_Fluid_Cell_StainlessSteel -> ExtraIcons.stainlesssteelLargeCellInner;
+ case Large_Fluid_Cell_Titanium -> ExtraIcons.titaniumLargeCellInner;
+ case Large_Fluid_Cell_TungstenSteel -> ExtraIcons.tungstensteelLargeCellInner;
+ case Large_Fluid_Cell_Iridium -> ExtraIcons.iridiumLargeCellInner;
+ case Large_Fluid_Cell_Osmium -> ExtraIcons.osmiumLargeCellInner;
+ case Large_Fluid_Cell_Chrome -> ExtraIcons.chromiumLargeCellInner;
+ case Large_Fluid_Cell_Neutronium -> ExtraIcons.neutroniumLargeCellInner;
+ default -> Textures.ItemIcons.RENDERING_ERROR.getIcon();
+ };
+
+ // Empty inner side
+ Minecraft.getMinecraft().renderEngine.bindTexture(TextureMap.locationItemsTexture);
+ markNeedsAnimationUpdate(inner);
+ GT_RenderUtil.renderItem(type, inner);
+
+ FluidStack fluidStack = GT_Utility.getFluidForFilledItem(stack, true);
+
+ if (fluidStack != null && fluidStack.getFluid() != null) {
+ IIcon fluidIcon = fluidStack.getFluid()
+ .getIcon(fluidStack);
+ if (fluidIcon == null) {
+ fluidIcon = Textures.ItemIcons.RENDERING_ERROR.getIcon();
+ }
+ int fluidColor = fluidStack.getFluid()
+ .getColor(fluidStack);
+
+ Minecraft.getMinecraft().renderEngine.bindTexture(TextureMap.locationBlocksTexture);
+ markNeedsAnimationUpdate(fluidIcon);
+ GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ GL11.glDepthFunc(GL11.GL_EQUAL);
+ GL11.glColor3ub((byte) (fluidColor >> 16), (byte) (fluidColor >> 8), (byte) fluidColor);
+ GT_RenderUtil.renderItem(type, fluidIcon);
+
+ GL11.glColor3ub((byte) -1, (byte) -1, (byte) -1);
+ GL11.glDepthFunc(GL11.GL_LEQUAL);
+ }
+ }
+
+ private static boolean isSame(ItemList item, ItemStack stack) {
+ ItemStack internal = item.getInternalStack_unsafe();
+ if (GT_Utility.isStackInvalid(internal)) return false;
+
+ return internal.getItem() == stack.getItem() && internal.getItemDamage() == stack.getItemDamage();
+ }
+
+ protected void markNeedsAnimationUpdate(IIcon icon) {
+ if (HodgePodge.isModLoaded() && icon instanceof IPatchedTextureAtlasSprite) {
+ ((IPatchedTextureAtlasSprite) icon).markNeedsAnimationUpdate();
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/render/items/GT_GeneratedMaterial_Renderer.java b/src/main/java/gregtech/common/render/items/GT_GeneratedMaterial_Renderer.java
new file mode 100644
index 0000000000..a67d5512ed
--- /dev/null
+++ b/src/main/java/gregtech/common/render/items/GT_GeneratedMaterial_Renderer.java
@@ -0,0 +1,130 @@
+package gregtech.common.render.items;
+
+import static gregtech.api.enums.Mods.HodgePodge;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.IIcon;
+import net.minecraftforge.client.IItemRenderer;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidStack;
+
+import org.lwjgl.opengl.GL11;
+
+import com.mitchej123.hodgepodge.textures.IPatchedTextureAtlasSprite;
+
+import codechicken.lib.render.TextureUtils;
+import gregtech.api.interfaces.IGT_ItemWithMaterialRenderer;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.render.GT_RenderUtil;
+
+public class GT_GeneratedMaterial_Renderer implements IItemRenderer {
+
+ @Override
+ public boolean handleRenderType(ItemStack item, ItemRenderType type) {
+ return type == ItemRenderType.EQUIPPED || type == ItemRenderType.EQUIPPED_FIRST_PERSON
+ || type == ItemRenderType.INVENTORY
+ || type == ItemRenderType.ENTITY;
+ }
+
+ @Override
+ public boolean shouldUseRenderHelper(ItemRenderType type, ItemStack item, ItemRendererHelper helper) {
+ return type == ItemRenderType.ENTITY && helper == ItemRendererHelper.ENTITY_BOBBING
+ || (helper == ItemRendererHelper.ENTITY_ROTATION && Minecraft.getMinecraft().gameSettings.fancyGraphics);
+ }
+
+ /**
+ * Handle special fluid display rendering. Return false if does not need such kind of handling. Note: annotations
+ * should not be rendered here. Only render the fluid texture. Parameters are values passed from
+ * {@link IItemRenderer#renderItem(ItemRenderType, ItemStack, Object...)} verbatim. Do not modify the argument.
+ * <p>
+ * While this is called, BLEND and ALPHA_TEST is on. It is expected that these remain enabled while exit.
+ *
+ * @return true if did special fluid display rendering. false otherwise.
+ */
+ public boolean renderFluidDisplayItem(ItemRenderType type, ItemStack aStack, Object... data) {
+ return false;
+ }
+
+ @Override
+ public void renderItem(ItemRenderType type, ItemStack aStack, Object... data) {
+ short aMetaData = (short) aStack.getItemDamage();
+ if (!(aStack.getItem() instanceof IGT_ItemWithMaterialRenderer aItem)) return;
+
+ int passes = 1;
+ if (aItem.requiresMultipleRenderPasses()) {
+ passes = aItem.getRenderPasses(aMetaData);
+ }
+
+ for (int pass = 0; pass < passes; pass++) {
+ IIcon tIcon = aItem.getIcon(aMetaData, pass);
+ IIcon tOverlay = aItem.getOverlayIcon(aMetaData, pass);
+ FluidStack aFluid = GT_Utility.getFluidForFilledItem(aStack, true);
+
+ GL11.glEnable(GL11.GL_BLEND);
+ GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ GL11.glEnable(GL11.GL_ALPHA_TEST);
+
+ if (tIcon != null) {
+ markNeedsAnimationUpdate(tIcon);
+ renderRegularItem(type, aStack, tIcon, aFluid == null, pass, data);
+ }
+
+ if (tOverlay != null && aFluid != null && aFluid.getFluid() != null) {
+ IIcon fluidIcon = aFluid.getFluid()
+ .getIcon(aFluid);
+ if (fluidIcon != null) {
+ markNeedsAnimationUpdate(fluidIcon);
+ // Adds colour to a cells fluid. Does not colour full fluid icons as shown in NEI etc.
+ renderContainedFluid(type, aFluid, fluidIcon);
+ }
+ }
+
+ if (tOverlay != null) {
+ GL11.glColor3f(1.0F, 1.0F, 1.0F);
+ TextureUtils.bindAtlas(aItem.getSpriteNumber());
+ markNeedsAnimationUpdate(tOverlay);
+ renderItemOverlay(type, tOverlay);
+ }
+
+ GL11.glDisable(GL11.GL_BLEND);
+ }
+ }
+
+ protected void renderRegularItem(ItemRenderType type, ItemStack aStack, IIcon icon, boolean shouldModulateColor,
+ int pass, Object... data) {
+ renderRegularItem(type, aStack, icon, shouldModulateColor);
+ }
+
+ protected void renderRegularItem(ItemRenderType type, ItemStack aStack, IIcon icon, boolean shouldModulateColor) {
+ if (!(aStack.getItem() instanceof IGT_ItemWithMaterialRenderer aItem)) return;
+
+ if (shouldModulateColor) {
+ short[] tModulation = aItem.getRGBa(aStack);
+ GL11.glColor3f(tModulation[0] / 255.0F, tModulation[1] / 255.0F, tModulation[2] / 255.0F);
+ }
+
+ GT_RenderUtil.renderItem(type, icon);
+ }
+
+ protected void renderContainedFluid(ItemRenderType type, FluidStack aFluidStack, IIcon fluidIcon) {
+ Fluid aFluid = aFluidStack.getFluid();
+ int tColor = aFluid.getColor(aFluidStack);
+ GL11.glColor3f((tColor >> 16 & 0xFF) / 255.0F, (tColor >> 8 & 0xFF) / 255.0F, (tColor & 0xFF) / 255.0F);
+ TextureUtils.bindAtlas(aFluid.getSpriteNumber());
+
+ GL11.glDepthFunc(GL11.GL_EQUAL);
+ GT_RenderUtil.renderItem(type, fluidIcon);
+ GL11.glDepthFunc(GL11.GL_LEQUAL);
+ }
+
+ protected void renderItemOverlay(ItemRenderType type, IIcon overlay) {
+ GT_RenderUtil.renderItem(type, overlay);
+ }
+
+ protected void markNeedsAnimationUpdate(IIcon icon) {
+ if (HodgePodge.isModLoaded() && icon instanceof IPatchedTextureAtlasSprite) {
+ ((IPatchedTextureAtlasSprite) icon).markNeedsAnimationUpdate();
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/render/items/GT_MetaGenerated_Item_Renderer.java b/src/main/java/gregtech/common/render/items/GT_MetaGenerated_Item_Renderer.java
new file mode 100644
index 0000000000..d7425c2fcb
--- /dev/null
+++ b/src/main/java/gregtech/common/render/items/GT_MetaGenerated_Item_Renderer.java
@@ -0,0 +1,85 @@
+package gregtech.common.render.items;
+
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.client.IItemRenderer;
+import net.minecraftforge.client.MinecraftForgeClient;
+
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Materials;
+import gregtech.api.interfaces.IGT_ItemWithMaterialRenderer;
+import gregtech.api.objects.ItemData;
+import gregtech.api.util.GT_OreDictUnificator;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.render.GT_RenderUtil;
+
+public class GT_MetaGenerated_Item_Renderer implements IItemRenderer {
+
+ private final IItemRenderer mItemRenderer = new GT_GeneratedItem_Renderer();
+ private final IItemRenderer mMaterialRenderer = new GT_GeneratedMaterial_Renderer();
+
+ private final IItemRenderer mDataStickRenderer = new GT_DataStick_Renderer();
+
+ public GT_MetaGenerated_Item_Renderer() {}
+
+ public <T extends Item & IGT_ItemWithMaterialRenderer> void registerItem(T item) {
+ MinecraftForgeClient.registerItemRenderer(item, this);
+ }
+
+ @Override
+ public boolean handleRenderType(ItemStack aStack, ItemRenderType aType) {
+ if ((GT_Utility.isStackInvalid(aStack)) || (aStack.getItemDamage() < 0)
+ || !(aStack.getItem() instanceof IGT_ItemWithMaterialRenderer)
+ || !((IGT_ItemWithMaterialRenderer) aStack.getItem()).shouldUseCustomRenderer(aStack.getItemDamage())) {
+ return false;
+ }
+ return getRendererForItemStack(aStack).handleRenderType(aStack, aType);
+ }
+
+ @Override
+ public boolean shouldUseRenderHelper(ItemRenderType aType, ItemStack aStack, ItemRendererHelper aHelper) {
+ if (GT_Utility.isStackInvalid(aStack)) {
+ return false;
+ }
+ return getRendererForItemStack(aStack).shouldUseRenderHelper(aType, aStack, aHelper);
+ }
+
+ @Override
+ public void renderItem(ItemRenderType type, ItemStack aStack, Object... data) {
+ GT_RenderUtil.applyStandardItemTransform(type);
+
+ IItemRenderer itemRenderer = getRendererForItemStack(aStack);
+ itemRenderer.renderItem(type, aStack, data);
+ }
+
+ private IItemRenderer getRendererForItemStack(ItemStack aStack) {
+ short aMetaData = (short) aStack.getItemDamage();
+ IGT_ItemWithMaterialRenderer aItem = (IGT_ItemWithMaterialRenderer) aStack.getItem();
+
+ if (aItem != null && aItem.allowMaterialRenderer(aMetaData)) {
+ IItemRenderer aMaterialRenderer = aItem.getMaterialRenderer(aMetaData);
+
+ // Handle fluid rendering.
+ if (aMaterialRenderer == null) {
+ ItemData itemData = GT_OreDictUnificator.getAssociation(aStack);
+ if (itemData != null) {
+ Materials material = itemData.mMaterial.mMaterial;
+ if (material.renderer != null) {
+ aMaterialRenderer = material.renderer;
+ }
+ }
+ }
+
+ return aMaterialRenderer != null ? aMaterialRenderer : mMaterialRenderer;
+ }
+
+ // handle data stick
+ if (aStack.getItem() == ItemList.Tool_DataStick.getItem() && aStack.hasTagCompound()
+ && aStack.getTagCompound()
+ .hasKey("output")) {
+ return mDataStickRenderer;
+ }
+
+ return mItemRenderer;
+ }
+}
diff --git a/src/main/java/gregtech/common/render/items/GaiaSpiritRenderer.java b/src/main/java/gregtech/common/render/items/GaiaSpiritRenderer.java
new file mode 100644
index 0000000000..08663adf4d
--- /dev/null
+++ b/src/main/java/gregtech/common/render/items/GaiaSpiritRenderer.java
@@ -0,0 +1,27 @@
+package gregtech.common.render.items;
+
+import java.awt.Color;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.IIcon;
+
+import org.lwjgl.opengl.GL11;
+
+import gregtech.GT_Mod;
+import gregtech.common.render.GT_RenderUtil;
+
+public class GaiaSpiritRenderer extends GT_GeneratedMaterial_Renderer {
+
+ @Override
+ protected void renderRegularItem(ItemRenderType type, ItemStack aStack, IIcon icon, boolean shouldModulateColor) {
+ long animationTicks = GT_Mod.gregtechproxy.getAnimationTicks();
+ float partialTicks = GT_Mod.gregtechproxy.getPartialRenderTicks();
+
+ if (shouldModulateColor) {
+ Color color = Color.getHSBColor((animationTicks % 360 + partialTicks) % 180 / 180f, 0.4f, 0.9f);
+ GL11.glColor3f(color.getRed() / 255.0F, color.getGreen() / 255.0F, color.getBlue() / 255.0F);
+ }
+
+ GT_RenderUtil.renderItem(type, icon);
+ }
+}
diff --git a/src/main/java/gregtech/common/render/items/InfinityRenderer.java b/src/main/java/gregtech/common/render/items/InfinityRenderer.java
new file mode 100644
index 0000000000..3a98898b8a
--- /dev/null
+++ b/src/main/java/gregtech/common/render/items/InfinityRenderer.java
@@ -0,0 +1,139 @@
+package gregtech.common.render.items;
+
+import java.util.Random;
+
+import net.minecraft.client.renderer.Tessellator;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.IIcon;
+import net.minecraftforge.fluids.FluidStack;
+
+import org.lwjgl.opengl.GL11;
+
+import codechicken.lib.render.TextureUtils;
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IGT_ItemWithMaterialRenderer;
+import gregtech.api.util.GT_Utility;
+
+// TODO: Render effects outside inventory.
+
+public class InfinityRenderer extends GT_GeneratedMaterial_Renderer {
+
+ public Random rand = new Random();
+
+ @Override
+ public void renderItem(ItemRenderType type, ItemStack aStack, Object... data) {
+ short aMetaData = (short) aStack.getItemDamage();
+ if (!(aStack.getItem() instanceof IGT_ItemWithMaterialRenderer aItem)) return;
+
+ int passes = 1;
+ if (aItem.requiresMultipleRenderPasses()) {
+ passes = aItem.getRenderPasses(aMetaData);
+ }
+
+ for (int pass = 0; pass < passes; pass++) {
+ IIcon tIcon = aItem.getIcon(aMetaData, pass);
+ IIcon tOverlay = aItem.getOverlayIcon(aMetaData, pass);
+ FluidStack aFluid = GT_Utility.getFluidForFilledItem(aStack, true);
+
+ GL11.glEnable(GL11.GL_BLEND);
+ GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ GL11.glEnable(GL11.GL_ALPHA_TEST);
+
+ if (type == ItemRenderType.INVENTORY) {
+ if (pass == 0) {
+ renderHalo();
+ }
+ renderPulse(tOverlay, tIcon);
+ }
+
+ // Workaround for cell and comb:
+ // 1. BW capsule needs `renderContainedFluid` call as it doesn't have
+ // `materialicons/CUSTOM/infinity/capsuleMolten`
+ // 2. Without these 2 GL calls fluid texture leaks out of the cell / capsule
+ // 3. Comb texture doesn't like depth enabled
+ if (passes == 1) {
+ GL11.glEnable(GL11.GL_DEPTH_TEST);
+ }
+ GL11.glEnable(GL11.GL_ALPHA_TEST);
+
+ if (tIcon != null) {
+ markNeedsAnimationUpdate(tIcon);
+ renderRegularItem(type, aStack, tIcon, aFluid == null);
+ }
+
+ if (tOverlay != null && aFluid != null && aFluid.getFluid() != null) {
+ IIcon fluidIcon = aFluid.getFluid()
+ .getIcon(aFluid);
+ if (fluidIcon != null) {
+ markNeedsAnimationUpdate(fluidIcon);
+ // Adds colour to a cells fluid. Does not colour full fluid icons as shown in NEI etc.
+ renderContainedFluid(type, aFluid, fluidIcon);
+ }
+ }
+
+ if (tOverlay != null) {
+ GL11.glColor3f(1.0F, 1.0F, 1.0F);
+ TextureUtils.bindAtlas(aItem.getSpriteNumber());
+ markNeedsAnimationUpdate(tOverlay);
+ renderItemOverlay(type, tOverlay);
+ }
+
+ GL11.glDisable(GL11.GL_BLEND);
+ }
+ }
+
+ private void renderHalo() {
+ GL11.glPushMatrix();
+ IIcon halo = Textures.ItemIcons.HALO.getIcon();
+
+ int spread = 10;
+ int haloAlpha = 0xFF000000;
+
+ if (halo == null) {
+ return;
+ }
+
+ Tessellator t = Tessellator.instance;
+
+ GL11.glEnable(GL11.GL_BLEND);
+ GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+
+ GL11.glDisable(GL11.GL_ALPHA_TEST);
+ GL11.glDisable(GL11.GL_DEPTH_TEST);
+
+ GL11.glColor4f(20 / 255.0f, 20 / 255.0f, 20 / 255.0f, (float) (haloAlpha >> 24 & 255) / 255.0F);
+
+ t.startDrawingQuads();
+ t.addVertexWithUV(-spread, -spread, 0, halo.getMinU(), halo.getMinV());
+ t.addVertexWithUV(-spread, 16 + spread, 0, halo.getMinU(), halo.getMaxV());
+ t.addVertexWithUV(16 + spread, 16 + spread, 0, halo.getMaxU(), halo.getMaxV());
+ t.addVertexWithUV(16 + spread, -spread, 0, halo.getMaxU(), halo.getMinV());
+ t.draw();
+ GL11.glPopMatrix();
+ }
+
+ private void renderPulse(IIcon... icons) {
+ Tessellator t = Tessellator.instance;
+ double random = rand.nextGaussian();
+ double scale = (random * 0.15) + 0.95;
+ double offset = (1.0 - scale) / 2.0;
+
+ for (IIcon icon : icons) {
+ if (icon == null) continue;
+ GL11.glPushMatrix();
+ GL11.glEnable(GL11.GL_BLEND);
+ GL11.glTranslated(offset * 16.0, offset * 16.0, 1.0);
+ GL11.glScaled(scale, scale, 1.0);
+
+ t.startDrawingQuads();
+ t.setColorRGBA_F(1.0f, 1.0f, 1.0f, 0.6f);
+ t.addVertexWithUV(0 - offset, 0 - offset, 0, icon.getMinU(), icon.getMinV());
+ t.addVertexWithUV(0 - offset, 16 + offset, 0, icon.getMinU(), icon.getMaxV());
+ t.addVertexWithUV(16 + offset, 16 + offset, 0, icon.getMaxU(), icon.getMaxV());
+ t.addVertexWithUV(16 + offset, 0 - offset, 0, icon.getMaxU(), icon.getMinV());
+ t.draw();
+
+ GL11.glPopMatrix();
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/render/items/TranscendentMetalRenderer.java b/src/main/java/gregtech/common/render/items/TranscendentMetalRenderer.java
new file mode 100644
index 0000000000..8583033e0f
--- /dev/null
+++ b/src/main/java/gregtech/common/render/items/TranscendentMetalRenderer.java
@@ -0,0 +1,145 @@
+package gregtech.common.render.items;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.ItemRenderer;
+import net.minecraft.client.renderer.Tessellator;
+import net.minecraft.client.renderer.entity.RenderItem;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.IIcon;
+import net.minecraftforge.client.IItemRenderer;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidStack;
+
+import org.lwjgl.opengl.GL11;
+
+import codechicken.lib.render.TextureUtils;
+import gregtech.GT_Mod;
+import gregtech.api.interfaces.IGT_ItemWithMaterialRenderer;
+import gregtech.api.util.GT_Util;
+
+public class TranscendentMetalRenderer extends GT_GeneratedMaterial_Renderer {
+
+ @Override
+ public void renderItem(ItemRenderType type, ItemStack aStack, Object... data) {
+ if (type == ItemRenderType.ENTITY) {
+ // Pretend fancy graphics is enabled
+ if (!Minecraft.getMinecraft().gameSettings.fancyGraphics) {
+ if (RenderItem.renderInFrame) {
+ GL11.glRotatef(180.0F, 0.0F, 1.0F, 0.0F);
+ }
+ // Magic numbers calculated from vanilla code
+ GL11.glTranslatef(-0.5F, -0.25F, 0.0421875F);
+ }
+ }
+ super.renderItem(type, aStack, data);
+ }
+
+ @Override
+ protected void renderRegularItem(ItemRenderType type, ItemStack itemStack, IIcon icon,
+ boolean shouldModulateColor) {
+
+ if (!(itemStack.getItem() instanceof final IGT_ItemWithMaterialRenderer itemRenderer)) return;
+
+ GL11.glPushMatrix();
+ applyEffect(type, itemRenderer.getRGBa(itemStack), shouldModulateColor);
+
+ if (shouldModulateColor) {
+ short[] tModulation = itemRenderer.getRGBa(itemStack);
+ GL11.glColor3f(tModulation[0] / 255.0F, tModulation[1] / 255.0F, tModulation[2] / 255.0F);
+ }
+
+ if (type.equals(IItemRenderer.ItemRenderType.INVENTORY)) {
+ GL11.glScalef(16, 16, 32);
+ }
+ ItemRenderer.renderItemIn2D(
+ Tessellator.instance,
+ icon.getMaxU(),
+ icon.getMinV(),
+ icon.getMinU(),
+ icon.getMaxV(),
+ icon.getIconWidth(),
+ icon.getIconHeight(),
+ 0.0625F);
+
+ GL11.glPopMatrix();
+ }
+
+ @Override
+ protected void renderContainedFluid(ItemRenderType type, FluidStack fluidStack, IIcon fluidIcon) {
+ GL11.glPushMatrix();
+
+ Fluid fluid = fluidStack.getFluid();
+ applyEffect(type, GT_Util.getRGBaArray(fluid.getColor()), true);
+
+ TextureUtils.bindAtlas(fluid.getSpriteNumber());
+ GL11.glDepthFunc(GL11.GL_EQUAL);
+ if (type.equals(IItemRenderer.ItemRenderType.INVENTORY)) {
+ GL11.glScalef(16, 16, 32);
+ }
+
+ ItemRenderer.renderItemIn2D(
+ Tessellator.instance,
+ fluidIcon.getMaxU(),
+ fluidIcon.getMinV(),
+ fluidIcon.getMinU(),
+ fluidIcon.getMaxV(),
+ fluidIcon.getIconWidth(),
+ fluidIcon.getIconHeight(),
+ 0.0625F);
+
+ GL11.glDepthFunc(GL11.GL_LEQUAL);
+ GL11.glPopMatrix();
+ }
+
+ @Override
+ protected void renderItemOverlay(ItemRenderType type, IIcon overlay) {
+ GL11.glPushMatrix();
+ applyEffect(type, null, false);
+
+ if (type.equals(IItemRenderer.ItemRenderType.INVENTORY)) {
+ GL11.glScalef(16, 16, 32);
+ }
+ ItemRenderer.renderItemIn2D(
+ Tessellator.instance,
+ overlay.getMaxU(),
+ overlay.getMinV(),
+ overlay.getMinU(),
+ overlay.getMaxV(),
+ overlay.getIconWidth(),
+ overlay.getIconHeight(),
+ 0.0625F);
+
+ GL11.glPopMatrix();
+ }
+
+ private void applyEffect(ItemRenderType type, short[] modulation, boolean shouldModulateColor) {
+ if (RenderItem.renderInFrame) {
+ // Float in front of item frame
+ GL11.glTranslatef(0.0f, 0.0f, -0.5f);
+ }
+
+ if (type.equals(IItemRenderer.ItemRenderType.INVENTORY)) {
+ GL11.glTranslatef(8f, 8f, 0f);
+ } else {
+ GL11.glTranslatef(0.5f, 0.5f, 0.0f);
+ }
+
+ GL11.glRotatef((GT_Mod.gregtechproxy.getAnimationTicks() * 3.5f) % 360, 0.3f, 0.5f, 0.2f);
+ GL11.glRotatef(180, 0.5f, 0.0f, 0.0f);
+
+ if (type.equals(IItemRenderer.ItemRenderType.INVENTORY)) {
+ GL11.glTranslatef(-8f, -8f, 0f);
+ } else {
+ GL11.glTranslatef(-0.5f, -0.5f, 0.0f);
+ }
+
+ // Center on point of rotation
+ GL11.glTranslatef(0.0f, 0.0f, 0.03125F);
+
+ if (shouldModulateColor) {
+ GL11.glColor4f(modulation[0] / 255.0F, modulation[1] / 255.0F, modulation[2] / 255.0F, 255);
+ } else {
+ GL11.glColor4f(1f, 1f, 1f, 255);
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/render/items/UniversiumRenderer.java b/src/main/java/gregtech/common/render/items/UniversiumRenderer.java
new file mode 100644
index 0000000000..92b86071cf
--- /dev/null
+++ b/src/main/java/gregtech/common/render/items/UniversiumRenderer.java
@@ -0,0 +1,197 @@
+package gregtech.common.render.items;
+
+import static gregtech.api.enums.Mods.Avaritia;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.RenderHelper;
+import net.minecraft.client.renderer.Tessellator;
+import net.minecraft.client.renderer.entity.RenderItem;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.item.EntityItem;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.IIcon;
+import net.minecraft.util.MathHelper;
+import net.minecraft.util.ResourceLocation;
+
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL12;
+import org.lwjgl.opengl.GL20;
+
+import codechicken.lib.render.TextureUtils;
+import fox.spiteful.avaritia.render.CosmicRenderShenanigans;
+import gregtech.api.enums.ItemList;
+import gregtech.api.interfaces.IGT_ItemWithMaterialRenderer;
+import gregtech.common.render.GT_RenderUtil;
+
+@SuppressWarnings("RedundantLabeledSwitchRuleCodeBlock")
+public class UniversiumRenderer extends GT_GeneratedMaterial_Renderer {
+
+ private static final float cosmicOpacity = 2.5f;
+
+ @Override
+ public boolean renderFluidDisplayItem(ItemRenderType type, ItemStack aStack, Object... data) {
+ Item item = aStack.getItem();
+ if (item == null) return false;
+
+ magicRenderMethod(
+ type,
+ ItemList.Emitter_UEV.get(1), // hack to make it render correctly
+ item.getIconFromDamage(aStack.getItemDamage()),
+ true,
+ data);
+ return true;
+ }
+
+ @Override
+ public void renderItem(ItemRenderType type, ItemStack aStack, Object... data) {
+ short aMetaData = (short) aStack.getItemDamage();
+ if (!(aStack.getItem() instanceof IGT_ItemWithMaterialRenderer aItem)) return;
+
+ int passes = 1;
+ if (aItem.requiresMultipleRenderPasses()) {
+ passes = aItem.getRenderPasses(aMetaData);
+ }
+
+ for (int pass = 0; pass < passes; pass++) {
+ IIcon tIcon = aItem.getIcon(aMetaData, pass);
+ IIcon tOverlay = aItem.getOverlayIcon(aMetaData, pass);
+
+ GL11.glEnable(GL11.GL_BLEND);
+ GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ GL11.glEnable(GL11.GL_ALPHA_TEST);
+
+ if (tIcon != null) {
+ markNeedsAnimationUpdate(tIcon);
+ magicRenderMethod(type, aStack, tIcon, false, data);
+ }
+
+ GL11.glDisable(GL11.GL_LIGHTING);
+
+ if (tOverlay != null) {
+ GL11.glColor3f(1.0F, 1.0F, 1.0F);
+ TextureUtils.bindAtlas(aItem.getSpriteNumber());
+ markNeedsAnimationUpdate(tOverlay);
+ renderItemOverlay(type, tOverlay);
+ }
+
+ GL11.glDisable(GL11.GL_BLEND);
+ }
+ }
+
+ private void magicRenderMethod(ItemRenderType type, ItemStack aStack, IIcon tIcon, boolean fluidDisplay,
+ Object... data) {
+ if (!Avaritia.isModLoaded()) {
+ return;
+ }
+
+ RenderItem r = RenderItem.getInstance();
+ Minecraft mc = Minecraft.getMinecraft();
+ Tessellator t = Tessellator.instance;
+ float minU = tIcon.getMinU();
+ float maxU = tIcon.getMaxU();
+ float minV = tIcon.getMinV();
+ float maxV = tIcon.getMaxV();
+
+ processLightLevel(type, data);
+
+ GL11.glPushMatrix();
+ GL11.glEnable(GL11.GL_BLEND);
+ GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+
+ if (type == ItemRenderType.INVENTORY) {
+ RenderHelper.enableGUIStandardItemLighting();
+
+ GL11.glDisable(GL11.GL_ALPHA_TEST);
+ GL11.glDisable(GL11.GL_DEPTH_TEST);
+
+ if (fluidDisplay) {
+ // this somehow makes shader render correctly
+ ResourceLocation resourcelocation = mc.getTextureManager()
+ .getResourceLocation(aStack.getItemSpriteNumber());
+ mc.getTextureManager()
+ .bindTexture(resourcelocation);
+ } else {
+ GT_RenderUtil.renderItem(type, tIcon);
+ }
+
+ GL11.glEnable(GL11.GL_BLEND);
+ GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ RenderHelper.enableGUIStandardItemLighting();
+
+ GL11.glDisable(GL11.GL_ALPHA_TEST);
+ GL11.glDisable(GL11.GL_DEPTH_TEST);
+
+ if (fluidDisplay) {
+ GL11.glDisable(GL11.GL_BLEND);
+ }
+
+ CosmicRenderShenanigans.cosmicOpacity = cosmicOpacity;
+ CosmicRenderShenanigans.inventoryRender = true;
+ CosmicRenderShenanigans.useShader();
+
+ GL11.glColor4d(1, 1, 1, 1);
+
+ // Draw cosmic overlay
+ GT_RenderUtil.renderItem(type, tIcon);
+
+ CosmicRenderShenanigans.releaseShader();
+ CosmicRenderShenanigans.inventoryRender = false;
+
+ GL11.glEnable(GL12.GL_RESCALE_NORMAL);
+ } else {
+ // RENDER ITEM
+ GT_RenderUtil.renderItem(type, tIcon);
+
+ int program = GL11.glGetInteger(GL20.GL_CURRENT_PROGRAM);
+
+ GL11.glDisable(GL11.GL_ALPHA_TEST);
+ GL11.glDepthFunc(GL11.GL_EQUAL);
+ CosmicRenderShenanigans.cosmicOpacity = cosmicOpacity;
+ CosmicRenderShenanigans.useShader();
+
+ // RENDER COSMIC OVERLAY
+ GT_RenderUtil.renderItem(type, tIcon);
+ CosmicRenderShenanigans.releaseShader();
+ GL11.glDepthFunc(GL11.GL_LEQUAL);
+
+ GL20.glUseProgram(program);
+ }
+
+ GL11.glEnable(GL11.GL_DEPTH_TEST);
+ GL11.glEnable(GL11.GL_ALPHA_TEST);
+ GL11.glDisable(GL11.GL_BLEND);
+ GL11.glPopMatrix();
+ }
+
+ private void processLightLevel(ItemRenderType type, Object... data) {
+ switch (type) {
+ case ENTITY -> {
+ EntityItem ent = (EntityItem) (data[1]);
+ if (ent != null) {
+ CosmicRenderShenanigans.setLightFromLocation(
+ ent.worldObj,
+ MathHelper.floor_double(ent.posX),
+ MathHelper.floor_double(ent.posY),
+ MathHelper.floor_double(ent.posZ));
+ }
+ }
+ case EQUIPPED, EQUIPPED_FIRST_PERSON -> {
+ EntityLivingBase ent = (EntityLivingBase) (data[1]);
+ if (ent != null) {
+ CosmicRenderShenanigans.setLightFromLocation(
+ ent.worldObj,
+ MathHelper.floor_double(ent.posX),
+ MathHelper.floor_double(ent.posY),
+ MathHelper.floor_double(ent.posZ));
+ }
+ }
+ case INVENTORY -> {
+ CosmicRenderShenanigans.setLightLevel(10.2f);
+ }
+ default -> {
+ CosmicRenderShenanigans.setLightLevel(1.0f);
+ }
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_ChestBuffer.java b/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_ChestBuffer.java
new file mode 100644
index 0000000000..67c38fad9e
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_ChestBuffer.java
@@ -0,0 +1,137 @@
+package gregtech.common.tileentities.automation;
+
+import static gregtech.api.enums.Textures.BlockIcons.AUTOMATION_CHESTBUFFER;
+import static gregtech.api.enums.Textures.BlockIcons.AUTOMATION_CHESTBUFFER_GLOW;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.common.widget.DrawableWidget;
+
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Buffer;
+import gregtech.api.render.TextureFactory;
+
+public class GT_MetaTileEntity_ChestBuffer extends GT_MetaTileEntity_Buffer {
+
+ private static final int[] tickRate = { 400, 200, 100, 20, 4, 1, 1, 1, 1, 1, 1, 1, 1 };
+ private static final int[] maxStacks = { 1, 1, 1, 1, 1, 1, 2, 4, 8, 16, 32, 64, 128 };
+
+ public GT_MetaTileEntity_ChestBuffer(int aID, String aName, String aNameRegional, int aTier) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ 28,
+ new String[] { "Buffers up to 27 Item Stacks", "Use Screwdriver to regulate output stack size",
+ getTickRateDesc(aTier) });
+ }
+
+ public GT_MetaTileEntity_ChestBuffer(int aID, String aName, String aNameRegional, int aTier, int aInvSlotCount,
+ String aDescription) {
+ super(aID, aName, aNameRegional, aTier, aInvSlotCount, aDescription);
+ }
+
+ public GT_MetaTileEntity_ChestBuffer(int aID, String aName, String aNameRegional, int aTier, int aInvSlotCount,
+ String[] aDescription) {
+ super(aID, aName, aNameRegional, aTier, aInvSlotCount, aDescription);
+ }
+
+ public GT_MetaTileEntity_ChestBuffer(String aName, int aTier, int aInvSlotCount, String aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aInvSlotCount, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_ChestBuffer(String aName, int aTier, int aInvSlotCount, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aInvSlotCount, aDescription, aTextures);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_ChestBuffer(
+ this.mName,
+ this.mTier,
+ this.mInventory.length,
+ this.mDescriptionArray,
+ this.mTextures);
+ }
+
+ @Override
+ public ITexture getOverlayIcon() {
+ return TextureFactory.of(
+ TextureFactory.of(AUTOMATION_CHESTBUFFER),
+ TextureFactory.builder()
+ .addIcon(AUTOMATION_CHESTBUFFER_GLOW)
+ .glow()
+ .build());
+ }
+
+ @Override
+ public boolean isValidSlot(int aIndex) {
+ return aIndex < this.mInventory.length - 1;
+ }
+
+ @Override
+ protected void moveItems(IGregTechTileEntity aBaseMetaTileEntity, long aTimer) {
+ if (aTimer % tickRate[mTier] > 0) return;
+
+ // mSuccess will be negative if the call is caused by the %200 aTimer, always try to push. Otherwise it will be
+ // positive.
+ // For the first 6 ticks after a successful move (49->44), push every tick. Then go to every 5 ticks.
+ if ((mSuccess <= 0) || (mSuccess > 43) || ((mSuccess % 5) == 0)) {
+ super.moveItems(aBaseMetaTileEntity, aTimer, Math.min(MAX, maxStacks[mTier]));
+ }
+
+ if (mSuccess < 0) {
+ mSuccess = 0;
+ }
+ }
+
+ protected static String getTickRateDesc(int tier) {
+ int tickRate = getTickRate(tier);
+ String timeStr = "";
+ String numStr = "";
+ if (maxStacks[tier] > 1) {
+ numStr = maxStacks[tier] + " items";
+ } else {
+ numStr = "1 item";
+ }
+ if (tickRate < 20) timeStr = "1/" + 20 / tickRate + " ";
+ else if (tickRate > 20) {
+ timeStr = (tickRate / 20) + "th ";
+ }
+ return "Moves " + numStr + " every " + timeStr + "second";
+ }
+
+ protected static int getTickRate(int tier) {
+ if (tier > 9) return 1;
+ return tickRate[tier];
+ }
+
+ protected static int getMaxStacks(int tier) {
+ // Included higher tiers on the off chance they actually work without blowing things up lmao
+ return tier > 9 ? MAX : Math.min(maxStacks[tier], MAX);
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ super.addUIWidgets(builder, buildContext);
+ addSortStacksButton(builder);
+ addEmitRedstoneIfFullButton(builder);
+ addInvertRedstoneButton(builder);
+ addStockingModeButton(builder);
+ builder.widget(
+ new DrawableWidget().setDrawable(GT_UITextures.PICTURE_ARROW_22_RED.apply(69, true))
+ .setPos(98, 60)
+ .setSize(51, 22));
+ addMainUI(builder);
+ }
+
+ protected void addMainUI(ModularWindow.Builder builder) {
+ addInventorySlots(builder);
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_Filter.java b/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_Filter.java
new file mode 100644
index 0000000000..b6f1d53604
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_Filter.java
@@ -0,0 +1,144 @@
+package gregtech.common.tileentities.automation;
+
+import static gregtech.api.enums.Textures.BlockIcons.AUTOMATION_FILTER;
+import static gregtech.api.enums.Textures.BlockIcons.AUTOMATION_FILTER_GLOW;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.common.widget.DrawableWidget;
+import com.gtnewhorizons.modularui.common.widget.SlotGroup;
+
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_FilterBase;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_Filter extends GT_MetaTileEntity_FilterBase {
+
+ private static final int NUM_FILTER_SLOTS = 9;
+ private static final String IGNORE_NBT_TOOLTIP = "GT5U.machines.ignore_nbt.tooltip";
+ private boolean ignoreNbt = false;
+
+ public GT_MetaTileEntity_Filter(int aID, String aName, String aNameRegional, int aTier) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ 19,
+ new String[] { "Filters up to 9 different Items", "Use Screwdriver to regulate output stack size" });
+ }
+
+ public GT_MetaTileEntity_Filter(String aName, int aTier, int aInvSlotCount, String aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aInvSlotCount, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_Filter(String aName, int aTier, int aInvSlotCount, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aInvSlotCount, aDescription, aTextures);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Filter(
+ this.mName,
+ this.mTier,
+ this.mInventory.length,
+ this.mDescriptionArray,
+ this.mTextures);
+ }
+
+ @Override
+ public ITexture getOverlayIcon() {
+ return TextureFactory.of(
+ TextureFactory.of(AUTOMATION_FILTER),
+ TextureFactory.builder()
+ .addIcon(AUTOMATION_FILTER_GLOW)
+ .glow()
+ .build());
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ aNBT.setBoolean("bIgnoreNBT", this.ignoreNbt);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ this.ignoreNbt = aNBT.getBoolean("bIgnoreNBT");
+ }
+
+ @Override
+ public boolean allowPutStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ if (!super.allowPutStack(aBaseMetaTileEntity, aIndex, side, aStack)) {
+ return false;
+ }
+ if (this.invertFilter) {
+ for (int i = 0; i < NUM_FILTER_SLOTS; i++) {
+ if (GT_Utility.areStacksEqual(this.mInventory[FILTER_SLOT_INDEX + i], aStack, this.ignoreNbt)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return GT_Utility.areStacksEqual(this.mInventory[(FILTER_SLOT_INDEX + aIndex)], aStack, this.ignoreNbt);
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ super.addUIWidgets(builder, buildContext);
+ addAllowNbtButton(builder);
+ builder.widget(
+ new DrawableWidget().setDrawable(GT_UITextures.PICTURE_ARROW_24_WHITE.apply(9, false))
+ .setPos(6, 19)
+ .setSize(9, 24))
+ .widget(
+ new DrawableWidget().setDrawable(GT_UITextures.PICTURE_ARROW_24_BLUE.apply(24, true))
+ .setPos(71, 19)
+ .setSize(24, 24))
+ .widget(
+ new DrawableWidget().setDrawable(GT_UITextures.PICTURE_ARROW_24_RED.apply(19, true))
+ .setPos(152, 19)
+ .setSize(19, 24))
+ .widget(
+ new DrawableWidget().setDrawable(GT_UITextures.PICTURE_SLOTS_HOLO_3BY3)
+ .setPos(16, 4)
+ .setSize(54, 54))
+ .widget(
+ SlotGroup.ofItemHandler(inventoryHandler, 3)
+ .startFromSlot(FILTER_SLOT_INDEX)
+ .endAtSlot(FILTER_SLOT_INDEX + NUM_FILTER_SLOTS - 1)
+ .phantom(true)
+ .applyForWidget(
+ widget -> widget.disableShiftInsert()
+ .setBackground(GT_UITextures.TRANSPARENT))
+ .build()
+ .setPos(16, 4))
+ .widget(
+ SlotGroup.ofItemHandler(inventoryHandler, 3)
+ .startFromSlot(0)
+ .endAtSlot(NUM_INVENTORY_SLOTS - 1)
+ .build()
+ .setPos(97, 4));
+ }
+
+ private void addAllowNbtButton(ModularWindow.Builder builder) {
+ builder.widget(
+ createToggleButton(
+ () -> ignoreNbt,
+ val -> ignoreNbt = val,
+ GT_UITextures.OVERLAY_BUTTON_NBT,
+ () -> mTooltipCache.getData(IGNORE_NBT_TOOLTIP)));
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_ItemDistributor.java b/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_ItemDistributor.java
new file mode 100644
index 0000000000..58b7fa57df
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_ItemDistributor.java
@@ -0,0 +1,204 @@
+package gregtech.common.tileentities.automation;
+
+import static gregtech.api.enums.Textures.BlockIcons.AUTOMATION_ITEMDISTRIBUTOR;
+import static gregtech.api.enums.Textures.BlockIcons.AUTOMATION_ITEMDISTRIBUTOR_GLOW;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.common.widget.DrawableWidget;
+
+import gregtech.api.enums.Textures;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Buffer;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_ItemDistributor extends GT_MetaTileEntity_Buffer {
+
+ private byte[] itemsPerSide = new byte[6];
+ private ForgeDirection currentSide = ForgeDirection.DOWN;
+ private byte currentSideItemCount = 0;
+
+ public GT_MetaTileEntity_ItemDistributor(int aID, String aName, String aNameRegional, int aTier) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ 28,
+ new String[] { "Distributes Items between different Machine Sides", "Default Items per Machine Side: 0",
+ "Use Screwdriver to increase/decrease Items per Side" });
+ }
+
+ public GT_MetaTileEntity_ItemDistributor(int aID, String aName, String aNameRegional, int aTier, int aInvSlotCount,
+ String aDescription) {
+ super(aID, aName, aNameRegional, aTier, aInvSlotCount, aDescription);
+ }
+
+ public GT_MetaTileEntity_ItemDistributor(String aName, int aTier, int aInvSlotCount, String aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aInvSlotCount, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_ItemDistributor(String aName, int aTier, int aInvSlotCount, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aInvSlotCount, aDescription, aTextures);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_ItemDistributor(
+ this.mName,
+ this.mTier,
+ this.mInventory.length,
+ this.mDescriptionArray,
+ this.mTextures);
+ }
+
+ @Override
+ public ITexture getOverlayIcon() {
+ return TextureFactory.of(
+ TextureFactory.of(AUTOMATION_ITEMDISTRIBUTOR),
+ TextureFactory.builder()
+ .addIcon(AUTOMATION_ITEMDISTRIBUTOR_GLOW)
+ .glow()
+ .build());
+ }
+
+ @Override
+ public boolean allowPutStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return side == aBaseMetaTileEntity.getFrontFacing();
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection aFacing,
+ int colorIndex, boolean aActive, boolean redstoneLevel) {
+ if (side == aFacing) {
+ return mTextures[0][colorIndex + 1];
+ } else {
+ return mTextures[1][colorIndex + 1];
+ }
+ }
+
+ @Override
+ public ITexture[][][] getTextureSet(ITexture[] aTextures) {
+ ITexture[][][] returnTextures = new ITexture[2][17][];
+ ITexture baseIcon = getOverlayIcon(), pipeIcon = TextureFactory.of(Textures.BlockIcons.OVERLAY_PIPE_OUT);
+ for (int i = 0; i < 17; i++) {
+ returnTextures[0][i] = new ITexture[] { Textures.BlockIcons.MACHINE_CASINGS[mTier][i], baseIcon };
+ returnTextures[1][i] = new ITexture[] { Textures.BlockIcons.MACHINE_CASINGS[mTier][i], pipeIcon, baseIcon };
+ }
+ return returnTextures;
+ }
+
+ @Override
+ public boolean isInputFacing(ForgeDirection side) {
+ return getBaseMetaTileEntity().getFrontFacing() == side || itemsPerSide[side.ordinal()] == 0;
+ }
+
+ @Override
+ public boolean isOutputFacing(ForgeDirection side) {
+ return getBaseMetaTileEntity().getFrontFacing() != side && itemsPerSide[side.ordinal()] > 0;
+ }
+
+ @Override
+ public boolean isValidSlot(int aIndex) {
+ return aIndex < this.mInventory.length - 1;
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ itemsPerSide = aNBT.getByteArray("mItemsPerSide");
+ if (itemsPerSide.length != 6) {
+ itemsPerSide = new byte[6];
+ }
+ currentSide = ForgeDirection.getOrientation(aNBT.getByte("mCurrentSide"));
+ currentSideItemCount = aNBT.getByte("mCurrentSideItemCount");
+ }
+
+ @Override
+ protected void moveItems(IGregTechTileEntity aBaseMetaTileEntity, long aTimer) {
+ int currentSideOrdinal = currentSide.ordinal();
+ fillStacksIntoFirstSlots();
+ int movedItems;
+ TileEntity adjacentTileEntity = aBaseMetaTileEntity.getTileEntityAtSide(currentSide);
+ int inspectedSides = 0;
+ while (itemsPerSide[currentSideOrdinal] == 0) {
+ currentSideOrdinal = ((currentSideOrdinal + 1) % 6);
+ currentSide = ForgeDirection.getOrientation(currentSideOrdinal);
+ currentSideItemCount = 0;
+ adjacentTileEntity = aBaseMetaTileEntity.getTileEntityAtSide(currentSide);
+ inspectedSides += 1;
+ if (inspectedSides == 6) {
+ return;
+ }
+ }
+ movedItems = GT_Utility.moveOneItemStack(
+ aBaseMetaTileEntity,
+ adjacentTileEntity,
+ currentSide,
+ currentSide.getOpposite(),
+ null,
+ false,
+ (byte) 64,
+ (byte) 1,
+ (byte) (itemsPerSide[currentSideOrdinal] - currentSideItemCount),
+ (byte) 1);
+ currentSideItemCount += movedItems;
+ if (currentSideItemCount >= itemsPerSide[currentSideOrdinal]) {
+ currentSideOrdinal = ((currentSideOrdinal + 1) % 6);
+ currentSide = ForgeDirection.getOrientation(currentSideOrdinal);
+ currentSideItemCount = 0;
+ }
+ if (movedItems > 0 || aBaseMetaTileEntity.hasInventoryBeenModified()) {
+ mSuccess = 50;
+ }
+ fillStacksIntoFirstSlots();
+ }
+
+ @Override
+ public void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ final int ordinalSide = side.ordinal();
+ // Adjust items per side by 1 or -1, constrained to the cyclic interval [0, 127]
+ itemsPerSide[ordinalSide] += aPlayer.isSneaking() ? -1 : 1;
+ itemsPerSide[ordinalSide] = (byte) ((itemsPerSide[ordinalSide] + 128) % 128);
+ GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("211", "Items per side: ") + itemsPerSide[ordinalSide]);
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ aNBT.setByteArray("mItemsPerSide", itemsPerSide);
+ aNBT.setByte("mCurrentSide", (byte) currentSide.ordinal());
+ aNBT.setByte("mCurrentSideItemCount", currentSideItemCount);
+ }
+
+ @Override
+ public void setItemNBT(NBTTagCompound aNBT) {
+ super.setItemNBT(aNBT);
+ aNBT.setByteArray("mItemsPerSide", itemsPerSide);
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ super.addUIWidgets(builder, buildContext);
+ addEmitRedstoneIfFullButton(builder);
+ addInvertRedstoneButton(builder);
+ builder.widget(
+ new DrawableWidget().setDrawable(GT_UITextures.PICTURE_ARROW_22_RED.apply(87, true))
+ .setPos(62, 60)
+ .setSize(87, 22));
+ addInventorySlots(builder);
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_RecipeFilter.java b/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_RecipeFilter.java
new file mode 100644
index 0000000000..05128ee255
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_RecipeFilter.java
@@ -0,0 +1,328 @@
+package gregtech.common.tileentities.automation;
+
+import static gregtech.api.enums.Textures.BlockIcons.AUTOMATION_RECIPEFILTER;
+import static gregtech.api.enums.Textures.BlockIcons.AUTOMATION_RECIPEFILTER_GLOW;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraft.network.PacketBuffer;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.StatCollector;
+import net.minecraftforge.common.util.Constants;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.gtnewhorizons.modularui.api.drawable.Text;
+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.internal.wrapper.BaseSlot;
+import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget;
+import com.gtnewhorizons.modularui.common.widget.SlotWidget;
+
+import codechicken.nei.recipe.RecipeCatalysts;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.interfaces.tileentity.RecipeMapWorkable;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_SpecialFilter;
+import gregtech.api.multitileentity.MultiTileEntityContainer;
+import gregtech.api.multitileentity.MultiTileEntityItemInternal;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.blocks.GT_Item_Machines;
+import gregtech.loaders.preload.GT_Loader_MultiTileEntities;
+
+public class GT_MetaTileEntity_RecipeFilter extends GT_MetaTileEntity_SpecialFilter {
+
+ private static final String TT_machineType = "GT5U.MBTT.MachineType";
+ private static final String REPRESENTATION_SLOT_TOOLTIP = "GT5U.recipe_filter.representation_slot.tooltip";
+ private static final String EMPTY_REPRESENTATION_SLOT_TOOLTIP = "GT5U.recipe_filter.empty_representation_slot.tooltip";
+ public RecipeMap<?> mRecipeMap;
+ private List<ItemStack> filteredMachines = new ArrayList<>();
+ public int mRotationIndex = 0;
+
+ public GT_MetaTileEntity_RecipeFilter(int aID, String aName, String aNameRegional, int aTier) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ new String[] { "Filters 1 Recipe Type", "Use Screwdriver to regulate output stack size" });
+ }
+
+ public GT_MetaTileEntity_RecipeFilter(String aName, int aTier, int aInvSlotCount, String aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aInvSlotCount, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_RecipeFilter(String aName, int aTier, int aInvSlotCount, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aInvSlotCount, aDescription, aTextures);
+ }
+
+ private static RecipeMap<?> getItemStackMachineRecipeMap(ItemStack stack) {
+ if (stack != null) {
+ IMetaTileEntity metaTileEntity = GT_Item_Machines.getMetaTileEntity(stack);
+ if (metaTileEntity != null) {
+ return getMetaTileEntityRecipeMap(metaTileEntity);
+ } else if (stack.getItem() instanceof MultiTileEntityItemInternal) {
+ return getMuTeRecipeMap(stack);
+ }
+ }
+ return null;
+ }
+
+ private static RecipeMap<?> getMetaTileEntityRecipeMap(IMetaTileEntity metaTileEntity) {
+ if (metaTileEntity instanceof RecipeMapWorkable recipeMapWorkable) {
+ return recipeMapWorkable.getRecipeMap();
+ }
+ return null;
+ }
+
+ private static RecipeMap<?> getMuTeRecipeMap(@NotNull ItemStack stack) {
+ MultiTileEntityContainer muTeEntityContainer = GT_Loader_MultiTileEntities.MACHINE_REGISTRY
+ .getNewTileEntityContainer(stack);
+ if (muTeEntityContainer != null
+ && muTeEntityContainer.mTileEntity instanceof RecipeMapWorkable recipeMapWorkable) {
+ return recipeMapWorkable.getRecipeMap();
+ }
+ return null;
+ }
+
+ private static List<ItemStack> getFilteredMachines(RecipeMap<?> recipeMap) {
+ return RecipeCatalysts.getRecipeCatalysts(
+ recipeMap.getFrontend()
+ .getUIProperties().neiTransferRectId)
+ .stream()
+ .map(positionedStack -> positionedStack.item)
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public void onPreTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ super.onPreTick(aBaseMetaTileEntity, aTick);
+ if ((!getBaseMetaTileEntity().isServerSide()) || ((aTick % 8L != 0L) && mRotationIndex != -1)) return;
+ if (this.filteredMachines.isEmpty()) {
+ return;
+ }
+ this.mInventory[FILTER_SLOT_INDEX] = GT_Utility.copyAmount(
+ 1,
+ this.filteredMachines.get(this.mRotationIndex = (this.mRotationIndex + 1) % this.filteredMachines.size()));
+ if (this.mInventory[FILTER_SLOT_INDEX] == null) return;
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_RecipeFilter(
+ this.mName,
+ this.mTier,
+ this.mInventory.length,
+ this.mDescriptionArray,
+ this.mTextures);
+ }
+
+ @Override
+ public ITexture getOverlayIcon() {
+ return TextureFactory.of(
+ TextureFactory.of(AUTOMATION_RECIPEFILTER),
+ TextureFactory.builder()
+ .addIcon(AUTOMATION_RECIPEFILTER_GLOW)
+ .glow()
+ .build());
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ if (mRecipeMap != null) {
+ aNBT.setString("mRecipeMap", this.mRecipeMap.unlocalizedName);
+ }
+ NBTTagList tagList = new NBTTagList();
+ for (ItemStack filteredMachine : filteredMachines) {
+ tagList.appendTag(filteredMachine.writeToNBT(new NBTTagCompound()));
+ }
+ aNBT.setTag("filteredMachines", tagList);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ this.mRecipeMap = RecipeMap.getFromOldIdentifier(aNBT.getString("mRecipeMap"));
+ filteredMachines.clear();
+ NBTTagList tagList = aNBT.getTagList("filteredMachines", Constants.NBT.TAG_COMPOUND);
+ for (int i = 0; i < tagList.tagCount(); i++) {
+ ItemStack readStack = ItemStack.loadItemStackFromNBT(tagList.getCompoundTagAt(i));
+ if (readStack != null) {
+ filteredMachines.add(readStack);
+ }
+ }
+ }
+
+ @Override
+ protected boolean isStackAllowed(ItemStack aStack) {
+ return mRecipeMap != null && mRecipeMap.containsInput(aStack);
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ super.addUIWidgets(builder, buildContext);
+ builder.widget(
+ new FakeSyncWidget.StringSyncer(
+ () -> this.mRecipeMap == null ? "" : this.mRecipeMap.unlocalizedName,
+ id -> this.mRecipeMap = RecipeMap.ALL_RECIPE_MAPS.get(id)));
+ }
+
+ @Override
+ protected List<Text> getEmptySlotTooltip() {
+ return Collections.singletonList(Text.localised(EMPTY_REPRESENTATION_SLOT_TOOLTIP));
+ }
+
+ @Override
+ public Function<List<String>, List<String>> getItemStackReplacementTooltip() {
+ if (mRecipeMap != null) {
+ List<String> tooltip = assembleItemStackReplacementTooltip(mRecipeMap);
+ return list -> tooltip;
+ }
+ return super.getItemStackReplacementTooltip();
+ }
+
+ @NotNull
+ private List<String> assembleItemStackReplacementTooltip(RecipeMap<?> recipeMap) {
+ List<String> tooltip = new ArrayList<>();
+ tooltip.add(
+ StatCollector.translateToLocal(TT_machineType) + ": "
+ + EnumChatFormatting.YELLOW
+ + StatCollector.translateToLocal(recipeMap.unlocalizedName)
+ + EnumChatFormatting.RESET);
+ int recipeSize = recipeMap.getAllRecipes()
+ .size();
+ if (recipeSize > 0) {
+ tooltip.add("Filter size: §e" + recipeSize + "§r");
+ }
+ tooltip.addAll(mTooltipCache.getData(REPRESENTATION_SLOT_TOOLTIP).text);
+ return tooltip;
+ }
+
+ @Override
+ protected SlotWidget createFilterIconSlot(BaseSlot slot) {
+ return new RecipeFilterIconSlotWidget(slot);
+ }
+
+ private class RecipeFilterIconSlotWidget extends FilterIconSlotWidget {
+
+ private static final int SYNC_RECIPEMAP_C2S = 98;
+ private static final int REQUEST_FILTERED_MACHINES_S2C = 99;
+
+ public RecipeFilterIconSlotWidget(BaseSlot slot) {
+ super(slot);
+ }
+
+ @Override
+ protected void phantomClick(ClickData clickData, ItemStack cursorStack) {}
+
+ // region client
+
+ @Override
+ public ClickResult onClick(int buttonId, boolean doubleClick) {
+ updateAndSendRecipeMapToServer(
+ getContext().getCursor()
+ .getItemStack());
+ return ClickResult.SUCCESS;
+ }
+
+ @Override
+ public boolean handleDragAndDrop(ItemStack draggedStack, int button) {
+ updateAndSendRecipeMapToServer(draggedStack);
+ draggedStack.stackSize = 0;
+ return true;
+ }
+
+ private void updateAndSendRecipeMapToServer(ItemStack stack) {
+ mRecipeMap = getItemStackMachineRecipeMap(stack);
+ updateAndSendRecipeMapToServer(mRecipeMap);
+ }
+
+ private void updateAndSendRecipeMapToServer(RecipeMap<?> recipeMap) {
+ if (recipeMap != null) {
+ filteredMachines = getFilteredMachines(recipeMap);
+ } else {
+ filteredMachines = new ArrayList<>();
+ mInventory[FILTER_SLOT_INDEX] = null;
+ }
+ mRotationIndex = -1;
+ syncToServer(SYNC_RECIPEMAP_C2S, buffer -> {
+ NetworkUtils.writeStringSafe(buffer, recipeMap != null ? recipeMap.unlocalizedName : null);
+ buffer.writeVarIntToBuffer(filteredMachines.size());
+ for (ItemStack filteredMachine : filteredMachines) {
+ NetworkUtils.writeItemStack(buffer, filteredMachine);
+ }
+ });
+ }
+
+ @Override
+ public void readOnClient(int id, PacketBuffer buf) {
+ if (id != REQUEST_FILTERED_MACHINES_S2C) {
+ super.readOnClient(id, buf);
+ return;
+ }
+
+ String recipeMapName = NetworkUtils.readStringSafe(buf);
+ mRecipeMap = recipeMapName != null ? RecipeMap.ALL_RECIPE_MAPS.get(recipeMapName) : null;
+ if (mRecipeMap != null) {
+ updateAndSendRecipeMapToServer(mRecipeMap);
+ }
+ }
+
+ // endregion
+
+ // region server
+
+ @Override
+ public void readOnServer(int id, PacketBuffer buf) throws IOException {
+ if (id != SYNC_RECIPEMAP_C2S) {
+ super.readOnServer(id, buf);
+ return;
+ }
+
+ String recipeMapName = NetworkUtils.readStringSafe(buf);
+ mRecipeMap = recipeMapName != null ? RecipeMap.getFromOldIdentifier(recipeMapName) : null;
+ mRotationIndex = -1;
+ mInventory[FILTER_SLOT_INDEX] = null;
+ filteredMachines.clear();
+
+ if (mRecipeMap != null) {
+ int filteredMachineSize = buf.readVarIntFromBuffer();
+ filteredMachineSize = Math.min(filteredMachineSize, 256); // Prevent storing too many items
+ for (int i = 0; i < filteredMachineSize; i++) {
+ ItemStack stack = NetworkUtils.readItemStack(buf);
+ if (stack != null) {
+ filteredMachines.add(stack);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void detectAndSendChanges(boolean init) {
+ super.detectAndSendChanges(init);
+ if (init && mRecipeMap != null && filteredMachines.isEmpty()) {
+ // backward compatibility: This machine used to store only mRecipeMap, not filteredMachines
+ syncToClient(
+ REQUEST_FILTERED_MACHINES_S2C,
+ buffer -> NetworkUtils.writeStringSafe(buffer, mRecipeMap.unlocalizedName));
+ }
+ }
+
+ // endregion
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_Regulator.java b/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_Regulator.java
new file mode 100644
index 0000000000..08d3d32512
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_Regulator.java
@@ -0,0 +1,228 @@
+package gregtech.common.tileentities.automation;
+
+import static gregtech.api.enums.Textures.BlockIcons.AUTOMATION_REGULATOR;
+import static gregtech.api.enums.Textures.BlockIcons.AUTOMATION_REGULATOR_GLOW;
+
+import java.util.Collections;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.common.internal.wrapper.BaseSlot;
+import com.gtnewhorizons.modularui.common.widget.DrawableWidget;
+import com.gtnewhorizons.modularui.common.widget.SlotGroup;
+import com.gtnewhorizons.modularui.common.widget.SlotWidget;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Buffer;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_Regulator extends GT_MetaTileEntity_Buffer {
+
+ public int[] mTargetSlots = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ private boolean charge = false, decharge = false;
+
+ public GT_MetaTileEntity_Regulator(int aID, String aName, String aNameRegional, int aTier) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ 20,
+ new String[] { "Filters up to 9 different Items", "Allows Item-specific output stack size",
+ "Allows Item-specific output slot" });
+ }
+
+ public GT_MetaTileEntity_Regulator(String aName, int aTier, int aInvSlotCount, String aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aInvSlotCount, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_Regulator(String aName, int aTier, int aInvSlotCount, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aInvSlotCount, aDescription, aTextures);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Regulator(
+ this.mName,
+ this.mTier,
+ this.mInventory.length,
+ this.mDescriptionArray,
+ this.mTextures);
+ }
+
+ @Override
+ public ITexture getOverlayIcon() {
+ return TextureFactory.of(
+ TextureFactory.of(AUTOMATION_REGULATOR),
+ TextureFactory.builder()
+ .addIcon(AUTOMATION_REGULATOR_GLOW)
+ .glow()
+ .build());
+ }
+
+ @Override
+ public boolean isValidSlot(int aIndex) {
+ return aIndex < 9 || aIndex == rechargerSlotStartIndex();
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ aNBT.setInteger("mTargetSlot1", this.mTargetSlots[0]);
+ aNBT.setInteger("mTargetSlot2", this.mTargetSlots[1]);
+ aNBT.setInteger("mTargetSlot3", this.mTargetSlots[2]);
+ aNBT.setInteger("mTargetSlot4", this.mTargetSlots[3]);
+ aNBT.setInteger("mTargetSlot5", this.mTargetSlots[4]);
+ aNBT.setInteger("mTargetSlot6", this.mTargetSlots[5]);
+ aNBT.setInteger("mTargetSlot7", this.mTargetSlots[6]);
+ aNBT.setInteger("mTargetSlot8", this.mTargetSlots[7]);
+ aNBT.setInteger("mTargetSlot9", this.mTargetSlots[8]);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ this.mTargetSlots[0] = aNBT.getInteger("mTargetSlot1");
+ this.mTargetSlots[1] = aNBT.getInteger("mTargetSlot2");
+ this.mTargetSlots[2] = aNBT.getInteger("mTargetSlot3");
+ this.mTargetSlots[3] = aNBT.getInteger("mTargetSlot4");
+ this.mTargetSlots[4] = aNBT.getInteger("mTargetSlot5");
+ this.mTargetSlots[5] = aNBT.getInteger("mTargetSlot6");
+ this.mTargetSlots[6] = aNBT.getInteger("mTargetSlot7");
+ this.mTargetSlots[7] = aNBT.getInteger("mTargetSlot8");
+ this.mTargetSlots[8] = aNBT.getInteger("mTargetSlot9");
+ }
+
+ @Override
+ public void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ // Regulation per Screwdriver is overridden by GUI regulation.
+ }
+
+ @Override
+ public void moveItems(IGregTechTileEntity aBaseMetaTileEntity, long aTimer) {
+ for (int i = 0, tCosts; i < 9; i++) {
+ if (this.mInventory[(i + 9)] != null) {
+ tCosts = GT_Utility.moveOneItemStackIntoSlot(
+ getBaseMetaTileEntity(),
+ getBaseMetaTileEntity().getTileEntityAtSide(getBaseMetaTileEntity().getBackFacing()),
+ getBaseMetaTileEntity().getBackFacing(),
+ this.mTargetSlots[i],
+ Collections.singletonList(this.mInventory[(i + 9)]),
+ false,
+ (byte) this.mInventory[(i + 9)].stackSize,
+ (byte) this.mInventory[(i + 9)].stackSize,
+ (byte) 64,
+ (byte) 1) * 3;
+ if (tCosts > 0) {
+ this.mSuccess = 50;
+ break;
+ }
+ }
+ }
+ }
+
+ @Override
+ public boolean allowPutStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return super.allowPutStack(aBaseMetaTileEntity, aIndex, side, aStack) && aIndex >= 0
+ && aIndex <= 8
+ && GT_Utility.areStacksEqual(aStack, this.mInventory[(aIndex + 9)]);
+ }
+
+ @Override
+ public int rechargerSlotStartIndex() {
+ return 19;
+ }
+
+ @Override
+ public int dechargerSlotStartIndex() {
+ return 19;
+ }
+
+ @Override
+ public int rechargerSlotCount() {
+ return charge ? 1 : 0;
+ }
+
+ @Override
+ public int dechargerSlotCount() {
+ return decharge ? 1 : 0;
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ super.onPostTick(aBaseMetaTileEntity, aTick);
+ if (aBaseMetaTileEntity.isServerSide()) {
+ charge = aBaseMetaTileEntity.getStoredEU() / 2 > aBaseMetaTileEntity.getEUCapacity() / 3;
+ decharge = aBaseMetaTileEntity.getStoredEU() < aBaseMetaTileEntity.getEUCapacity() / 3;
+ }
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ super.addUIWidgets(builder, buildContext);
+ builder.widget(createChargerSlot(43, 62));
+ builder.widget(
+ new DrawableWidget().setDrawable(GT_UITextures.PICTURE_ARROW_22_RED.apply(84, true))
+ .setPos(65, 60)
+ .setSize(84, 22))
+ .widget(
+ SlotGroup.ofItemHandler(inventoryHandler, 3)
+ .startFromSlot(0)
+ .endAtSlot(8)
+ .build()
+ .setPos(7, 5))
+ .widget(
+ new DrawableWidget().setDrawable(GT_UITextures.PICTURE_SLOTS_HOLO_3BY3)
+ .setPos(62, 5)
+ .setSize(54, 54))
+ .widget(
+ SlotGroup.ofItemHandler(inventoryHandler, 3)
+ .phantom(true)
+ .startFromSlot(9)
+ .endAtSlot(17)
+ .applyForWidget(
+ widget -> widget.setControlsAmount(true)
+ .setBackground(GT_UITextures.TRANSPARENT))
+ .build()
+ .setPos(62, 5))
+ .widget(
+ new DrawableWidget().setDrawable(GT_UITextures.PICTURE_SLOTS_HOLO_3BY3)
+ .setPos(117, 5)
+ .setSize(54, 54));
+
+ int xBase = 117, yBase = 5;
+ for (int i = 0; i < mTargetSlots.length; i++) {
+ final int index = i;
+ int xPos = xBase + (i % 3) * 18, yPos = yBase + (i / 3) * 18;
+ builder.widget(new SlotWidget(BaseSlot.empty()) {
+
+ @Override
+ protected void phantomClick(ClickData clickData, ItemStack cursorStack) {
+ mTargetSlots[index] = Math.min(
+ 99,
+ Math.max(
+ 0,
+ mTargetSlots[index] + (clickData.mouseButton == 0 ? -1 : 1) * (clickData.shift ? 16 : 1)));
+ }
+ }.setBackground(GT_UITextures.TRANSPARENT)
+ .setPos(xPos, yPos))
+ .widget(
+ TextWidget.dynamicString(() -> String.valueOf(mTargetSlots[index]))
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setPos(xPos + 2 + (i % 3 == 0 ? 1 : 0), yPos + 3 + (i / 3 == 0 ? 1 : 0)));
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_SuperBuffer.java b/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_SuperBuffer.java
new file mode 100644
index 0000000000..9a1d2d7dcf
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_SuperBuffer.java
@@ -0,0 +1,105 @@
+package gregtech.common.tileentities.automation;
+
+import static gregtech.api.enums.Textures.BlockIcons.AUTOMATION_SUPERBUFFER;
+import static gregtech.api.enums.Textures.BlockIcons.AUTOMATION_SUPERBUFFER_GLOW;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.minecraft.item.ItemStack;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.common.widget.DrawableWidget;
+
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_SuperBuffer extends GT_MetaTileEntity_ChestBuffer {
+
+ public GT_MetaTileEntity_SuperBuffer(int aID, String aName, String aNameRegional, int aTier) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ 257,
+ new String[] { "Buffers up to 256 Item Stacks", "Use Screwdriver to regulate output stack size",
+ getTickRateDesc(aTier) });
+ }
+
+ public GT_MetaTileEntity_SuperBuffer(String aName, int aTier, int aInvSlotCount, String aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aInvSlotCount, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_SuperBuffer(String aName, int aTier, int aInvSlotCount, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aInvSlotCount, aDescription, aTextures);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_SuperBuffer(
+ this.mName,
+ this.mTier,
+ this.mInventory.length,
+ this.mDescriptionArray,
+ this.mTextures);
+ }
+
+ @Override
+ public ITexture getOverlayIcon() {
+ return TextureFactory.of(
+ TextureFactory.of(AUTOMATION_SUPERBUFFER),
+ TextureFactory.builder()
+ .addIcon(AUTOMATION_SUPERBUFFER_GLOW)
+ .glow()
+ .build());
+ }
+
+ @Override
+ protected void fillStacksIntoFirstSlots() {
+ // no order, this is super buffer
+ HashMap<GT_Utility.ItemId, Integer> slots = new HashMap<>(mInventory.length);
+ HashMap<GT_Utility.ItemId, ItemStack> stacks = new HashMap<>(mInventory.length);
+ List<Integer> validSlots = new ArrayList<>(mInventory.length);
+ // List<String> order = new ArrayList<>(mInventory.length);
+ for (int i = 0; i < mInventory.length - 1; i++) {
+ if (!isValidSlot(i)) continue;
+ validSlots.add(i);
+ ItemStack s = mInventory[i];
+ if (s == null) continue;
+ GT_Utility.ItemId sID = GT_Utility.ItemId.createNoCopy(s);
+ slots.merge(sID, s.stackSize, Integer::sum);
+ if (!stacks.containsKey(sID)) stacks.put(sID, s);
+ // order.add(sID);
+ mInventory[i] = null;
+ }
+ int i = 0;
+ for (Map.Entry<GT_Utility.ItemId, Integer> entry : slots.entrySet()) {
+ do {
+ int slot = validSlots.get(i);
+ mInventory[slot] = stacks.get(entry.getKey())
+ .copy();
+ int toSet = Math.min(entry.getValue(), mInventory[slot].getMaxStackSize());
+ mInventory[slot].stackSize = toSet;
+ entry.setValue(entry.getValue() - toSet);
+ i++;
+ } while (entry.getValue() > 0);
+ }
+ }
+
+ @Override
+ protected void addMainUI(ModularWindow.Builder builder) {
+ builder.widget(
+ new DrawableWidget().setDrawable(GT_UITextures.PICTURE_SUPER_BUFFER)
+ .setPos(61, 4)
+ .setSize(54, 54));
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_TypeFilter.java b/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_TypeFilter.java
new file mode 100644
index 0000000000..be4a2226a1
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_TypeFilter.java
@@ -0,0 +1,213 @@
+package gregtech.common.tileentities.automation;
+
+import static gregtech.api.enums.GT_Values.W;
+import static gregtech.api.enums.Textures.BlockIcons.AUTOMATION_TYPEFILTER;
+import static gregtech.api.enums.Textures.BlockIcons.AUTOMATION_TYPEFILTER_GLOW;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Function;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+
+import com.google.common.collect.ImmutableList;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.common.internal.wrapper.BaseSlot;
+import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget;
+import com.gtnewhorizons.modularui.common.widget.SlotWidget;
+
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_SpecialFilter;
+import gregtech.api.objects.ItemData;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_OreDictUnificator;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_TypeFilter extends GT_MetaTileEntity_SpecialFilter {
+
+ private static final String REPRESENTATION_SLOT_TOOLTIP = "GT5U.type_filter.representation_slot.tooltip";
+ public int mRotationIndex = 0;
+ public OrePrefixes mPrefix = OrePrefixes.ore;
+
+ public static ImmutableList<OrePrefixes> OREBLOCK_PREFIXES = ImmutableList.of(
+ OrePrefixes.oreBlackgranite,
+ OrePrefixes.oreDense,
+ OrePrefixes.oreEnd,
+ OrePrefixes.oreEndstone,
+ OrePrefixes.oreNether,
+ OrePrefixes.oreNetherrack,
+ OrePrefixes.oreNormal,
+ OrePrefixes.orePoor,
+ OrePrefixes.oreRedgranite,
+ OrePrefixes.oreRich,
+ OrePrefixes.oreSmall,
+ OrePrefixes.oreBasalt,
+ OrePrefixes.oreMarble);
+
+ public GT_MetaTileEntity_TypeFilter(int aID, String aName, String aNameRegional, int aTier) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ new String[] { "Filters 1 Item Type", "Use Screwdriver to regulate output stack size" });
+ }
+
+ public GT_MetaTileEntity_TypeFilter(String aName, int aTier, int aInvSlotCount, String aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aInvSlotCount, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_TypeFilter(String aName, int aTier, int aInvSlotCount, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aInvSlotCount, aDescription, aTextures);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_TypeFilter(
+ this.mName,
+ this.mTier,
+ this.mInventory.length,
+ this.mDescriptionArray,
+ this.mTextures);
+ }
+
+ @Override
+ public ITexture getOverlayIcon() {
+ return TextureFactory.of(
+ TextureFactory.of(AUTOMATION_TYPEFILTER),
+ TextureFactory.builder()
+ .addIcon(AUTOMATION_TYPEFILTER_GLOW)
+ .glow()
+ .build());
+ }
+
+ public void clickTypeIcon(boolean aRightClick, ItemStack aHandStack) {
+ if (getBaseMetaTileEntity().isServerSide()) {
+ if (aHandStack != null) {
+ copyHeldItemPrefix(aHandStack);
+ } else {
+ cyclePrefix(aRightClick);
+ }
+ }
+ }
+
+ private void copyHeldItemPrefix(ItemStack handStack) {
+ ItemData data = GT_OreDictUnificator.getAssociation(handStack);
+ if (data != null && data.hasValidPrefixData()) {
+ this.mPrefix = data.mPrefix;
+ this.mRotationIndex = -1;
+ }
+ }
+
+ private void cyclePrefix(boolean aRightClick) {
+ for (int i = 0; i < OrePrefixes.values().length; i++) {
+ if (this.mPrefix == OrePrefixes.values()[i]) {
+ for (this.mPrefix = null; this.mPrefix == null; this.mPrefix = OrePrefixes.values()[i]) {
+ if (aRightClick) {
+ do {
+ i--;
+ if (i < 0) {
+ i = OrePrefixes.values().length - 1;
+ }
+ } while (OrePrefixes.values()[i].mPrefixedItems.isEmpty());
+ } else {
+ do {
+ i++;
+ if (i >= OrePrefixes.values().length) {
+ i = 0;
+ }
+ } while (OrePrefixes.values()[i].mPrefixedItems.isEmpty());
+ }
+ if (!OrePrefixes.values()[i].mPrefixedItems.isEmpty()
+ && OrePrefixes.values()[i].mPrefixInto == OrePrefixes.values()[i])
+ mPrefix = OrePrefixes.values()[i];
+ }
+ }
+ this.mRotationIndex = -1;
+ }
+ }
+
+ @Override
+ public void onPreTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ super.onPreTick(aBaseMetaTileEntity, aTick);
+ if ((!getBaseMetaTileEntity().isServerSide()) || ((aTick % 8L != 0L) && mRotationIndex != -1)) return;
+ if (this.mPrefix.mPrefixedItems.isEmpty()) {
+ this.mInventory[FILTER_SLOT_INDEX] = null;
+ return;
+ }
+ this.mInventory[FILTER_SLOT_INDEX] = GT_Utility.copyAmount(
+ 1,
+ this.mPrefix.mPrefixedItems
+ .get(this.mRotationIndex = (this.mRotationIndex + 1) % this.mPrefix.mPrefixedItems.size()));
+ if (this.mInventory[FILTER_SLOT_INDEX] == null) return;
+ if (this.mInventory[FILTER_SLOT_INDEX].getItemDamage() == W) this.mInventory[9].setItemDamage(0);
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ aNBT.setString("mPrefix", this.mPrefix.toString());
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ this.mPrefix = OrePrefixes.getPrefix(aNBT.getString("mPrefix"), this.mPrefix);
+ }
+
+ @Override
+ protected boolean isStackAllowed(ItemStack aStack) {
+ if (this.mPrefix == OrePrefixes.ore) {
+ ItemData data = GT_OreDictUnificator.getItemData(aStack);
+ if (data != null && data.mPrefix != null && OREBLOCK_PREFIXES.contains(data.mPrefix)) {
+ return true;
+ }
+ }
+ return this.mPrefix.contains(aStack);
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ super.addUIWidgets(builder, buildContext);
+ builder.widget(
+ new FakeSyncWidget.StringSyncer(
+ () -> this.mPrefix.toString(),
+ (prefix) -> this.mPrefix = OrePrefixes.getPrefix(prefix, this.mPrefix)));
+ }
+
+ @Override
+ protected Function<List<String>, List<String>> getItemStackReplacementTooltip() {
+ return (itemTooltip) -> {
+ List<String> replacementTooltip = new ArrayList<>();
+ replacementTooltip.add("Filter set to " + mPrefix.mRegularLocalName);
+ replacementTooltip.add("Ore prefix: §e" + mPrefix + "§r");
+ replacementTooltip.add("Filter size: §e" + mPrefix.mPrefixedItems.size() + "§r");
+ replacementTooltip.addAll(mTooltipCache.getData(REPRESENTATION_SLOT_TOOLTIP).text);
+ return replacementTooltip;
+ };
+ }
+
+ @Override
+ protected SlotWidget createFilterIconSlot(BaseSlot slot) {
+ return new TypeFilterIconSlotWidget(slot);
+ }
+
+ private class TypeFilterIconSlotWidget extends FilterIconSlotWidget {
+
+ public TypeFilterIconSlotWidget(BaseSlot slot) {
+ super(slot);
+ }
+
+ @Override
+ protected void phantomClick(ClickData clickData, ItemStack cursorStack) {
+ clickTypeIcon(clickData.mouseButton != 0, cursorStack);
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/boilers/GT_MetaTileEntity_Boiler.java b/src/main/java/gregtech/common/tileentities/boilers/GT_MetaTileEntity_Boiler.java
new file mode 100644
index 0000000000..6b245a9da1
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/boilers/GT_MetaTileEntity_Boiler.java
@@ -0,0 +1,516 @@
+package gregtech.common.tileentities.boilers;
+
+import static gregtech.api.objects.XSTR.XSTR_INSTANCE;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Items;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidStack;
+import net.minecraftforge.fluids.IFluidHandler;
+
+import com.gtnewhorizons.modularui.api.drawable.IDrawable;
+import com.gtnewhorizons.modularui.api.drawable.UITexture;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.common.widget.DrawableWidget;
+import com.gtnewhorizons.modularui.common.widget.ProgressBar;
+import com.gtnewhorizons.modularui.common.widget.SlotWidget;
+
+import gregtech.GT_Mod;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.ParticleFX;
+import gregtech.api.enums.SoundResource;
+import gregtech.api.enums.SteamVariant;
+import gregtech.api.gui.modularui.GT_UIInfos;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.gui.modularui.GUITextureSet;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.modularui.IAddUIWidgets;
+import gregtech.api.interfaces.modularui.IGetTitleColor;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicTank;
+import gregtech.api.objects.GT_ItemStack;
+import gregtech.api.util.GT_Log;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.WorldSpawnedEventBuilder.ParticleEventBuilder;
+import gregtech.common.GT_Pollution;
+
+public abstract class GT_MetaTileEntity_Boiler extends GT_MetaTileEntity_BasicTank
+ implements IGetTitleColor, IAddUIWidgets {
+
+ public static final byte SOUND_EVENT_LET_OFF_EXCESS_STEAM = 1;
+ public int mTemperature = 20;
+ public int mProcessingEnergy = 0;
+ public int mLossTimer = 0;
+ public FluidStack mSteam = null;
+ public boolean mHadNoWater = false;
+ private int mExcessWater = 0;
+
+ public GT_MetaTileEntity_Boiler(int aID, String aName, String aNameRegional, String aDescription,
+ ITexture... aTextures) {
+ super(aID, aName, aNameRegional, 0, 4, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_Boiler(int aID, String aName, String aNameRegional, String[] aDescription,
+ ITexture... aTextures) {
+ super(aID, aName, aNameRegional, 0, 4, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_Boiler(String aName, int aTier, String aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, 4, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_Boiler(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, 4, aDescription, aTextures);
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity baseMetaTileEntity, ForgeDirection sideDirection,
+ ForgeDirection facingDirection, int colorIndex, boolean active, boolean redstoneLevel) {
+ ITexture[] tmp;
+ if ((sideDirection.flag & (ForgeDirection.UP.flag | ForgeDirection.DOWN.flag)) == 0) { // Horizontal
+ if (sideDirection != facingDirection) tmp = mTextures[2][colorIndex + 1];
+ else tmp = mTextures[(byte) (active ? 4 : 3)][colorIndex + 1];
+ } else {
+ tmp = mTextures[sideDirection.ordinal()][colorIndex + 1];
+ }
+ if (sideDirection != facingDirection && tmp.length == 2) {
+ tmp = new ITexture[] { tmp[0] };
+ }
+ return tmp;
+ }
+
+ @Override
+ public boolean isElectric() {
+ return false;
+ }
+
+ @Override
+ public boolean isFacingValid(ForgeDirection facingDirection) {
+ return (facingDirection.flag & (ForgeDirection.UP.flag | ForgeDirection.DOWN.flag)) == 0;
+ }
+
+ @Override
+ public boolean isAccessAllowed(EntityPlayer aPlayer) {
+ return true;
+ }
+
+ @Override
+ public boolean isValidSlot(int aIndex) {
+ return true;
+ }
+
+ @Override
+ public int getProgresstime() {
+ return this.mTemperature;
+ }
+
+ @Override
+ public int maxProgresstime() {
+ return 500;
+ }
+
+ @Override
+ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) {
+ if (aBaseMetaTileEntity.isClientSide()) {
+ return true;
+ }
+ if (aPlayer != null) {
+ if (GT_Utility.areStacksEqual(aPlayer.getCurrentEquippedItem(), new ItemStack(Items.water_bucket, 1))) {
+ fill(Materials.Water.getFluid(1000L * (long) aPlayer.getCurrentEquippedItem().stackSize), true);
+
+ if (!aPlayer.capabilities.isCreativeMode) {
+ aPlayer.getCurrentEquippedItem()
+ .func_150996_a(Items.bucket);
+ }
+ } else {
+ GT_UIInfos.openGTTileEntityUI(aBaseMetaTileEntity, aPlayer);
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean doesFillContainers() {
+ return true;
+ }
+
+ @Override
+ public boolean doesEmptyContainers() {
+ return true;
+ }
+
+ @Override
+ public boolean canTankBeFilled() {
+ return true;
+ }
+
+ @Override
+ public boolean canTankBeEmptied() {
+ return true;
+ }
+
+ @Override
+ public boolean displaysItemStack() {
+ return false;
+ }
+
+ @Override
+ public boolean displaysStackSize() {
+ return false;
+ }
+
+ @Override
+ public boolean isFluidInputAllowed(FluidStack aFluid) {
+ return GT_ModHandler.isWater(aFluid);
+ }
+
+ @Override
+ public FluidStack getDrainableStack() {
+ return this.mSteam;
+ }
+
+ @Override
+ public FluidStack setDrainableStack(FluidStack aFluid) {
+ this.mSteam = aFluid;
+ return this.mSteam;
+ }
+
+ @Override
+ public boolean isDrainableStackSeparate() {
+ return true;
+ }
+
+ @Override
+ public boolean allowCoverOnSide(ForgeDirection side, GT_ItemStack aCover) {
+ return GregTech_API.getCoverBehaviorNew(aCover.toStack())
+ .isSimpleCover();
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ aNBT.setInteger("mLossTimer", this.mLossTimer);
+ aNBT.setInteger("mTemperature", this.mTemperature);
+ aNBT.setInteger("mProcessingEnergy", this.mProcessingEnergy);
+ aNBT.setInteger("mExcessWater", this.mExcessWater);
+ if (this.mSteam == null) {
+ return;
+ }
+ try {
+ aNBT.setTag("mSteam", this.mSteam.writeToNBT(new NBTTagCompound()));
+ } catch (Throwable ignored) {}
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ this.mLossTimer = aNBT.getInteger("mLossTimer");
+ this.mTemperature = aNBT.getInteger("mTemperature");
+ this.mProcessingEnergy = aNBT.getInteger("mProcessingEnergy");
+ this.mExcessWater = aNBT.getInteger("mExcessWater");
+ this.mSteam = FluidStack.loadFluidStackFromNBT(aNBT.getCompoundTag("mSteam"));
+ }
+
+ /**
+ * Produce some steam. Assume water is present.
+ */
+ protected void produceSteam(int aAmount) {
+ mExcessWater -= aAmount;
+ if (mExcessWater < 0) {
+ int tWaterToConsume = -mExcessWater / GT_Values.STEAM_PER_WATER;
+ mFluid.amount -= tWaterToConsume;
+ mExcessWater += GT_Values.STEAM_PER_WATER * tWaterToConsume;
+ }
+ if (GT_ModHandler.isSteam(this.mSteam)) {
+ this.mSteam.amount += aAmount;
+ } else {
+ this.mSteam = GT_ModHandler.getSteam(aAmount);
+ }
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ pollute(aTick);
+
+ if (isNotAllowedToWork(aBaseMetaTileEntity, aTick)) return;
+
+ calculateCooldown();
+ pushSteamToInventories(aBaseMetaTileEntity);
+
+ if (canNotCreateSteam(aBaseMetaTileEntity, aTick)) {
+ pollute(aTick);
+ return;
+ }
+
+ ventSteamIfTankIsFull();
+ updateFuelTimed(aBaseMetaTileEntity, aTick);
+ calculateHeatUp(aBaseMetaTileEntity, aTick);
+ }
+
+ private boolean isNotAllowedToWork(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ return (!aBaseMetaTileEntity.isServerSide()) || (aTick <= 20L);
+ }
+
+ private void pollute(long aTick) {
+ if (this.mProcessingEnergy > 0 && (aTick % 20L == 0L)) {
+ GT_Pollution.addPollution(getBaseMetaTileEntity(), getPollution());
+ }
+ }
+
+ private void calculateHeatUp(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ if ((this.mTemperature < getMaxTemperature()) && (this.mProcessingEnergy > 0)
+ && (aTick % getHeatUpRate() == 0L)) {
+ this.mProcessingEnergy -= getEnergyConsumption();
+ this.mTemperature += getHeatUpAmount();
+ }
+ aBaseMetaTileEntity.setActive(this.mProcessingEnergy > 0);
+ }
+
+ private void updateFuelTimed(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ if ((this.mProcessingEnergy <= 0) && (aBaseMetaTileEntity.isAllowedToWork()))
+ updateFuel(aBaseMetaTileEntity, aTick);
+ }
+
+ protected void ventSteamIfTankIsFull() {
+ if ((this.mSteam != null) && (this.mSteam.amount > getSteamCapacity())) {
+ sendSound(SOUND_EVENT_LET_OFF_EXCESS_STEAM);
+ this.mSteam.amount = getSteamCapacity() * 3 / 4;
+ }
+ }
+
+ private boolean canNotCreateSteam(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ if (aTick % 10L != 0L) {
+ return false;
+ }
+
+ if (this.mTemperature > 100) {
+ if ((!GT_ModHandler.isWater(this.mFluid)) || (this.mFluid.amount <= 0)) {
+ this.mHadNoWater = true;
+ } else {
+ if (this.mHadNoWater) {
+ GT_Log.exp.println("Boiler " + this.mName + " had no Water!");
+ onDangerousWaterLack(aBaseMetaTileEntity, aTick);
+ return true;
+ }
+ produceSteam(getProductionPerSecond() / 2);
+ }
+ } else {
+ this.mHadNoWater = false;
+ }
+ return false;
+ }
+
+ protected void onDangerousWaterLack(IGregTechTileEntity tile, long ignoredTicks) {
+ tile.doExplosion(2048L);
+ }
+
+ /**
+ * Pushes Steam to a Side of this Boiler
+ *
+ * @param aBaseMetaTileEntity The tile-entity instance of this Boiler
+ * @param side The direction of the side to push Steam to
+ */
+ protected final void pushSteamToSide(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side) {
+ if (mSteam == null || mSteam.amount == 0) return;
+ final IFluidHandler tTileEntity = aBaseMetaTileEntity.getITankContainerAtSide(side);
+ if (tTileEntity == null) return;
+ GT_Utility.moveFluid(aBaseMetaTileEntity, tTileEntity, side, Math.max(1, this.mSteam.amount / 2), null);
+ }
+
+ /**
+ * Pushes steam to Fluid inventories at all sides except Front and Bottom.
+ *
+ * @param aBaseMetaTileEntity The tile-entity instance of this Boiler
+ */
+ protected void pushSteamToInventories(IGregTechTileEntity aBaseMetaTileEntity) {
+ if (mSteam == null || mSteam.amount == 0) return;
+ for (final ForgeDirection direction : ForgeDirection.VALID_DIRECTIONS) {
+ if (direction == aBaseMetaTileEntity.getFrontFacing() || direction == ForgeDirection.DOWN) continue;
+ if (this.mSteam == null) break;
+ pushSteamToSide(aBaseMetaTileEntity, direction);
+ }
+ }
+
+ private void calculateCooldown() {
+ if (this.mTemperature <= 20) {
+ this.mTemperature = 20;
+ this.mLossTimer = 0;
+ } else if (++this.mLossTimer > getCooldownInterval()) {
+ // only loss temperature if hot
+ this.mTemperature -= 1;
+ this.mLossTimer = 0;
+ }
+ }
+
+ @Override
+ public boolean allowPullStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return GT_Mod.gregtechproxy.mAllowSmallBoilerAutomation;
+ }
+
+ @Override
+ public boolean allowPutStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return GT_Mod.gregtechproxy.mAllowSmallBoilerAutomation;
+ }
+
+ @Override
+ public void doSound(byte aIndex, double aX, double aY, double aZ) {
+ if (aIndex == GT_MetaTileEntity_Boiler.SOUND_EVENT_LET_OFF_EXCESS_STEAM) {
+ GT_Utility.doSoundAtClient(SoundResource.RANDOM_FIZZ, 2, 1.0F, aX, aY, aZ);
+
+ new ParticleEventBuilder().setIdentifier(ParticleFX.CLOUD)
+ .setWorld(getBaseMetaTileEntity().getWorld())
+ .setMotion(0D, 0D, 0D)
+ .<ParticleEventBuilder>times(
+ 8,
+ x -> x.setPosition(aX - 0.5D + XSTR_INSTANCE.nextFloat(), aY, aZ - 0.5D + XSTR_INSTANCE.nextFloat())
+ .run());
+ }
+ }
+
+ @Override
+ public int getTankPressure() {
+ return 100;
+ }
+
+ protected abstract int getPollution();
+
+ @Override
+ public int getCapacity() {
+ return 16000;
+ }
+
+ protected int getSteamCapacity() {
+ return getCapacity();
+ }
+
+ protected abstract int getProductionPerSecond();
+
+ protected abstract int getMaxTemperature();
+
+ protected abstract int getEnergyConsumption();
+
+ protected abstract int getCooldownInterval();
+
+ protected int getHeatUpRate() {
+ return 12;
+ }
+
+ protected int getHeatUpAmount() {
+ return 1;
+ }
+
+ protected abstract void updateFuel(IGregTechTileEntity aBaseMetaTileEntity, long aTick);
+
+ @Override
+ public SteamVariant getSteamVariant() {
+ return SteamVariant.BRONZE;
+ }
+
+ protected IDrawable[] getFuelSlotBackground() {
+ return new IDrawable[] { getGUITextureSet().getItemSlot(),
+ GT_UITextures.OVERLAY_SLOT_COAL_STEAM.get(getSteamVariant()) };
+ }
+
+ protected IDrawable[] getAshSlotBackground() {
+ return new IDrawable[] { getGUITextureSet().getItemSlot(),
+ GT_UITextures.OVERLAY_SLOT_DUST_STEAM.get(getSteamVariant()) };
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ builder.widget(
+ new SlotWidget(inventoryHandler, 0).setPos(43, 25)
+ .setBackground(getGUITextureSet().getItemSlot(), getOverlaySlotIn()))
+ .widget(
+ new SlotWidget(inventoryHandler, 1).setPos(43, 61)
+ .setBackground(getGUITextureSet().getItemSlot(), getOverlaySlotOut()))
+ .widget(createFuelSlot())
+ .widget(createAshSlot())
+ .widget(
+ new ProgressBar().setProgress(() -> mSteam == null ? 0 : (float) mSteam.amount / getSteamCapacity())
+ .setTexture(getProgressbarEmpty(), GT_UITextures.PROGRESSBAR_BOILER_STEAM, 10)
+ .setDirection(ProgressBar.Direction.UP)
+ .setPos(70, 25)
+ .setSize(10, 54))
+ .widget(
+ new ProgressBar().setProgress(() -> mFluid == null ? 0 : (float) mFluid.amount / getCapacity())
+ .setTexture(getProgressbarEmpty(), GT_UITextures.PROGRESSBAR_BOILER_WATER, 10)
+ .setDirection(ProgressBar.Direction.UP)
+ .setPos(83, 25)
+ .setSize(10, 54))
+ .widget(
+ new ProgressBar().setProgress(() -> (float) mTemperature / maxProgresstime())
+ .setTexture(getProgressbarEmpty(), GT_UITextures.PROGRESSBAR_BOILER_HEAT, 10)
+ .setDirection(ProgressBar.Direction.UP)
+ .setPos(96, 25)
+ .setSize(10, 54))
+ .widget(
+ new ProgressBar()
+ // cap minimum so that one can easily see there's fuel remaining
+ .setProgress(() -> mProcessingEnergy > 0 ? Math.max((float) mProcessingEnergy / 1000, 1f / 5) : 0)
+ .setTexture(getProgressbarFuel(), 14)
+ .setDirection(ProgressBar.Direction.UP)
+ .setPos(116, 45)
+ .setSize(14, 14))
+ .widget(
+ new DrawableWidget().setDrawable(getOverlaySlotCanister())
+ .setPos(43, 43)
+ .setSize(18, 18));
+ }
+
+ protected SlotWidget createFuelSlot() {
+ return (SlotWidget) new SlotWidget(inventoryHandler, 2).setPos(115, 61)
+ .setBackground(getFuelSlotBackground());
+ }
+
+ protected SlotWidget createAshSlot() {
+ return (SlotWidget) new SlotWidget(inventoryHandler, 3).setAccess(true, false)
+ .setPos(115, 25)
+ .setBackground(getAshSlotBackground());
+ }
+
+ @Override
+ public GUITextureSet getGUITextureSet() {
+ return GUITextureSet.STEAM.apply(getSteamVariant());
+ }
+
+ @Override
+ public int getTitleColor() {
+ return getSteamVariant() == SteamVariant.BRONZE ? COLOR_TITLE.get() : COLOR_TITLE_WHITE.get();
+ }
+
+ // for GT++
+
+ protected IDrawable getOverlaySlotIn() {
+ return GT_UITextures.OVERLAY_SLOT_IN_STEAM.get(getSteamVariant());
+ }
+
+ protected IDrawable getOverlaySlotOut() {
+ return GT_UITextures.OVERLAY_SLOT_OUT_STEAM.get(getSteamVariant());
+ }
+
+ protected IDrawable getOverlaySlotCanister() {
+ return GT_UITextures.OVERLAY_SLOT_CANISTER_STEAM.get(getSteamVariant());
+ }
+
+ protected UITexture getProgressbarEmpty() {
+ return GT_UITextures.PROGRESSBAR_BOILER_EMPTY_STEAM.get(getSteamVariant());
+ }
+
+ protected UITexture getProgressbarFuel() {
+ return GT_UITextures.PROGRESSBAR_FUEL_STEAM.get(getSteamVariant());
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/boilers/GT_MetaTileEntity_Boiler_Bronze.java b/src/main/java/gregtech/common/tileentities/boilers/GT_MetaTileEntity_Boiler_Bronze.java
new file mode 100644
index 0000000000..9e746dc5e9
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/boilers/GT_MetaTileEntity_Boiler_Bronze.java
@@ -0,0 +1,311 @@
+package gregtech.common.tileentities.boilers;
+
+import static gregtech.api.enums.Textures.BlockIcons.BOILER_FRONT;
+import static gregtech.api.enums.Textures.BlockIcons.BOILER_FRONT_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.BOILER_FRONT_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.BOILER_FRONT_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_BRONZEBRICKS_BOTTOM;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_BRONZEBRICKS_SIDE;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_BRONZEBRICKS_TOP;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_PIPE;
+import static gregtech.api.objects.XSTR.XSTR_INSTANCE;
+
+import net.minecraft.block.Block;
+import net.minecraft.tileentity.TileEntityFurnace;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.GT_Mod;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.enums.ParticleFX;
+import gregtech.api.enums.SteamVariant;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.objects.XSTR;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_OreDictUnificator;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.WorldSpawnedEventBuilder.ParticleEventBuilder;
+import gregtech.common.GT_Pollution;
+
+public class GT_MetaTileEntity_Boiler_Bronze extends GT_MetaTileEntity_Boiler {
+
+ public GT_MetaTileEntity_Boiler_Bronze(int aID, String aName, String aNameRegional) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ new String[] { "An early way to get Steam Power", "Produces 120L of Steam per second",
+ "Causes " + GT_Mod.gregtechproxy.mPollutionSmallCoalBoilerPerSecond + " Pollution per second" });
+ }
+
+ public GT_MetaTileEntity_Boiler_Bronze(int aID, String aName, String aNameRegional, String[] aDescription) {
+ super(aID, aName, aNameRegional, aDescription);
+ }
+
+ public GT_MetaTileEntity_Boiler_Bronze(String aName, int aTier, String aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_Boiler_Bronze(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ }
+
+ @Override
+ public ITexture[][][] getTextureSet(ITexture[] aTextures) {
+ ITexture[][][] rTextures = new ITexture[5][17][];
+ final ITexture[] texBottom = { TextureFactory.of(MACHINE_BRONZEBRICKS_BOTTOM) },
+ texTop = { TextureFactory.of(MACHINE_BRONZEBRICKS_TOP), TextureFactory.of(OVERLAY_PIPE) },
+ texSide = { TextureFactory.of(MACHINE_BRONZEBRICKS_SIDE), TextureFactory.of(OVERLAY_PIPE) },
+ texFront = { TextureFactory.of(MACHINE_BRONZEBRICKS_SIDE), TextureFactory.of(BOILER_FRONT),
+ TextureFactory.builder()
+ .addIcon(BOILER_FRONT_GLOW)
+ .glow()
+ .build() },
+ texFrontActive = { TextureFactory.of(MACHINE_BRONZEBRICKS_SIDE), TextureFactory.of(BOILER_FRONT_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(BOILER_FRONT_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ for (int i = 0; i < 17; i++) {
+ rTextures[0][i] = texBottom;
+ rTextures[1][i] = texTop;
+ rTextures[2][i] = texSide;
+ rTextures[3][i] = texFront;
+ rTextures[4][i] = texFrontActive;
+ }
+ return rTextures;
+ }
+
+ @Override
+ public int maxProgresstime() {
+ return 500;
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Boiler_Bronze(this.mName, this.mTier, this.mDescriptionArray, this.mTextures);
+ }
+
+ /**
+ * Draws random flames and smoke particles in front of active boiler
+ *
+ * @param aBaseMetaTileEntity The entity that will handle the {@link Block#randomDisplayTick}
+ */
+ @SideOnly(Side.CLIENT)
+ @Override
+ public void onRandomDisplayTick(IGregTechTileEntity aBaseMetaTileEntity) {
+ if (aBaseMetaTileEntity.isActive()) {
+
+ final ForgeDirection frontFacing = aBaseMetaTileEntity.getFrontFacing();
+
+ if ((frontFacing.flag & (ForgeDirection.UP.flag | ForgeDirection.DOWN.flag)) == 0
+ && aBaseMetaTileEntity.getCoverIDAtSide(frontFacing) == 0
+ && !aBaseMetaTileEntity.getOpacityAtSide(frontFacing)) {
+
+ final double oX = aBaseMetaTileEntity.getOffsetX(frontFacing, 1) + 8D / 16D;
+ final double oY = aBaseMetaTileEntity.getOffsetY(frontFacing, 1);
+ final double oZ = aBaseMetaTileEntity.getOffsetZ(frontFacing, 1) + 8D / 16D;
+ final double offset = -0.48D;
+ final double horizontal = XSTR_INSTANCE.nextFloat() * 10D / 16D - 5D / 16D;
+
+ final double x, y, z;
+
+ y = oY + XSTR_INSTANCE.nextFloat() * 6D / 16D;
+
+ if (frontFacing == ForgeDirection.WEST) {
+ x = oX - offset;
+ z = oZ + horizontal;
+ } else if (frontFacing == ForgeDirection.EAST) {
+ x = oX + offset;
+ z = oZ + horizontal;
+ } else if (frontFacing == ForgeDirection.NORTH) {
+ x = oX + horizontal;
+ z = oZ - offset;
+ } else // if (frontFacing == ForgeDirection.SOUTH)
+ {
+ x = oX + horizontal;
+ z = oZ + offset;
+ }
+
+ ParticleEventBuilder particleEventBuilder = (new ParticleEventBuilder()).setMotion(0D, 0D, 0D)
+ .setPosition(x, y, z)
+ .setWorld(getBaseMetaTileEntity().getWorld());
+ particleEventBuilder.setIdentifier(ParticleFX.SMOKE)
+ .run();
+ particleEventBuilder.setIdentifier(ParticleFX.FLAME)
+ .run();
+ }
+ }
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ super.onPostTick(aBaseMetaTileEntity, aTick);
+ if ((aBaseMetaTileEntity.isServerSide()) && (aTick > 20L)
+ && this.mProcessingEnergy > 0
+ && (aTick % 20L == 0L)) {
+ GT_Pollution.addPollution(getBaseMetaTileEntity(), getPollution());
+ }
+ }
+
+ @Override
+ protected int getPollution() {
+ return GT_Mod.gregtechproxy.mPollutionSmallCoalBoilerPerSecond;
+ }
+
+ @Override
+ protected int getProductionPerSecond() {
+ return 120;
+ }
+
+ @Override
+ protected int getMaxTemperature() {
+ return 500;
+ }
+
+ @Override
+ protected int getEnergyConsumption() {
+ return 1;
+ }
+
+ @Override
+ protected int getCooldownInterval() {
+ return 45;
+ }
+
+ @Override
+ protected void updateFuel(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ if (this.mInventory[2] == null) return;
+ if ((GT_Utility.isPartOfMaterials(this.mInventory[2], Materials.Coal)
+ && !GT_Utility.isPartOfOrePrefix(this.mInventory[2], OrePrefixes.block))
+ || (GT_Utility.isPartOfMaterials(this.mInventory[2], Materials.Charcoal)
+ && !GT_Utility.isPartOfOrePrefix(this.mInventory[2], OrePrefixes.block))
+ || (GT_Utility.isPartOfMaterials(this.mInventory[2], Materials.Lignite)
+ && !GT_Utility.isPartOfOrePrefix(this.mInventory[2], OrePrefixes.block))
+ || (GT_Utility.isPartOfMaterials(this.mInventory[2], Materials.Diamond)
+ && !GT_Utility.isPartOfOrePrefix(this.mInventory[2], OrePrefixes.block))
+ || GT_OreDictUnificator.isItemStackInstanceOf(this.mInventory[2], "fuelCoke")
+ || GT_OreDictUnificator.isItemStackInstanceOf(this.mInventory[2], "fuelCactusCharcoal")
+ || GT_OreDictUnificator.isItemStackInstanceOf(this.mInventory[2], "fuelCactusCoke")
+ || GT_OreDictUnificator.isItemStackInstanceOf(this.mInventory[2], "fuelSugarCharcoal")
+ || GT_OreDictUnificator.isItemStackInstanceOf(this.mInventory[2], "fuelSugarCoke")) {
+ if ((TileEntityFurnace.getItemBurnTime(this.mInventory[2]) / 10) > 0) {
+ this.mProcessingEnergy += (TileEntityFurnace.getItemBurnTime(this.mInventory[2]) / 10);
+ if (XSTR.XSTR_INSTANCE.nextInt(
+ GT_Utility.isPartOfMaterials(this.mInventory[2], Materials.Coal)
+ || GT_Utility.isPartOfMaterials(this.mInventory[2], Materials.Charcoal) ? 3
+ : GT_Utility.isPartOfMaterials(this.mInventory[2], Materials.Lignite) ? 8 : 2)
+ == 0) {
+ aBaseMetaTileEntity.addStackToSlot(
+ 3,
+ GT_OreDictUnificator.get(
+ OrePrefixes.dustTiny,
+ (GT_Utility.isPartOfMaterials(this.mInventory[2], Materials.Lignite)
+ || GT_Utility.isPartOfMaterials(this.mInventory[2], Materials.Coal)) ? Materials.DarkAsh
+ : Materials.Ash,
+ 1L));
+ }
+ aBaseMetaTileEntity.decrStackSize(2, 1);
+ }
+ } else if (
+ // If its a block of the following materials
+ GT_OreDictUnificator.isItemStackInstanceOf(this.mInventory[2], OrePrefixes.block.get(Materials.Coal))
+ || GT_OreDictUnificator.isItemStackInstanceOf(this.mInventory[2], OrePrefixes.block.get(Materials.Lignite))
+ || GT_OreDictUnificator.isItemStackInstanceOf(this.mInventory[2], OrePrefixes.block.get(Materials.Charcoal))
+ || GT_OreDictUnificator.isItemStackInstanceOf(this.mInventory[2], OrePrefixes.block.get(Materials.Diamond))
+ ||
+
+ // if its either a Railcraft Coke Block or a custom GTNH compressed Coal/charcoal/lignite/coke block
+ (Block.getBlockFromItem(this.mInventory[2].getItem()) != null && // check if the block exists
+ (Block.getBlockFromItem(this.mInventory[2].getItem())
+ .getUnlocalizedName()
+ .toLowerCase()
+ .contains("tile") && // check if the block is a tile -> block
+ (
+ // If the name of the block contains these names
+ Block.getBlockFromItem(this.mInventory[2].getItem())
+ .getUnlocalizedName()
+ .toLowerCase()
+ .contains("charcoal")
+ || Block.getBlockFromItem(this.mInventory[2].getItem())
+ .getUnlocalizedName()
+ .toLowerCase()
+ .contains("coal")
+ || Block.getBlockFromItem(this.mInventory[2].getItem())
+ .getUnlocalizedName()
+ .toLowerCase()
+ .contains("diamond")
+ || Block.getBlockFromItem(this.mInventory[2].getItem())
+ .getUnlocalizedName()
+ .toLowerCase()
+ .contains("coke")
+ || Block.getBlockFromItem(this.mInventory[2].getItem())
+ .getUnlocalizedName()
+ .toLowerCase()
+ .contains("railcraft.cube")
+ || Block.getBlockFromItem(this.mInventory[2].getItem())
+ .getUnlocalizedName()
+ .toLowerCase()
+ .contains("lignite"))))) {
+ // try to add 10% of the burnvalue as Processing energy, no boost
+ // for coal coke here
+ if ((TileEntityFurnace.getItemBurnTime(this.mInventory[2]) / 10) > 0) {
+ this.mProcessingEnergy += (TileEntityFurnace.getItemBurnTime(this.mInventory[2])
+ / 10);
+ aBaseMetaTileEntity.addStackToSlot(
+ 3,
+ GT_OreDictUnificator.get(
+ OrePrefixes.dust,
+ (GT_Utility.isPartOfMaterials(this.mInventory[2], Materials.Lignite)
+ || GT_Utility.isPartOfMaterials(this.mInventory[2], Materials.Coal)
+ || Block.getBlockFromItem(this.mInventory[2].getItem())
+ .getUnlocalizedName()
+ .toLowerCase()
+ .contains("coal")
+ || Block.getBlockFromItem(this.mInventory[2].getItem())
+ .getUnlocalizedName()
+ .toLowerCase()
+ .contains("lignite")) ? Materials.DarkAsh : Materials.Ash,
+ 1L));
+ aBaseMetaTileEntity.decrStackSize(2, 1);
+ }
+ // enables every other fuel with at least 2000 burntime as a fuel,
+ // i.e. peat, Magic/Solid Super Fuel, Coal
+ // Singularities, Nitor, while bucket of creosite should be blocked
+ // same goes for lava
+ } else
+ if ((TileEntityFurnace.getItemBurnTime(this.mInventory[2])) >= 2000
+ && !(this.mInventory[2].getUnlocalizedName()
+ .toLowerCase()
+ .contains("bucket")
+ || this.mInventory[2].getUnlocalizedName()
+ .toLowerCase()
+ .contains("cell"))) {
+ this.mProcessingEnergy += (TileEntityFurnace.getItemBurnTime(this.mInventory[2]) / 10);
+ // adds tiny pile of ash for burntime under 10k, small pile for
+ // under 100k and pile for
+ // bigger values
+ if (XSTR.XSTR_INSTANCE.nextInt(2) == 0)
+ aBaseMetaTileEntity.addStackToSlot(
+ 3,
+ GT_OreDictUnificator.get(
+ (TileEntityFurnace.getItemBurnTime(this.mInventory[2]) >= 10000
+ ? TileEntityFurnace.getItemBurnTime(this.mInventory[2]) >= 100000
+ ? OrePrefixes.dust
+ : OrePrefixes.dustSmall
+ : OrePrefixes.dustTiny),
+ Materials.Ash,
+ 1L));
+ aBaseMetaTileEntity.decrStackSize(2, 1);
+ }
+ }
+
+ @Override
+ public SteamVariant getSteamVariant() {
+ return SteamVariant.BRONZE;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/boilers/GT_MetaTileEntity_Boiler_Lava.java b/src/main/java/gregtech/common/tileentities/boilers/GT_MetaTileEntity_Boiler_Lava.java
new file mode 100644
index 0000000000..7fe3a3f4bb
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/boilers/GT_MetaTileEntity_Boiler_Lava.java
@@ -0,0 +1,524 @@
+package gregtech.common.tileentities.boilers;
+
+import static gregtech.api.enums.Textures.BlockIcons.BOILER_LAVA_FRONT;
+import static gregtech.api.enums.Textures.BlockIcons.BOILER_LAVA_FRONT_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.BOILER_LAVA_FRONT_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.BOILER_LAVA_FRONT_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.FLUID_IN_SIGN;
+import static gregtech.api.enums.Textures.BlockIcons.FLUID_OUT_SIGN;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_STEELBRICKS_BOTTOM;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_STEELBRICKS_SIDE;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_STEELBRICKS_TOP;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_DRAIN;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_PIPE_OUT;
+import static gregtech.api.objects.XSTR.XSTR_INSTANCE;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.item.EntityItem;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidRegistry;
+import net.minecraftforge.fluids.FluidStack;
+import net.minecraftforge.fluids.FluidTank;
+import net.minecraftforge.fluids.FluidTankInfo;
+import net.minecraftforge.fluids.IFluidContainerItem;
+import net.minecraftforge.fluids.IFluidHandler;
+import net.minecraftforge.fluids.IFluidTank;
+
+import com.gtnewhorizons.modularui.api.drawable.IDrawable;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.common.widget.DrawableWidget;
+import com.gtnewhorizons.modularui.common.widget.FluidSlotWidget;
+import com.gtnewhorizons.modularui.common.widget.ProgressBar;
+import com.gtnewhorizons.modularui.common.widget.SlotWidget;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.GT_Mod;
+import gregtech.api.enums.Dyes;
+import gregtech.api.enums.ParticleFX;
+import gregtech.api.enums.SoundResource;
+import gregtech.api.enums.SteamVariant;
+import gregtech.api.gui.modularui.GT_UIInfos;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.WorldSpawnedEventBuilder.ParticleEventBuilder;
+
+public class GT_MetaTileEntity_Boiler_Lava extends GT_MetaTileEntity_Boiler {
+
+ public static final int COOLDOWN_INTERVAL = 20;
+ public static final int ENERGY_PER_LAVA = 1;
+ public static final int CONSUMPTION_PER_HEATUP = 3;
+ public static final int PRODUCTION_PER_SECOND = 600;
+ private final FluidTank lavaTank = new LavaTank(null, getCapacity());
+ private int mCooledLava = 0;
+
+ public GT_MetaTileEntity_Boiler_Lava(int aID, String aName, String aNameRegional) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ new String[] { "A Boiler running off Lava", "Produces " + PRODUCTION_PER_SECOND + "L of Steam per second",
+ "Causes " + GT_Mod.gregtechproxy.mPollutionHighPressureLavaBoilerPerSecond + " Pollution per second",
+ "Consumes " + ((double) CONSUMPTION_PER_HEATUP / ENERGY_PER_LAVA)
+ + "L of Lava every "
+ + COOLDOWN_INTERVAL
+ + " ticks when fully heat up" });
+ }
+
+ public GT_MetaTileEntity_Boiler_Lava(String aName, int aTier, String aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_Boiler_Lava(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity baseMetaTileEntity, ForgeDirection sideDirection,
+ ForgeDirection facingDirection, int colorIndex, boolean active, boolean redstoneLevel) {
+ final ForgeDirection rearDirection = facingDirection.getOpposite();
+ final ITexture[] tmp;
+ if ((sideDirection.flag & (ForgeDirection.UP.flag | ForgeDirection.DOWN.flag)) == 0) {
+ if (sideDirection == facingDirection) {
+ if (active) tmp = mTextures[4][colorIndex + 1];
+ else tmp = mTextures[3][colorIndex + 1];
+ } else if (sideDirection == rearDirection) {
+ tmp = mTextures[5][colorIndex + 1];
+ } else {
+ tmp = mTextures[2][colorIndex + 1];
+ }
+ } else tmp = mTextures[sideDirection.ordinal()][colorIndex + 1];
+ if (sideDirection != facingDirection && tmp.length == 2) {
+ return new ITexture[] { tmp[0] };
+ }
+ return tmp;
+ }
+
+ @Override
+ public ITexture[][][] getTextureSet(ITexture[] aTextures) {
+ ITexture[][][] rTextures = new ITexture[6][17][];
+ for (byte color = -1; color < 16; color++) {
+ int i = color + 1;
+ short[] colorModulation = Dyes.getModulation(color, Dyes._NULL.mRGBa);
+ rTextures[0][i] = new ITexture[] { TextureFactory.of(MACHINE_STEELBRICKS_BOTTOM, colorModulation) };
+ rTextures[1][i] = new ITexture[] { TextureFactory.of(MACHINE_STEELBRICKS_TOP, colorModulation),
+ TextureFactory.of(OVERLAY_DRAIN), TextureFactory.of(FLUID_IN_SIGN) };
+ rTextures[2][i] = new ITexture[] { TextureFactory.of(MACHINE_STEELBRICKS_SIDE, colorModulation),
+ TextureFactory.of(OVERLAY_PIPE_OUT), TextureFactory.of(FLUID_IN_SIGN) };
+ rTextures[3][i] = new ITexture[] { TextureFactory.of(MACHINE_STEELBRICKS_SIDE, colorModulation),
+ TextureFactory.of(BOILER_LAVA_FRONT, colorModulation), TextureFactory.of(BOILER_LAVA_FRONT_GLOW) };
+ rTextures[4][i] = new ITexture[] { TextureFactory.of(MACHINE_STEELBRICKS_SIDE, colorModulation),
+ TextureFactory.of(BOILER_LAVA_FRONT_ACTIVE), TextureFactory.builder()
+ .addIcon(BOILER_LAVA_FRONT_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ rTextures[5][i] = new ITexture[] { TextureFactory.of(MACHINE_STEELBRICKS_SIDE, colorModulation),
+ TextureFactory.of(OVERLAY_PIPE_OUT), TextureFactory.of(FLUID_OUT_SIGN) };
+ }
+ return rTextures;
+ }
+
+ @Override
+ public int maxProgresstime() {
+ return 1000;
+ }
+
+ @Override
+ public int getCapacity() {
+ return 32000;
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Boiler_Lava(this.mName, this.mTier, this.mDescriptionArray, this.mTextures);
+ }
+
+ @Override
+ protected int getPollution() {
+ return GT_Mod.gregtechproxy.mPollutionHighPressureLavaBoilerPerSecond;
+ }
+
+ @Override
+ protected int getProductionPerSecond() {
+ return PRODUCTION_PER_SECOND;
+ }
+
+ @Override
+ protected int getMaxTemperature() {
+ return 1000;
+ }
+
+ @Override
+ protected int getEnergyConsumption() {
+ this.mCooledLava += CONSUMPTION_PER_HEATUP;
+ return CONSUMPTION_PER_HEATUP;
+ }
+
+ @Override
+ protected int getCooldownInterval() {
+ return COOLDOWN_INTERVAL;
+ }
+
+ /**
+ * Attempts to fill an {@link IFluidTank} from the {@link FluidStack} content of an {@link ItemStack}
+ *
+ * @param destinationIFluidTank The destination {@link IFluidTank} to fill
+ * @param SourceItemStack The source {@link ItemStack} containing the Fluid
+ * @return The {@link ItemStack} of the Empty version of the source {@link ItemStack} or {@code null} if none
+ */
+ public static ItemStack fillIFluidTankFromItemStack(IFluidTank destinationIFluidTank, ItemStack SourceItemStack) {
+ if (destinationIFluidTank == null || SourceItemStack == null) return null;
+
+ final FluidStack containedFluidStack = GT_Utility.getFluidForFilledItem(SourceItemStack, true);
+ if (containedFluidStack == null || containedFluidStack.amount == 0) return null;
+
+ final int fillableAmount = destinationIFluidTank.fill(containedFluidStack, false);
+ if (fillableAmount <= 0) return null;
+
+ final Item containerItem = SourceItemStack.getItem();
+ if (containerItem instanceof IFluidContainerItem equippedIFluidContainerItem) {
+ destinationIFluidTank.fill(equippedIFluidContainerItem.drain(SourceItemStack, fillableAmount, true), true);
+ return null;
+ } else {
+ final ItemStack emptyContainerItemStack = GT_Utility.getContainerForFilledItem(SourceItemStack, false);
+ destinationIFluidTank.fill(containedFluidStack, true);
+ return emptyContainerItemStack;
+ }
+ }
+
+ @Override
+ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) {
+ if (aBaseMetaTileEntity.isClientSide() || aPlayer == null) return true;
+
+ final ItemStack equippedItemStack = aPlayer.getCurrentEquippedItem();
+ final FluidStack equippedContainerFluidStack = GT_Utility.getFluidForFilledItem(equippedItemStack, true);
+ final ItemStack returnedItemStack;
+ final IFluidTank tank;
+
+ if (GT_ModHandler.isWater(equippedContainerFluidStack)) {
+ tank = this;
+ } else if (GT_ModHandler.isLava(equippedContainerFluidStack)) {
+ tank = lavaTank;
+ } else {
+ GT_UIInfos.openGTTileEntityUI(aBaseMetaTileEntity, aPlayer);
+ return true;
+ }
+ returnedItemStack = fillIFluidTankFromItemStack(tank, equippedItemStack);
+ if (returnedItemStack != null && !aPlayer.capabilities.isCreativeMode) {
+ if (equippedItemStack.stackSize > 1) {
+ if (!aPlayer.inventory.addItemStackToInventory(returnedItemStack)) {
+ aBaseMetaTileEntity.getWorld()
+ .spawnEntityInWorld(
+ new EntityItem(
+ aBaseMetaTileEntity.getWorld(),
+ (double) aBaseMetaTileEntity.getXCoord() + 0.5D,
+ (double) aBaseMetaTileEntity.getYCoord() + 1.5D,
+ (double) aBaseMetaTileEntity.getZCoord() + 0.5D,
+ equippedItemStack));
+ } else if (aPlayer instanceof EntityPlayerMP) {
+ ((EntityPlayerMP) aPlayer).sendContainerToPlayer(aPlayer.inventoryContainer);
+ }
+ aPlayer.inventory.decrStackSize(aPlayer.inventory.currentItem, 1);
+ } else {
+ aPlayer.inventory.setInventorySlotContents(aPlayer.inventory.currentItem, returnedItemStack);
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ if (lavaTank.getFluid() != null) aNBT.setTag(
+ "mLava",
+ lavaTank.getFluid()
+ .writeToNBT(new NBTTagCompound()));
+ aNBT.setInteger("mCooledLava", this.mCooledLava);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ lavaTank.setFluid(FluidStack.loadFluidStackFromNBT(aNBT.getCompoundTag("mLava")));
+ this.mCooledLava = aNBT.getInteger("mCooledLava");
+ }
+
+ /**
+ * Pushes steam to Fluid inventory at the rear.
+ *
+ * @param aBaseMetaTileEntity The tile-entity instance of this Lava Boiler
+ */
+ @Override
+ protected void pushSteamToInventories(IGregTechTileEntity aBaseMetaTileEntity) {
+ if (mSteam == null || mSteam.amount == 0) return;
+ pushSteamToSide(
+ aBaseMetaTileEntity,
+ aBaseMetaTileEntity.getFrontFacing()
+ .getOpposite());
+ }
+
+ /**
+ * Drains Lava from Fluid inventory on top
+ *
+ * @param aBaseMetaTileEntity The tile-entity instance of this Lava Boiler
+ */
+ protected void drainLava(IGregTechTileEntity aBaseMetaTileEntity) {
+ final IFluidHandler upTank = aBaseMetaTileEntity.getITankContainerAtSide(ForgeDirection.UP);
+ if (upTank == null) return;
+ // Simulates drain of maximum lava amount up to 1000L that can fit the internal tank
+ final FluidStack drainableLavaStack = upTank.drain(
+ ForgeDirection.DOWN,
+ FluidRegistry.getFluidStack(
+ "lava",
+ Math.min(
+ this.lavaTank.getCapacity()
+ - (this.lavaTank.getFluid() != null ? this.lavaTank.getFluid().amount : 0),
+ 1000)),
+ false);
+ if (!GT_ModHandler.isLava(drainableLavaStack) || drainableLavaStack.amount <= 0) return;
+ // Performs actual drain up and fill internal tank
+ this.lavaTank.fill(upTank.drain(ForgeDirection.DOWN, drainableLavaStack, true), true);
+ }
+
+ /**
+ * Processes cooled Lava into Obsidian
+ *
+ * @return success | failure when cannot output
+ */
+ private boolean lavaToObsidian() {
+ if (this.mCooledLava >= 1000) {
+ if (getBaseMetaTileEntity().addStackToSlot(3, new ItemStack(Blocks.obsidian, 1))) {
+ this.mCooledLava -= 1000;
+ } else {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Draws random flames and smoke particles in front of this Lava Boiler when it is active
+ *
+ * @param aBaseMetaTileEntity The entity that will handle the {@link Block#randomDisplayTick}
+ */
+ @SideOnly(Side.CLIENT)
+ @Override
+ public void onRandomDisplayTick(IGregTechTileEntity aBaseMetaTileEntity) {
+ if (aBaseMetaTileEntity.isActive()) {
+
+ final ForgeDirection frontFacing = aBaseMetaTileEntity.getFrontFacing();
+
+ if ((frontFacing.flag & (ForgeDirection.UP.flag | ForgeDirection.DOWN.flag)) == 0
+ && aBaseMetaTileEntity.getCoverIDAtSide(frontFacing) == 0
+ && !aBaseMetaTileEntity.getOpacityAtSide(frontFacing)) {
+
+ final double oX = aBaseMetaTileEntity.getOffsetX(frontFacing, 1) + 8D / 16D;
+ final double oY = aBaseMetaTileEntity.getOffsetY(frontFacing, 1);
+ final double oZ = aBaseMetaTileEntity.getOffsetZ(frontFacing, 1) + 8D / 16D;
+ final double offset = -0.48D;
+ final double horizontal = XSTR_INSTANCE.nextFloat() * 10D / 16D - 5D / 16D;
+
+ final double x, y, z;
+
+ y = oY + XSTR_INSTANCE.nextFloat() * 6D / 16D;
+
+ switch (frontFacing) {
+ case WEST -> {
+ x = oX - offset;
+ z = oZ + horizontal;
+ }
+ case EAST -> {
+ x = oX + offset;
+ z = oZ + horizontal;
+ }
+ case NORTH -> {
+ x = oX + horizontal;
+ z = oZ - offset;
+ }
+ default -> { // case SOUTH:
+ x = oX + horizontal;
+ z = oZ + offset;
+ }
+ }
+
+ ParticleEventBuilder particleEventBuilder = (new ParticleEventBuilder()).setMotion(0D, 0D, 0D)
+ .setPosition(x, y, z)
+ .setWorld(getBaseMetaTileEntity().getWorld());
+ particleEventBuilder.setIdentifier(ParticleFX.SMOKE)
+ .run();
+ particleEventBuilder.setIdentifier(ParticleFX.FLAME)
+ .run();
+ }
+ }
+ }
+
+ @Override
+ public boolean isFluidInputAllowed(FluidStack aFluid) {
+ return GT_ModHandler.isWater(aFluid) || GT_ModHandler.isLava(aFluid);
+ }
+
+ @Override
+ public void onPreTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ if (!aBaseMetaTileEntity.isServerSide()) return;
+ final FluidStack containedFluidStack = GT_Utility.getFluidForFilledItem(mInventory[getInputSlot()], true);
+ if (GT_ModHandler.isWater(containedFluidStack)) super.onPreTick(aBaseMetaTileEntity, aTick);
+ if (GT_ModHandler.isLava(containedFluidStack)
+ && lavaTank.fill(containedFluidStack, false) == containedFluidStack.amount
+ && aBaseMetaTileEntity.addStackToSlot(
+ getOutputSlot(),
+ GT_Utility.getContainerForFilledItem(mInventory[getInputSlot()], true),
+ 1)) {
+ lavaTank.fill(containedFluidStack, true);
+ aBaseMetaTileEntity.decrStackSize(getInputSlot(), 1);
+ }
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ if (aTick % 20 == 0) drainLava(aBaseMetaTileEntity);
+ super.onPostTick(aBaseMetaTileEntity, aTick);
+ }
+
+ @Override
+ public boolean allowPullStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return true;
+ }
+
+ @Override
+ public boolean allowPutStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return true;
+ }
+
+ @Override
+ public void doSound(byte aIndex, double aX, double aY, double aZ) {
+ if (aIndex != GT_MetaTileEntity_Boiler.SOUND_EVENT_LET_OFF_EXCESS_STEAM) return;
+
+ final ForgeDirection rearDirection = getBaseMetaTileEntity().getFrontFacing()
+ .getOpposite();
+ GT_Utility.doSoundAtClient(
+ SoundResource.RANDOM_FIZZ,
+ 2,
+ 1.0F,
+ // Sound emitted from center of rear face (Steam Output)
+ aX + 0.5 * rearDirection.offsetX,
+ aY,
+ aZ + 0.5 * rearDirection.offsetZ);
+
+ new ParticleEventBuilder().setIdentifier(ParticleFX.CLOUD)
+ .setWorld(getBaseMetaTileEntity().getWorld())
+ // Particles emitted with a 1 block/s velocity toward rear
+ .setMotion(rearDirection.offsetX / 20D, 0D, rearDirection.offsetZ / 20D)
+ .<ParticleEventBuilder>times(
+ 8,
+ // Particles emitted from center of rear face (Steam Output)
+ x -> x.setPosition(aX + rearDirection.offsetX / 2D, aY, aZ + rearDirection.offsetZ / 2D)
+ .run());
+ }
+
+ @Override
+ protected void updateFuel(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ if (!lavaToObsidian()) return;
+ if (lavaTank.getFluid() == null || lavaTank.getFluid().amount <= 0) return;
+ final int amountToDrain = Math.min(lavaTank.getFluid().amount, 1000);
+ final FluidStack drainedLava = lavaTank.drain(amountToDrain, false);
+ if (drainedLava == null || drainedLava.amount == 0) return;
+ lavaTank.drain(amountToDrain, true);
+ this.mProcessingEnergy += drainedLava.amount * ENERGY_PER_LAVA;
+ }
+
+ @Override
+ public SteamVariant getSteamVariant() {
+ return SteamVariant.STEEL;
+ }
+
+ @Override
+ public int fill(FluidStack aFluid, boolean doFill) {
+ if (GT_ModHandler.isWater(aFluid)) return super.fill(aFluid, doFill);
+ if (GT_ModHandler.isLava(aFluid)) return lavaTank.fill(aFluid, doFill);
+ return 0;
+ }
+
+ @Override
+ public FluidTankInfo[] getTankInfo(ForgeDirection side) {
+ return new FluidTankInfo[] { super.getTankInfo(side)[0],
+ new FluidTankInfo(this.lavaTank.getFluid(), this.lavaTank.getCapacity()),
+ new FluidTankInfo(getDrainableStack(), getSteamCapacity()) };
+ }
+
+ @Override
+ protected IDrawable[] getAshSlotBackground() {
+ return new IDrawable[] { getGUITextureSet().getItemSlot(),
+ GT_UITextures.OVERLAY_SLOT_BLOCK_STEAM.get(getSteamVariant()) };
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ builder.widget(
+ new SlotWidget(inventoryHandler, 0).setPos(43, 25)
+ .setBackground(getGUITextureSet().getItemSlot(), getOverlaySlotIn()))
+ .widget(
+ new SlotWidget(inventoryHandler, 1).setAccess(true, false)
+ .setPos(43, 61)
+ .setBackground(getGUITextureSet().getItemSlot(), getOverlaySlotOut()))
+ .widget(
+ new FluidSlotWidget(lavaTank).setBackground(getGUITextureSet().getFluidSlot(), getOverlaySlotIn())
+ .setPos(115, 61))
+ .widget(createAshSlot())
+ .widget(
+ new ProgressBar().setProgress(() -> mSteam == null ? 0 : (float) mSteam.amount / getSteamCapacity())
+ .setTexture(getProgressbarEmpty(), GT_UITextures.PROGRESSBAR_BOILER_STEAM, 10)
+ .setDirection(ProgressBar.Direction.UP)
+ .setPos(70, 25)
+ .setSize(10, 54))
+ .widget(
+ new ProgressBar().setProgress(() -> mFluid == null ? 0 : (float) mFluid.amount / getCapacity())
+ .setTexture(getProgressbarEmpty(), GT_UITextures.PROGRESSBAR_BOILER_WATER, 10)
+ .setDirection(ProgressBar.Direction.UP)
+ .setPos(83, 25)
+ .setSize(10, 54))
+ .widget(
+ new ProgressBar().setProgress(() -> (float) mTemperature / maxProgresstime())
+ .setTexture(getProgressbarEmpty(), GT_UITextures.PROGRESSBAR_BOILER_HEAT, 10)
+ .setDirection(ProgressBar.Direction.UP)
+ .setPos(96, 25)
+ .setSize(10, 54))
+ .widget(
+ new ProgressBar()
+ // cap minimum so that one can easily see there's fuel remaining
+ .setProgress(() -> mProcessingEnergy > 0 ? Math.max((float) mProcessingEnergy / 1000, 1f / 5) : 0)
+ .setTexture(getProgressbarFuel(), 14)
+ .setDirection(ProgressBar.Direction.UP)
+ .setPos(116, 45)
+ .setSize(14, 14))
+ .widget(
+ new DrawableWidget().setDrawable(getOverlaySlotCanister())
+ .setPos(43, 43)
+ .setSize(18, 18));
+ }
+
+ static class LavaTank extends FluidTank {
+
+ public LavaTank(FluidStack stack, int capacity) {
+ super(stack, capacity);
+ }
+
+ @Override
+ public int fill(FluidStack resource, boolean doFill) {
+ return GT_ModHandler.isLava(resource) ? super.fill(resource, doFill) : 0;
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/boilers/GT_MetaTileEntity_Boiler_Solar.java b/src/main/java/gregtech/common/tileentities/boilers/GT_MetaTileEntity_Boiler_Solar.java
new file mode 100644
index 0000000000..f5c59330ed
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/boilers/GT_MetaTileEntity_Boiler_Solar.java
@@ -0,0 +1,381 @@
+package gregtech.common.tileentities.boilers;
+
+import static gregtech.api.GregTech_API.sMachineFile;
+import static gregtech.api.enums.ConfigCategories.machineconfig;
+import static mcp.mobius.waila.api.SpecialChars.GOLD;
+import static mcp.mobius.waila.api.SpecialChars.RESET;
+
+import java.util.List;
+
+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.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.gtnewhorizons.modularui.api.drawable.IDrawable;
+import com.gtnewhorizons.modularui.common.widget.SlotWidget;
+
+import gregtech.api.enums.Dyes;
+import gregtech.api.enums.SteamVariant;
+import gregtech.api.enums.Textures.BlockIcons;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_LanguageManager;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_Utility;
+import mcp.mobius.waila.api.IWailaConfigHandler;
+import mcp.mobius.waila.api.IWailaDataAccessor;
+
+public class GT_MetaTileEntity_Boiler_Solar extends GT_MetaTileEntity_Boiler {
+
+ public static final String LPS_FMT = "%s L/s";
+ private static final String localizedDescFormat = GT_LanguageManager.addStringLocalization(
+ "gt.blockmachines.boiler.solar.desc.format",
+ "Steam Power by the Sun%n" + "Produces %sL of Steam per second%n"
+ + "Calcifies over time, reducing Steam output to %sL/s%n"
+ + "Break and replace to descale");
+ protected final Config mConfig;
+ protected final int basicTemperatureMod = 5; // Base Celsius gain or loss
+ private int mRunTimeTicks = 0;
+
+ public GT_MetaTileEntity_Boiler_Solar(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional, new String[0]);
+ mConfig = createConfig();
+ }
+
+ public GT_MetaTileEntity_Boiler_Solar(String aName, int aTier, String aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ mConfig = createConfig();
+ }
+
+ public GT_MetaTileEntity_Boiler_Solar(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ mConfig = createConfig();
+ }
+
+ protected GT_MetaTileEntity_Boiler_Solar(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures,
+ Config aConfig) {
+ super(aName, aTier, aDescription, aTextures);
+ mConfig = aConfig;
+ }
+
+ protected Config createConfig() {
+ return new Config(machineconfig + ".boiler.solar.bronze", 1080000, 40, 120, 45);
+ }
+
+ public int getMaxOutputPerSecond() {
+ return mConfig.getMaxOutputPerSecond();
+ }
+
+ @Override
+ public String[] getDescription() {
+ return String
+ .format(
+ localizedDescFormat,
+ GT_Utility.formatNumbers(getMaxOutputPerSecond()),
+ GT_Utility.formatNumbers(getMinOutputPerSecond()))
+ .split("\\R");
+ }
+
+ public int getMinOutputPerSecond() {
+ return mConfig.getMinOutputPerSecond();
+ }
+
+ @Override
+ public ITexture[][][] getTextureSet(ITexture[] aTextures) {
+ ITexture[][][] rTextures = new ITexture[4][17][];
+ for (int color = -1; color < 16; color++) {
+ int i = color + 1;
+ short[] colorModulation = Dyes.getModulation(color, Dyes._NULL.mRGBa);
+ rTextures[0][i] = new ITexture[] {
+ TextureFactory.of(BlockIcons.MACHINE_BRONZEBRICKS_BOTTOM, colorModulation) };
+ rTextures[1][i] = new ITexture[] { TextureFactory.of(BlockIcons.MACHINE_BRONZEBRICKS_TOP, colorModulation),
+ TextureFactory.of(BlockIcons.BOILER_SOLAR) };
+ rTextures[2][i] = new ITexture[] {
+ TextureFactory.of(BlockIcons.MACHINE_BRONZEBRICKS_SIDE, colorModulation) };
+ rTextures[3][i] = new ITexture[] { TextureFactory.of(BlockIcons.MACHINE_BRONZEBRICKS_SIDE, colorModulation),
+ TextureFactory.of(BlockIcons.OVERLAY_PIPE) };
+ }
+ return rTextures;
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity baseMetaTileEntity, ForgeDirection sideDirection,
+ ForgeDirection facingDirection, int colorIndex, boolean active, boolean redstoneLevel) {
+ final int i = colorIndex + 1;
+ if ((sideDirection.flag & (ForgeDirection.UP.flag | ForgeDirection.DOWN.flag)) == 0) { // Horizontal
+ if (sideDirection != facingDirection) return mTextures[2][i];
+ return mTextures[3][i];
+ }
+ return mTextures[sideDirection.ordinal()][i];
+ }
+
+ @Override
+ public int maxProgresstime() {
+ return 500;
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ aNBT.setInteger("mRunTime", mRunTimeTicks);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ mRunTimeTicks = aNBT.getInteger("mRunTime");
+ }
+
+ @Override
+ protected void produceSteam(int aAmount) {
+ super.produceSteam(aAmount);
+ // Disable calcification when using distilled water
+ if (mFluid.isFluidEqual(GT_ModHandler.getWater(1))) {
+ // produceSteam is getting called every 10 ticks
+ if (mRunTimeTicks >= 0 && mRunTimeTicks < (Integer.MAX_VALUE - 10)) mRunTimeTicks += 10;
+ else mRunTimeTicks = Integer.MAX_VALUE; // Prevent Integer overflow wrap
+ }
+ }
+
+ @Override
+ protected void pushSteamToInventories(IGregTechTileEntity aBaseMetaTileEntity) {
+ if (mSteam == null || mSteam.amount == 0) return;
+ pushSteamToSide(aBaseMetaTileEntity, aBaseMetaTileEntity.getFrontFacing());
+ }
+
+ @Override
+ protected int getPollution() {
+ return 0;
+ }
+
+ @Override
+ public int getProductionPerSecond() {
+ if (mTemperature < 100) {
+ return 0;
+ }
+ if (mRunTimeTicks > mConfig.getMaxRuntimeTicks()) {
+ return mConfig.getMinOutputPerSecond();
+ } else if (mRunTimeTicks > mConfig.getCalcificationTicks()) {
+ /*
+ * When reaching calcification ticks; discount the proportion of run-time spent on calcification from the
+ * maximum output per second, and return this or the minimum output per second
+ */
+ return mConfig.getMaxOutputPerSecond()
+ - mConfig.getMaxOutputPerSecond() * (mRunTimeTicks - mConfig.getCalcificationTicks())
+ / mConfig.getCalcificationTicks();
+ } else {
+ return mConfig.getMaxOutputPerSecond();
+ }
+ }
+
+ @Override
+ protected int getMaxTemperature() {
+ return 500;
+ }
+
+ @Override
+ protected int getEnergyConsumption() {
+ return basicTemperatureMod;
+ }
+
+ @Override
+ protected int getCooldownInterval() {
+ return mConfig.getCoolDownTicks() / basicTemperatureMod;
+ }
+
+ @Override
+ protected int getHeatUpAmount() {
+ return basicTemperatureMod;
+ }
+
+ @Override
+ protected void updateFuel(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ World world = aBaseMetaTileEntity.getWorld();
+ // Heat-up every 12s (240 ticks), has to be multiple of 20 ticks
+ if ((aTick % 240L != 0L) || (world.isThundering())) {
+ return;
+ }
+ if (!aBaseMetaTileEntity.getSkyAtSide(ForgeDirection.UP)) {
+ return;
+ }
+ boolean weatherClear = !world.isRaining() || aBaseMetaTileEntity.getBiome().rainfall == 0.0F;
+ if (!weatherClear && world.skylightSubtracted >= 4) {
+ return;
+ }
+ if (weatherClear) {
+ if (world.isDaytime()) {
+ mProcessingEnergy += 8 * basicTemperatureMod;
+ } else {
+ mProcessingEnergy += basicTemperatureMod;
+ }
+ } else {
+ mProcessingEnergy += basicTemperatureMod;
+ }
+ }
+
+ @Override
+ public SteamVariant getSteamVariant() {
+ return SteamVariant.BRONZE;
+ }
+
+ @Override
+ public boolean isGivingInformation() {
+ return true;
+ }
+
+ @Override
+ public String[] getInfoData() {
+ return String
+ .format(
+ "Heat Capacity: " + EnumChatFormatting.GREEN
+ + "%s %%"
+ + EnumChatFormatting.RESET
+ + " Hot time: "
+ + EnumChatFormatting.RED
+ + "%s s"
+ + EnumChatFormatting.RESET
+ + "%n"
+ + "Min output: "
+ + EnumChatFormatting.RED
+ + LPS_FMT
+ + EnumChatFormatting.RESET
+ + " Max output: "
+ + EnumChatFormatting.RED
+ + LPS_FMT
+ + EnumChatFormatting.RESET
+ + "%n"
+ + "Current Output: "
+ + EnumChatFormatting.YELLOW
+ + LPS_FMT
+ + EnumChatFormatting.RESET,
+ GT_Utility.formatNumbers(getHeatCapacityPercent()),
+ GT_Utility.formatNumbers(getHotTimeSeconds()),
+ GT_Utility.formatNumbers(getMinOutputPerSecond()),
+ GT_Utility.formatNumbers(getMaxOutputPerSecond()),
+ GT_Utility.formatNumbers(getProductionPerSecond()))
+ .split("\\R");
+ }
+
+ public int getHeatCapacityPercent() {
+ return mTemperature * 100 / maxProgresstime();
+ }
+
+ public int getHotTimeSeconds() {
+ return mRunTimeTicks / 20;
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Boiler_Solar(mName, mTier, mDescriptionArray, mTextures, mConfig);
+ }
+
+ @Override
+ protected IDrawable[] getFuelSlotBackground() {
+ return new IDrawable[] { GT_UITextures.TRANSPARENT };
+ }
+
+ @Override
+ protected IDrawable[] getAshSlotBackground() {
+ return new IDrawable[] { GT_UITextures.TRANSPARENT };
+ }
+
+ @Override
+ protected SlotWidget createFuelSlot() {
+ // todo: remove this slot after some time
+ return super.createFuelSlot().setAccess(true, false);
+ }
+
+ @Override
+ protected SlotWidget createAshSlot() {
+ // todo: remove this slot after some time
+ return super.createAshSlot().setAccess(true, false);
+ }
+
+ @Override
+ public void getWailaBody(ItemStack itemStack, List<String> currentTip, IWailaDataAccessor accessor,
+ IWailaConfigHandler config) {
+ final NBTTagCompound tag = accessor.getNBTData();
+ currentTip.add(
+ String.format(
+ (GOLD + "Solar Boiler Output: " + RESET + "%d/%d L/s"),
+ tag.getInteger("calcificationOutput"),
+ tag.getInteger("maxCalcificationOutput")));
+
+ super.getWailaBody(itemStack, currentTip, accessor, config);
+ }
+
+ @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("calcificationOutput", (getProductionPerSecond()));
+ tag.setInteger("maxCalcificationOutput", (getMaxOutputPerSecond()));
+ }
+
+ protected static class Config {
+
+ private final int calcificationTicks;
+ private final int minOutputPerSecond;
+ private final int maxOutputPerSecond;
+ private final int coolDownTicks;
+ private final int maxRuntimeTicks;
+
+ public Config(String aCategory, int aDefaultCalcificationTicks, int aDefaultMinOutputPerSecond,
+ int aDefaultMaxOutputPerSecond, int aDefaultCoolDownTicks) {
+ calcificationTicks = get(
+ aCategory,
+ "CalcificationTicks",
+ aDefaultCalcificationTicks,
+ "Number of run-time ticks before boiler starts calcification.",
+ "100% calcification and minimal output will be reached at 2 times this.");
+ minOutputPerSecond = get(aCategory, "MinOutputPerSecond", aDefaultMinOutputPerSecond);
+ maxOutputPerSecond = get(aCategory, "MaxOutputPerSecond", aDefaultMaxOutputPerSecond);
+ coolDownTicks = get(
+ aCategory,
+ "CoolDownTicks",
+ aDefaultCoolDownTicks,
+ "Number of ticks it takes to lose 1°C.");
+ // After which min output is reached.
+ maxRuntimeTicks = (getMaxOutputPerSecond() - getMinOutputPerSecond()) * getCalcificationTicks()
+ / getMaxOutputPerSecond() + getCalcificationTicks();
+ }
+
+ protected int get(final String aCategory, final String aKey, final int aDefaultValue,
+ final String... aComments) {
+ final StringBuilder tCommentBuilder = new StringBuilder();
+ for (String tComment : aComments) tCommentBuilder.append(tComment)
+ .append('\n');
+ tCommentBuilder.append("Default: ")
+ .append(aDefaultValue);
+ return sMachineFile.mConfig.get(aCategory, aKey, aDefaultValue, tCommentBuilder.toString())
+ .getInt();
+ }
+
+ public int getCalcificationTicks() {
+ return calcificationTicks;
+ }
+
+ public int getMinOutputPerSecond() {
+ return minOutputPerSecond;
+ }
+
+ public int getMaxOutputPerSecond() {
+ return maxOutputPerSecond;
+ }
+
+ public int getCoolDownTicks() {
+ return coolDownTicks;
+ }
+
+ public int getMaxRuntimeTicks() {
+ return maxRuntimeTicks;
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/boilers/GT_MetaTileEntity_Boiler_Solar_Steel.java b/src/main/java/gregtech/common/tileentities/boilers/GT_MetaTileEntity_Boiler_Solar_Steel.java
new file mode 100644
index 0000000000..c20ea4018a
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/boilers/GT_MetaTileEntity_Boiler_Solar_Steel.java
@@ -0,0 +1,77 @@
+package gregtech.common.tileentities.boilers;
+
+import static gregtech.api.enums.ConfigCategories.machineconfig;
+
+import gregtech.api.enums.Dyes;
+import gregtech.api.enums.SteamVariant;
+import gregtech.api.enums.Textures.BlockIcons;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.render.TextureFactory;
+
+public class GT_MetaTileEntity_Boiler_Solar_Steel extends GT_MetaTileEntity_Boiler_Solar {
+
+ public GT_MetaTileEntity_Boiler_Solar_Steel(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_Boiler_Solar_Steel(String aName, int aTier, String aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_Boiler_Solar_Steel(String aName, int aTier, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_Boiler_Solar_Steel(String aName, int aTier, String[] aDescription,
+ ITexture[][][] aTextures, Config aConfig) {
+ super(aName, aTier, aDescription, aTextures, aConfig);
+ }
+
+ @Override
+ protected Config createConfig() {
+ return new Config(machineconfig + ".boiler.solar.steel", 1080000, 120, 360, 75);
+ }
+
+ @Override
+ public ITexture[][][] getTextureSet(ITexture[] aTextures) {
+
+ ITexture[][][] rTextures = new ITexture[4][17][];
+ for (int color = -1; color < 16; color++) {
+ int i = color + 1;
+ short[] colorModulation = Dyes.getModulation(color, Dyes._NULL.mRGBa);
+ rTextures[0][i] = new ITexture[] {
+ TextureFactory.of(BlockIcons.MACHINE_STEELBRICKS_BOTTOM, colorModulation) };
+ rTextures[1][i] = new ITexture[] { TextureFactory.of(BlockIcons.MACHINE_STEELBRICKS_TOP, colorModulation),
+ TextureFactory.of(BlockIcons.BOILER_SOLAR) };
+ rTextures[2][i] = new ITexture[] {
+ TextureFactory.of(BlockIcons.MACHINE_STEELBRICKS_SIDE, colorModulation) };
+ rTextures[3][i] = new ITexture[] { TextureFactory.of(BlockIcons.MACHINE_STEELBRICKS_SIDE, colorModulation),
+ TextureFactory.of(BlockIcons.OVERLAY_PIPE) };
+ }
+ return rTextures;
+ }
+
+ @Override
+ public int getCapacity() {
+ return 32000;
+ }
+
+ @Override
+ public SteamVariant getSteamVariant() {
+ return SteamVariant.STEEL;
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Boiler_Solar_Steel(
+ this.mName,
+ this.mTier,
+ this.mDescriptionArray,
+ this.mTextures,
+ this.mConfig);
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/boilers/GT_MetaTileEntity_Boiler_Steel.java b/src/main/java/gregtech/common/tileentities/boilers/GT_MetaTileEntity_Boiler_Steel.java
new file mode 100644
index 0000000000..12374c3313
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/boilers/GT_MetaTileEntity_Boiler_Steel.java
@@ -0,0 +1,108 @@
+package gregtech.common.tileentities.boilers;
+
+import static gregtech.api.enums.Textures.BlockIcons.BOILER_FRONT;
+import static gregtech.api.enums.Textures.BlockIcons.BOILER_FRONT_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.BOILER_FRONT_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.BOILER_FRONT_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_STEELBRICKS_BOTTOM;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_STEELBRICKS_SIDE;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_STEELBRICKS_TOP;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_PIPE;
+
+import gregtech.GT_Mod;
+import gregtech.api.enums.SteamVariant;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.render.TextureFactory;
+
+public class GT_MetaTileEntity_Boiler_Steel extends GT_MetaTileEntity_Boiler_Bronze {
+
+ public GT_MetaTileEntity_Boiler_Steel(int aID, String aName, String aNameRegional) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ new String[] { "Faster than the Bronze Boiler", "Produces 300L of Steam per second",
+ "Causes " + GT_Mod.gregtechproxy.mPollutionHighPressureCoalBoilerPerSecond + " Pollution per second" });
+ }
+
+ public GT_MetaTileEntity_Boiler_Steel(String aName, int aTier, String aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_Boiler_Steel(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ }
+
+ @Override
+ public ITexture[][][] getTextureSet(ITexture[] aTextures) {
+ ITexture[][][] rTextures = new ITexture[5][17][];
+ final ITexture[] texBottom = { TextureFactory.of(MACHINE_STEELBRICKS_BOTTOM) },
+ texTop = { TextureFactory.of(MACHINE_STEELBRICKS_TOP), TextureFactory.of(OVERLAY_PIPE) },
+ texSide = { TextureFactory.of(MACHINE_STEELBRICKS_SIDE), TextureFactory.of(OVERLAY_PIPE) },
+ texFront = { TextureFactory.of(MACHINE_STEELBRICKS_SIDE), TextureFactory.of(BOILER_FRONT),
+ TextureFactory.builder()
+ .addIcon(BOILER_FRONT_GLOW)
+ .glow()
+ .build() },
+ texFrontActive = { TextureFactory.of(MACHINE_STEELBRICKS_SIDE), TextureFactory.of(BOILER_FRONT_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(BOILER_FRONT_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ for (int i = 0; i < 17; i++) {
+ rTextures[0][i] = texBottom;
+ rTextures[1][i] = texTop;
+ rTextures[2][i] = texSide;
+ rTextures[3][i] = texFront;
+ rTextures[4][i] = texFrontActive;
+ }
+ return rTextures;
+ }
+
+ @Override
+ public int maxProgresstime() {
+ return 1000;
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Boiler_Steel(this.mName, this.mTier, this.mDescriptionArray, this.mTextures);
+ }
+
+ @Override
+ protected int getPollution() {
+ return GT_Mod.gregtechproxy.mPollutionHighPressureCoalBoilerPerSecond;
+ }
+
+ @Override
+ public int getCapacity() {
+ return 32000;
+ }
+
+ @Override
+ protected int getProductionPerSecond() {
+ return 300;
+ }
+
+ @Override
+ protected int getMaxTemperature() {
+ return 1000;
+ }
+
+ @Override
+ protected int getEnergyConsumption() {
+ return 2;
+ }
+
+ @Override
+ protected int getCooldownInterval() {
+ return 40;
+ }
+
+ @Override
+ public SteamVariant getSteamVariant() {
+ return SteamVariant.STEEL;
+ }
+}
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/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/Ampere.java b/src/main/java/gregtech/common/tileentities/casings/upgrade/Ampere.java
new file mode 100644
index 0000000000..1644f8fde0
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/casings/upgrade/Ampere.java
@@ -0,0 +1,47 @@
+package gregtech.common.tileentities.casings.upgrade;
+
+import java.util.List;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+
+import gregtech.api.enums.GT_Values;
+import gregtech.api.multitileentity.interfaces.IMultiBlockController;
+import gregtech.api.multitileentity.multiblock.casing.UpgradeCasing;
+import gregtech.api.util.GT_Utility;
+
+public class Ampere extends UpgradeCasing {
+
+ private long amperage;
+
+ @Override
+ public String getTileEntityName() {
+ return "gt.multitileentity.multiblock.functional.amperage";
+ }
+
+ @Override
+ public void readMultiTileNBT(NBTTagCompound aNBT) {
+ super.readMultiTileNBT(aNBT);
+ amperage = aNBT.getInteger(GT_Values.NBT.UPGRADE_AMPERAGE);
+ }
+
+ @Override
+ protected void customWork(IMultiBlockController target) {
+ target.setMaxAmperage(amperage);
+ }
+
+ @Override
+ public boolean breakBlock() {
+ final IMultiBlockController controller = getTarget(false);
+ if (controller != null) {
+ controller.setMaxAmperage(2);
+ }
+ return super.breakBlock();
+ }
+
+ @Override
+ public void addToolTips(List<String> list, ItemStack stack, boolean f3_h) {
+ super.addToolTips(list, stack, f3_h);
+ list.add("Increases allowed amperage to " + GT_Utility.formatNumbers(amperage));
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/casings/upgrade/Cleanroom.java b/src/main/java/gregtech/common/tileentities/casings/upgrade/Cleanroom.java
new file mode 100644
index 0000000000..641327b427
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/casings/upgrade/Cleanroom.java
@@ -0,0 +1,26 @@
+package gregtech.common.tileentities.casings.upgrade;
+
+import gregtech.api.multitileentity.interfaces.IMultiBlockController;
+import gregtech.api.multitileentity.multiblock.casing.UpgradeCasing;
+
+public class Cleanroom extends UpgradeCasing {
+
+ @Override
+ public String getTileEntityName() {
+ return "gt.multitileentity.multiblock.functional.cleanroom";
+ }
+
+ @Override
+ protected void customWork(IMultiBlockController target) {
+ target.setCleanroom(true);
+ }
+
+ @Override
+ public boolean breakBlock() {
+ final IMultiBlockController controller = getTarget(false);
+ if (controller != null) {
+ controller.setCleanroom(false);
+ }
+ return super.breakBlock();
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/casings/upgrade/Heater.java b/src/main/java/gregtech/common/tileentities/casings/upgrade/Heater.java
new file mode 100644
index 0000000000..6d8bd81d0f
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/casings/upgrade/Heater.java
@@ -0,0 +1,21 @@
+package gregtech.common.tileentities.casings.upgrade;
+
+import gregtech.api.multitileentity.interfaces.IMultiBlockController;
+import gregtech.api.multitileentity.interfaces.UpgradableModularMuTE;
+import gregtech.api.multitileentity.multiblock.casing.UpgradeCasing;
+import gregtech.api.util.GT_StructureUtilityMuTE.UpgradeCasings;
+
+public class Heater extends UpgradeCasing {
+
+ @Override
+ public String getTileEntityName() {
+ return "gt.multitileentity.multiblock.modular.heater";
+ }
+
+ @Override
+ protected void customWork(IMultiBlockController target) {
+ if (target instanceof UpgradableModularMuTE upgradable) {
+ upgradable.increaseMucCount(UpgradeCasings.Heater, this.tier);
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/casings/upgrade/Insulator.java b/src/main/java/gregtech/common/tileentities/casings/upgrade/Insulator.java
new file mode 100644
index 0000000000..6cb0b630d6
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/casings/upgrade/Insulator.java
@@ -0,0 +1,22 @@
+package gregtech.common.tileentities.casings.upgrade;
+
+import gregtech.api.multitileentity.interfaces.IMultiBlockController;
+import gregtech.api.multitileentity.interfaces.UpgradableModularMuTE;
+import gregtech.api.multitileentity.multiblock.casing.UpgradeCasing;
+import gregtech.api.util.GT_StructureUtilityMuTE.UpgradeCasings;
+
+public class Insulator extends UpgradeCasing {
+
+ @Override
+ public String getTileEntityName() {
+ return "gt.multitileentity.multiblock.modular.insulator";
+ }
+
+ @Override
+ protected void customWork(IMultiBlockController target) {
+ if (target instanceof UpgradableModularMuTE upgradable) {
+ upgradable.increaseMucCount(UpgradeCasings.Insulator, this.tier);
+ }
+ }
+
+}
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..31294c7002
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/casings/upgrade/Inventory.java
@@ -0,0 +1,123 @@
+package gregtech.common.tileentities.casings.upgrade;
+
+import java.util.List;
+import java.util.UUID;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraftforge.common.util.ForgeDirection;
+
+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.enums.InventoryType;
+import gregtech.api.multitileentity.interfaces.IMultiBlockController;
+import gregtech.api.multitileentity.multiblock.casing.UpgradeCasing;
+
+public class Inventory extends UpgradeCasing {
+
+ public UUID inventoryID;
+
+ private String inventoryName = "inventory";
+ private int inventorySize;
+ private InventoryType type = InventoryType.Both;
+
+ public String getCustomInventoryName() {
+ return inventoryName;
+ }
+
+ public String getInventoryID() {
+ return inventoryID.toString();
+ }
+
+ public void setInventoryName(String aInventoryName) {
+ inventoryName = aInventoryName;
+ }
+
+ public InventoryType getType() {
+ return type;
+ }
+
+ @Override
+ protected void customWork(IMultiBlockController target) {
+ int invSize = inventorySize;
+ if (type == InventoryType.Both) {
+ invSize /= 2;
+ }
+ target.registerItemInventory(invSize, tier, type, true);
+ if (isServerSide()) {
+ issueClientUpdate();
+ }
+ }
+
+ @Override
+ public String getTileEntityName() {
+ return "gt.multitileentity.multiblock.inventory";
+ }
+
+ @Override
+ public void readMultiTileNBT(NBTTagCompound aNBT) {
+ super.readMultiTileNBT(aNBT);
+ if (aNBT.hasKey(NBT.UPGRADE_INVENTORY_NAME)) {
+ inventoryName = aNBT.getString(NBT.UPGRADE_INVENTORY_NAME);
+ } else {
+ inventoryName = "inventory";
+ }
+ inventorySize = aNBT.getInteger(NBT.UPGRADE_INVENTORY_SIZE);
+ }
+
+ @Override
+ public void writeMultiTileNBT(NBTTagCompound aNBT) {
+ super.writeMultiTileNBT(aNBT);
+ aNBT.setString(NBT.UPGRADE_INVENTORY_UUID, inventoryID.toString());
+ aNBT.setString(NBT.UPGRADE_INVENTORY_NAME, inventoryName);
+ }
+
+ @Override
+ public boolean breakBlock() {
+ final IMultiBlockController controller = getTarget(false);
+ if (controller != null) {
+ controller.unregisterItemInventory(inventoryID, type);
+ }
+ return super.breakBlock();
+ }
+
+ @Override
+ public boolean hasGui(ForgeDirection side) {
+ return true;
+ }
+
+ @Override
+ public void addUIWidgets(Builder builder, UIBuildContext buildContext) {
+ builder.widget(
+ new TextFieldWidget().setGetter(() -> inventoryName)
+ .setSetter((val) -> {
+ inventoryName = val;
+ final IMultiBlockController controller = getTarget(false);
+ if (controller != null) {
+ controller.changeItemInventoryDisplayName(inventoryID, inventoryName, type);
+ }
+ })
+ .setSize(100, 25)
+ .setPos(50, 30));
+ }
+
+ @Override
+ protected boolean canOpenControllerGui() {
+ return false;
+ }
+
+ @Override
+ public void addToolTips(List<String> list, ItemStack stack, boolean f3_h) {
+ super.addToolTips(list, stack, f3_h);
+ list.add("Adds another item inventory");
+ list.add("Inventory size: " + inventorySize);
+ list.add("Inventory Type: " + type);
+ }
+
+ public void setInventoryId(String inventoryID) {
+ this.inventoryID = UUID.fromString(inventoryID);
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/casings/upgrade/Laser.java b/src/main/java/gregtech/common/tileentities/casings/upgrade/Laser.java
new file mode 100644
index 0000000000..ab66281f54
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/casings/upgrade/Laser.java
@@ -0,0 +1,26 @@
+package gregtech.common.tileentities.casings.upgrade;
+
+import gregtech.api.multitileentity.interfaces.IMultiBlockController;
+import gregtech.api.multitileentity.multiblock.casing.UpgradeCasing;
+
+public class Laser extends UpgradeCasing {
+
+ @Override
+ public String getTileEntityName() {
+ return "gt.multitileentity.multiblock.functional.laser";
+ }
+
+ @Override
+ protected void customWork(IMultiBlockController target) {
+ target.setLaserSupport(true);
+ }
+
+ @Override
+ public boolean breakBlock() {
+ final IMultiBlockController controller = getTarget(false);
+ if (controller != null) {
+ controller.setLaserSupport(false);
+ }
+ return super.breakBlock();
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/casings/upgrade/Tank.java b/src/main/java/gregtech/common/tileentities/casings/upgrade/Tank.java
new file mode 100644
index 0000000000..ebc84be38a
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/casings/upgrade/Tank.java
@@ -0,0 +1,61 @@
+package gregtech.common.tileentities.casings.upgrade;
+
+import java.util.List;
+import java.util.UUID;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+
+import gregtech.api.enums.GT_Values;
+import gregtech.api.multitileentity.interfaces.IMultiBlockController;
+import gregtech.api.multitileentity.multiblock.casing.UpgradeCasing;
+import gregtech.api.util.GT_Utility;
+
+public class Tank extends UpgradeCasing {
+
+ private int tankCount;
+ private int tankCapacity;
+ public UUID tankID;
+ public static final int INPUT = 0;
+ public static final int OUTPUT = 1;
+ public static final int BOTH = 2;
+ private String tankName = "tank";
+ private int type = BOTH;
+
+ @Override
+ protected void customWork(IMultiBlockController aTarget) {
+
+ }
+
+ @Override
+ public String getTileEntityName() {
+ return "gt.multitileentity.multiblock.tank";
+ }
+
+ public String getCustomTankName() {
+ return tankName;
+ }
+
+ public String getTankID() {
+ return tankID.toString();
+ }
+
+ public int getType() {
+ return type;
+ }
+
+ @Override
+ public void readMultiTileNBT(NBTTagCompound aNBT) {
+ super.readMultiTileNBT(aNBT);
+ tankCount = aNBT.getInteger(GT_Values.NBT.UPGRADE_TANK_COUNT);
+ tankCapacity = aNBT.getInteger(GT_Values.NBT.UPGRADE_TANK_CAPACITY);
+ }
+
+ @Override
+ public void addToolTips(List<String> list, ItemStack stack, boolean f3_h) {
+ super.addToolTips(list, stack, f3_h);
+ list.add("Adds another tank inventory");
+ list.add("Number of tanks: " + tankCount);
+ list.add("Tank capacity: " + GT_Utility.formatNumbers(tankCapacity) + " L");
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/casings/upgrade/Wireless.java b/src/main/java/gregtech/common/tileentities/casings/upgrade/Wireless.java
new file mode 100644
index 0000000000..0cb6a595bf
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/casings/upgrade/Wireless.java
@@ -0,0 +1,26 @@
+package gregtech.common.tileentities.casings.upgrade;
+
+import gregtech.api.multitileentity.interfaces.IMultiBlockController;
+import gregtech.api.multitileentity.multiblock.casing.UpgradeCasing;
+
+public class Wireless extends UpgradeCasing {
+
+ @Override
+ public String getTileEntityName() {
+ return "gt.multitileentity.multiblock.functional.wireless";
+ }
+
+ @Override
+ protected void customWork(IMultiBlockController target) {
+ target.setWirelessSupport(true);
+ }
+
+ @Override
+ public boolean breakBlock() {
+ final IMultiBlockController controller = getTarget(false);
+ if (controller != null) {
+ controller.setWirelessSupport(false);
+ }
+ return super.breakBlock();
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/debug/GT_MetaTileEntity_AdvDebugStructureWriter.java b/src/main/java/gregtech/common/tileentities/debug/GT_MetaTileEntity_AdvDebugStructureWriter.java
new file mode 100644
index 0000000000..f143ec556e
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/debug/GT_MetaTileEntity_AdvDebugStructureWriter.java
@@ -0,0 +1,439 @@
+package gregtech.common.tileentities.debug;
+
+import static gregtech.GT_Mod.GT_FML_LOGGER;
+import static net.minecraft.util.StatCollector.translateToLocal;
+
+import java.util.HashMap;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.entity.EntityPlayerSP;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.ChatComponentTranslation;
+import net.minecraftforge.client.event.RenderWorldLastEvent;
+import net.minecraftforge.common.MinecraftForge;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import org.lwjgl.opengl.GL11;
+
+import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
+import com.gtnewhorizon.structurelib.structure.StructureUtility;
+import com.gtnewhorizon.structurelib.util.Vec3Impl;
+import com.gtnewhorizons.modularui.api.drawable.IDrawable;
+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.CycleButtonWidget;
+import com.gtnewhorizons.modularui.common.widget.DrawableWidget;
+import com.gtnewhorizons.modularui.common.widget.MultiChildWidget;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import cpw.mods.fml.common.eventhandler.SubscribeEvent;
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.api.enums.Textures;
+import gregtech.api.gui.modularui.GT_UIInfos;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.gui.modularui.GUITextureSet;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.modularui.IAddGregtechLogo;
+import gregtech.api.interfaces.modularui.IAddUIWidgets;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_TieredMachineBlock;
+import gregtech.api.render.TextureFactory;
+
+public class GT_MetaTileEntity_AdvDebugStructureWriter extends GT_MetaTileEntity_TieredMachineBlock
+ implements IAddGregtechLogo, IAddUIWidgets {
+
+ private static final HashMap<GT_MetaTileEntity_AdvDebugStructureWriter, BoundHighlighter> bondingBoxes = new HashMap<>(
+ 1);
+ private final BoundHighlighter boundingBox = new BoundHighlighter();
+ private final short[] numbers = new short[6];
+ private boolean transpose = false;
+ private boolean showHighlightBox = true;
+ private String[] result = new String[] { "Undefined" };
+
+ public GT_MetaTileEntity_AdvDebugStructureWriter(int aID, String aName, String aNameRegional, int aTier) {
+ super(aID, aName, aNameRegional, aTier, 0, "");
+ }
+
+ public GT_MetaTileEntity_AdvDebugStructureWriter(String aName, int aTier, String aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, 0, aDescription, aTextures);
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_AdvDebugStructureWriter(mName, mTier, "", mTextures);
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity baseMetaTileEntity, ForgeDirection sideDirection,
+ ForgeDirection facingDirection, int colorIndex, boolean active, boolean redstoneLevel) {
+ return new ITexture[] {
+ Textures.BlockIcons.MACHINE_CASINGS[mTier][colorIndex + 1], sideDirection != facingDirection
+ ? TextureFactory.of(
+ TextureFactory.builder()
+ .addIcon(Textures.BlockIcons.OVERLAY_TELEPORTER_ACTIVE)
+ .glow()
+ .build())
+ : TextureFactory.of(
+ TextureFactory.builder()
+ .addIcon(Textures.BlockIcons.STRUCTURE_MARK)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public ITexture[][][] getTextureSet(ITexture[] aTextures) {
+ return null;
+ }
+
+ @Override
+ public boolean allowPutStack(IGregTechTileEntity iGregTechTileEntity, int i, ForgeDirection b,
+ ItemStack itemStack) {
+ return false;
+ }
+
+ @Override
+ public boolean allowPullStack(IGregTechTileEntity iGregTechTileEntity, int i, ForgeDirection b,
+ ItemStack itemStack) {
+ return false;
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ for (int i = 0; i < numbers.length; i++) {
+ aNBT.setShort("eData" + i, numbers[i]);
+ }
+ aNBT.setBoolean("Transpose", transpose);
+ aNBT.setBoolean("HighlightBox", showHighlightBox);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ for (int i = 0; i < numbers.length; i++) {
+ numbers[i] = aNBT.getShort("eData" + i);
+ }
+ transpose = aNBT.getBoolean("Transpose");
+ showHighlightBox = aNBT.getBoolean("HighlightBox");
+ }
+
+ @Override
+ public boolean isSimpleMachine() {
+ return false;
+ }
+
+ @Override
+ public void onFirstTick(IGregTechTileEntity aBaseMetaTileEntity) {
+ super.onFirstTick(aBaseMetaTileEntity);
+ bondingBoxes.put(this, boundingBox);
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ if (aBaseMetaTileEntity.isServerSide()) {
+ ExtendedFacing writerFacing = ExtendedFacing.of(aBaseMetaTileEntity.getFrontFacing());
+ double[] abc = new double[3];
+ double[] xyz = new double[3];
+ boundingBox.dim = aBaseMetaTileEntity.getWorld().provider.dimensionId;
+ boundingBox.showHighlightBox = showHighlightBox;
+ abc[0] = -numbers[0] - 0.5;
+ abc[1] = -numbers[1] - 0.5;
+ abc[2] = -numbers[2] - 0.5;
+ writerFacing.getWorldOffset(abc, xyz);
+ boundingBox.pos1 = new Vec3Impl(
+ aBaseMetaTileEntity.getXCoord() + (int) (xyz[0] + 0.5),
+ aBaseMetaTileEntity.getYCoord() + (int) (xyz[1] + 0.5),
+ aBaseMetaTileEntity.getZCoord() + (int) (xyz[2] + 0.5));
+ abc[0] = -numbers[0] + numbers[3] - 0.5;
+ abc[1] = -numbers[1] + numbers[4] - 0.5;
+ abc[2] = -numbers[2] + numbers[5] - 0.5;
+ writerFacing.getWorldOffset(abc, xyz);
+ boundingBox.pos2 = new Vec3Impl(
+ aBaseMetaTileEntity.getXCoord() + (int) (xyz[0] + 0.5),
+ aBaseMetaTileEntity.getYCoord() + (int) (xyz[1] + 0.5),
+ aBaseMetaTileEntity.getZCoord() + (int) (xyz[2] + 0.5));
+ }
+ }
+
+ @Override
+ public void onRemoval() {
+ bondingBoxes.remove(this);
+ }
+
+ @Override
+ public void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ IGregTechTileEntity aBaseMetaTileEntity = getBaseMetaTileEntity();
+ printStructure(aPlayer);
+ aBaseMetaTileEntity.disableWorking();
+ }
+
+ public void printStructure(EntityPlayer aPlayer) {
+ IGregTechTileEntity aBaseMetaTileEntity = getBaseMetaTileEntity();
+ String pseudoJavaCode = StructureUtility.getPseudoJavaCode(
+ aBaseMetaTileEntity.getWorld(),
+ ExtendedFacing.of(aBaseMetaTileEntity.getFrontFacing()),
+ aBaseMetaTileEntity.getXCoord(),
+ aBaseMetaTileEntity.getYCoord(),
+ aBaseMetaTileEntity.getZCoord(),
+ numbers[0],
+ numbers[1],
+ numbers[2],
+ te -> te.getClass()
+ .getCanonicalName(),
+ numbers[3],
+ numbers[4],
+ numbers[5],
+ transpose);
+ GT_FML_LOGGER.info(pseudoJavaCode);
+ result = pseudoJavaCode.split("\\n");
+ aPlayer.addChatMessage(
+ new ChatComponentTranslation(translateToLocal("GT5U.machines.advdebugstructurewriter.printed")));
+ }
+
+ @Override
+ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) {
+ GT_UIInfos.openGTTileEntityUI(aBaseMetaTileEntity, aPlayer);
+ return true;
+ }
+
+ @Override
+ public boolean isFacingValid(ForgeDirection facing) {
+ return true;
+ }
+
+ @Override
+ public boolean isElectric() {
+ return false;
+ }
+
+ @Override
+ public boolean isAccessAllowed(EntityPlayer aPlayer) {
+ return true;
+ }
+
+ @Override
+ public String[] getDescription() {
+ return new String[] { translateToLocal("GT5U.machines.advdebugstructurewriter.tooltip"), // Scans Blocks Around
+ translateToLocal("GT5U.machines.advdebugstructurewriter.tooltip.1"), // Prints Multiblock NonTE
+ // structure check code
+ translateToLocal("GT5U.machines.advdebugstructurewriter.tooltip.2") // ABC axes aligned to machine front
+ };
+ }
+
+ @Override
+ public boolean isGivingInformation() {
+ return true;
+ }
+
+ @Override
+ public String[] getInfoData() {
+ return result;
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ builder.widget(
+ new DrawableWidget().setDrawable(GT_UITextures.PICTURE_SCREEN_BLACK)
+ .setSize(90, 112)
+ .setPos(43, 4))
+ .widget(new ButtonWidget().setOnClick((clickData, widget) -> {
+ if (getBaseMetaTileEntity().isServerSide()) {
+ printStructure(
+ widget.getContext()
+ .getPlayer());
+ }
+ })
+ .setBackground(GT_UITextures.BUTTON_STANDARD, GT_UITextures.OVERLAY_BUTTON_PRINT)
+ .setSize(18, 18)
+ .setPos(11, 128)
+ .addTooltip(translateToLocal("GT5U.machines.advdebugstructurewriter.gui.print.tooltip")))
+ .widget(
+ new CycleButtonWidget().setToggle(() -> transpose, aBoolean -> transpose = aBoolean)
+ .setVariableBackground(GT_UITextures.BUTTON_STANDARD_TOGGLE)
+ .setStaticTexture(GT_UITextures.OVERLAY_BUTTON_TRANSPOSE)
+ .setSize(18, 18)
+ .setPos(32, 128)
+ .addTooltip(translateToLocal("GT5U.machines.advdebugstructurewriter.gui.transpose.tooltip")))
+ .widget(
+ new CycleButtonWidget().setToggle(() -> showHighlightBox, aBoolean -> showHighlightBox = aBoolean)
+ .setVariableBackground(GT_UITextures.BUTTON_STANDARD_TOGGLE)
+ .setStaticTexture(GT_UITextures.OVERLAY_BUTTON_BOUNDING_BOX)
+ .setSize(18, 18)
+ .setPos(53, 128)
+ .addTooltip(translateToLocal("GT5U.machines.advdebugstructurewriter.gui.highlight.tooltip")))
+ .widget(
+ new MultiChildWidget()
+ .addChild(
+ new TextWidget(translateToLocal("GT5U.machines.advdebugstructurewriter.gui.origin"))
+ .setDefaultColor(0xf0f0ff)
+ .setPos(0, 0))
+ .addChild(
+ TextWidget.dynamicString(() -> "A: " + numbers[0])
+ .setDefaultColor(0xf0f0ff)
+ .setPos(0, 10))
+ .addChild(
+ TextWidget.dynamicString(() -> "B: " + numbers[1])
+ .setDefaultColor(0xf0f0ff)
+ .setPos(0, 18))
+ .addChild(
+ TextWidget.dynamicString(() -> "C: " + numbers[2])
+ .setDefaultColor(0xf0f0ff)
+ .setPos(0, 26))
+ .addChild(
+ new TextWidget(translateToLocal("GT5U.machines.advdebugstructurewriter.gui.size"))
+ .setDefaultColor(0xf0f0ff)
+ .setPos(0, 52))
+ .addChild(
+ TextWidget.dynamicString(() -> "A: " + numbers[3])
+ .setDefaultColor(0xf0f0ff)
+ .setPos(0, 62))
+ .addChild(
+ TextWidget.dynamicString(() -> "B: " + numbers[4])
+ .setDefaultColor(0xf0f0ff)
+ .setPos(0, 70))
+ .addChild(
+ TextWidget.dynamicString(() -> "C: " + numbers[5])
+ .setDefaultColor(0xf0f0ff)
+ .setPos(0, 78))
+ .setPos(46, 8));
+ addChangeNumberButtons(builder, GT_UITextures.OVERLAY_BUTTON_MINUS_LARGE, -512, -64, 7);
+ addChangeNumberButtons(builder, GT_UITextures.OVERLAY_BUTTON_MINUS_SMALL, -16, -1, 25);
+ addChangeNumberButtons(builder, GT_UITextures.OVERLAY_BUTTON_PLUS_SMALL, 16, 1, 133);
+ addChangeNumberButtons(builder, GT_UITextures.OVERLAY_BUTTON_PLUS_LARGE, 512, 64, 151);
+ }
+
+ private void addChangeNumberButtons(ModularWindow.Builder builder, IDrawable overlay, int addNumberShift,
+ int addNumber, int xPos) {
+ int[] yPos = new int[] { 4, 22, 40, 62, 80, 98 };
+ for (int i = 0; i < yPos.length; i++) {
+ final int index = i; // needed for lambda
+ builder.widget(
+ new ButtonWidget()
+ .setOnClick((clickData, widget) -> numbers[index] += clickData.shift ? addNumberShift : addNumber)
+ .setBackground(GT_UITextures.BUTTON_STANDARD, overlay)
+ .setSize(18, 18)
+ .setPos(xPos, yPos[index]));
+ }
+ }
+
+ @Override
+ public GUITextureSet getGUITextureSet() {
+ return new GUITextureSet().setGregTechLogo(GT_UITextures.PICTURE_GT_LOGO_17x17_TRANSPARENT_GRAY);
+ }
+
+ @Override
+ public void addGregTechLogo(ModularWindow.Builder builder) {
+ builder.widget(
+ new DrawableWidget().setDrawable(getGUITextureSet().getGregTechLogo())
+ .setSize(17, 17)
+ .setPos(113, 96));
+ }
+
+ @Override
+ public boolean doesBindPlayerInventory() {
+ return false;
+ }
+
+ public static class ForgeEventHandler {
+
+ public ForgeEventHandler() {
+ MinecraftForge.EVENT_BUS.register(this);
+ }
+
+ @SuppressWarnings("unused")
+ @SideOnly(Side.CLIENT)
+ @SubscribeEvent
+ public void onRenderWorldLast(RenderWorldLastEvent e) {
+ for (BoundHighlighter boundingBox : bondingBoxes.values()) {
+ boundingBox.renderHighlightedBlock(e);
+ }
+ }
+ }
+
+ private static class BoundHighlighter {
+
+ public Vec3Impl pos1;
+ public Vec3Impl pos2;
+ public boolean showHighlightBox;
+ public int dim;
+
+ @SideOnly(Side.CLIENT)
+ private void renderHighlightedBlock(RenderWorldLastEvent event) {
+ if (pos1 == null || pos2 == null || !showHighlightBox) {
+ return;
+ }
+ Minecraft mc = Minecraft.getMinecraft();
+ int dimension = mc.theWorld.provider.dimensionId;
+
+ if (dimension != dim) {
+ pos1 = null;
+ pos2 = null;
+ return;
+ }
+
+ EntityPlayerSP p = mc.thePlayer;
+ double doubleX = p.lastTickPosX + (p.posX - p.lastTickPosX) * event.partialTicks;
+ double doubleY = p.lastTickPosY + (p.posY - p.lastTickPosY) * event.partialTicks;
+ double doubleZ = p.lastTickPosZ + (p.posZ - p.lastTickPosZ) * event.partialTicks;
+
+ GL11.glPushMatrix();
+ GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
+ GL11.glLineWidth(3);
+ GL11.glTranslated(-doubleX, -doubleY, -doubleZ);
+
+ GL11.glDisable(GL11.GL_DEPTH_TEST);
+ GL11.glDisable(GL11.GL_TEXTURE_2D);
+
+ GL11.glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
+ renderHighLightedArenaOutline(pos1.get0(), pos1.get1(), pos1.get2(), pos2.get0(), pos2.get1(), pos2.get2());
+
+ GL11.glPopAttrib();
+ GL11.glPopMatrix();
+ }
+
+ @SideOnly(Side.CLIENT)
+ static void renderHighLightedArenaOutline(double x1, double y1, double z1, double x2, double y2, double z2) {
+ GL11.glBegin(GL11.GL_LINE_STRIP);
+
+ GL11.glVertex3d(x1, y1, z1);
+ GL11.glVertex3d(x1, y2, z1);
+ GL11.glVertex3d(x1, y2, z2);
+ GL11.glVertex3d(x1, y1, z2);
+ GL11.glVertex3d(x1, y1, z1);
+
+ GL11.glVertex3d(x2, y1, z1);
+ GL11.glVertex3d(x2, y2, z1);
+ GL11.glVertex3d(x2, y2, z2);
+ GL11.glVertex3d(x2, y1, z2);
+ GL11.glVertex3d(x2, y1, z1);
+
+ GL11.glVertex3d(x1, y1, z1);
+ GL11.glVertex3d(x2, y1, z1);
+ GL11.glVertex3d(x2, y1, z2);
+ GL11.glVertex3d(x1, y1, z2);
+ GL11.glVertex3d(x1, y2, z2);
+ GL11.glVertex3d(x2, y2, z2);
+ GL11.glVertex3d(x2, y2, z1);
+ GL11.glVertex3d(x2, y1, z1);
+ GL11.glVertex3d(x1, y1, z1);
+ GL11.glVertex3d(x2, y1, z1);
+ GL11.glVertex3d(x2, y2, z1);
+ GL11.glVertex3d(x1, y2, z1);
+ GL11.glVertex3d(x1, y2, z2);
+ GL11.glVertex3d(x2, y2, z2);
+ GL11.glVertex3d(x2, y1, z2);
+ GL11.glVertex3d(x1, y1, z2);
+
+ GL11.glEnd();
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_DieselGenerator.java b/src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_DieselGenerator.java
new file mode 100644
index 0000000000..5047cb7624
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_DieselGenerator.java
@@ -0,0 +1,283 @@
+package gregtech.common.tileentities.generators;
+
+import static gregtech.api.enums.Textures.BlockIcons.DIESEL_GENERATOR_BACK;
+import static gregtech.api.enums.Textures.BlockIcons.DIESEL_GENERATOR_BACK_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.DIESEL_GENERATOR_BACK_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.DIESEL_GENERATOR_BACK_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.DIESEL_GENERATOR_BOTTOM;
+import static gregtech.api.enums.Textures.BlockIcons.DIESEL_GENERATOR_BOTTOM_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.DIESEL_GENERATOR_BOTTOM_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.DIESEL_GENERATOR_BOTTOM_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.DIESEL_GENERATOR_FRONT;
+import static gregtech.api.enums.Textures.BlockIcons.DIESEL_GENERATOR_FRONT_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.DIESEL_GENERATOR_FRONT_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.DIESEL_GENERATOR_FRONT_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.DIESEL_GENERATOR_SIDE;
+import static gregtech.api.enums.Textures.BlockIcons.DIESEL_GENERATOR_SIDE_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.DIESEL_GENERATOR_SIDE_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.DIESEL_GENERATOR_SIDE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.DIESEL_GENERATOR_TOP;
+import static gregtech.api.enums.Textures.BlockIcons.DIESEL_GENERATOR_TOP_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.DIESEL_GENERATOR_TOP_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.DIESEL_GENERATOR_TOP_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAYS_ENERGY_OUT;
+import static gregtech.api.objects.XSTR.XSTR_INSTANCE;
+
+import net.minecraft.block.Block;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import cpw.mods.fml.common.registry.GameRegistry;
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.GT_Mod;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.ConfigCategories;
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.ParticleFX;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicGenerator;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Log;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.WorldSpawnedEventBuilder.ParticleEventBuilder;
+
+public class GT_MetaTileEntity_DieselGenerator extends GT_MetaTileEntity_BasicGenerator {
+
+ public int mEfficiency;
+
+ public GT_MetaTileEntity_DieselGenerator(int aID, String aName, String aNameRegional, int aTier) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ new String[] { "Requires liquid Fuel",
+ "Causes "
+ + (int) (GT_Mod.gregtechproxy.mPollutionBaseDieselGeneratorPerSecond
+ * GT_Mod.gregtechproxy.mPollutionDieselGeneratorReleasedByTier[aTier])
+ + " Pollution per second" });
+ onConfigLoad();
+ }
+
+ public GT_MetaTileEntity_DieselGenerator(String aName, int aTier, String aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ onConfigLoad();
+ }
+
+ public GT_MetaTileEntity_DieselGenerator(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ onConfigLoad();
+ }
+
+ @Override
+ public boolean isOutputFacing(ForgeDirection side) {
+ return side == getBaseMetaTileEntity().getFrontFacing();
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_DieselGenerator(this.mName, this.mTier, this.mDescriptionArray, this.mTextures);
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.dieselFuels;
+ }
+
+ @Override
+ public int getCapacity() {
+ return 16000;
+ }
+
+ public void onConfigLoad() {
+ this.mEfficiency = GregTech_API.sMachineFile.get(
+ ConfigCategories.machineconfig,
+ "DieselGenerator.efficiency.tier." + this.mTier,
+ (100 - this.mTier * 5));
+ }
+
+ @Override
+ public int getEfficiency() {
+ return this.mEfficiency;
+ }
+
+ @Override
+ public int getFuelValue(ItemStack aStack) {
+ if (GT_Utility.isStackInvalid(aStack) || getRecipeMap() == null) return 0;
+ long rValue = super.getFuelValue(aStack);
+ if (ItemList.Fuel_Can_Plastic_Filled.isStackEqual(aStack, false, true)) {
+ rValue = Math.max(rValue, GameRegistry.getFuelValue(aStack) * 3L);
+ }
+ if (rValue > Integer.MAX_VALUE) {
+ throw new ArithmeticException("Integer LOOPBACK!");
+ }
+ return (int) rValue;
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ if (aTick % 100 == 0 && mFluid != null && mFluid.amount > this.getCapacity()) {
+ GT_Log.err.println(
+ "Dupe Abuse: " + aBaseMetaTileEntity.getOwnerName()
+ + " Coords: "
+ + aBaseMetaTileEntity.getXCoord()
+ + " "
+ + aBaseMetaTileEntity.getYCoord()
+ + " "
+ + aBaseMetaTileEntity.getZCoord());
+ aBaseMetaTileEntity.setToFire();
+ }
+ super.onPostTick(aBaseMetaTileEntity, aTick);
+ }
+
+ /**
+ * Draws random smoke particles on top when active
+ *
+ * @param aBaseMetaTileEntity The entity that will handle the {@link Block#randomDisplayTick}
+ */
+ @SideOnly(Side.CLIENT)
+ @Override
+ public void onRandomDisplayTick(IGregTechTileEntity aBaseMetaTileEntity) {
+ if (aBaseMetaTileEntity.isActive()) {
+
+ if (aBaseMetaTileEntity.getCoverIDAtSide(ForgeDirection.UP) == 0
+ && !aBaseMetaTileEntity.getOpacityAtSide(ForgeDirection.UP)) {
+
+ final double x = aBaseMetaTileEntity.getOffsetX(ForgeDirection.UP, 1) + 2D / 16D
+ + XSTR_INSTANCE.nextFloat() * 14D / 16D;
+ final double y = aBaseMetaTileEntity.getOffsetY(ForgeDirection.UP, 1) + 1D / 32D;
+ final double z = aBaseMetaTileEntity.getOffsetZ(ForgeDirection.UP, 1) + 2D / 16D
+ + XSTR_INSTANCE.nextFloat() * 14D / 16D;
+
+ new ParticleEventBuilder().setMotion(0D, 0D, 0D)
+ .setPosition(x, y, z)
+ .setWorld(getBaseMetaTileEntity().getWorld())
+ .setIdentifier(ParticleFX.SMOKE)
+ .run();
+ }
+ }
+ }
+
+ @Override
+ public ITexture[] getFront(byte aColor) {
+ return new ITexture[] { super.getFront(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(DIESEL_GENERATOR_FRONT),
+ TextureFactory.builder()
+ .addIcon(DIESEL_GENERATOR_FRONT_GLOW)
+ .glow()
+ .build()),
+ OVERLAYS_ENERGY_OUT[this.mTier] };
+ }
+
+ @Override
+ public ITexture[] getBack(byte aColor) {
+ return new ITexture[] { super.getBack(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(DIESEL_GENERATOR_BACK),
+ TextureFactory.builder()
+ .addIcon(DIESEL_GENERATOR_BACK_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public ITexture[] getBottom(byte aColor) {
+ return new ITexture[] { super.getBottom(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(DIESEL_GENERATOR_BOTTOM),
+ TextureFactory.builder()
+ .addIcon(DIESEL_GENERATOR_BOTTOM_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public ITexture[] getTop(byte aColor) {
+ return new ITexture[] { super.getTop(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(DIESEL_GENERATOR_TOP),
+ TextureFactory.builder()
+ .addIcon(DIESEL_GENERATOR_TOP_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public ITexture[] getSides(byte aColor) {
+ return new ITexture[] { super.getSides(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(DIESEL_GENERATOR_SIDE),
+ TextureFactory.builder()
+ .addIcon(DIESEL_GENERATOR_SIDE_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public ITexture[] getFrontActive(byte aColor) {
+ return new ITexture[] { super.getFrontActive(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(DIESEL_GENERATOR_FRONT_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(DIESEL_GENERATOR_FRONT_ACTIVE_GLOW)
+ .glow()
+ .build()),
+ OVERLAYS_ENERGY_OUT[this.mTier] };
+ }
+
+ @Override
+ public ITexture[] getBackActive(byte aColor) {
+ return new ITexture[] { super.getBackActive(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(DIESEL_GENERATOR_BACK_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(DIESEL_GENERATOR_BACK_ACTIVE_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public ITexture[] getBottomActive(byte aColor) {
+ return new ITexture[] { super.getBottomActive(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(DIESEL_GENERATOR_BOTTOM_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(DIESEL_GENERATOR_BOTTOM_ACTIVE_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public ITexture[] getTopActive(byte aColor) {
+ return new ITexture[] { super.getTopActive(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(DIESEL_GENERATOR_TOP_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(DIESEL_GENERATOR_TOP_ACTIVE_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public ITexture[] getSidesActive(byte aColor) {
+ return new ITexture[] { super.getSidesActive(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(DIESEL_GENERATOR_SIDE_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(DIESEL_GENERATOR_SIDE_ACTIVE_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public int getPollution() {
+ return (int) (GT_Mod.gregtechproxy.mPollutionBaseDieselGeneratorPerSecond
+ * GT_Mod.gregtechproxy.mPollutionDieselGeneratorReleasedByTier[mTier]);
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_GasTurbine.java b/src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_GasTurbine.java
new file mode 100644
index 0000000000..e18bc00b51
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_GasTurbine.java
@@ -0,0 +1,216 @@
+package gregtech.common.tileentities.generators;
+
+import static gregtech.api.enums.Textures.BlockIcons.GAS_TURBINE_BACK;
+import static gregtech.api.enums.Textures.BlockIcons.GAS_TURBINE_BACK_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.GAS_TURBINE_BACK_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.GAS_TURBINE_BACK_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.GAS_TURBINE_BOTTOM;
+import static gregtech.api.enums.Textures.BlockIcons.GAS_TURBINE_BOTTOM_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.GAS_TURBINE_BOTTOM_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.GAS_TURBINE_BOTTOM_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.GAS_TURBINE_FRONT;
+import static gregtech.api.enums.Textures.BlockIcons.GAS_TURBINE_FRONT_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.GAS_TURBINE_FRONT_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.GAS_TURBINE_FRONT_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.GAS_TURBINE_SIDE;
+import static gregtech.api.enums.Textures.BlockIcons.GAS_TURBINE_SIDE_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.GAS_TURBINE_SIDE_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.GAS_TURBINE_SIDE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.GAS_TURBINE_TOP;
+import static gregtech.api.enums.Textures.BlockIcons.GAS_TURBINE_TOP_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.GAS_TURBINE_TOP_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.GAS_TURBINE_TOP_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAYS_ENERGY_OUT;
+
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.GT_Mod;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.ConfigCategories;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicGenerator;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.render.TextureFactory;
+
+public class GT_MetaTileEntity_GasTurbine extends GT_MetaTileEntity_BasicGenerator {
+
+ public int mEfficiency;
+
+ public GT_MetaTileEntity_GasTurbine(int aID, String aName, String aNameRegional, int aTier, int mEfficiency) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ new String[] { "Requires flammable Gasses",
+ "Causes "
+ + (int) (GT_Mod.gregtechproxy.mPollutionBaseGasTurbinePerSecond
+ * GT_Mod.gregtechproxy.mPollutionGasTurbineReleasedByTier[aTier])
+ + " Pollution per second" });
+ this.mEfficiency = mEfficiency;
+ onConfigLoad();
+ }
+
+ public GT_MetaTileEntity_GasTurbine(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures,
+ int mEfficiency) {
+ super(aName, aTier, aDescription, aTextures);
+ this.mEfficiency = mEfficiency;
+ onConfigLoad();
+ }
+
+ @Override
+ public boolean isOutputFacing(ForgeDirection side) {
+ return side == getBaseMetaTileEntity().getFrontFacing();
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_GasTurbine(
+ this.mName,
+ this.mTier,
+ this.mDescriptionArray,
+ this.mTextures,
+ this.mEfficiency);
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.gasTurbineFuels;
+ }
+
+ @Override
+ public int getCapacity() {
+ return 16000;
+ }
+
+ public void onConfigLoad() {
+ this.mEfficiency = GregTech_API.sMachineFile
+ .get(ConfigCategories.machineconfig, "GasTurbine.efficiency.tier." + this.mTier, this.mEfficiency);
+ }
+
+ @Override
+ public int getEfficiency() {
+ return this.mEfficiency;
+ }
+
+ @Override
+ public ITexture[] getFront(byte aColor) {
+ return new ITexture[] { super.getFront(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(GAS_TURBINE_FRONT),
+ TextureFactory.builder()
+ .addIcon(GAS_TURBINE_FRONT_GLOW)
+ .glow()
+ .build()),
+ OVERLAYS_ENERGY_OUT[this.mTier] };
+ }
+
+ @Override
+ public ITexture[] getBack(byte aColor) {
+ return new ITexture[] { super.getBack(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(GAS_TURBINE_BACK),
+ TextureFactory.builder()
+ .addIcon(GAS_TURBINE_BACK_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public ITexture[] getBottom(byte aColor) {
+ return new ITexture[] { super.getBottom(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(GAS_TURBINE_BOTTOM),
+ TextureFactory.builder()
+ .addIcon(GAS_TURBINE_BOTTOM_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public ITexture[] getTop(byte aColor) {
+ return new ITexture[] { super.getTop(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(GAS_TURBINE_TOP),
+ TextureFactory.builder()
+ .addIcon(GAS_TURBINE_TOP_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public ITexture[] getSides(byte aColor) {
+ return new ITexture[] { super.getSides(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(GAS_TURBINE_SIDE),
+ TextureFactory.builder()
+ .addIcon(GAS_TURBINE_SIDE_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public ITexture[] getFrontActive(byte aColor) {
+ return new ITexture[] { super.getFrontActive(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(GAS_TURBINE_FRONT_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(GAS_TURBINE_FRONT_ACTIVE_GLOW)
+ .glow()
+ .build()),
+ OVERLAYS_ENERGY_OUT[this.mTier] };
+ }
+
+ @Override
+ public ITexture[] getBackActive(byte aColor) {
+ return new ITexture[] { super.getBackActive(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(GAS_TURBINE_BACK_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(GAS_TURBINE_BACK_ACTIVE_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public ITexture[] getBottomActive(byte aColor) {
+ return new ITexture[] { super.getBottomActive(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(GAS_TURBINE_BOTTOM_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(GAS_TURBINE_BOTTOM_ACTIVE_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public ITexture[] getTopActive(byte aColor) {
+ return new ITexture[] { super.getTopActive(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(GAS_TURBINE_TOP_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(GAS_TURBINE_TOP_ACTIVE_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public ITexture[] getSidesActive(byte aColor) {
+ return new ITexture[] { super.getSidesActive(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(GAS_TURBINE_SIDE_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(GAS_TURBINE_SIDE_ACTIVE_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public int getPollution() {
+ return (int) (GT_Mod.gregtechproxy.mPollutionBaseGasTurbinePerSecond
+ * GT_Mod.gregtechproxy.mPollutionGasTurbineReleasedByTier[mTier]);
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_LightningRod.java b/src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_LightningRod.java
new file mode 100644
index 0000000000..9809dba278
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_LightningRod.java
@@ -0,0 +1,169 @@
+package gregtech.common.tileentities.generators;
+
+import static gregtech.api.objects.XSTR.XSTR_INSTANCE;
+
+import net.minecraft.entity.effect.EntityLightningBolt;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.enums.GT_Values;
+import gregtech.api.enums.Textures.BlockIcons;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_TieredMachineBlock;
+import gregtech.api.render.TextureFactory;
+
+public class GT_MetaTileEntity_LightningRod extends GT_MetaTileEntity_TieredMachineBlock {
+
+ public GT_MetaTileEntity_LightningRod(int aID, String aName, String aNameRegional, int aTier) {
+ super(aID, aName, aNameRegional, aTier, 0, "Generates EU From Lightning Bolts");
+ }
+
+ public GT_MetaTileEntity_LightningRod(String aName, int aTier, int aInvSlotCount, String aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aInvSlotCount, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_LightningRod(String aName, int aTier, int aInvSlotCount, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aInvSlotCount, aDescription, aTextures);
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity baseMetaTileEntity, ForgeDirection sideDirection,
+ ForgeDirection facingDirection, int colorIndex, boolean active, boolean redstoneLevel) {
+ if (sideDirection != ForgeDirection.UP) {
+ return new ITexture[] { BlockIcons.MACHINE_CASINGS[mTier][colorIndex + 1],
+ BlockIcons.OVERLAYS_ENERGY_OUT_POWER[mTier] };
+ }
+ if (!active) return new ITexture[] { BlockIcons.MACHINE_CASINGS[mTier][colorIndex + 1],
+ TextureFactory.of(BlockIcons.MACHINE_CASING_FUSION_GLASS) };
+ return new ITexture[] { BlockIcons.MACHINE_CASINGS[mTier][colorIndex + 1],
+ TextureFactory.of(BlockIcons.MACHINE_CASING_FUSION_GLASS_YELLOW), TextureFactory.builder()
+ .addIcon(BlockIcons.MACHINE_CASING_FUSION_GLASS_YELLOW_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[][][] getTextureSet(ITexture[] aTextures) {
+ return null;
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_LightningRod(
+ this.mName,
+ this.mTier,
+ this.mInventory.length,
+ this.mDescriptionArray,
+ this.mTextures);
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ World aWorld = aBaseMetaTileEntity.getWorld();
+ if (!aWorld.isRemote) {
+ if (aBaseMetaTileEntity.getStoredEU() > 0) {
+ aBaseMetaTileEntity.setActive(true);
+ aBaseMetaTileEntity.decreaseStoredEnergyUnits(aBaseMetaTileEntity.getStoredEU() / 100 + 1, false);
+ } else {
+ aBaseMetaTileEntity.setActive(false);
+ }
+
+ if (aTick % 256 == 0 && (aWorld.isThundering() || (aWorld.isRaining() && XSTR_INSTANCE.nextInt(10) == 0))) {
+ int aRodValue = 0;
+ boolean isRodValid = true;
+ int aX = aBaseMetaTileEntity.getXCoord();
+ int aY = aBaseMetaTileEntity.getYCoord();
+ int aZ = aBaseMetaTileEntity.getZCoord();
+
+ for (int i = aBaseMetaTileEntity.getYCoord() + 1; i < aWorld.getHeight() - 1; i++) {
+ if (isRodValid && aBaseMetaTileEntity.getBlock(aX, i, aZ)
+ .getUnlocalizedName()
+ .equals("blockFenceIron")) {
+ aRodValue++;
+ } else {
+ isRodValid = false;
+ if (aBaseMetaTileEntity.getBlock(aX, i, aZ) != Blocks.air) {
+ aRodValue = 0;
+ break;
+ }
+ }
+ }
+ if (!aWorld.isThundering() && ((aY + aRodValue) < 128)) aRodValue = 0;
+ if (XSTR_INSTANCE.nextInt(4 * aWorld.getHeight()) < (aRodValue * (aY + aRodValue))) {
+ aBaseMetaTileEntity
+ .increaseStoredEnergyUnits(maxEUStore() - aBaseMetaTileEntity.getStoredEU(), false);
+ aWorld.addWeatherEffect(new EntityLightningBolt(aWorld, aX, aY + aRodValue, aZ));
+ // randomly break a rod
+ if (aWorld.isThundering()) {
+ aWorld.setBlockToAir(aX, aY + XSTR_INSTANCE.nextInt(aRodValue) + 1, aZ);
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public boolean allowPullStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public boolean allowPutStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public boolean isSimpleMachine() {
+ return false;
+ }
+
+ @Override
+ public boolean isFacingValid(ForgeDirection facing) {
+ return facing == ForgeDirection.UP;
+ }
+
+ @Override
+ public boolean isOutputFacing(ForgeDirection side) {
+ return true;
+ }
+
+ @Override
+ public boolean isEnetOutput() {
+ return true;
+ }
+
+ @Override
+ public boolean isEnetInput() {
+ return false;
+ }
+
+ @Override
+ public long maxEUStore() {
+ return 50000000;
+ }
+
+ @Override
+ public long maxEUOutput() {
+ return GT_Values.V[mTier];
+ }
+
+ @Override
+ public long maxAmperesOut() {
+ return 512;
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {}
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {}
+}
diff --git a/src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_MagicEnergyConverter.java b/src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_MagicEnergyConverter.java
new file mode 100644
index 0000000000..7317180b5d
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_MagicEnergyConverter.java
@@ -0,0 +1,178 @@
+package gregtech.common.tileentities.generators;
+
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASING_MAGIC;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASING_MAGIC_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASING_MAGIC_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASING_MAGIC_FRONT;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASING_MAGIC_FRONT_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASING_MAGIC_FRONT_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASING_MAGIC_FRONT_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASING_MAGIC_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAYS_ENERGY_OUT;
+
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.ConfigCategories;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicGenerator;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.render.TextureFactory;
+
+public class GT_MetaTileEntity_MagicEnergyConverter extends GT_MetaTileEntity_BasicGenerator {
+
+ public int mEfficiency;
+
+ public GT_MetaTileEntity_MagicEnergyConverter(int aID, String aName, String aNameRegional, int aTier) {
+ super(aID, aName, aNameRegional, aTier, "Put your strange stuff in here");
+ onConfigLoad();
+ }
+
+ public GT_MetaTileEntity_MagicEnergyConverter(String aName, int aTier, String aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ onConfigLoad();
+ }
+
+ public GT_MetaTileEntity_MagicEnergyConverter(String aName, int aTier, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ onConfigLoad();
+ }
+
+ @Override
+ public boolean isOutputFacing(ForgeDirection side) {
+ return side == getBaseMetaTileEntity().getFrontFacing();
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_MagicEnergyConverter(
+ this.mName,
+ this.mTier,
+ this.mDescriptionArray,
+ this.mTextures);
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.magicFuels;
+ }
+
+ @Override
+ public int getCapacity() {
+ return 16000;
+ }
+
+ public void onConfigLoad() {
+ this.mEfficiency = GregTech_API.sMachineFile.get(
+ ConfigCategories.machineconfig,
+ "MagicEnergyConverter.efficiency.tier." + this.mTier,
+ 100 - this.mTier * 5);
+ }
+
+ @Override
+ public int getEfficiency() {
+ return this.mEfficiency;
+ }
+
+ @Override
+ public ITexture[] getFront(byte aColor) {
+ return new ITexture[] { super.getFront(aColor)[0], TextureFactory.of(MACHINE_CASING_MAGIC),
+ TextureFactory.builder()
+ .addIcon(MACHINE_CASING_MAGIC_GLOW)
+ .glow()
+ .build(),
+ OVERLAYS_ENERGY_OUT[mTier] };
+ }
+
+ @Override
+ public ITexture[] getBack(byte aColor) {
+ return new ITexture[] { super.getBack(aColor)[0], TextureFactory.of(MACHINE_CASING_MAGIC_FRONT),
+ TextureFactory.builder()
+ .addIcon(MACHINE_CASING_MAGIC_FRONT_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getBottom(byte aColor) {
+ return new ITexture[] { super.getBottom(aColor)[0], TextureFactory.of(MACHINE_CASING_MAGIC),
+ TextureFactory.builder()
+ .addIcon(MACHINE_CASING_MAGIC_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getTop(byte aColor) {
+ return new ITexture[] { super.getTop(aColor)[0], TextureFactory.of(MACHINE_CASING_MAGIC),
+ TextureFactory.builder()
+ .addIcon(MACHINE_CASING_MAGIC_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getSides(byte aColor) {
+ return new ITexture[] { super.getSides(aColor)[0], TextureFactory.of(MACHINE_CASING_MAGIC),
+ TextureFactory.builder()
+ .addIcon(MACHINE_CASING_MAGIC_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getFrontActive(byte aColor) {
+ return new ITexture[] { super.getFrontActive(aColor)[0], TextureFactory.of(MACHINE_CASING_MAGIC_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(MACHINE_CASING_MAGIC_ACTIVE_GLOW)
+ .glow()
+ .build(),
+ OVERLAYS_ENERGY_OUT[mTier] };
+ }
+
+ @Override
+ public ITexture[] getBackActive(byte aColor) {
+ return new ITexture[] { super.getBackActive(aColor)[0], TextureFactory.of(MACHINE_CASING_MAGIC_FRONT_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(MACHINE_CASING_MAGIC_FRONT_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getBottomActive(byte aColor) {
+ return new ITexture[] { super.getBottomActive(aColor)[0], TextureFactory.of(MACHINE_CASING_MAGIC_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(MACHINE_CASING_MAGIC_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getTopActive(byte aColor) {
+ return new ITexture[] { super.getTopActive(aColor)[0], TextureFactory.of(MACHINE_CASING_MAGIC_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(MACHINE_CASING_MAGIC_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getSidesActive(byte aColor) {
+ return new ITexture[] { super.getSidesActive(aColor)[0], TextureFactory.of(MACHINE_CASING_MAGIC_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(MACHINE_CASING_MAGIC_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public int getPollution() {
+ return 0;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_MagicalEnergyAbsorber.java b/src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_MagicalEnergyAbsorber.java
new file mode 100644
index 0000000000..8dc3417a84
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_MagicalEnergyAbsorber.java
@@ -0,0 +1,817 @@
+package gregtech.common.tileentities.generators;
+
+import static gregtech.api.enums.ConfigCategories.machineconfig;
+import static gregtech.api.enums.GT_Values.V;
+import static gregtech.api.enums.Mods.Thaumcraft;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASING_DRAGONEGG;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASING_DRAGONEGG_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASING_MAGIC;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASING_MAGIC_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASING_MAGIC_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASING_MAGIC_FRONT;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASING_MAGIC_FRONT_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASING_MAGIC_FRONT_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASING_MAGIC_FRONT_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASING_MAGIC_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAYS_ENERGY_OUT;
+import static gregtech.api.objects.XSTR.XSTR_INSTANCE;
+import static net.minecraft.util.EnumChatFormatting.GRAY;
+import static net.minecraft.util.EnumChatFormatting.GREEN;
+import static net.minecraft.util.EnumChatFormatting.LIGHT_PURPLE;
+import static net.minecraft.util.EnumChatFormatting.RESET;
+import static net.minecraft.util.EnumChatFormatting.UNDERLINE;
+import static net.minecraft.util.EnumChatFormatting.YELLOW;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.BlockDragonEgg;
+import net.minecraft.enchantment.Enchantment;
+import net.minecraft.enchantment.EnchantmentHelper;
+import net.minecraft.entity.item.EntityEnderCrystal;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraft.init.Items;
+import net.minecraft.item.ItemEnchantedBook;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.AxisAlignedBB;
+import net.minecraft.world.World;
+import net.minecraft.world.chunk.Chunk;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.google.common.base.Enums;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.ParticleFX;
+import gregtech.api.enums.TC_Aspects;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicGenerator;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Config;
+import gregtech.api.util.GT_LanguageManager;
+import gregtech.api.util.GT_Log;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.WorldSpawnedEventBuilder.ParticleEventBuilder;
+import thaumcraft.api.aspects.Aspect;
+import thaumcraft.api.aspects.AspectList;
+import thaumcraft.api.aspects.AspectSourceHelper;
+import thaumcraft.api.aspects.IAspectContainer;
+import thaumcraft.api.visnet.VisNetHandler;
+
+interface MagicalEnergyBBListener {
+
+ void onMagicalEnergyBBUpdate();
+}
+
+public class GT_MetaTileEntity_MagicalEnergyAbsorber extends GT_MetaTileEntity_BasicGenerator
+ implements MagicalEnergyBBListener {
+
+ private static final boolean THAUMCRAFT_LOADED = Thaumcraft.isModLoaded();
+ private static final ConcurrentHashMap<UUID, GT_MetaTileEntity_MagicalEnergyAbsorber> sSubscribedCrystals = new ConcurrentHashMap<>(
+ 4);
+ private static final List<Aspect> sPrimalAspects = (THAUMCRAFT_LOADED) ? Aspect.getPrimalAspects()
+ : new ArrayList<>();
+ private static final Map<Aspect, Integer> sAspectsEnergy = new HashMap<>();
+ private static boolean sAllowMultipleEggs = false;
+ private static GT_MetaTileEntity_MagicalEnergyAbsorber sActiveSiphon = null;
+ private static int sEnergyPerEndercrystal = 512;
+ private static int sEnergyFromVis = 20;
+ private static int sEnergyPerEssentia = 320;
+ private static int sDragonEggEnergyPerTick = 2048;
+ private static int sCreeperEggEnergyPerTick = 512;
+ private final MagicalEnergyBB mMagicalEnergyBB = new MagicalEnergyBB(this, mTier, mTier + 2);
+ private int mEfficiency;
+ private int mMaxVisPerDrain;
+ private long mNextGenerateTickRate = 1;
+ private int mNoGenerationTicks = 0;
+ private boolean mUsingEssentia = true;
+
+ public GT_MetaTileEntity_MagicalEnergyAbsorber(int aID, String aName, String aNameRegional, int aTier) {
+ super(aID, aName, aNameRegional, aTier, "Feasts on magic close to it:");
+ onConfigLoad(GregTech_API.sMachineFile);
+ }
+
+ private GT_MetaTileEntity_MagicalEnergyAbsorber(String aName, int aTier, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ onConfigLoad(GregTech_API.sMachineFile);
+ }
+
+ /**
+ * Populates static variables dependant on config settings
+ *
+ * @param aConfig GT_Config
+ */
+ private static void sharedConfigLoad(GT_Config aConfig) {
+ sAllowMultipleEggs = aConfig.get(machineconfig, "MagicEnergyAbsorber.AllowMultipleEggs", false);
+ sDragonEggEnergyPerTick = aConfig.get(machineconfig, "MagicEnergyAbsorber.EnergyPerTick.DragonEgg", 2048);
+ sCreeperEggEnergyPerTick = aConfig.get(machineconfig, "MagicEnergyAbsorber.EnergyPerTick.CreeperEgg", 512);
+ sEnergyPerEndercrystal = aConfig.get(machineconfig, "MagicEnergyAbsorber.EnergyPerTick.EnderCrystal", 512);
+ if (THAUMCRAFT_LOADED) {
+ sEnergyFromVis = aConfig.get(machineconfig, "MagicEnergyAbsorber.EnergyPerVis", 20);
+ sEnergyPerEssentia = aConfig.get(machineconfig, "MagicEnergyAbsorber.EnergyPerEssentia", 320);
+ for (Aspect tAspect : Aspect.aspects.values()) {
+ // noinspection UnstableApiUsage
+ sAspectsEnergy.put(
+ tAspect,
+ Enums.getIfPresent(
+ TC_Aspects.class,
+ tAspect.getTag()
+ .toUpperCase(Locale.ENGLISH))
+ .or(TC_Aspects.AER).mValue * sEnergyPerEssentia);
+ }
+ }
+ }
+
+ private static void setActiveSiphon(GT_MetaTileEntity_MagicalEnergyAbsorber aSiphon) {
+ sActiveSiphon = aSiphon;
+ }
+
+ @Override
+ public void onConfigLoad(GT_Config aConfig) {
+ sharedConfigLoad(aConfig);
+ mEfficiency = aConfig.get(machineconfig, "MagicEnergyAbsorber.efficiency.tier." + mTier, 100 - mTier * 10);
+ mMaxVisPerDrain = (int) Math.round(
+ Math.sqrt((double) (V[mTier] * 10000) / (sEnergyFromVis * (getEfficiency() != 0 ? getEfficiency() : 100))));
+ if (Math.pow(mMaxVisPerDrain, 2) * sEnergyFromVis * (getEfficiency() != 0 ? getEfficiency() : 100) < V[mTier]) {
+ mMaxVisPerDrain += 1;
+ }
+ }
+
+ @Override
+ public void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ if (aPlayer.isSneaking()) mMagicalEnergyBB.decreaseTier();
+ else mMagicalEnergyBB.increaseTier();
+ GT_Utility.sendChatToPlayer(
+ aPlayer,
+ String.format(
+ GT_LanguageManager.addStringLocalization(
+ "Interaction_DESCRIPTION_MagicalEnergyAbsorber_Screwdriver",
+ "Absorption range: %s blocks"),
+ mMagicalEnergyBB.getRange(),
+ true));
+ mMagicalEnergyBB.update();
+ }
+
+ @Override
+ public void onFirstTick(IGregTechTileEntity aBaseMetaTileEntity) {
+ if (!aBaseMetaTileEntity.isServerSide()) return;
+ mMagicalEnergyBB.update();
+ }
+
+ @Override
+ public void onRemoval() {
+ super.onRemoval();
+ releaseEgg();
+ unsubscribeCrystals();
+ }
+
+ private void releaseEgg() {
+ if (sActiveSiphon == this) {
+ setActiveSiphon(null);
+ }
+ }
+
+ private void unsubscribeCrystals() {
+ for (UUID tCrystalID : sSubscribedCrystals.keySet()) {
+ sSubscribedCrystals.remove(tCrystalID, this);
+ }
+ }
+
+ /**
+ * Call-back from the Bounding Box when its content is updated
+ */
+ @Override
+ public void onMagicalEnergyBBUpdate() {
+ List<UUID> tCrystalIDsInRange = mMagicalEnergyBB.getLivingCrystalIDs();
+ // Release unreachable Crystals subscriptions
+ for (UUID tSubscribedCrystalID : sSubscribedCrystals.keySet()) {
+ if (!tCrystalIDsInRange.contains(tSubscribedCrystalID)) {
+ sSubscribedCrystals.remove(tSubscribedCrystalID, this);
+ }
+ }
+ // Subscribe to available and not already subscribed Crystals
+ for (UUID tCrystalID : tCrystalIDsInRange) {
+ sSubscribedCrystals.putIfAbsent(tCrystalID, this);
+ }
+ }
+
+ @Override
+ public String[] getDescription() {
+ final String LI = "- %%%";
+ final String EU_PER = "%%%EU per ";
+ List<String> description = new ArrayList<>();
+ description
+ .add(UNDERLINE + "Feasts on " + LIGHT_PURPLE + UNDERLINE + "magic" + GRAY + UNDERLINE + " close to it:");
+ description.add(
+ LI + (sAllowMultipleEggs ? "A " : "An " + YELLOW + UNDERLINE + "EXCLUSIVE" + RESET)
+ + GRAY
+ + " "
+ + LIGHT_PURPLE
+ + "Dragon Egg"
+ + GRAY
+ + " atop");
+ if (sEnergyPerEndercrystal > 0) {
+ description.add(LI + sEnergyPerEndercrystal + EU_PER + LIGHT_PURPLE + "Ender Crystal" + GRAY + " in range");
+ }
+ if (THAUMCRAFT_LOADED) {
+ description.add(LI + mMaxVisPerDrain + "%%%CV/t from an " + LIGHT_PURPLE + "Energised Node" + GRAY);
+ description.add(
+ LI + (sEnergyPerEssentia * getEfficiency()) / 100
+ + EU_PER
+ + LIGHT_PURPLE
+ + "Essentia"
+ + GRAY
+ + " Aspect-Value from containers in range");
+ }
+ description.add(" ");
+ description.add(UNDERLINE + "Lookup range (Use Screwdriver to change):");
+ description.add("Default: %%%" + GREEN + mMagicalEnergyBB.getDefaultRange());
+ description.add("Max: %%%" + GREEN + mMagicalEnergyBB.getMaxRange());
+ description.add(" ");
+ description
+ .add(UNDERLINE + "Fuels on " + LIGHT_PURPLE + UNDERLINE + "enchantments" + GRAY + UNDERLINE + " input:");
+ description.add(
+ "- Item: %%%" + (10000 * getEfficiency()) / 100
+ + EU_PER
+ + LIGHT_PURPLE
+ + "enchant"
+ + GRAY
+ + " weight × level / max");
+ description.add("- Book: %%%" + 10000 + EU_PER + LIGHT_PURPLE + "enchant" + GRAY + " weight × level / max");
+ description.add(" ");
+ description.add("Efficiency: %%%" + GREEN + getEfficiency() + "%");
+ return description.toArray(new String[0]);
+ }
+
+ @Override
+ public ITexture[] getFront(byte aColor) {
+ return new ITexture[] { super.getFront(aColor)[0], TextureFactory.of(MACHINE_CASING_MAGIC),
+ TextureFactory.builder()
+ .addIcon(MACHINE_CASING_MAGIC_GLOW)
+ .glow()
+ .build(),
+ OVERLAYS_ENERGY_OUT[mTier] };
+ }
+
+ @Override
+ public ITexture[] getBack(byte aColor) {
+ return new ITexture[] { super.getBack(aColor)[0], TextureFactory.of(MACHINE_CASING_MAGIC_FRONT),
+ TextureFactory.builder()
+ .addIcon(MACHINE_CASING_MAGIC_FRONT_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getBottom(byte aColor) {
+ return new ITexture[] { super.getBottom(aColor)[0], TextureFactory.of(MACHINE_CASING_MAGIC),
+ TextureFactory.builder()
+ .addIcon(MACHINE_CASING_MAGIC_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getTop(byte aColor) {
+ return new ITexture[] { super.getTop(aColor)[0], TextureFactory.of(MACHINE_CASING_DRAGONEGG) };
+ }
+
+ @Override
+ public ITexture[] getSides(byte aColor) {
+ return new ITexture[] { super.getSides(aColor)[0], TextureFactory.of(MACHINE_CASING_MAGIC),
+ TextureFactory.builder()
+ .addIcon(MACHINE_CASING_MAGIC_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getFrontActive(byte aColor) {
+ return new ITexture[] { super.getFrontActive(aColor)[0], TextureFactory.of(MACHINE_CASING_MAGIC_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(MACHINE_CASING_MAGIC_ACTIVE_GLOW)
+ .glow()
+ .build(),
+ OVERLAYS_ENERGY_OUT[mTier] };
+ }
+
+ @Override
+ public ITexture[] getBackActive(byte aColor) {
+ return new ITexture[] { super.getBackActive(aColor)[0], TextureFactory.of(MACHINE_CASING_MAGIC_FRONT_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(MACHINE_CASING_MAGIC_FRONT_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getBottomActive(byte aColor) {
+ return new ITexture[] { super.getBottomActive(aColor)[0], TextureFactory.of(MACHINE_CASING_MAGIC_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(MACHINE_CASING_MAGIC_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getTopActive(byte aColor) {
+ return new ITexture[] { super.getTopActive(aColor)[0], TextureFactory.of(MACHINE_CASING_DRAGONEGG),
+ TextureFactory.builder()
+ .addIcon(MACHINE_CASING_DRAGONEGG_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getSidesActive(byte aColor) {
+ return new ITexture[] { super.getSidesActive(aColor)[0], TextureFactory.of(MACHINE_CASING_MAGIC_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(MACHINE_CASING_MAGIC_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public boolean isOutputFacing(ForgeDirection side) {
+ return side == getBaseMetaTileEntity().getFrontFacing();
+ }
+
+ @Override
+ public long maxEUStore() {
+ return Math.max(getEUVar(), V[mTier] * 16000 + getMinimumStoredEU());
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ if (!aBaseMetaTileEntity.isServerSide()) return;
+ if (!aBaseMetaTileEntity.isAllowedToWork()) return;
+ if ((aBaseMetaTileEntity.getUniversalEnergyStored() >= aBaseMetaTileEntity.getEUCapacity())) return;
+
+ long tGeneratedEU;
+
+ if (aTick % 100 == 0 && mUsingEssentia) mMagicalEnergyBB.update();
+
+ // Adaptive EU Generation Ticking
+ if (aTick % mNextGenerateTickRate == 0) {
+ tGeneratedEU = generateEU();
+ if (tGeneratedEU > 0) {
+ mNoGenerationTicks = 0;
+ if (tGeneratedEU >= 2 * V[mTier])
+ mNextGenerateTickRate = (long) (1.0D / ((2.0D * (double) (V[mTier])) / (double) tGeneratedEU));
+ else mNextGenerateTickRate = 1;
+ mInventory[getStackDisplaySlot()] = new ItemStack(Blocks.fire, 1);
+ mInventory[getStackDisplaySlot()].setStackDisplayName("Generating: " + tGeneratedEU + " EU");
+ } else {
+ mInventory[getStackDisplaySlot()] = null;
+ mNoGenerationTicks += 1;
+ }
+ if (mNoGenerationTicks > 20) {
+ mNoGenerationTicks = 0;
+ mNextGenerateTickRate = 20;
+ }
+ aBaseMetaTileEntity.increaseStoredEnergyUnits(tGeneratedEU, true);
+ aBaseMetaTileEntity.setActive(
+ aBaseMetaTileEntity.isAllowedToWork()
+ && aBaseMetaTileEntity.getUniversalEnergyStored() >= maxEUOutput() + getMinimumStoredEU());
+ }
+ }
+
+ /**
+ * Draws random portal particles on top when active with an egg on top
+ *
+ * @param aBaseMetaTileEntity The entity that will handle the {@link Block#randomDisplayTick}
+ */
+ @SideOnly(Side.CLIENT)
+ @Override
+ public void onRandomDisplayTick(IGregTechTileEntity aBaseMetaTileEntity) {
+
+ if (aBaseMetaTileEntity.isActive()) {
+
+ if (isEgg(aBaseMetaTileEntity.getBlockAtSide(ForgeDirection.UP))) {
+
+ final double oX = aBaseMetaTileEntity.getXCoord() + 8D / 16D;
+ final double oY = aBaseMetaTileEntity.getYCoord() + 17D / 32D;
+ final double oZ = aBaseMetaTileEntity.getZCoord() + 8D / 16D;
+
+ final ParticleEventBuilder particleEventBuilder = new ParticleEventBuilder()
+ .setWorld(getBaseMetaTileEntity().getWorld())
+ .setIdentifier(ParticleFX.PORTAL);
+
+ for (int i = 0; i < 9; i++) {
+ final double dX = (XSTR_INSTANCE.nextFloat() - 0.5D) / 2D;
+ final double dY = XSTR_INSTANCE.nextFloat() * 1.5;
+ final double dZ = (XSTR_INSTANCE.nextFloat() - 0.5D) / 2D;
+
+ final double x = oX + dX;
+ final double y = oY + dY;
+ final double z = oZ + dZ;
+
+ final double mX = dX * 4D;
+ final double dXZ = Math.sqrt(dX * dX + dZ * dZ);
+ final double mY = -(dXZ * dY) / 4D;
+ final double mZ = dZ * 4D;
+
+ particleEventBuilder.setMotion(mX, mY, mZ)
+ .setPosition(x, y, z)
+ .run();
+ }
+ }
+ }
+ }
+
+ @Override
+ public int getPollution() {
+ return 0;
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.magicFuels;
+ }
+
+ @Override
+ public int getEfficiency() {
+ return mEfficiency;
+ }
+
+ @Override
+ public boolean allowPutStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ // Restrict input to disenchantable items or enchanted books
+ return (isDisenchantableItem(aStack) || isEnchantedBook(aStack));
+ }
+
+ @Override
+ public int getCapacity() {
+ return 16000;
+ }
+
+ private boolean isDisenchantableItem(ItemStack aStack) {
+ return ((aStack.isItemEnchanted()) && (aStack.getItem()
+ .getItemEnchantability() > 0));
+ }
+
+ private boolean isEnchantedBook(ItemStack aStack) {
+ return (aStack.getItem() instanceof ItemEnchantedBook);
+ }
+
+ private long generateEU() {
+ long tEU;
+
+ mUsingEssentia = false;
+ if ((tEU = absorbFromEgg()) > 0) return tEU;
+ if ((tEU = absorbFromEnderCrystals()) > 0) return tEU;
+ if ((tEU = absorbFromEnchantedItems()) > 0) return tEU;
+ if ((tEU = absorbFromVisNet()) > 0) return tEU;
+ mUsingEssentia = true;
+ if ((tEU = absorbFromEssentiaContainers()) > 0) return tEU;
+ return 0;
+ }
+
+ private long absorbFromEnchantedItems() {
+ ItemStack tStack = getBaseMetaTileEntity().getStackInSlot(getInputSlot());
+ if (tStack == null) return 0;
+ if (tStack.stackSize == 0) return 0;
+ if (!(isDisenchantableItem(tStack) || isEnchantedBook(tStack))) return 0;
+ long tEU = 0;
+ // Convert enchantments to their EU Value
+ Map<?, ?> tMap = EnchantmentHelper.getEnchantments(tStack);
+ for (Map.Entry<?, ?> e : tMap.entrySet()) {
+ if ((Integer) e.getKey() < Enchantment.enchantmentsList.length) {
+ Enchantment tEnchantment = Enchantment.enchantmentsList[(Integer) e.getKey()];
+ Integer tLevel = (Integer) e.getValue();
+ tEU += 1000000L * tLevel / tEnchantment.getMaxLevel() / tEnchantment.getWeight();
+ }
+ }
+
+ ItemStack tOutputStack = GT_Utility.copyAmount(1, tStack);
+ if (tOutputStack != null) {
+ if (isDisenchantableItem(tOutputStack)) {
+ tEU = tEU * getEfficiency() / 100;
+ EnchantmentHelper.setEnchantments(new HashMap<>(), tOutputStack);
+ } else if (isEnchantedBook(tOutputStack)) {
+ tOutputStack = new ItemStack(Items.book, 1);
+ }
+ }
+
+ // Only consume input when it can store EU and push output
+ if ((getBaseMetaTileEntity().getStoredEU() + tEU) < getBaseMetaTileEntity().getEUCapacity()
+ && getBaseMetaTileEntity().addStackToSlot(getOutputSlot(), tOutputStack)) {
+ decrStackSize(getInputSlot(), 1);
+ } else {
+ tEU = 0;
+ }
+ return tEU;
+ }
+
+ private boolean hasEgg() {
+ Block above = getBaseMetaTileEntity().getBlockOffset(0, 1, 0);
+ return isEgg(above);
+ }
+
+ private long absorbFromEgg() {
+ if (!hasEgg()) return 0;
+ if (!sAllowMultipleEggs) {
+ if (sActiveSiphon != null && sActiveSiphon != this
+ && sActiveSiphon.getBaseMetaTileEntity() != null
+ && !sActiveSiphon.getBaseMetaTileEntity()
+ .isInvalidTileEntity()
+ && sActiveSiphon.isChunkLoaded()
+ && sActiveSiphon.hasEgg()) {
+ getBaseMetaTileEntity().doExplosion(Integer.MAX_VALUE);
+ } else {
+ setActiveSiphon(this);
+ }
+ }
+ Block egg = getBaseMetaTileEntity().getBlockOffset(0, 1, 0);
+ if (egg == Blocks.dragon_egg) {
+ return sDragonEggEnergyPerTick;
+ } else if (egg.getUnlocalizedName()
+ .contains("creeperEgg")) {
+ return sCreeperEggEnergyPerTick;
+ }
+ return 0;
+ }
+
+ private long absorbFromEnderCrystals() {
+ if (sEnergyPerEndercrystal <= 0) return 0;
+ long tEU = 0;
+ for (GT_MetaTileEntity_MagicalEnergyAbsorber tSubscriber : sSubscribedCrystals.values()) {
+ if (tSubscriber == this) { // This Crystal is for me
+ tEU += sEnergyPerEndercrystal;
+ }
+ }
+ return tEU;
+ }
+
+ private long absorbFromVisNet() {
+ if (!THAUMCRAFT_LOADED) return 0;
+
+ long tEU;
+ IGregTechTileEntity tBaseMetaTileEntity = getBaseMetaTileEntity();
+ World tWorld = tBaseMetaTileEntity.getWorld();
+ int tX = tBaseMetaTileEntity.getXCoord();
+ int tY = tBaseMetaTileEntity.getYCoord();
+ int tZ = tBaseMetaTileEntity.getZCoord();
+
+ // Attempt to drain as much Vis as needed for max EU/t, from all primal aspects.
+ int toDrain = mMaxVisPerDrain;
+
+ for (int i = sPrimalAspects.size() - 1; i >= 0 && toDrain > 0; i--) {
+ toDrain -= VisNetHandler.drainVis(tWorld, tX, tY, tZ, sPrimalAspects.get(i), toDrain);
+ }
+
+ int drained = mMaxVisPerDrain - toDrain;
+ tEU = (long) Math.min(maxEUOutput(), (Math.pow(drained, 2) * sEnergyFromVis * getEfficiency() / 10000));
+
+ return tEU;
+ }
+
+ private long absorbFromEssentiaContainers() {
+ if (!THAUMCRAFT_LOADED) return 0;
+
+ long tEU = 0;
+
+ long tEUtoGen = getBaseMetaTileEntity().getEUCapacity() - getBaseMetaTileEntity().getUniversalEnergyStored();
+ List<Aspect> mAvailableEssentiaAspects = mMagicalEnergyBB.getAvailableAspects();
+
+ // try to drain 1 of whatever aspect available in containers within RANGE
+ for (int i = mAvailableEssentiaAspects.size() - 1; i >= 0 && tEUtoGen > 0; i--) {
+ Aspect aspect = mAvailableEssentiaAspects.get(i);
+ long tAspectEU = ((long) sAspectsEnergy.get(aspect) * getEfficiency()) / 100;
+ if (tAspectEU <= tEUtoGen && AspectSourceHelper.drainEssentia(
+ (TileEntity) getBaseMetaTileEntity(),
+ aspect,
+ ForgeDirection.UNKNOWN,
+ mMagicalEnergyBB.getRange())) {
+ tEUtoGen -= tAspectEU;
+ tEU += tAspectEU;
+ }
+ }
+ return tEU;
+ }
+
+ private boolean isEgg(Block aBlock) {
+ if (aBlock == null) return false;
+ if (aBlock == Blocks.air) return false;
+ if (aBlock == Blocks.dragon_egg) return true;
+ if (aBlock instanceof BlockDragonEgg) return true;
+ return (aBlock.getUnlocalizedName()
+ .equals("tile.dragonEgg"));
+ }
+
+ private boolean isChunkLoaded() {
+ IGregTechTileEntity tBaseMetaTileEntity = getBaseMetaTileEntity();
+ int tX = tBaseMetaTileEntity.getXCoord();
+ int tY = tBaseMetaTileEntity.getYCoord();
+ World tWorld = tBaseMetaTileEntity.getWorld();
+ Chunk tChunk = tWorld.getChunkFromBlockCoords(tX, tY);
+ return tChunk.isChunkLoaded;
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_MagicalEnergyAbsorber(mName, mTier, mDescriptionArray, mTextures);
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ aNBT.setInteger("mMagicalEnergyBBTier", mMagicalEnergyBB.getTier());
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ mMagicalEnergyBB.setTier(aNBT.getInteger("mMagicalEnergyBBTier"));
+ }
+
+ /**
+ * Handles Bounding Box ranged operations for Magic sources
+ */
+ static class MagicalEnergyBB {
+
+ private final GT_MetaTileEntity_MagicalEnergyAbsorber mAbsorber;
+ private final MagicalEnergyBBListener mListener;
+ private final int mDefaultTier;
+ private int mTier;
+ private final int mMaxTier;
+ private final List<UUID> mLivingCrystalIDs = new ArrayList<>();
+ private List<Aspect> mAvailableAspects;
+
+ /**
+ * @param aAbsorber user and subscriber for updated BB content
+ * @param aDefaultTier Initial tier value
+ * @param aMaxTier Maximum allowed tier
+ */
+ MagicalEnergyBB(GT_MetaTileEntity_MagicalEnergyAbsorber aAbsorber, int aDefaultTier, int aMaxTier) {
+ mAbsorber = aAbsorber;
+ mListener = aAbsorber;
+ mMaxTier = Math.max(Math.max(aMaxTier, 0), Math.max(aDefaultTier, 0));
+ mDefaultTier = Math.min(aDefaultTier, mMaxTier);
+ mTier = mDefaultTier;
+ if (THAUMCRAFT_LOADED) mAvailableAspects = new ArrayList<>(Aspect.aspects.size());
+ }
+
+ int getTier() {
+ return mTier;
+ }
+
+ /**
+ * Set Bounding Box Tier within allowed bounds
+ *
+ * @param aTier new tier value
+ * @return effective new tier
+ */
+ int setTier(int aTier) {
+ if (aTier >= 0) {
+ mTier = Math.min(aTier, mMaxTier);
+ } else {
+ mTier = 0;
+ }
+ return mTier;
+ }
+
+ int getRange() {
+ return getRange(mTier);
+ }
+
+ int getRange(int aTier) {
+ return 1 << aTier;
+ }
+
+ int getDefaultTier() {
+ return mDefaultTier;
+ }
+
+ int getDefaultRange() {
+ return getRange(getDefaultTier());
+ }
+
+ int getMaxTier() {
+ return mMaxTier;
+ }
+
+ int getMaxRange() {
+ return getRange(getMaxTier());
+ }
+
+ private AxisAlignedBB getAxisAlignedBB() {
+ double tRange = getRange();
+ IGregTechTileEntity tBaseMetaTileEntity = mAbsorber.getBaseMetaTileEntity();
+ double tX = tBaseMetaTileEntity.getXCoord();
+ double tY = tBaseMetaTileEntity.getYCoord();
+ double tZ = tBaseMetaTileEntity.getZCoord();
+ return AxisAlignedBB
+ .getBoundingBox(tX - tRange, tY - tRange, tZ - tRange, tX + tRange, tY + tRange, tZ + tRange);
+ }
+
+ private void scanLivingCrystals() {
+ World tWorld = mAbsorber.getBaseMetaTileEntity()
+ .getWorld();
+ mLivingCrystalIDs.clear();
+ for (EntityEnderCrystal o : tWorld.getEntitiesWithinAABB(EntityEnderCrystal.class, getAxisAlignedBB())) {
+ if (o.isEntityAlive()) {
+ mLivingCrystalIDs.add(o.getPersistentID());
+ }
+ }
+ }
+
+ private void scanAvailableAspects() {
+ if (!THAUMCRAFT_LOADED) return;
+ IGregTechTileEntity tBaseMetaTileEntity = mAbsorber.getBaseMetaTileEntity();
+ if (tBaseMetaTileEntity.isInvalidTileEntity()) return;
+ int tRange = getRange();
+ int tY = tBaseMetaTileEntity.getYCoord();
+ int tMaxY = tBaseMetaTileEntity.getWorld()
+ .getHeight() - 1;
+ // Make sure relative Y range stays between 0 and world max Y
+ int rYMin = (tY - tRange >= 0) ? -tRange : -(tY);
+ int rYMax = (((tY + tRange) <= tMaxY) ? tRange : tMaxY - tY);
+ mAvailableAspects.clear();
+ for (int rX = -tRange; rX <= tRange; rX++) {
+ for (int rZ = -tRange; rZ <= tRange; rZ++) {
+ // rY < rYMax is not a bug. See: thaumcraft.common.lib.events.EssentiaHandler.getSources()
+ for (int rY = rYMin; rY < rYMax; rY++) {
+ TileEntity tTile = tBaseMetaTileEntity.getTileEntityOffset(rX, rY, rZ);
+ if (tTile instanceof IAspectContainer) {
+ AspectList tAspectList = ((IAspectContainer) tTile).getAspects();
+ if (tAspectList == null || tAspectList.aspects.isEmpty()) continue;
+ Set<Aspect> tAspects = tAspectList.aspects.keySet();
+ mAvailableAspects.addAll(tAspects);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * @return List of Living Ender Crystal Entity IDs in range
+ */
+ List<UUID> getLivingCrystalIDs() {
+ return mLivingCrystalIDs;
+ }
+
+ /**
+ * @return List of drainable Essentia Aspects from containers in range
+ */
+ List<Aspect> getAvailableAspects() {
+ return mAvailableAspects;
+ }
+
+ /**
+ * Scan range for magic sources
+ */
+ void update() {
+ if (mAbsorber == null) return;
+ if (mAbsorber.getBaseMetaTileEntity() == null) return;
+ if (mAbsorber.getBaseMetaTileEntity()
+ .isInvalidTileEntity()) return;
+ if (mAbsorber.getBaseMetaTileEntity()
+ .getWorld() == null) return;
+ scanLivingCrystals();
+ scanAvailableAspects();
+ if (mListener != null) {
+ mListener.onMagicalEnergyBBUpdate();
+ }
+ }
+
+ void increaseTier() {
+ offsetTier(1);
+ }
+
+ void decreaseTier() {
+ offsetTier(-1);
+ }
+
+ /**
+ * Change the Bounding Box tier relatively to offset with wrapping at tier limits
+ *
+ * @param aOffset relative tier change
+ */
+ void offsetTier(int aOffset) {
+ int tNumTiers = mMaxTier + 1;
+ int tTier = (mTier + aOffset + tNumTiers) % tNumTiers;
+ int tTrueTier = setTier(tTier);
+ if (tTier != tTrueTier) {
+ GT_Log.out.format("Absorber's BB Tier set to %d was capped to %d", tTier, tTrueTier);
+ }
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_NaquadahReactor.java b/src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_NaquadahReactor.java
new file mode 100644
index 0000000000..ba5aaf4c64
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_NaquadahReactor.java
@@ -0,0 +1,208 @@
+package gregtech.common.tileentities.generators;
+
+import static gregtech.api.enums.Textures.BlockIcons.NAQUADAH_REACTOR_SOLID_BACK;
+import static gregtech.api.enums.Textures.BlockIcons.NAQUADAH_REACTOR_SOLID_BACK_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.NAQUADAH_REACTOR_SOLID_BACK_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.NAQUADAH_REACTOR_SOLID_BACK_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.NAQUADAH_REACTOR_SOLID_BOTTOM;
+import static gregtech.api.enums.Textures.BlockIcons.NAQUADAH_REACTOR_SOLID_BOTTOM_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.NAQUADAH_REACTOR_SOLID_BOTTOM_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.NAQUADAH_REACTOR_SOLID_BOTTOM_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.NAQUADAH_REACTOR_SOLID_FRONT;
+import static gregtech.api.enums.Textures.BlockIcons.NAQUADAH_REACTOR_SOLID_FRONT_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.NAQUADAH_REACTOR_SOLID_FRONT_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.NAQUADAH_REACTOR_SOLID_FRONT_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.NAQUADAH_REACTOR_SOLID_SIDE;
+import static gregtech.api.enums.Textures.BlockIcons.NAQUADAH_REACTOR_SOLID_SIDE_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.NAQUADAH_REACTOR_SOLID_SIDE_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.NAQUADAH_REACTOR_SOLID_SIDE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.NAQUADAH_REACTOR_SOLID_TOP;
+import static gregtech.api.enums.Textures.BlockIcons.NAQUADAH_REACTOR_SOLID_TOP_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.NAQUADAH_REACTOR_SOLID_TOP_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.NAQUADAH_REACTOR_SOLID_TOP_GLOW;
+
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.ConfigCategories;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicGenerator;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.render.TextureFactory;
+
+public class GT_MetaTileEntity_NaquadahReactor extends GT_MetaTileEntity_BasicGenerator {
+
+ private int mEfficiency;
+
+ public GT_MetaTileEntity_NaquadahReactor(int aID, String aName, String[] aDescription, String aNameRegional,
+ int aTier) {
+ super(aID, aName, aNameRegional, aTier, aDescription);
+ if (aTier > 8 || aTier < 4) {
+ new Exception("Tier without Recipe Map!").printStackTrace();
+ }
+ onConfigLoad();
+ }
+
+ public GT_MetaTileEntity_NaquadahReactor(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ if (aTier > 8 || aTier < 4) {
+ new Exception("Tier without Recipe Map!").printStackTrace();
+ }
+ onConfigLoad();
+ }
+
+ @Override
+ public boolean isOutputFacing(ForgeDirection side) {
+ if (side == ForgeDirection.UNKNOWN) return false;
+ return ((side.flag & (ForgeDirection.UP.flag | ForgeDirection.DOWN.flag)) == 0)
+ && (side != getBaseMetaTileEntity().getFrontFacing())
+ && (side != getBaseMetaTileEntity().getBackFacing());
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_NaquadahReactor(mName, mTier, mDescriptionArray, mTextures);
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ RecipeMap<?> ret;
+ switch (mTier) {
+ case 4 -> ret = RecipeMaps.smallNaquadahReactorFuels;
+ case 5 -> ret = RecipeMaps.largeNaquadahReactorFuels;
+ case 6 -> ret = RecipeMaps.hugeNaquadahReactorFuels;
+ case 7 -> ret = RecipeMaps.extremeNaquadahReactorFuels;
+ case 8 -> ret = RecipeMaps.ultraHugeNaquadahReactorFuels;
+ default -> ret = null;
+ }
+ return ret;
+ }
+
+ @Override
+ public int getCapacity() {
+ return getRecipeMap() != null ? getRecipeMap().getBackend()
+ .getProperties().minFluidInputs > 0 ? 8000 * (mTier + 1) : 0 : 0;
+ }
+
+ @Override
+ public int getEfficiency() {
+ return mEfficiency == 0 ? onConfigLoad() : mEfficiency;
+ }
+
+ private int getBaseEff() {
+ return mTier == 4 ? 80 : 100 + (50 * (mTier - 5));
+ }
+
+ public int onConfigLoad() {
+ return mEfficiency = GregTech_API.sMachineFile
+ .get(ConfigCategories.machineconfig, "SolidNaquadah.efficiency.tier." + mTier, getBaseEff());
+ }
+
+ @Override
+ public ITexture[] getFront(byte aColor) {
+ return new ITexture[] { super.getFront(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(NAQUADAH_REACTOR_SOLID_FRONT),
+ TextureFactory.builder()
+ .addIcon(NAQUADAH_REACTOR_SOLID_FRONT_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public ITexture[] getBack(byte aColor) {
+ return new ITexture[] { super.getBack(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(NAQUADAH_REACTOR_SOLID_BACK),
+ TextureFactory.builder()
+ .addIcon(NAQUADAH_REACTOR_SOLID_BACK_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public ITexture[] getBottom(byte aColor) {
+ return new ITexture[] { super.getBottom(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(NAQUADAH_REACTOR_SOLID_BOTTOM),
+ TextureFactory.builder()
+ .addIcon(NAQUADAH_REACTOR_SOLID_BOTTOM_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public ITexture[] getTop(byte aColor) {
+ return new ITexture[] { super.getTop(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(NAQUADAH_REACTOR_SOLID_TOP),
+ TextureFactory.builder()
+ .addIcon(NAQUADAH_REACTOR_SOLID_TOP_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public ITexture[] getSides(byte aColor) {
+ return new ITexture[] { super.getSides(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(NAQUADAH_REACTOR_SOLID_SIDE),
+ TextureFactory.builder()
+ .addIcon(NAQUADAH_REACTOR_SOLID_SIDE_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public ITexture[] getFrontActive(byte aColor) {
+ return new ITexture[] { super.getFrontActive(aColor)[0], TextureFactory.of(NAQUADAH_REACTOR_SOLID_FRONT_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(NAQUADAH_REACTOR_SOLID_FRONT_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getBackActive(byte aColor) {
+ return new ITexture[] { super.getBackActive(aColor)[0], TextureFactory.of(NAQUADAH_REACTOR_SOLID_BACK_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(NAQUADAH_REACTOR_SOLID_BACK_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getBottomActive(byte aColor) {
+ return new ITexture[] { super.getBottomActive(aColor)[0],
+ TextureFactory.of(NAQUADAH_REACTOR_SOLID_BOTTOM_ACTIVE), TextureFactory.builder()
+ .addIcon(NAQUADAH_REACTOR_SOLID_BOTTOM_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getTopActive(byte aColor) {
+ return new ITexture[] { super.getTopActive(aColor)[0], TextureFactory.of(NAQUADAH_REACTOR_SOLID_TOP_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(NAQUADAH_REACTOR_SOLID_TOP_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getSidesActive(byte aColor) {
+ return new ITexture[] { super.getSidesActive(aColor)[0], TextureFactory.of(NAQUADAH_REACTOR_SOLID_SIDE_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(NAQUADAH_REACTOR_SOLID_SIDE_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public int getPollution() {
+ return 0;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_PlasmaGenerator.java b/src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_PlasmaGenerator.java
new file mode 100644
index 0000000000..603c1439ba
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_PlasmaGenerator.java
@@ -0,0 +1,147 @@
+package gregtech.common.tileentities.generators;
+
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASING_FUSION_GLASS;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASING_FUSION_GLASS_YELLOW;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASING_FUSION_GLASS_YELLOW_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAYS_ENERGY_OUT;
+
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.ConfigCategories;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicGenerator;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.render.TextureFactory;
+
+public class GT_MetaTileEntity_PlasmaGenerator extends GT_MetaTileEntity_BasicGenerator {
+
+ public int mEfficiency;
+
+ public GT_MetaTileEntity_PlasmaGenerator(int aID, String aName, String aNameRegional, int aTier) {
+ super(aID, aName, aNameRegional, aTier, "Plasma into energy");
+ onConfigLoad();
+ }
+
+ public GT_MetaTileEntity_PlasmaGenerator(String aName, int aTier, String aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ onConfigLoad();
+ }
+
+ public GT_MetaTileEntity_PlasmaGenerator(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ onConfigLoad();
+ }
+
+ @Override
+ public ITexture[] getFront(byte aColor) {
+ return new ITexture[] { super.getFront(aColor)[0], TextureFactory.of(MACHINE_CASING_FUSION_GLASS),
+ OVERLAYS_ENERGY_OUT[mTier] };
+ }
+
+ @Override
+ public ITexture[] getBack(byte aColor) {
+ return new ITexture[] { super.getBack(aColor)[0], TextureFactory.of(MACHINE_CASING_FUSION_GLASS) };
+ }
+
+ @Override
+ public ITexture[] getBottom(byte aColor) {
+ return new ITexture[] { super.getBottom(aColor)[0], TextureFactory.of(MACHINE_CASING_FUSION_GLASS) };
+ }
+
+ @Override
+ public ITexture[] getTop(byte aColor) {
+ return new ITexture[] { super.getTop(aColor)[0], TextureFactory.of(MACHINE_CASING_FUSION_GLASS) };
+ }
+
+ @Override
+ public ITexture[] getSides(byte aColor) {
+ return new ITexture[] { super.getSides(aColor)[0], TextureFactory.of(MACHINE_CASING_FUSION_GLASS) };
+ }
+
+ @Override
+ public ITexture[] getFrontActive(byte aColor) {
+ return new ITexture[] { super.getFrontActive(aColor)[0], TextureFactory.of(MACHINE_CASING_FUSION_GLASS_YELLOW),
+ TextureFactory.builder()
+ .addIcon(MACHINE_CASING_FUSION_GLASS_YELLOW_GLOW)
+ .glow()
+ .build(),
+ OVERLAYS_ENERGY_OUT[mTier] };
+ }
+
+ @Override
+ public ITexture[] getBackActive(byte aColor) {
+ return new ITexture[] { super.getBackActive(aColor)[0], TextureFactory.of(MACHINE_CASING_FUSION_GLASS_YELLOW),
+ TextureFactory.builder()
+ .addIcon(MACHINE_CASING_FUSION_GLASS_YELLOW_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getBottomActive(byte aColor) {
+ return new ITexture[] { super.getBottomActive(aColor)[0], TextureFactory.of(MACHINE_CASING_FUSION_GLASS_YELLOW),
+ TextureFactory.builder()
+ .addIcon(MACHINE_CASING_FUSION_GLASS_YELLOW_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getTopActive(byte aColor) {
+ return new ITexture[] { super.getTopActive(aColor)[0], TextureFactory.of(MACHINE_CASING_FUSION_GLASS_YELLOW),
+ TextureFactory.builder()
+ .addIcon(MACHINE_CASING_FUSION_GLASS_YELLOW_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getSidesActive(byte aColor) {
+ return new ITexture[] { super.getSidesActive(aColor)[0], TextureFactory.of(MACHINE_CASING_FUSION_GLASS_YELLOW),
+ TextureFactory.builder()
+ .addIcon(MACHINE_CASING_FUSION_GLASS_YELLOW_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public boolean isOutputFacing(ForgeDirection side) {
+ return side == getBaseMetaTileEntity().getFrontFacing();
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.plasmaFuels;
+ }
+
+ @Override
+ public int getEfficiency() {
+ return this.mEfficiency;
+ }
+
+ @Override
+ public int getCapacity() {
+ return 16000;
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_PlasmaGenerator(this.mName, this.mTier, this.mDescriptionArray, this.mTextures);
+ }
+
+ public void onConfigLoad() {
+ this.mEfficiency = GregTech_API.sMachineFile.get(
+ ConfigCategories.machineconfig,
+ "PlasmaGenerator.efficiency.tier." + this.mTier,
+ Math.max(10, 10 + Math.min(90, this.mTier * 10)));
+ }
+
+ @Override
+ public int getPollution() {
+ return 0;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_SteamTurbine.java b/src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_SteamTurbine.java
new file mode 100644
index 0000000000..3c9a89815a
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/generators/GT_MetaTileEntity_SteamTurbine.java
@@ -0,0 +1,245 @@
+package gregtech.common.tileentities.generators;
+
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAYS_ENERGY_OUT;
+import static gregtech.api.enums.Textures.BlockIcons.STEAM_TURBINE_BACK;
+import static gregtech.api.enums.Textures.BlockIcons.STEAM_TURBINE_BACK_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.STEAM_TURBINE_BACK_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.STEAM_TURBINE_BACK_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.STEAM_TURBINE_BOTTOM;
+import static gregtech.api.enums.Textures.BlockIcons.STEAM_TURBINE_BOTTOM_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.STEAM_TURBINE_BOTTOM_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.STEAM_TURBINE_BOTTOM_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.STEAM_TURBINE_FRONT;
+import static gregtech.api.enums.Textures.BlockIcons.STEAM_TURBINE_FRONT_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.STEAM_TURBINE_FRONT_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.STEAM_TURBINE_FRONT_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.STEAM_TURBINE_SIDE;
+import static gregtech.api.enums.Textures.BlockIcons.STEAM_TURBINE_SIDE_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.STEAM_TURBINE_SIDE_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.STEAM_TURBINE_SIDE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.STEAM_TURBINE_TOP;
+import static gregtech.api.enums.Textures.BlockIcons.STEAM_TURBINE_TOP_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.STEAM_TURBINE_TOP_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.STEAM_TURBINE_TOP_GLOW;
+
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidStack;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.ConfigCategories;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicGenerator;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_ModHandler;
+
+public class GT_MetaTileEntity_SteamTurbine extends GT_MetaTileEntity_BasicGenerator {
+
+ public int mEfficiency;
+
+ public GT_MetaTileEntity_SteamTurbine(int aID, String aName, String aNameRegional, int aTier) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ new String[] { "Converts Steam into EU", "Base rate: 2L of Steam -> 1 EU" });
+ onConfigLoad();
+ }
+
+ public GT_MetaTileEntity_SteamTurbine(String aName, int aTier, String aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ onConfigLoad();
+ }
+
+ public GT_MetaTileEntity_SteamTurbine(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ onConfigLoad();
+ }
+
+ @Override
+ public boolean isOutputFacing(ForgeDirection side) {
+ return side == getBaseMetaTileEntity().getFrontFacing();
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_SteamTurbine(this.mName, this.mTier, this.mDescriptionArray, this.mTextures);
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return null;
+ }
+
+ @Override
+ public String[] getDescription() {
+ String[] desc = new String[mDescriptionArray.length + 2];
+ System.arraycopy(mDescriptionArray, 0, desc, 0, mDescriptionArray.length);
+ desc[mDescriptionArray.length] = "Fuel Efficiency: " + (600 / getEfficiency()) + "%";
+ desc[mDescriptionArray.length + 1] = String.format(
+ "Consumes up to %sL of Steam per second",
+ (int) (4000 * (8 * Math.pow(4, mTier) + Math.pow(2, Math.max(mTier - 1, 0))) / (600 / getEfficiency())));
+ return desc;
+ }
+
+ @Override
+ public int getCapacity() {
+ return 24000 * this.mTier;
+ }
+
+ public void onConfigLoad() {
+ this.mEfficiency = GregTech_API.sMachineFile
+ .get(ConfigCategories.machineconfig, "SteamTurbine.efficiency.tier." + this.mTier, 6 + this.mTier);
+ }
+
+ @Override
+ public int getEfficiency() {
+ return this.mEfficiency;
+ }
+
+ @Override
+ public long getFuelValue(FluidStack aLiquid, boolean aLong) {
+ return getFuelValue(aLiquid);
+ }
+
+ @Override
+ public int getFuelValue(FluidStack aLiquid) {
+ if (aLiquid == null) return 0;
+ return GT_ModHandler.isAnySteam(aLiquid) ? 3 : 0;
+ }
+
+ @Override
+ public int consumedFluidPerOperation(FluidStack aLiquid) {
+ return this.mEfficiency;
+ }
+
+ @Override
+ public ITexture[] getFront(byte aColor) {
+ return new ITexture[] { super.getFront(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(STEAM_TURBINE_FRONT),
+ TextureFactory.builder()
+ .addIcon(STEAM_TURBINE_FRONT_GLOW)
+ .glow()
+ .build()),
+ OVERLAYS_ENERGY_OUT[this.mTier] };
+ }
+
+ @Override
+ public ITexture[] getBack(byte aColor) {
+ return new ITexture[] { super.getBack(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(STEAM_TURBINE_BACK),
+ TextureFactory.builder()
+ .addIcon(STEAM_TURBINE_BACK_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public ITexture[] getBottom(byte aColor) {
+ return new ITexture[] { super.getBottom(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(STEAM_TURBINE_BOTTOM),
+ TextureFactory.builder()
+ .addIcon(STEAM_TURBINE_BOTTOM_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public ITexture[] getTop(byte aColor) {
+ return new ITexture[] { super.getTop(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(STEAM_TURBINE_TOP),
+ TextureFactory.builder()
+ .addIcon(STEAM_TURBINE_TOP_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public ITexture[] getSides(byte aColor) {
+ return new ITexture[] { super.getSides(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(STEAM_TURBINE_SIDE),
+ TextureFactory.builder()
+ .addIcon(STEAM_TURBINE_SIDE_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public ITexture[] getFrontActive(byte aColor) {
+ return new ITexture[] { super.getFrontActive(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(STEAM_TURBINE_FRONT_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(STEAM_TURBINE_FRONT_ACTIVE_GLOW)
+ .glow()
+ .build()),
+ OVERLAYS_ENERGY_OUT[this.mTier] };
+ }
+
+ @Override
+ public ITexture[] getBackActive(byte aColor) {
+ return new ITexture[] { super.getBackActive(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(STEAM_TURBINE_BACK_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(STEAM_TURBINE_BACK_ACTIVE_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public ITexture[] getBottomActive(byte aColor) {
+ return new ITexture[] { super.getBottomActive(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(STEAM_TURBINE_BOTTOM_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(STEAM_TURBINE_BOTTOM_ACTIVE_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public ITexture[] getTopActive(byte aColor) {
+ return new ITexture[] { super.getTopActive(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(STEAM_TURBINE_TOP_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(STEAM_TURBINE_TOP_ACTIVE_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public ITexture[] getSidesActive(byte aColor) {
+ return new ITexture[] { super.getSidesActive(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(STEAM_TURBINE_SIDE_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(STEAM_TURBINE_SIDE_ACTIVE_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public int getPollution() {
+ return 0;
+ }
+
+ @Override
+ public boolean isFluidInputAllowed(FluidStack aFluid) {
+ if (GT_ModHandler.isSuperHeatedSteam(aFluid)) {
+ aFluid.amount = 0;
+ aFluid = null;
+ return false;
+ }
+ return super.isFluidInputAllowed(aFluid);
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_BasicHull_Bronze.java b/src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_BasicHull_Bronze.java
new file mode 100644
index 0000000000..252cc6a5b8
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_BasicHull_Bronze.java
@@ -0,0 +1,45 @@
+package gregtech.common.tileentities.machines;
+
+import gregtech.api.enums.Dyes;
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicHull_NonElectric;
+import gregtech.api.render.TextureFactory;
+
+public class GT_MetaTileEntity_BasicHull_Bronze extends GT_MetaTileEntity_BasicHull_NonElectric {
+
+ public GT_MetaTileEntity_BasicHull_Bronze(int aID, String aName, String aNameRegional, int aTier,
+ String aDescription) {
+ super(aID, aName, aNameRegional, aTier, aDescription);
+ }
+
+ public GT_MetaTileEntity_BasicHull_Bronze(String aName, int aTier, String aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_BasicHull_Bronze(String aName, int aTier, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_BasicHull_Bronze(this.mName, this.mTier, this.mDescriptionArray, this.mTextures);
+ }
+
+ @Override
+ public ITexture[][][] getTextureSet(ITexture[] aTextures) {
+ ITexture[][][] rTextures = new ITexture[3][17][];
+ for (byte i = -1; i < 16; i = (byte) (i + 1)) {
+ rTextures[0][(i + 1)] = new ITexture[] {
+ TextureFactory.of(Textures.BlockIcons.MACHINE_BRONZE_BOTTOM, Dyes.getModulation(i, Dyes._NULL.mRGBa)) };
+ rTextures[1][(i + 1)] = new ITexture[] {
+ TextureFactory.of(Textures.BlockIcons.MACHINE_BRONZE_TOP, Dyes.getModulation(i, Dyes._NULL.mRGBa)) };
+ rTextures[2][(i + 1)] = new ITexture[] {
+ TextureFactory.of(Textures.BlockIcons.MACHINE_BRONZE_SIDE, Dyes.getModulation(i, Dyes._NULL.mRGBa)) };
+ }
+ return rTextures;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_BasicHull_BronzeBricks.java b/src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_BasicHull_BronzeBricks.java
new file mode 100644
index 0000000000..ee788ba8c0
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_BasicHull_BronzeBricks.java
@@ -0,0 +1,53 @@
+package gregtech.common.tileentities.machines;
+
+import gregtech.api.enums.Dyes;
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicHull_NonElectric;
+import gregtech.api.render.TextureFactory;
+
+public class GT_MetaTileEntity_BasicHull_BronzeBricks extends GT_MetaTileEntity_BasicHull_NonElectric {
+
+ public GT_MetaTileEntity_BasicHull_BronzeBricks(int aID, String aName, String aNameRegional, int aTier,
+ String aDescription) {
+ super(aID, aName, aNameRegional, aTier, aDescription);
+ }
+
+ public GT_MetaTileEntity_BasicHull_BronzeBricks(String aName, int aTier, String aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_BasicHull_BronzeBricks(String aName, int aTier, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_BasicHull_BronzeBricks(
+ this.mName,
+ this.mTier,
+ this.mDescriptionArray,
+ this.mTextures);
+ }
+
+ @Override
+ public ITexture[][][] getTextureSet(ITexture[] aTextures) {
+ ITexture[][][] rTextures = new ITexture[3][17][];
+ for (byte i = -1; i < 16; i = (byte) (i + 1)) {
+ ITexture[] tmp0 = { TextureFactory
+ .of(Textures.BlockIcons.MACHINE_BRONZEBRICKS_BOTTOM, Dyes.getModulation(i, Dyes._NULL.mRGBa)) };
+ rTextures[0][(i + 1)] = tmp0;
+ ITexture[] tmp1 = { TextureFactory
+ .of(Textures.BlockIcons.MACHINE_BRONZEBRICKS_TOP, Dyes.getModulation(i, Dyes._NULL.mRGBa)) };
+ rTextures[1][(i + 1)] = tmp1;
+ ITexture[] tmp2 = { TextureFactory
+ .of(Textures.BlockIcons.MACHINE_BRONZEBRICKS_SIDE, Dyes.getModulation(i, Dyes._NULL.mRGBa)) };
+ rTextures[2][(i + 1)] = tmp2;
+ }
+ return rTextures;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_BasicHull_Steel.java b/src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_BasicHull_Steel.java
new file mode 100644
index 0000000000..85e461bf47
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_BasicHull_Steel.java
@@ -0,0 +1,47 @@
+package gregtech.common.tileentities.machines;
+
+import gregtech.api.enums.Dyes;
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicHull_NonElectric;
+import gregtech.api.render.TextureFactory;
+
+public class GT_MetaTileEntity_BasicHull_Steel extends GT_MetaTileEntity_BasicHull_NonElectric {
+
+ public GT_MetaTileEntity_BasicHull_Steel(int aID, String aName, String aNameRegional, int aTier,
+ String aDescription) {
+ super(aID, aName, aNameRegional, aTier, aDescription);
+ }
+
+ public GT_MetaTileEntity_BasicHull_Steel(String aName, int aTier, String aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_BasicHull_Steel(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_BasicHull_Steel(this.mName, this.mTier, this.mDescriptionArray, this.mTextures);
+ }
+
+ @Override
+ public ITexture[][][] getTextureSet(ITexture[] aTextures) {
+ ITexture[][][] rTextures = new ITexture[3][17][];
+ for (byte i = -1; i < 16; i = (byte) (i + 1)) {
+ ITexture[] tmp0 = {
+ TextureFactory.of(Textures.BlockIcons.MACHINE_STEEL_BOTTOM, Dyes.getModulation(i, Dyes._NULL.mRGBa)) };
+ rTextures[0][(i + 1)] = tmp0;
+ ITexture[] tmp1 = {
+ TextureFactory.of(Textures.BlockIcons.MACHINE_STEEL_TOP, Dyes.getModulation(i, Dyes._NULL.mRGBa)) };
+ rTextures[1][(i + 1)] = tmp1;
+ ITexture[] tmp2 = {
+ TextureFactory.of(Textures.BlockIcons.MACHINE_STEEL_SIDE, Dyes.getModulation(i, Dyes._NULL.mRGBa)) };
+ rTextures[2][(i + 1)] = tmp2;
+ }
+ return rTextures;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_BasicHull_SteelBricks.java b/src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_BasicHull_SteelBricks.java
new file mode 100644
index 0000000000..cd5f547d22
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_BasicHull_SteelBricks.java
@@ -0,0 +1,53 @@
+package gregtech.common.tileentities.machines;
+
+import gregtech.api.enums.Dyes;
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicHull_NonElectric;
+import gregtech.api.render.TextureFactory;
+
+public class GT_MetaTileEntity_BasicHull_SteelBricks extends GT_MetaTileEntity_BasicHull_NonElectric {
+
+ public GT_MetaTileEntity_BasicHull_SteelBricks(int aID, String aName, String aNameRegional, int aTier,
+ String aDescription) {
+ super(aID, aName, aNameRegional, aTier, aDescription);
+ }
+
+ public GT_MetaTileEntity_BasicHull_SteelBricks(String aName, int aTier, String aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_BasicHull_SteelBricks(String aName, int aTier, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_BasicHull_SteelBricks(
+ this.mName,
+ this.mTier,
+ this.mDescriptionArray,
+ this.mTextures);
+ }
+
+ @Override
+ public ITexture[][][] getTextureSet(ITexture[] aTextures) {
+ ITexture[][][] rTextures = new ITexture[3][17][];
+ for (byte i = -1; i < 16; i = (byte) (i + 1)) {
+ ITexture[] tmp0 = { TextureFactory
+ .of(Textures.BlockIcons.MACHINE_STEELBRICKS_BOTTOM, Dyes.getModulation(i, Dyes._NULL.mRGBa)) };
+ rTextures[0][(i + 1)] = tmp0;
+ ITexture[] tmp1 = { TextureFactory
+ .of(Textures.BlockIcons.MACHINE_STEELBRICKS_TOP, Dyes.getModulation(i, Dyes._NULL.mRGBa)) };
+ rTextures[1][(i + 1)] = tmp1;
+ ITexture[] tmp2 = { TextureFactory
+ .of(Textures.BlockIcons.MACHINE_STEELBRICKS_SIDE, Dyes.getModulation(i, Dyes._NULL.mRGBa)) };
+ rTextures[2][(i + 1)] = tmp2;
+ }
+ return rTextures;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_Hatch_CraftingInput_ME.java b/src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_Hatch_CraftingInput_ME.java
new file mode 100644
index 0000000000..f7ba3af5f0
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_Hatch_CraftingInput_ME.java
@@ -0,0 +1,1039 @@
+package gregtech.common.tileentities.machines;
+
+import static gregtech.api.enums.GT_Values.TIER_COLORS;
+import static gregtech.api.enums.GT_Values.VN;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_ME_CRAFTING_INPUT_BUFFER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_ME_CRAFTING_INPUT_BUS;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+import javax.annotation.Nullable;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.inventory.IInventory;
+import net.minecraft.inventory.InventoryCrafting;
+import net.minecraft.inventory.Slot;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.ChatComponentTranslation;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.Constants;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.event.ForgeEventFactory;
+import net.minecraftforge.fluids.FluidStack;
+
+import org.apache.commons.lang3.ArrayUtils;
+import org.jetbrains.annotations.NotNull;
+
+import com.glodblock.github.common.item.ItemFluidPacket;
+import com.google.common.collect.ImmutableList;
+import com.gtnewhorizons.modularui.api.math.Alignment;
+import com.gtnewhorizons.modularui.api.math.Size;
+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.SlotGroup;
+import com.gtnewhorizons.modularui.common.widget.SlotWidget;
+
+import appeng.api.AEApi;
+import appeng.api.implementations.ICraftingPatternItem;
+import appeng.api.implementations.IPowerChannelState;
+import appeng.api.networking.GridFlags;
+import appeng.api.networking.IGridNode;
+import appeng.api.networking.crafting.ICraftingPatternDetails;
+import appeng.api.networking.crafting.ICraftingProvider;
+import appeng.api.networking.crafting.ICraftingProviderHelper;
+import appeng.api.networking.events.MENetworkCraftingPatternChange;
+import appeng.api.networking.security.BaseActionSource;
+import appeng.api.networking.security.IActionHost;
+import appeng.api.networking.security.MachineSource;
+import appeng.api.storage.IMEMonitor;
+import appeng.api.storage.data.IAEFluidStack;
+import appeng.api.storage.data.IAEItemStack;
+import appeng.api.util.AECableType;
+import appeng.api.util.DimensionalCoord;
+import appeng.api.util.IInterfaceViewable;
+import appeng.core.AppEng;
+import appeng.core.sync.GuiBridge;
+import appeng.helpers.ICustomNameObject;
+import appeng.items.misc.ItemEncodedPattern;
+import appeng.items.tools.quartz.ToolQuartzCuttingKnife;
+import appeng.me.GridAccessException;
+import appeng.me.helpers.AENetworkProxy;
+import appeng.me.helpers.IGridProxyable;
+import appeng.util.IWideReadableNumberConverter;
+import appeng.util.Platform;
+import appeng.util.ReadableNumberConverter;
+import gregtech.GT_Mod;
+import gregtech.api.enums.ItemList;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.IConfigurationCircuitSupport;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.modularui.IAddGregtechLogo;
+import gregtech.api.interfaces.modularui.IAddUIWidgets;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_InputBus;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.extensions.ArrayExt;
+import mcp.mobius.waila.api.IWailaConfigHandler;
+import mcp.mobius.waila.api.IWailaDataAccessor;
+
+public class GT_MetaTileEntity_Hatch_CraftingInput_ME extends GT_MetaTileEntity_Hatch_InputBus
+ implements IConfigurationCircuitSupport, IAddGregtechLogo, IAddUIWidgets, IPowerChannelState, ICraftingProvider,
+ IGridProxyable, IDualInputHatch, ICustomNameObject, IInterfaceViewable {
+
+ // Each pattern slot in the crafting input hatch has its own internal inventory
+ public static class PatternSlot implements IDualInputInventory {
+
+ public interface SharedItemGetter {
+
+ ItemStack[] getSharedItem();
+ }
+
+ private final ItemStack pattern;
+ private final ICraftingPatternDetails patternDetails;
+ private final List<ItemStack> itemInventory;
+ private final List<FluidStack> fluidInventory;
+ private final SharedItemGetter sharedItemGetter;
+
+ public PatternSlot(ItemStack pattern, World world, SharedItemGetter getter) {
+ this.pattern = pattern;
+ this.patternDetails = ((ICraftingPatternItem) Objects.requireNonNull(pattern.getItem()))
+ .getPatternForItem(pattern, world);
+ this.itemInventory = new ArrayList<>();
+ this.fluidInventory = new ArrayList<>();
+ this.sharedItemGetter = getter;
+ }
+
+ public PatternSlot(ItemStack pattern, NBTTagCompound nbt, World world, SharedItemGetter getter) {
+ this.pattern = pattern;
+ this.patternDetails = ((ICraftingPatternItem) Objects.requireNonNull(pattern.getItem()))
+ .getPatternForItem(pattern, world);
+ this.itemInventory = new ArrayList<>();
+ this.fluidInventory = new ArrayList<>();
+ this.sharedItemGetter = getter;
+ NBTTagList inv = nbt.getTagList("inventory", Constants.NBT.TAG_COMPOUND);
+ for (int i = 0; i < inv.tagCount(); i++) {
+ NBTTagCompound tagItemStack = inv.getCompoundTagAt(i);
+ var item = GT_Utility.loadItem(tagItemStack);
+ if (item != null) {
+ if (item.stackSize > 0) {
+ itemInventory.add(item);
+ }
+ } else {
+ GT_Mod.GT_FML_LOGGER.warn(
+ "An error occurred while loading contents of ME Crafting Input Bus. This item has been voided: "
+ + tagItemStack);
+ }
+ }
+ NBTTagList fluidInv = nbt.getTagList("fluidInventory", Constants.NBT.TAG_COMPOUND);
+ for (int i = 0; i < fluidInv.tagCount(); i++) {
+ NBTTagCompound tagFluidStack = fluidInv.getCompoundTagAt(i);
+ var fluid = FluidStack.loadFluidStackFromNBT(tagFluidStack);
+ if (fluid != null) {
+ if (fluid.amount > 0) {
+ fluidInventory.add(fluid);
+ }
+ } else {
+ GT_Mod.GT_FML_LOGGER.warn(
+ "An error occurred while loading contents of ME Crafting Input Bus. This fluid has been voided: "
+ + tagFluidStack);
+ }
+ }
+ }
+
+ public boolean hasChanged(ItemStack newPattern, World world) {
+ return newPattern == null
+ || (!ItemStack.areItemStacksEqual(pattern, newPattern) && !this.patternDetails.equals(
+ ((ICraftingPatternItem) Objects.requireNonNull(pattern.getItem()))
+ .getPatternForItem(newPattern, world)));
+ }
+
+ private boolean isEmpty() {
+ // if one item / fluid is empty then it should be safe to assume all other is empty,
+ // or at least won't require a recipe check, as long as the pattern is sane
+ if (!itemInventory.isEmpty()) {
+ return itemInventory.get(0) == null || itemInventory.get(0).stackSize <= 0;
+ }
+
+ if (!fluidInventory.isEmpty()) {
+ return fluidInventory.get(0) == null || fluidInventory.get(0).amount <= 0;
+ }
+ return true;
+ }
+
+ @Override
+ public ItemStack[] getItemInputs() {
+ if (isEmpty()) return new ItemStack[0];
+ return ArrayUtils.addAll(itemInventory.toArray(new ItemStack[0]), sharedItemGetter.getSharedItem());
+ }
+
+ @Override
+ public FluidStack[] getFluidInputs() {
+ if (isEmpty()) return new FluidStack[0];
+ return fluidInventory.toArray(new FluidStack[0]);
+ }
+
+ public ICraftingPatternDetails getPatternDetails() {
+ return patternDetails;
+ }
+
+ public void refund(AENetworkProxy proxy, BaseActionSource src) throws GridAccessException {
+ IMEMonitor<IAEItemStack> sg = proxy.getStorage()
+ .getItemInventory();
+ for (ItemStack itemStack : itemInventory) {
+ if (itemStack == null || itemStack.stackSize == 0) continue;
+ IAEItemStack rest = Platform.poweredInsert(
+ proxy.getEnergy(),
+ sg,
+ AEApi.instance()
+ .storage()
+ .createItemStack(itemStack),
+ src);
+ itemStack.stackSize = rest != null && rest.getStackSize() > 0 ? (int) rest.getStackSize() : 0;
+ }
+ IMEMonitor<IAEFluidStack> fsg = proxy.getStorage()
+ .getFluidInventory();
+ for (FluidStack fluidStack : fluidInventory) {
+ if (fluidStack == null || fluidStack.amount == 0) continue;
+ IAEFluidStack rest = Platform.poweredInsert(
+ proxy.getEnergy(),
+ fsg,
+ AEApi.instance()
+ .storage()
+ .createFluidStack(fluidStack),
+ src);
+ fluidStack.amount = rest != null && rest.getStackSize() > 0 ? (int) rest.getStackSize() : 0;
+ }
+ }
+
+ public boolean insertItemsAndFluids(InventoryCrafting inventoryCrafting) {
+ int errorIndex = -1; // overflow may occur at this index
+ for (int i = 0; i < inventoryCrafting.getSizeInventory(); ++i) {
+ ItemStack itemStack = inventoryCrafting.getStackInSlot(i);
+ if (itemStack == null) continue;
+
+ boolean inserted = false;
+ if (itemStack.getItem() instanceof ItemFluidPacket) { // insert fluid
+ var fluidStack = ItemFluidPacket.getFluidStack(itemStack);
+ if (fluidStack == null) continue;
+ for (var fluid : fluidInventory) {
+ if (!fluid.isFluidEqual(fluidStack)) continue;
+ if (Integer.MAX_VALUE - fluidStack.amount < fluid.amount) {
+ // Overflow detected
+ errorIndex = i;
+ break;
+ }
+ fluid.amount += fluidStack.amount;
+ inserted = true;
+ break;
+ }
+ if (errorIndex != -1) break;
+ if (!inserted) {
+ fluidInventory.add(fluidStack);
+ }
+ } else { // insert item
+ for (var item : itemInventory) {
+ if (!itemStack.isItemEqual(item)) continue;
+ if (Integer.MAX_VALUE - itemStack.stackSize < item.stackSize) {
+ // Overflow detected
+ errorIndex = i;
+ break;
+ }
+ item.stackSize += itemStack.stackSize;
+ inserted = true;
+ break;
+ }
+ if (errorIndex != -1) break;
+ if (!inserted) {
+ itemInventory.add(itemStack);
+ }
+ }
+ }
+ if (errorIndex != -1) { // need to rollback
+ // Clean up the inserted items/liquids
+ for (int i = 0; i < errorIndex; ++i) {
+ var itemStack = inventoryCrafting.getStackInSlot(i);
+ if (itemStack == null) continue;
+ if (itemStack.getItem() instanceof ItemFluidPacket) { // remove fluid
+ var fluidStack = ItemFluidPacket.getFluidStack(itemStack);
+ if (fluidStack == null) continue;
+ for (var fluid : fluidInventory) {
+ if (fluid.isFluidEqual(fluidStack)) {
+ fluid.amount -= fluidStack.amount;
+ break;
+ }
+ }
+ } else { // remove item
+ for (var item : itemInventory) {
+ if (item.isItemEqual(itemStack)) {
+ item.stackSize -= itemStack.stackSize;
+ break;
+ }
+ }
+ }
+ }
+ return false;
+ }
+ return true;
+ }
+
+ public NBTTagCompound writeToNBT(NBTTagCompound nbt) {
+ nbt.setTag("pattern", pattern.writeToNBT(new NBTTagCompound()));
+
+ NBTTagList itemInventoryNbt = new NBTTagList();
+ for (ItemStack itemStack : this.itemInventory) {
+ itemInventoryNbt.appendTag(GT_Utility.saveItem(itemStack));
+ }
+ nbt.setTag("inventory", itemInventoryNbt);
+
+ NBTTagList fluidInventoryNbt = new NBTTagList();
+ for (FluidStack fluidStack : fluidInventory) {
+ fluidInventoryNbt.appendTag(fluidStack.writeToNBT(new NBTTagCompound()));
+ }
+ nbt.setTag("fluidInventory", fluidInventoryNbt);
+
+ return nbt;
+ }
+ }
+
+ // mInventory is used for storing patterns, circuit and manual slot (typically NC items)
+ private static final int MAX_PATTERN_COUNT = 4 * 9;
+ private static final int SLOT_MANUAL_SIZE = 9;
+ private static final int MAX_INV_COUNT = MAX_PATTERN_COUNT + SLOT_MANUAL_SIZE + 1;
+ private static final int SLOT_CIRCUIT = MAX_PATTERN_COUNT;
+ private static final int SLOT_MANUAL_START = SLOT_CIRCUIT + 1;
+ private static final int MANUAL_SLOT_WINDOW = 10;
+ private BaseActionSource requestSource = null;
+ private @Nullable AENetworkProxy gridProxy = null;
+
+ // holds all internal inventories
+ private PatternSlot[] internalInventory = new PatternSlot[MAX_PATTERN_COUNT];
+
+ // a hash map for faster lookup of pattern slots, not necessarily all valid.
+ private Map<ICraftingPatternDetails, PatternSlot> patternDetailsPatternSlotMap = new HashMap<>(MAX_PATTERN_COUNT);
+
+ private boolean needPatternSync = true;
+ private boolean justHadNewItems = false;
+
+ private String customName = null;
+ private boolean supportFluids;
+ private boolean additionalConnection = false;
+
+ public GT_MetaTileEntity_Hatch_CraftingInput_ME(int aID, String aName, String aNameRegional,
+ boolean supportFluids) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ supportFluids ? 11 : 6,
+ MAX_INV_COUNT,
+ new String[] { "Advanced item input for Multiblocks",
+ "Hatch Tier: " + TIER_COLORS[supportFluids ? 11 : 6] + VN[supportFluids ? 11 : 6],
+ "Processes patterns directly from ME",
+ supportFluids ? "It supports patterns including fluids"
+ : "It does not support patterns including fluids",
+ "Change ME connection behavior by right-clicking with wire cutter" });
+ disableSort = true;
+ this.supportFluids = supportFluids;
+ }
+
+ public GT_MetaTileEntity_Hatch_CraftingInput_ME(String aName, int aTier, String[] aDescription,
+ ITexture[][][] aTextures, boolean supportFluids) {
+ super(aName, aTier, MAX_INV_COUNT, aDescription, aTextures);
+ this.supportFluids = supportFluids;
+ disableSort = true;
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Hatch_CraftingInput_ME(mName, mTier, mDescriptionArray, mTextures, supportFluids);
+ }
+
+ @Override
+ public ITexture[] getTexturesActive(ITexture aBaseTexture) {
+ return getTexturesInactive(aBaseTexture);
+ }
+
+ @Override
+ public ITexture[] getTexturesInactive(ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture,
+ TextureFactory.of(supportFluids ? OVERLAY_ME_CRAFTING_INPUT_BUFFER : OVERLAY_ME_CRAFTING_INPUT_BUS) };
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTimer) {
+ super.onPostTick(aBaseMetaTileEntity, aTimer);
+
+ if (getBaseMetaTileEntity().isServerSide()) {
+ if (needPatternSync && aTimer % 10 == 0) {
+ needPatternSync = !postMEPatternChange();
+ }
+ if (aTimer % 20 == 0) {
+ getBaseMetaTileEntity().setActive(isActive());
+ }
+ }
+ }
+
+ @Override
+ public void onFirstTick(IGregTechTileEntity aBaseMetaTileEntity) {
+ super.onFirstTick(aBaseMetaTileEntity);
+ getProxy().onReady();
+ }
+
+ @Override
+ public IGridNode getGridNode(ForgeDirection dir) {
+ return getProxy().getNode();
+ }
+
+ @Override
+ public AECableType getCableConnectionType(ForgeDirection forgeDirection) {
+ return isOutputFacing(forgeDirection) ? AECableType.SMART : AECableType.NONE;
+ }
+
+ private void updateValidGridProxySides() {
+ if (additionalConnection) {
+ getProxy().setValidSides(EnumSet.complementOf(EnumSet.of(ForgeDirection.UNKNOWN)));
+ } else {
+ getProxy().setValidSides(EnumSet.of(getBaseMetaTileEntity().getFrontFacing()));
+ }
+ }
+
+ @Override
+ public void onFacingChange() {
+ updateValidGridProxySides();
+ }
+
+ @Override
+ public void securityBreak() {}
+
+ @Override
+ public boolean onWireCutterRightClick(ForgeDirection side, ForgeDirection wrenchingSide, EntityPlayer aPlayer,
+ float aX, float aY, float aZ) {
+ additionalConnection = !additionalConnection;
+ updateValidGridProxySides();
+ aPlayer.addChatComponentMessage(
+ new ChatComponentTranslation("GT5U.hatch.additionalConnection." + additionalConnection));
+ return true;
+ }
+
+ @Override
+ public AENetworkProxy getProxy() {
+ if (gridProxy == null) {
+ gridProxy = new AENetworkProxy(this, "proxy", ItemList.Hatch_CraftingInput_Bus_ME.get(1), true);
+ gridProxy.setFlags(GridFlags.REQUIRE_CHANNEL);
+ updateValidGridProxySides();
+ if (getBaseMetaTileEntity().getWorld() != null) gridProxy.setOwner(
+ getBaseMetaTileEntity().getWorld()
+ .getPlayerEntityByName(getBaseMetaTileEntity().getOwnerName()));
+ }
+
+ return this.gridProxy;
+ }
+
+ @Override
+ public DimensionalCoord getLocation() {
+ return new DimensionalCoord(
+ getBaseMetaTileEntity().getWorld(),
+ getBaseMetaTileEntity().getXCoord(),
+ getBaseMetaTileEntity().getYCoord(),
+ getBaseMetaTileEntity().getZCoord());
+ }
+
+ @Override
+ public int rows() {
+ return 4;
+ }
+
+ @Override
+ public int rowSize() {
+ return 9;
+ }
+
+ @Override
+ public IInventory getPatterns() {
+ return this;
+ }
+
+ @Override
+ public String getName() {
+ if (hasCustomName()) {
+ return getCustomName();
+ }
+ StringBuilder name = new StringBuilder();
+ if (getCrafterIcon() != null) {
+ name.append(getCrafterIcon().getDisplayName());
+ } else {
+ name.append(getLocalName());
+ }
+
+ if (mInventory[SLOT_CIRCUIT] != null) {
+ name.append(" - ");
+ name.append(mInventory[SLOT_CIRCUIT].getItemDamage());
+ }
+ if (mInventory[SLOT_MANUAL_START] != null) {
+ name.append(" - ");
+ name.append(mInventory[SLOT_MANUAL_START].getDisplayName());
+ }
+ return name.toString();
+ }
+
+ @Override
+ public TileEntity getTileEntity() {
+ return (TileEntity) getBaseMetaTileEntity();
+ }
+
+ @Override
+ public boolean shouldDisplay() {
+ return true;
+ }
+
+ @Override
+ public void gridChanged() {
+ needPatternSync = true;
+ }
+
+ @Override
+ public boolean isPowered() {
+ return getProxy() != null && getProxy().isPowered();
+ }
+
+ @Override
+ public boolean isActive() {
+ return getProxy() != null && getProxy().isActive();
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+
+ // save internalInventory
+ NBTTagList internalInventoryNBT = new NBTTagList();
+ for (int i = 0; i < internalInventory.length; i++) {
+ if (internalInventory[i] != null) {
+ NBTTagCompound internalInventorySlotNBT = new NBTTagCompound();
+ internalInventorySlotNBT.setInteger("patternSlot", i);
+ internalInventorySlotNBT
+ .setTag("patternSlotNBT", internalInventory[i].writeToNBT(new NBTTagCompound()));
+ internalInventoryNBT.appendTag(internalInventorySlotNBT);
+ }
+ }
+ aNBT.setTag("internalInventory", internalInventoryNBT);
+ if (customName != null) aNBT.setString("customName", customName);
+ aNBT.setBoolean("additionalConnection", additionalConnection);
+ getProxy().writeToNBT(aNBT);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ // load internalInventory
+ NBTTagList internalInventoryNBT = aNBT.getTagList("internalInventory", Constants.NBT.TAG_COMPOUND);
+ for (int i = 0; i < internalInventoryNBT.tagCount(); i++) {
+ NBTTagCompound internalInventorySlotNBT = internalInventoryNBT.getCompoundTagAt(i);
+ int patternSlot = internalInventorySlotNBT.getInteger("patternSlot");
+ NBTTagCompound patternSlotNBT = internalInventorySlotNBT.getCompoundTag("patternSlotNBT");
+ ItemStack pattern = ItemStack.loadItemStackFromNBT(patternSlotNBT.getCompoundTag("pattern"));
+ if (pattern != null) {
+ internalInventory[patternSlot] = new PatternSlot(
+ pattern,
+ patternSlotNBT,
+ getBaseMetaTileEntity().getWorld(),
+ this::getSharedItems);
+ } else {
+ GT_Mod.GT_FML_LOGGER.warn(
+ "An error occurred while loading contents of ME Crafting Input Bus. This pattern has been voided: "
+ + patternSlotNBT);
+ }
+ }
+
+ // Migrate from 4x8 to 4x9 pattern inventory
+ int oldPatternCount = 4 * 8;
+ int oldSlotManual = oldPatternCount + 1;
+ int oldSlotCircuit = oldPatternCount;
+
+ if (internalInventory[oldSlotManual] == null && mInventory[oldSlotManual] != null) {
+ mInventory[SLOT_MANUAL_START] = mInventory[oldSlotManual];
+ mInventory[oldSlotManual] = null;
+ }
+ if (internalInventory[oldSlotCircuit] == null && mInventory[oldSlotCircuit] != null) {
+ mInventory[SLOT_CIRCUIT] = mInventory[oldSlotCircuit];
+ mInventory[oldSlotCircuit] = null;
+ }
+
+ // reconstruct patternDetailsPatternSlotMap
+ patternDetailsPatternSlotMap.clear();
+ for (PatternSlot patternSlot : internalInventory) {
+ if (patternSlot != null) {
+ patternDetailsPatternSlotMap.put(patternSlot.getPatternDetails(), patternSlot);
+ }
+ }
+
+ if (aNBT.hasKey("customName")) customName = aNBT.getString("customName");
+ additionalConnection = aNBT.getBoolean("additionalConnection");
+
+ getProxy().readFromNBT(aNBT);
+ }
+
+ @Override
+ public boolean isGivingInformation() {
+ return true;
+ }
+
+ private String describePattern(ICraftingPatternDetails patternDetails) {
+ return Arrays.stream(patternDetails.getCondensedOutputs())
+ .map(
+ aeItemStack -> aeItemStack.getItem()
+ .getItemStackDisplayName(aeItemStack.getItemStack()))
+ .collect(Collectors.joining(", "));
+ }
+
+ @Override
+ public String[] getInfoData() {
+ var ret = new ArrayList<String>();
+ ret.add(
+ "The bus is " + ((getProxy() != null && getProxy().isActive()) ? EnumChatFormatting.GREEN + "online"
+ : EnumChatFormatting.RED + "offline" + getAEDiagnostics()) + EnumChatFormatting.RESET);
+ ret.add("Internal Inventory: ");
+ var i = 0;
+ for (var slot : internalInventory) {
+ if (slot == null) continue;
+ IWideReadableNumberConverter nc = ReadableNumberConverter.INSTANCE;
+
+ i += 1;
+ ret.add(
+ "Slot " + i
+ + " "
+ + EnumChatFormatting.BLUE
+ + describePattern(slot.patternDetails)
+ + EnumChatFormatting.RESET);
+ for (var item : slot.itemInventory) {
+ if (item == null || item.stackSize == 0) continue;
+ ret.add(
+ item.getItem()
+ .getItemStackDisplayName(item) + ": "
+ + EnumChatFormatting.GOLD
+ + nc.toWideReadableForm(item.stackSize)
+ + EnumChatFormatting.RESET);
+ }
+ for (var fluid : slot.fluidInventory) {
+ if (fluid == null || fluid.amount == 0) continue;
+ ret.add(
+ fluid.getLocalizedName() + ": "
+ + EnumChatFormatting.AQUA
+ + nc.toWideReadableForm(fluid.amount)
+ + EnumChatFormatting.RESET);
+ }
+ }
+ return ret.toArray(new String[0]);
+ }
+
+ @Override
+ public boolean allowPullStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public boolean allowPutStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public int getCircuitSlot() {
+ return SLOT_CIRCUIT;
+ }
+
+ @Override
+ public int getCircuitSlotX() {
+ return 170;
+ }
+
+ @Override
+ public int getCircuitSlotY() {
+ return 64;
+ }
+
+ @Override
+ public boolean isValidSlot(int aIndex) {
+ return true;
+ }
+
+ @Override
+ public int getGUIWidth() {
+ return super.getGUIWidth() + 16;
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.@NotNull Builder builder, UIBuildContext buildContext) {
+ buildContext.addSyncedWindow(MANUAL_SLOT_WINDOW, this::createSlotManualWindow);
+ builder.widget(
+ SlotGroup.ofItemHandler(inventoryHandler, 9)
+ .startFromSlot(0)
+ .endAtSlot(MAX_PATTERN_COUNT - 1)
+ .phantom(false)
+ .background(getGUITextureSet().getItemSlot(), GT_UITextures.OVERLAY_SLOT_PATTERN_ME)
+ .widgetCreator(slot -> new SlotWidget(slot) {
+
+ @Override
+ protected ItemStack getItemStackForRendering(Slot slotIn) {
+ var stack = slot.getStack();
+ if (stack == null || !(stack.getItem() instanceof ItemEncodedPattern patternItem)) {
+ return stack;
+ }
+ var output = patternItem.getOutput(stack);
+ return output != null ? output : stack;
+ }
+ }.setFilter(itemStack -> itemStack.getItem() instanceof ICraftingPatternItem)
+ .setChangeListener(() -> onPatternChange(slot.getSlotIndex(), slot.getStack())))
+ .build()
+ .setPos(7, 9))
+ .widget(new ButtonWidget().setOnClick((clickData, widget) -> {
+ if (clickData.mouseButton == 0) {
+ widget.getContext()
+ .openSyncedWindow(MANUAL_SLOT_WINDOW);
+ }
+ })
+ .setPlayClickSound(true)
+ .setBackground(GT_UITextures.BUTTON_STANDARD, GT_UITextures.OVERLAY_BUTTON_PLUS_LARGE)
+ .addTooltips(ImmutableList.of("Place manual items"))
+ .setSize(16, 16)
+ .setPos(170, 45))
+ .widget(new ButtonWidget().setOnClick((clickData, widget) -> {
+ if (clickData.mouseButton == 0) {
+ refundAll();
+ }
+ })
+ .setPlayClickSound(true)
+ .setBackground(GT_UITextures.BUTTON_STANDARD, GT_UITextures.OVERLAY_BUTTON_EXPORT)
+ .addTooltips(ImmutableList.of("Return all internally stored items back to AE"))
+ .setSize(16, 16)
+ .setPos(170, 28));
+ }
+
+ @Override
+ public void updateSlots() {
+ for (int slotId = SLOT_MANUAL_START; slotId < SLOT_MANUAL_START + SLOT_MANUAL_SIZE; ++slotId) {
+ if (mInventory[slotId] != null && mInventory[slotId].stackSize <= 0) mInventory[slotId] = null;
+ }
+ }
+
+ private BaseActionSource getRequest() {
+ if (requestSource == null) requestSource = new MachineSource((IActionHost) getBaseMetaTileEntity());
+ return requestSource;
+ }
+
+ private void onPatternChange(int index, ItemStack newItem) {
+ if (!getBaseMetaTileEntity().isServerSide()) return;
+
+ var world = getBaseMetaTileEntity().getWorld();
+
+ // remove old if applicable
+ var originalPattern = internalInventory[index];
+ if (originalPattern != null) {
+ if (originalPattern.hasChanged(newItem, world)) {
+ try {
+ originalPattern.refund(getProxy(), getRequest());
+ } catch (GridAccessException ignored) {}
+ internalInventory[index] = null;
+ needPatternSync = true;
+ } else {
+ return; // nothing has changed
+ }
+ }
+
+ // original does not exist or has changed
+ if (newItem == null || !(newItem.getItem() instanceof ICraftingPatternItem)) return;
+
+ var patternSlot = new PatternSlot(newItem, world, this::getSharedItems);
+ internalInventory[index] = patternSlot;
+ patternDetailsPatternSlotMap.put(patternSlot.getPatternDetails(), patternSlot);
+
+ needPatternSync = true;
+ }
+
+ public ItemStack[] getSharedItems() {
+ ItemStack[] sharedItems = new ItemStack[SLOT_MANUAL_SIZE + 1];
+ sharedItems[0] = mInventory[SLOT_CIRCUIT];
+ System.arraycopy(mInventory, SLOT_MANUAL_START, sharedItems, 1, SLOT_MANUAL_SIZE);
+ return ArrayExt.withoutNulls(sharedItems, ItemStack[]::new);
+ }
+
+ @Override
+ public void getWailaBody(ItemStack itemStack, List<String> currenttip, IWailaDataAccessor accessor,
+ IWailaConfigHandler config) {
+ NBTTagCompound tag = accessor.getNBTData();
+ if (tag.hasKey("name"))
+ currenttip.add(EnumChatFormatting.AQUA + tag.getString("name") + EnumChatFormatting.RESET);
+ if (tag.hasKey("inventory")) {
+ var inventory = tag.getTagList("inventory", Constants.NBT.TAG_COMPOUND);
+ for (int i = 0; i < inventory.tagCount(); ++i) {
+ var item = inventory.getCompoundTagAt(i);
+ var name = item.getString("name");
+ var amount = item.getLong("amount");
+ currenttip.add(
+ name + ": "
+ + EnumChatFormatting.GOLD
+ + ReadableNumberConverter.INSTANCE.toWideReadableForm(amount)
+ + EnumChatFormatting.RESET);
+ }
+ }
+ super.getWailaBody(itemStack, currenttip, accessor, config);
+ }
+
+ @Override
+ public void getWailaNBTData(EntityPlayerMP player, TileEntity tile, NBTTagCompound tag, World world, int x, int y,
+ int z) {
+
+ NBTTagList inventory = new NBTTagList();
+ HashMap<String, Long> nameToAmount = new HashMap<>();
+ for (Iterator<PatternSlot> it = inventories(); it.hasNext();) {
+ var i = it.next();
+ for (var item : i.itemInventory) {
+ if (item != null && item.stackSize > 0) {
+ var name = item.getDisplayName();
+ var amount = nameToAmount.getOrDefault(name, 0L);
+ nameToAmount.put(name, amount + item.stackSize);
+ }
+ }
+ for (var fluid : i.fluidInventory) {
+ if (fluid != null && fluid.amount > 0) {
+ var name = fluid.getLocalizedName();
+ var amount = nameToAmount.getOrDefault(name, 0L);
+ nameToAmount.put(name, amount + fluid.amount);
+ }
+ }
+ }
+ for (var entry : nameToAmount.entrySet()) {
+ var item = new NBTTagCompound();
+ item.setString("name", entry.getKey());
+ item.setLong("amount", entry.getValue());
+ inventory.appendTag(item);
+ }
+
+ tag.setTag("inventory", inventory);
+ if (!Objects.equals(getName(), getLocalName())) {
+ tag.setString("name", getName());
+ }
+ super.getWailaNBTData(player, tile, tag, world, x, y, z);
+ }
+
+ @Override
+ public void provideCrafting(ICraftingProviderHelper craftingTracker) {
+ if (!isActive()) return;
+
+ for (PatternSlot slot : internalInventory) {
+ if (slot == null) continue;
+ ICraftingPatternDetails details = slot.getPatternDetails();
+ if (details == null) {
+ GT_Mod.GT_FML_LOGGER.warn(
+ "Found an invalid pattern at " + getBaseMetaTileEntity().getCoords()
+ + " in dim "
+ + getBaseMetaTileEntity().getWorld().provider.dimensionId);
+ continue;
+ }
+ craftingTracker.addCraftingOption(this, details);
+ }
+ }
+
+ @Override
+ public boolean pushPattern(ICraftingPatternDetails patternDetails, InventoryCrafting table) {
+ if (!isActive()) return false;
+
+ if (!supportFluids) {
+ for (int i = 0; i < table.getSizeInventory(); ++i) {
+ ItemStack itemStack = table.getStackInSlot(i);
+ if (itemStack == null) continue;
+ if (itemStack.getItem() instanceof ItemFluidPacket) return false;
+ }
+ }
+ if (!patternDetailsPatternSlotMap.get(patternDetails)
+ .insertItemsAndFluids(table)) {
+ return false;
+ }
+ justHadNewItems = true;
+ return true;
+ }
+
+ @Override
+ public boolean isBusy() {
+ return false;
+ }
+
+ @Override
+ public Iterator<PatternSlot> inventories() {
+ return Arrays.stream(internalInventory)
+ .filter(Objects::nonNull)
+ .iterator();
+ }
+
+ @Override
+ public void onBlockDestroyed() {
+ refundAll();
+ super.onBlockDestroyed();
+ }
+
+ private void refundAll() {
+ for (var slot : internalInventory) {
+ if (slot == null) continue;
+ try {
+ slot.refund(getProxy(), getRequest());
+ } catch (GridAccessException ignored) {}
+ }
+ }
+
+ @Override
+ public boolean justUpdated() {
+ var ret = justHadNewItems;
+ justHadNewItems = false;
+ return ret;
+ }
+
+ @Override
+ public void onLeftclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) {
+ if (!(aPlayer instanceof EntityPlayerMP)) return;
+
+ ItemStack dataStick = aPlayer.inventory.getCurrentItem();
+ if (!ItemList.Tool_DataStick.isStackEqual(dataStick, false, true)) return;
+
+ NBTTagCompound tag = new NBTTagCompound();
+ tag.setString("type", "CraftingInputBuffer");
+ tag.setInteger("x", aBaseMetaTileEntity.getXCoord());
+ tag.setInteger("y", aBaseMetaTileEntity.getYCoord());
+ tag.setInteger("z", aBaseMetaTileEntity.getZCoord());
+
+ dataStick.stackTagCompound = tag;
+ dataStick.setStackDisplayName(
+ "Crafting Input Buffer Link Data Stick (" + aBaseMetaTileEntity
+ .getXCoord() + ", " + aBaseMetaTileEntity.getYCoord() + ", " + aBaseMetaTileEntity.getZCoord() + ")");
+ aPlayer.addChatMessage(new ChatComponentText("Saved Link Data to Data Stick"));
+ }
+
+ @Override
+ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer, ForgeDirection side,
+ float aX, float aY, float aZ) {
+ final ItemStack is = aPlayer.inventory.getCurrentItem();
+ if (is != null && is.getItem() instanceof ToolQuartzCuttingKnife) {
+ if (ForgeEventFactory.onItemUseStart(aPlayer, is, 1) <= 0) return false;
+ var te = getBaseMetaTileEntity();
+ aPlayer.openGui(
+ AppEng.instance(),
+ GuiBridge.GUI_RENAMER.ordinal() << 5 | (side.ordinal()),
+ te.getWorld(),
+ te.getXCoord(),
+ te.getYCoord(),
+ te.getZCoord());
+ return true;
+ }
+ return super.onRightclick(aBaseMetaTileEntity, aPlayer, side, aX, aY, aZ);
+ }
+
+ @Override
+ public ItemStack getCrafterIcon() {
+ return getMachineCraftingIcon();
+ }
+
+ private boolean postMEPatternChange() {
+ // don't post until it's active
+ if (!getProxy().isActive()) return false;
+ try {
+ getProxy().getGrid()
+ .postEvent(new MENetworkCraftingPatternChange(this, getProxy().getNode()));
+ } catch (GridAccessException ignored) {
+ return false;
+ }
+ return true;
+ }
+
+ protected ModularWindow createSlotManualWindow(final EntityPlayer player) {
+ final int WIDTH = 68;
+ final int HEIGHT = 68;
+ final int PARENT_WIDTH = getGUIWidth();
+ final int PARENT_HEIGHT = getGUIHeight();
+ ModularWindow.Builder builder = ModularWindow.builder(WIDTH, HEIGHT);
+ builder.setBackground(GT_UITextures.BACKGROUND_SINGLEBLOCK_DEFAULT);
+ builder.setGuiTint(getGUIColorization());
+ builder.setDraggable(true);
+ // make sure the manual window is within the parent window
+ // otherwise picking up manual items would toss them
+ // See GuiContainer.java flag1
+ builder.setPos(
+ (size, window) -> Alignment.Center.getAlignedPos(size, new Size(PARENT_WIDTH, PARENT_HEIGHT))
+ .add(Alignment.TopRight.getAlignedPos(new Size(PARENT_WIDTH, PARENT_HEIGHT), new Size(WIDTH, HEIGHT))));
+ builder.widget(
+ SlotGroup.ofItemHandler(inventoryHandler, 3)
+ .startFromSlot(SLOT_MANUAL_START)
+ .endAtSlot(SLOT_MANUAL_START + SLOT_MANUAL_SIZE - 1)
+ .phantom(false)
+ .background(getGUITextureSet().getItemSlot())
+ .build()
+ .setPos(7, 7));
+ return builder.build();
+ }
+
+ @Override
+ public void setInventorySlotContents(int aIndex, ItemStack aStack) {
+ super.setInventorySlotContents(aIndex, aStack);
+ if (aIndex >= MAX_PATTERN_COUNT) return;
+ onPatternChange(aIndex, aStack);
+ needPatternSync = true;
+ }
+
+ @Override
+ public String getCustomName() {
+ return customName;
+ }
+
+ @Override
+ public boolean hasCustomName() {
+ return customName != null;
+ }
+
+ @Override
+ public void setCustomName(String name) {
+ customName = name;
+ }
+
+ @Override
+ public Optional<IDualInputInventory> getFirstNonEmptyInventory() {
+ for (PatternSlot slot : internalInventory) {
+ if (slot != null && !slot.isEmpty()) return Optional.of(slot);
+ }
+ return Optional.empty();
+ }
+
+ @Override
+ public boolean supportsFluids() {
+ return this.supportFluids;
+ }
+
+ @Override
+ public List<ItemStack> getItemsForHoloGlasses() {
+ List<ItemStack> list = new ArrayList<>();
+ for (PatternSlot slot : internalInventory) {
+ if (slot == null) continue;
+
+ IAEItemStack[] outputs = slot.getPatternDetails()
+ .getCondensedOutputs();
+ list.add(outputs[0].getItemStack());
+ }
+ return list;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_Hatch_CraftingInput_Slave.java b/src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_Hatch_CraftingInput_Slave.java
new file mode 100644
index 0000000000..ee53e9494a
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_Hatch_CraftingInput_Slave.java
@@ -0,0 +1,262 @@
+package gregtech.common.tileentities.machines;
+
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_ME_CRAFTING_INPUT_SLAVE;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Optional;
+
+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.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.enums.ItemList;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_InputBus;
+import gregtech.api.render.TextureFactory;
+import mcp.mobius.waila.api.IWailaConfigHandler;
+import mcp.mobius.waila.api.IWailaDataAccessor;
+
+public class GT_MetaTileEntity_Hatch_CraftingInput_Slave extends GT_MetaTileEntity_Hatch_InputBus
+ implements IDualInputHatch {
+
+ private GT_MetaTileEntity_Hatch_CraftingInput_ME master; // use getMaster() to access
+ private int masterX, masterY, masterZ;
+ private boolean masterSet = false; // indicate if values of masterX, masterY, masterZ are valid
+
+ public GT_MetaTileEntity_Hatch_CraftingInput_Slave(int aID, String aName, String aNameRegional) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ 6,
+ 0,
+ new String[] { "Slave for Crafting Input Buffer/Bus",
+ "Link with Crafting Input Buffer/Bus using Data Stick to share inventory",
+ "Left click on the Crafting Input Buffer/Bus, then right click on this block to link them", });
+ disableSort = true;
+ }
+
+ public GT_MetaTileEntity_Hatch_CraftingInput_Slave(String aName, int aTier, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, 0, aDescription, aTextures);
+ disableSort = true;
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Hatch_CraftingInput_Slave(mName, mTier, mDescriptionArray, mTextures);
+ }
+
+ @Override
+ public ITexture[] getTexturesActive(ITexture aBaseTexture) {
+ return getTexturesInactive(aBaseTexture);
+ }
+
+ @Override
+ public ITexture[] getTexturesInactive(ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture, TextureFactory.of(OVERLAY_ME_CRAFTING_INPUT_SLAVE) };
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTimer) {
+ super.onPostTick(aBaseMetaTileEntity, aTimer);
+ if (aTimer % 100 == 0 && masterSet && getMaster() == null) {
+ trySetMasterFromCoord(masterX, masterY, masterZ);
+ }
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+
+ if (aNBT.hasKey("master")) {
+ NBTTagCompound masterNBT = aNBT.getCompoundTag("master");
+ masterX = masterNBT.getInteger("x");
+ masterY = masterNBT.getInteger("y");
+ masterZ = masterNBT.getInteger("z");
+ masterSet = true;
+ }
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ if (masterSet) {
+ NBTTagCompound masterNBT = new NBTTagCompound();
+ masterNBT.setInteger("x", masterX);
+ masterNBT.setInteger("y", masterY);
+ masterNBT.setInteger("z", masterZ);
+ aNBT.setTag("master", masterNBT);
+ }
+ }
+
+ @Override
+ public boolean isGivingInformation() {
+ return true;
+ }
+
+ @Override
+ public String[] getInfoData() {
+ var ret = new ArrayList<String>();
+ if (getMaster() != null) {
+ ret.add(
+ "This bus is linked to the Crafting Input Buffer at " + masterX
+ + ", "
+ + masterY
+ + ", "
+ + masterZ
+ + ".");
+ ret.addAll(Arrays.asList(getMaster().getInfoData()));
+ } else ret.add("This bus is not linked to any Crafting Input Buffer.");
+ return ret.toArray(new String[0]);
+ }
+
+ public GT_MetaTileEntity_Hatch_CraftingInput_ME getMaster() {
+ if (master == null) return null;
+ if (master.getBaseMetaTileEntity() == null) { // master disappeared
+ master = null;
+ }
+ return master;
+ }
+
+ @Override
+ public byte getTierForStructure() {
+ return getMaster() == null ? super.getTierForStructure() : getMaster().getTierForStructure();
+ }
+
+ @Override
+ public boolean allowPullStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public boolean allowPutStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public Iterator<GT_MetaTileEntity_Hatch_CraftingInput_ME.PatternSlot> inventories() {
+ return getMaster() != null ? getMaster().inventories() : Collections.emptyIterator();
+ }
+
+ @Override
+ public Optional<IDualInputInventory> getFirstNonEmptyInventory() {
+ return getMaster() != null ? getMaster().getFirstNonEmptyInventory() : Optional.empty();
+ }
+
+ @Override
+ public boolean supportsFluids() {
+ return getMaster() != null && getMaster().supportsFluids();
+ }
+
+ @Override
+ public boolean justUpdated() {
+ return getMaster() != null && getMaster().justUpdated();
+ }
+
+ public GT_MetaTileEntity_Hatch_CraftingInput_ME trySetMasterFromCoord(int x, int y, int z) {
+ var tileEntity = getBaseMetaTileEntity().getWorld()
+ .getTileEntity(x, y, z);
+ if (tileEntity == null) return null;
+ if (!(tileEntity instanceof IGregTechTileEntity gtTileEntity)) return null;
+ var metaTileEntity = gtTileEntity.getMetaTileEntity();
+ if (!(metaTileEntity instanceof GT_MetaTileEntity_Hatch_CraftingInput_ME)) return null;
+ masterX = x;
+ masterY = y;
+ masterZ = z;
+ masterSet = true;
+ master = (GT_MetaTileEntity_Hatch_CraftingInput_ME) metaTileEntity;
+ return master;
+ }
+
+ private boolean tryLinkDataStick(EntityPlayer aPlayer) {
+ ItemStack dataStick = aPlayer.inventory.getCurrentItem();
+
+ if (!ItemList.Tool_DataStick.isStackEqual(dataStick, false, true)) {
+ return false;
+ }
+ if (!dataStick.hasTagCompound() || !dataStick.stackTagCompound.getString("type")
+ .equals("CraftingInputBuffer")) {
+ return false;
+ }
+
+ NBTTagCompound nbt = dataStick.stackTagCompound;
+ int x = nbt.getInteger("x");
+ int y = nbt.getInteger("y");
+ int z = nbt.getInteger("z");
+ if (trySetMasterFromCoord(x, y, z) != null) {
+ aPlayer.addChatMessage(new ChatComponentText("Link successful"));
+ return true;
+ }
+ aPlayer.addChatMessage(new ChatComponentText("Link failed"));
+ return true;
+ }
+
+ @Override
+ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) {
+ if (!(aPlayer instanceof EntityPlayerMP)) {
+ return false;
+ }
+ if (tryLinkDataStick(aPlayer)) {
+ return true;
+ }
+ var master = getMaster();
+ if (master != null) {
+ return master.onRightclick(master.getBaseMetaTileEntity(), aPlayer);
+ }
+ return false;
+ }
+
+ @Override
+ public void getWailaBody(ItemStack itemStack, List<String> currenttip, IWailaDataAccessor accessor,
+ IWailaConfigHandler config) {
+ NBTTagCompound tag = accessor.getNBTData();
+ currenttip.add((tag.getBoolean("linked") ? "Linked" : "Not linked"));
+
+ if (tag.hasKey("masterX")) {
+ currenttip.add(
+ "Bound to " + tag
+ .getInteger("masterX") + ", " + tag.getInteger("masterY") + ", " + tag.getInteger("masterZ"));
+ }
+
+ if (tag.hasKey("masterName")) {
+ currenttip.add(EnumChatFormatting.GOLD + tag.getString("masterName") + EnumChatFormatting.RESET);
+ }
+
+ super.getWailaBody(itemStack, currenttip, accessor, config);
+ }
+
+ @Override
+ public void getWailaNBTData(EntityPlayerMP player, TileEntity tile, NBTTagCompound tag, World world, int x, int y,
+ int z) {
+
+ tag.setBoolean("linked", getMaster() != null);
+ if (masterSet) {
+ tag.setInteger("masterX", masterX);
+ tag.setInteger("masterY", masterY);
+ tag.setInteger("masterZ", masterZ);
+ }
+ if (getMaster() != null) tag.setString("masterName", getMaster().getName());
+
+ super.getWailaNBTData(player, tile, tag, world, x, y, z);
+ }
+
+ @Override
+ public List<ItemStack> getItemsForHoloGlasses() {
+ return getMaster() != null ? getMaster().getItemsForHoloGlasses() : null;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_Hatch_InputBus_ME.java b/src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_Hatch_InputBus_ME.java
new file mode 100644
index 0000000000..6b5ce10387
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_Hatch_InputBus_ME.java
@@ -0,0 +1,804 @@
+package gregtech.common.tileentities.machines;
+
+import static gregtech.api.enums.GT_Values.TIER_COLORS;
+import static gregtech.api.enums.GT_Values.VN;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_ME_INPUT_HATCH;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_ME_INPUT_HATCH_ACTIVE;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+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.ChatComponentTranslation;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.StatCollector;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.gtnewhorizons.modularui.api.ModularUITextures;
+import com.gtnewhorizons.modularui.api.drawable.IDrawable;
+import com.gtnewhorizons.modularui.api.math.Alignment;
+import com.gtnewhorizons.modularui.api.math.Color;
+import com.gtnewhorizons.modularui.api.math.Size;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.common.internal.wrapper.BaseSlot;
+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.SlotGroup;
+import com.gtnewhorizons.modularui.common.widget.SlotWidget;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+import com.gtnewhorizons.modularui.common.widget.textfield.NumericWidget;
+
+import appeng.api.config.Actionable;
+import appeng.api.config.PowerMultiplier;
+import appeng.api.implementations.IPowerChannelState;
+import appeng.api.networking.GridFlags;
+import appeng.api.networking.security.BaseActionSource;
+import appeng.api.networking.security.IActionHost;
+import appeng.api.networking.security.MachineSource;
+import appeng.api.storage.IMEMonitor;
+import appeng.api.storage.data.IAEItemStack;
+import appeng.api.util.AECableType;
+import appeng.core.localization.WailaText;
+import appeng.me.GridAccessException;
+import appeng.me.helpers.AENetworkProxy;
+import appeng.me.helpers.IGridProxyable;
+import appeng.util.item.AEItemStack;
+import gregtech.api.enums.ItemList;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.IConfigurationCircuitSupport;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.modularui.IAddGregtechLogo;
+import gregtech.api.interfaces.modularui.IAddUIWidgets;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_InputBus;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_MultiBlockBase;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.recipe.check.SimpleCheckRecipeResult;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.shutdown.ShutDownReasonRegistry;
+import gregtech.common.gui.modularui.widget.AESlotWidget;
+import mcp.mobius.waila.api.IWailaConfigHandler;
+import mcp.mobius.waila.api.IWailaDataAccessor;
+
+public class GT_MetaTileEntity_Hatch_InputBus_ME extends GT_MetaTileEntity_Hatch_InputBus implements
+ IConfigurationCircuitSupport, IRecipeProcessingAwareHatch, IAddGregtechLogo, IAddUIWidgets, IPowerChannelState {
+
+ private static final int SLOT_COUNT = 16;
+ private BaseActionSource requestSource = null;
+ private @Nullable AENetworkProxy gridProxy = null;
+ private final ItemStack[] shadowInventory = new ItemStack[SLOT_COUNT];
+ private final int[] savedStackSizes = new int[SLOT_COUNT];
+ private boolean processingRecipe = false;
+ private final boolean autoPullAvailable;
+ private boolean autoPullItemList = false;
+ private int minAutoPullStackSize = 1;
+ private int autoPullRefreshTime = 100;
+ private static final int CONFIG_WINDOW_ID = 10;
+ private boolean additionalConnection = false;
+
+ public GT_MetaTileEntity_Hatch_InputBus_ME(int aID, boolean autoPullAvailable, String aName, String aNameRegional) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ autoPullAvailable ? 6 : 3,
+ SLOT_COUNT * 2 + 2,
+ getDescriptionArray(autoPullAvailable));
+ this.autoPullAvailable = autoPullAvailable;
+ disableSort = true;
+ }
+
+ public GT_MetaTileEntity_Hatch_InputBus_ME(String aName, boolean autoPullAvailable, int aTier,
+ String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, SLOT_COUNT * 2 + 2, aDescription, aTextures);
+ this.autoPullAvailable = autoPullAvailable;
+ disableSort = true;
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Hatch_InputBus_ME(mName, autoPullAvailable, mTier, mDescriptionArray, mTextures);
+ }
+
+ @Override
+ public ITexture[] getTexturesActive(ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture, TextureFactory.of(OVERLAY_ME_INPUT_HATCH_ACTIVE) };
+ }
+
+ @Override
+ public ITexture[] getTexturesInactive(ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture, TextureFactory.of(OVERLAY_ME_INPUT_HATCH) };
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTimer) {
+ if (getBaseMetaTileEntity().isServerSide()) {
+ if (aTimer % autoPullRefreshTime == 0 && autoPullItemList) {
+ refreshItemList();
+ }
+ if (aTimer % 20 == 0) {
+ getBaseMetaTileEntity().setActive(isActive());
+ }
+ }
+ super.onPostTick(aBaseMetaTileEntity, aTimer);
+ }
+
+ @Override
+ public void onFirstTick(IGregTechTileEntity aBaseMetaTileEntity) {
+ super.onFirstTick(aBaseMetaTileEntity);
+ getProxy().onReady();
+ }
+
+ @Override
+ public AECableType getCableConnectionType(ForgeDirection forgeDirection) {
+ return isOutputFacing(forgeDirection) ? AECableType.SMART : AECableType.NONE;
+ }
+
+ private void updateValidGridProxySides() {
+ if (additionalConnection) {
+ getProxy().setValidSides(EnumSet.complementOf(EnumSet.of(ForgeDirection.UNKNOWN)));
+ } else {
+ getProxy().setValidSides(EnumSet.of(getBaseMetaTileEntity().getFrontFacing()));
+ }
+ }
+
+ @Override
+ public void onFacingChange() {
+ updateValidGridProxySides();
+ }
+
+ @Override
+ public boolean onWireCutterRightClick(ForgeDirection side, ForgeDirection wrenchingSide, EntityPlayer aPlayer,
+ float aX, float aY, float aZ) {
+ additionalConnection = !additionalConnection;
+ updateValidGridProxySides();
+ aPlayer.addChatComponentMessage(
+ new ChatComponentTranslation("GT5U.hatch.additionalConnection." + additionalConnection));
+ return true;
+ }
+
+ @Override
+ public AENetworkProxy getProxy() {
+ if (gridProxy == null) {
+ if (getBaseMetaTileEntity() instanceof IGridProxyable) {
+ gridProxy = new AENetworkProxy(
+ (IGridProxyable) getBaseMetaTileEntity(),
+ "proxy",
+ autoPullAvailable ? ItemList.Hatch_Input_Bus_ME_Advanced.get(1)
+ : ItemList.Hatch_Input_Bus_ME.get(1),
+ true);
+ gridProxy.setFlags(GridFlags.REQUIRE_CHANNEL);
+ updateValidGridProxySides();
+ if (getBaseMetaTileEntity().getWorld() != null) gridProxy.setOwner(
+ getBaseMetaTileEntity().getWorld()
+ .getPlayerEntityByName(getBaseMetaTileEntity().getOwnerName()));
+ }
+ }
+ return this.gridProxy;
+ }
+
+ @Override
+ public boolean isPowered() {
+ return getProxy() != null && getProxy().isPowered();
+ }
+
+ @Override
+ public boolean isActive() {
+ return getProxy() != null && getProxy().isActive();
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ int[] sizes = new int[16];
+ for (int i = 0; i < 16; ++i) sizes[i] = mInventory[i + 16] == null ? 0 : mInventory[i + 16].stackSize;
+ aNBT.setIntArray("sizes", sizes);
+ aNBT.setBoolean("autoStock", autoPullItemList);
+ aNBT.setInteger("minAutoPullStackSize", minAutoPullStackSize);
+ aNBT.setBoolean("additionalConnection", additionalConnection);
+ aNBT.setInteger("refreshTime", autoPullRefreshTime);
+ getProxy().writeToNBT(aNBT);
+ }
+
+ private void setAutoPullItemList(boolean pullItemList) {
+ if (!autoPullAvailable) {
+ return;
+ }
+
+ autoPullItemList = pullItemList;
+ if (!autoPullItemList) {
+ for (int i = 0; i < SLOT_COUNT; i++) {
+ mInventory[i] = null;
+ }
+ } else {
+ refreshItemList();
+ }
+ updateAllInformationSlots();
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ if (aNBT.hasKey("sizes")) {
+ int[] sizes = aNBT.getIntArray("sizes");
+ if (sizes.length == 16) {
+ for (int i = 0; i < 16; ++i) {
+ if (sizes[i] != 0 && mInventory[i] != null) {
+ ItemStack s = mInventory[i].copy();
+ s.stackSize = sizes[i];
+ mInventory[i + 16] = s;
+ }
+ }
+ }
+ }
+ autoPullItemList = aNBT.getBoolean("autoStock");
+ minAutoPullStackSize = aNBT.getInteger("minAutoPullStackSize");
+ additionalConnection = aNBT.getBoolean("additionalConnection");
+ if (aNBT.hasKey("refreshTime")) {
+ autoPullRefreshTime = aNBT.getInteger("refreshTime");
+ }
+ getProxy().readFromNBT(aNBT);
+
+ }
+
+ @Override
+ public boolean isGivingInformation() {
+ return true;
+ }
+
+ @Override
+ public String[] getInfoData() {
+ return new String[] {
+ "The bus is " + ((getProxy() != null && getProxy().isActive()) ? EnumChatFormatting.GREEN + "online"
+ : EnumChatFormatting.RED + "offline" + getAEDiagnostics()) + EnumChatFormatting.RESET };
+ }
+
+ @Override
+ public boolean allowPullStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public boolean allowPutStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ if (!autoPullAvailable) {
+ return;
+ }
+
+ setAutoPullItemList(!autoPullItemList);
+ aPlayer.addChatMessage(
+ new ChatComponentTranslation(
+ "GT5U.machines.stocking_bus.auto_pull_toggle." + (autoPullItemList ? "enabled" : "disabled")));
+ }
+
+ @Override
+ public void updateSlots() {
+ if (mInventory[getManualSlot()] != null && mInventory[getManualSlot()].stackSize <= 0)
+ mInventory[getManualSlot()] = null;
+ }
+
+ @Override
+ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer, ForgeDirection side,
+ float aX, float aY, float aZ) {
+ if (!(aPlayer instanceof EntityPlayerMP))
+ return super.onRightclick(aBaseMetaTileEntity, aPlayer, side, aX, aY, aZ);
+ ItemStack dataStick = aPlayer.inventory.getCurrentItem();
+ if (!ItemList.Tool_DataStick.isStackEqual(dataStick, false, true))
+ return super.onRightclick(aBaseMetaTileEntity, aPlayer, side, aX, aY, aZ);
+ if (!dataStick.hasTagCompound() || !"stockingBus".equals(dataStick.stackTagCompound.getString("type")))
+ return false;
+
+ NBTTagCompound nbt = dataStick.stackTagCompound;
+
+ ItemStack circuit = GT_Utility.loadItem(dataStick.stackTagCompound, "circuit");
+ if (GT_Utility.isStackInvalid(circuit)) circuit = null;
+
+ if (autoPullAvailable) {
+ setAutoPullItemList(nbt.getBoolean("autoPull"));
+ minAutoPullStackSize = nbt.getInteger("minStackSize");
+ autoPullRefreshTime = nbt.getInteger("refreshTime");
+ }
+
+ additionalConnection = nbt.getBoolean("additionalConnection");
+ if (!autoPullItemList) {
+ NBTTagList stockingItems = nbt.getTagList("itemsToStock", 10);
+ for (int i = 0; i < stockingItems.tagCount(); i++) {
+ this.mInventory[i] = GT_Utility.loadItem(stockingItems.getCompoundTagAt(i));
+ }
+ }
+ setInventorySlotContents(getCircuitSlot(), circuit);
+ updateValidGridProxySides();
+ aPlayer.addChatMessage(new ChatComponentTranslation("GT5U.machines.stocking_bus.loaded"));
+ return true;
+ }
+
+ @Override
+ public void onLeftclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) {
+ if (!(aPlayer instanceof EntityPlayerMP)) return;
+
+ ItemStack dataStick = aPlayer.inventory.getCurrentItem();
+ if (!ItemList.Tool_DataStick.isStackEqual(dataStick, false, true)) return;
+
+ NBTTagCompound tag = new NBTTagCompound();
+ tag.setString("type", "stockingBus");
+ tag.setBoolean("autoPull", autoPullItemList);
+ tag.setInteger("minStackSize", minAutoPullStackSize);
+ tag.setInteger("refreshTime", autoPullRefreshTime);
+ tag.setBoolean("additionalConnection", additionalConnection);
+ tag.setTag("circuit", GT_Utility.saveItem(getStackInSlot(getCircuitSlot())));
+
+ NBTTagList stockingItems = new NBTTagList();
+
+ if (!autoPullItemList) {
+ for (int index = 0; index < SLOT_COUNT; index++) {
+ stockingItems.appendTag(GT_Utility.saveItem(mInventory[index]));
+ }
+ tag.setTag("itemsToStock", stockingItems);
+ }
+ dataStick.stackTagCompound = tag;
+ dataStick.setStackDisplayName("Stocking Input Bus Configuration");
+ aPlayer.addChatMessage(new ChatComponentTranslation("GT5U.machines.stocking_bus.saved"));
+ }
+
+ private int getManualSlot() {
+ return SLOT_COUNT * 2 + 1;
+ }
+
+ @Override
+ public int getCircuitSlot() {
+ return SLOT_COUNT * 2;
+ }
+
+ @Override
+ public int getCircuitSlotX() {
+ return 80;
+ }
+
+ @Override
+ public int getCircuitSlotY() {
+ return 64;
+ }
+
+ @Override
+ public boolean setStackToZeroInsteadOfNull(int aIndex) {
+ return aIndex != getManualSlot();
+ }
+
+ @Override
+ public ItemStack getStackInSlot(int aIndex) {
+ if (!processingRecipe) return super.getStackInSlot(aIndex);
+ if (aIndex < 0 || aIndex > mInventory.length) return null;
+ if (aIndex >= SLOT_COUNT && aIndex < SLOT_COUNT * 2)
+ // Display slots
+ return null;
+ if (aIndex == getCircuitSlot() || aIndex == getManualSlot()) return mInventory[aIndex];
+ if (mInventory[aIndex] != null) {
+ AENetworkProxy proxy = getProxy();
+ if (proxy == null || !proxy.isActive()) {
+ return null;
+ }
+ try {
+ IMEMonitor<IAEItemStack> sg = proxy.getStorage()
+ .getItemInventory();
+ IAEItemStack request = AEItemStack.create(mInventory[aIndex]);
+ request.setStackSize(Integer.MAX_VALUE);
+ IAEItemStack result = sg.extractItems(request, Actionable.SIMULATE, getRequestSource());
+ if (result != null) {
+ this.shadowInventory[aIndex] = result.getItemStack();
+ this.savedStackSizes[aIndex] = this.shadowInventory[aIndex].stackSize;
+ this.setInventorySlotContents(aIndex + SLOT_COUNT, this.shadowInventory[aIndex]);
+ return this.shadowInventory[aIndex];
+ } else {
+ // Request failed
+ this.setInventorySlotContents(aIndex + SLOT_COUNT, null);
+ return null;
+ }
+ } catch (final GridAccessException ignored) {}
+ return null;
+ } else {
+ // AE available but no items requested
+ this.setInventorySlotContents(aIndex + SLOT_COUNT, null);
+ }
+ return mInventory[aIndex];
+ }
+
+ private BaseActionSource getRequestSource() {
+ if (requestSource == null) requestSource = new MachineSource((IActionHost) getBaseMetaTileEntity());
+ return requestSource;
+ }
+
+ @Override
+ public void onExplosion() {
+ for (int i = 0; i < SLOT_COUNT; i++) {
+ mInventory[i] = null;
+ }
+ }
+
+ @Override
+ public void startRecipeProcessing() {
+ processingRecipe = true;
+ updateAllInformationSlots();
+ }
+
+ private void refreshItemList() {
+ AENetworkProxy proxy = getProxy();
+ try {
+ IMEMonitor<IAEItemStack> sg = proxy.getStorage()
+ .getItemInventory();
+ Iterator<IAEItemStack> iterator = sg.getStorageList()
+ .iterator();
+ int index = 0;
+ while (iterator.hasNext() && index < SLOT_COUNT) {
+ IAEItemStack currItem = iterator.next();
+ if (currItem.getStackSize() >= minAutoPullStackSize) {
+ ItemStack itemstack = GT_Utility.copyAmount(1, currItem.getItemStack());
+ this.mInventory[index] = itemstack;
+ index++;
+ }
+ }
+ for (int i = index; i < SLOT_COUNT; i++) {
+ mInventory[i] = null;
+ }
+
+ } catch (final GridAccessException ignored) {}
+ }
+
+ private void updateAllInformationSlots() {
+ for (int index = 0; index < SLOT_COUNT; index++) {
+ updateInformationSlot(index, mInventory[index]);
+ }
+ }
+
+ @Override
+ public CheckRecipeResult endRecipeProcessing(GT_MetaTileEntity_MultiBlockBase controller) {
+ CheckRecipeResult checkRecipeResult = CheckRecipeResultRegistry.SUCCESSFUL;
+ for (int i = 0; i < SLOT_COUNT; ++i) {
+ if (savedStackSizes[i] != 0) {
+ ItemStack oldStack = shadowInventory[i];
+ if (oldStack == null || oldStack.stackSize < savedStackSizes[i]) {
+ AENetworkProxy proxy = getProxy();
+ try {
+ IMEMonitor<IAEItemStack> sg = proxy.getStorage()
+ .getItemInventory();
+ IAEItemStack request = AEItemStack.create(mInventory[i]);
+ int toExtract = savedStackSizes[i] - (oldStack == null ? 0 : oldStack.stackSize);
+ request.setStackSize(toExtract);
+ IAEItemStack result = sg.extractItems(request, Actionable.MODULATE, getRequestSource());
+ proxy.getEnergy()
+ .extractAEPower(request.getStackSize(), Actionable.MODULATE, PowerMultiplier.CONFIG);
+ setInventorySlotContents(i + SLOT_COUNT, oldStack);
+ if (result == null || result.getStackSize() != toExtract) {
+ controller.stopMachine(ShutDownReasonRegistry.CRITICAL_NONE);
+ checkRecipeResult = SimpleCheckRecipeResult
+ .ofFailurePersistOnShutdown("stocking_bus_fail_extraction");
+ }
+ } catch (final GridAccessException ignored) {
+ controller.stopMachine(ShutDownReasonRegistry.CRITICAL_NONE);
+ checkRecipeResult = SimpleCheckRecipeResult
+ .ofFailurePersistOnShutdown("stocking_hatch_fail_extraction");
+ }
+ }
+ savedStackSizes[i] = 0;
+ shadowInventory[i] = null;
+ if (mInventory[i + SLOT_COUNT] != null && mInventory[i + SLOT_COUNT].stackSize <= 0) {
+ mInventory[i + SLOT_COUNT] = null;
+ }
+ }
+ }
+ processingRecipe = false;
+ return checkRecipeResult;
+ }
+
+ public ItemStack updateInformationSlot(int aIndex, ItemStack aStack) {
+ if (aIndex >= 0 && aIndex < SLOT_COUNT) {
+ if (aStack == null) {
+ super.setInventorySlotContents(aIndex + SLOT_COUNT, null);
+ } else {
+ AENetworkProxy proxy = getProxy();
+ if (!proxy.isActive()) {
+ super.setInventorySlotContents(aIndex + SLOT_COUNT, null);
+ return null;
+ }
+ try {
+ IMEMonitor<IAEItemStack> sg = proxy.getStorage()
+ .getItemInventory();
+ IAEItemStack request = AEItemStack.create(mInventory[aIndex]);
+ request.setStackSize(Integer.MAX_VALUE);
+ IAEItemStack result = sg.extractItems(request, Actionable.SIMULATE, getRequestSource());
+ ItemStack s = (result != null) ? result.getItemStack() : null;
+ setInventorySlotContents(aIndex + SLOT_COUNT, s);
+ return s;
+ } catch (final GridAccessException ignored) {}
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Used to avoid slot update.
+ */
+ public ItemStack getShadowItemStack(int index) {
+ if (index < 0 || index >= shadowInventory.length) {
+ return null;
+ }
+ return shadowInventory[index];
+ }
+
+ @Override
+ public boolean isValidSlot(int aIndex) {
+ return aIndex == getManualSlot();
+ }
+
+ @Override
+ public int getGUIHeight() {
+ return 179;
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ final SlotWidget[] aeSlotWidgets = new SlotWidget[16];
+
+ if (autoPullAvailable) {
+ buildContext.addSyncedWindow(CONFIG_WINDOW_ID, this::createStackSizeConfigurationWindow);
+ }
+
+ builder.widget(
+ SlotGroup.ofItemHandler(inventoryHandler, 4)
+ .startFromSlot(0)
+ .endAtSlot(15)
+ .phantom(true)
+ .slotCreator(index -> new BaseSlot(inventoryHandler, index, true) {
+
+ @Override
+ public boolean isEnabled() {
+ return !autoPullItemList && super.isEnabled();
+ }
+ })
+ .widgetCreator(slot -> (SlotWidget) new SlotWidget(slot) {
+
+ @Override
+ protected void phantomClick(ClickData clickData, ItemStack cursorStack) {
+ if (clickData.mouseButton != 0 || !getMcSlot().isEnabled()) return;
+ final int aSlotIndex = getMcSlot().getSlotIndex();
+ if (cursorStack == null) {
+ getMcSlot().putStack(null);
+ } else {
+ if (containsSuchStack(cursorStack)) return;
+ getMcSlot().putStack(GT_Utility.copyAmount(1, cursorStack));
+ }
+ if (getBaseMetaTileEntity().isServerSide()) {
+ final ItemStack newInfo = updateInformationSlot(aSlotIndex, cursorStack);
+ aeSlotWidgets[getMcSlot().getSlotIndex()].getMcSlot()
+ .putStack(newInfo);
+ }
+ }
+
+ @Override
+ public IDrawable[] getBackground() {
+ IDrawable slot;
+ if (autoPullItemList) {
+ slot = GT_UITextures.SLOT_DARK_GRAY;
+ } else {
+ slot = ModularUITextures.ITEM_SLOT;
+ }
+ return new IDrawable[] { slot, GT_UITextures.OVERLAY_SLOT_ARROW_ME };
+ }
+
+ @Override
+ public List<String> getExtraTooltip() {
+ if (autoPullItemList) {
+ return Collections.singletonList(
+ StatCollector.translateToLocal("GT5U.machines.stocking_bus.cannot_set_slot"));
+ } else {
+ return Collections
+ .singletonList(StatCollector.translateToLocal("modularui.phantom.single.clear"));
+ }
+ }
+
+ private boolean containsSuchStack(ItemStack tStack) {
+ for (int i = 0; i < 16; ++i) {
+ if (GT_Utility.areStacksEqual(mInventory[i], tStack, false)) return true;
+ }
+ return false;
+ }
+ }.dynamicTooltip(() -> {
+ if (autoPullItemList) {
+ return Collections.singletonList(
+ StatCollector.translateToLocal("GT5U.machines.stocking_bus.cannot_set_slot"));
+ } else {
+ return Collections.emptyList();
+ }
+ })
+ .setUpdateTooltipEveryTick(true))
+ .build()
+ .setPos(7, 9))
+ .widget(
+ SlotGroup.ofItemHandler(inventoryHandler, 4)
+ .startFromSlot(16)
+ .endAtSlot(31)
+ .phantom(true)
+ .background(GT_UITextures.SLOT_DARK_GRAY)
+ .widgetCreator(
+ slot -> aeSlotWidgets[slot.getSlotIndex() - 16] = new AESlotWidget(slot).disableInteraction())
+ .build()
+ .setPos(97, 9))
+ .widget(
+ new DrawableWidget().setDrawable(GT_UITextures.PICTURE_ARROW_DOUBLE)
+ .setPos(82, 30)
+ .setSize(12, 12));
+
+ if (autoPullAvailable) {
+ builder.widget(new ButtonWidget().setOnClick((clickData, widget) -> {
+ if (clickData.mouseButton == 0) {
+ setAutoPullItemList(!autoPullItemList);
+ } else if (clickData.mouseButton == 1 && !widget.isClient()) {
+ widget.getContext()
+ .openSyncedWindow(CONFIG_WINDOW_ID);
+ }
+ })
+ .setBackground(() -> {
+ if (autoPullItemList) {
+ return new IDrawable[] { GT_UITextures.BUTTON_STANDARD_PRESSED,
+ GT_UITextures.OVERLAY_BUTTON_AUTOPULL_ME };
+ } else {
+ return new IDrawable[] { GT_UITextures.BUTTON_STANDARD,
+ GT_UITextures.OVERLAY_BUTTON_AUTOPULL_ME_DISABLED };
+ }
+ })
+ .addTooltips(
+ Arrays.asList(
+ StatCollector.translateToLocal("GT5U.machines.stocking_bus.auto_pull.tooltip.1"),
+ StatCollector.translateToLocal("GT5U.machines.stocking_bus.auto_pull.tooltip.2")))
+ .setSize(16, 16)
+ .setPos(80, 10))
+ .widget(new FakeSyncWidget.BooleanSyncer(() -> autoPullItemList, this::setAutoPullItemList));
+ }
+
+ builder.widget(TextWidget.dynamicString(() -> {
+ boolean isActive = isActive();
+ boolean isPowered = isPowered();
+ boolean isBooting = isBooting();
+ EnumChatFormatting color = (isActive && isPowered) ? EnumChatFormatting.GREEN : EnumChatFormatting.DARK_RED;
+ return color + WailaText.getPowerState(isActive, isPowered, isBooting);
+ })
+ .setTextAlignment(Alignment.Center)
+ .setSize(90, 9)
+ .setPos(43, 84))
+ .widget(
+ new SlotWidget(inventoryHandler, getManualSlot())
+ // ghost slots are prioritized over manual slot
+ .setShiftClickPriority(11)
+ .setPos(79, 45));
+ }
+
+ protected ModularWindow createStackSizeConfigurationWindow(final EntityPlayer player) {
+ final int WIDTH = 78;
+ final int HEIGHT = 80;
+ final int PARENT_WIDTH = getGUIWidth();
+ final int PARENT_HEIGHT = getGUIHeight();
+ ModularWindow.Builder builder = ModularWindow.builder(WIDTH, HEIGHT);
+ builder.setBackground(GT_UITextures.BACKGROUND_SINGLEBLOCK_DEFAULT);
+ builder.setGuiTint(getGUIColorization());
+ builder.setDraggable(true);
+ builder.setPos(
+ (size, window) -> Alignment.Center.getAlignedPos(size, new Size(PARENT_WIDTH, PARENT_HEIGHT))
+ .add(
+ Alignment.TopRight.getAlignedPos(new Size(PARENT_WIDTH, PARENT_HEIGHT), new Size(WIDTH, HEIGHT))
+ .add(WIDTH - 3, 0)));
+ builder.widget(
+ TextWidget.localised("GT5U.machines.stocking_bus.min_stack_size")
+ .setPos(3, 2)
+ .setSize(74, 14))
+ .widget(
+ new NumericWidget().setSetter(val -> minAutoPullStackSize = (int) val)
+ .setGetter(() -> minAutoPullStackSize)
+ .setBounds(1, Integer.MAX_VALUE)
+ .setScrollValues(1, 4, 64)
+ .setTextAlignment(Alignment.Center)
+ .setTextColor(Color.WHITE.normal)
+ .setSize(70, 18)
+ .setPos(3, 18)
+ .setBackground(GT_UITextures.BACKGROUND_TEXT_FIELD));
+ builder.widget(
+ TextWidget.localised("GT5U.machines.stocking_bus.refresh_time")
+ .setPos(3, 42)
+ .setSize(74, 14))
+ .widget(
+ new NumericWidget().setSetter(val -> autoPullRefreshTime = (int) val)
+ .setGetter(() -> autoPullRefreshTime)
+ .setBounds(1, Integer.MAX_VALUE)
+ .setScrollValues(1, 4, 64)
+ .setTextAlignment(Alignment.Center)
+ .setTextColor(Color.WHITE.normal)
+ .setSize(70, 18)
+ .setPos(3, 58)
+ .setBackground(GT_UITextures.BACKGROUND_TEXT_FIELD));
+ return builder.build();
+ }
+
+ @Override
+ public void addGregTechLogo(ModularWindow.Builder builder) {
+ builder.widget(
+ new DrawableWidget().setDrawable(getGUITextureSet().getGregTechLogo())
+ .setSize(17, 17)
+ .setPos(80, 63));
+ }
+
+ @Override
+ public void getWailaBody(ItemStack itemStack, List<String> currenttip, IWailaDataAccessor accessor,
+ IWailaConfigHandler config) {
+ if (!autoPullAvailable) {
+ super.getWailaBody(itemStack, currenttip, accessor, config);
+ return;
+ }
+
+ NBTTagCompound tag = accessor.getNBTData();
+ boolean autopull = tag.getBoolean("autoPull");
+ int minSize = tag.getInteger("minStackSize");
+ currenttip.add(
+ StatCollector.translateToLocal("GT5U.waila.stocking_bus.auto_pull." + (autopull ? "enabled" : "disabled")));
+ if (autopull) {
+ currenttip.add(
+ StatCollector.translateToLocalFormatted(
+ "GT5U.waila.stocking_bus.min_stack_size",
+ GT_Utility.formatNumbers(minSize)));
+ }
+ super.getWailaBody(itemStack, currenttip, accessor, config);
+ }
+
+ @Override
+ public void getWailaNBTData(EntityPlayerMP player, TileEntity tile, NBTTagCompound tag, World world, int x, int y,
+ int z) {
+ if (!autoPullAvailable) {
+ super.getWailaNBTData(player, tile, tag, world, x, y, z);
+ return;
+ }
+
+ tag.setBoolean("autoPull", autoPullItemList);
+ tag.setInteger("minStackSize", minAutoPullStackSize);
+ super.getWailaNBTData(player, tile, tag, world, x, y, z);
+ }
+
+ private static String[] getDescriptionArray(boolean autoPullAvailable) {
+ List<String> strings = new ArrayList<>(8);
+ strings.add("Advanced item input for Multiblocks");
+ strings.add("Hatch Tier: " + TIER_COLORS[autoPullAvailable ? 6 : 3] + VN[autoPullAvailable ? 6 : 3]);
+ strings.add("Retrieves directly from ME");
+ strings.add("Keeps 16 item types in stock");
+
+ if (autoPullAvailable) {
+ strings.add(
+ "Auto-Pull from ME mode will automatically stock the first 16 items in the ME system, updated every 5 seconds.");
+ strings.add("Toggle by right-clicking with screwdriver, or use the GUI.");
+ strings
+ .add("Use the GUI to limit the minimum stack size for Auto-Pulling and adjust the slot refresh timer.");
+ }
+
+ strings.add("Change ME connection behavior by right-clicking with wire cutter.");
+ strings.add("Configuration data can be copy+pasted using a data stick.");
+ return strings.toArray(new String[0]);
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_Hatch_Input_ME.java b/src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_Hatch_Input_ME.java
new file mode 100644
index 0000000000..18d4d669d1
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_Hatch_Input_ME.java
@@ -0,0 +1,884 @@
+package gregtech.common.tileentities.machines;
+
+import static gregtech.api.enums.GT_Values.TIER_COLORS;
+import static gregtech.api.enums.GT_Values.VN;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_ME_INPUT_FLUID_HATCH;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_ME_INPUT_FLUID_HATCH_ACTIVE;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import javax.annotation.Nullable;
+
+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.ChatComponentTranslation;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.StatCollector;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidStack;
+
+import com.gtnewhorizons.modularui.api.ModularUITextures;
+import com.gtnewhorizons.modularui.api.drawable.IDrawable;
+import com.gtnewhorizons.modularui.api.drawable.Text;
+import com.gtnewhorizons.modularui.api.math.Alignment;
+import com.gtnewhorizons.modularui.api.math.Color;
+import com.gtnewhorizons.modularui.api.math.Pos2d;
+import com.gtnewhorizons.modularui.api.math.Size;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.api.widget.Interactable;
+import com.gtnewhorizons.modularui.common.fluid.FluidStackTank;
+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.SlotGroup;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+import com.gtnewhorizons.modularui.common.widget.textfield.NumericWidget;
+
+import appeng.api.config.Actionable;
+import appeng.api.config.PowerMultiplier;
+import appeng.api.implementations.IPowerChannelState;
+import appeng.api.networking.GridFlags;
+import appeng.api.networking.security.BaseActionSource;
+import appeng.api.networking.security.IActionHost;
+import appeng.api.networking.security.MachineSource;
+import appeng.api.storage.IMEMonitor;
+import appeng.api.storage.data.IAEFluidStack;
+import appeng.api.util.AECableType;
+import appeng.core.localization.WailaText;
+import appeng.me.GridAccessException;
+import appeng.me.helpers.AENetworkProxy;
+import appeng.me.helpers.IGridProxyable;
+import appeng.util.item.AEFluidStack;
+import gregtech.api.enums.ItemList;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.modularui.IAddGregtechLogo;
+import gregtech.api.interfaces.modularui.IAddUIWidgets;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Input;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_MultiBlockBase;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.recipe.check.SimpleCheckRecipeResult;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.shutdown.ShutDownReasonRegistry;
+import mcp.mobius.waila.api.IWailaConfigHandler;
+import mcp.mobius.waila.api.IWailaDataAccessor;
+
+public class GT_MetaTileEntity_Hatch_Input_ME extends GT_MetaTileEntity_Hatch_Input
+ implements IPowerChannelState, IAddGregtechLogo, IAddUIWidgets, IRecipeProcessingAwareHatch {
+
+ private static final int SLOT_COUNT = 16;
+
+ protected final FluidStack[] storedFluids = new FluidStack[SLOT_COUNT];
+ protected final FluidStack[] storedInformationFluids = new FluidStack[SLOT_COUNT];
+
+ // these two fields should ALWAYS be mutated simultaneously
+ // in most cases, you should call setSavedFluid() instead of trying to write to the array directly
+ // a desync of these two fields can lead to catastrophe
+ protected final FluidStack[] shadowStoredFluids = new FluidStack[SLOT_COUNT];
+ private final int[] savedStackSizes = new int[SLOT_COUNT];
+
+ private boolean additionalConnection = false;
+
+ protected BaseActionSource requestSource = null;
+
+ @Nullable
+ protected AENetworkProxy gridProxy = null;
+
+ private final boolean autoPullAvailable;
+ protected boolean autoPullFluidList = false;
+ protected int minAutoPullAmount = 1;
+ private int autoPullRefreshTime = 100;
+ protected boolean processingRecipe = false;
+
+ protected static final int CONFIG_WINDOW_ID = 10;
+
+ protected static final FluidStack[] EMPTY_FLUID_STACK = new FluidStack[0];
+
+ public GT_MetaTileEntity_Hatch_Input_ME(int aID, boolean autoPullAvailable, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional, autoPullAvailable ? 10 : 8, 1, getDescriptionArray(autoPullAvailable));
+ this.autoPullAvailable = autoPullAvailable;
+ }
+
+ public GT_MetaTileEntity_Hatch_Input_ME(String aName, boolean autoPullAvailable, int aTier, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, 1, aTier, aDescription, aTextures);
+ this.autoPullAvailable = autoPullAvailable;
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Hatch_Input_ME(mName, autoPullAvailable, mTier, mDescriptionArray, mTextures);
+ }
+
+ @Override
+ public ITexture[] getTexturesActive(ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture, TextureFactory.of(OVERLAY_ME_INPUT_FLUID_HATCH_ACTIVE) };
+ }
+
+ @Override
+ public ITexture[] getTexturesInactive(ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture, TextureFactory.of(OVERLAY_ME_INPUT_FLUID_HATCH) };
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTimer) {
+ if (getBaseMetaTileEntity().isServerSide()) {
+ if (aTimer % autoPullRefreshTime == 0 && autoPullFluidList) {
+ refreshFluidList();
+ }
+ if (aTimer % 20 == 0) {
+ getBaseMetaTileEntity().setActive(isActive());
+ }
+ }
+ super.onPostTick(aBaseMetaTileEntity, aTimer);
+ }
+
+ private void refreshFluidList() {
+ AENetworkProxy proxy = getProxy();
+ if (proxy == null || !proxy.isActive()) {
+ return;
+ }
+
+ try {
+ IMEMonitor<IAEFluidStack> sg = proxy.getStorage()
+ .getFluidInventory();
+ Iterator<IAEFluidStack> iterator = sg.getStorageList()
+ .iterator();
+
+ int index = 0;
+ while (iterator.hasNext() && index < SLOT_COUNT) {
+ IAEFluidStack currItem = iterator.next();
+ if (currItem.getStackSize() >= minAutoPullAmount) {
+ FluidStack fluidStack = GT_Utility.copyAmount(1, currItem.getFluidStack());
+ storedFluids[index] = fluidStack;
+ index++;
+ }
+ }
+
+ for (int i = index; i < SLOT_COUNT; i++) {
+ storedFluids[i] = null;
+ }
+ } catch (final GridAccessException ignored) {}
+ }
+
+ @Override
+ public boolean displaysStackSize() {
+ return true;
+ }
+
+ protected void setSavedFluid(int i, FluidStack stack) {
+ shadowStoredFluids[i] = stack;
+ savedStackSizes[i] = stack == null ? 0 : stack.amount;
+ }
+
+ public FluidStack[] getStoredFluids() {
+ if (!processingRecipe) {
+ return EMPTY_FLUID_STACK;
+ }
+
+ AENetworkProxy proxy = getProxy();
+ if (proxy == null || !proxy.isActive()) {
+ return EMPTY_FLUID_STACK;
+ }
+
+ updateAllInformationSlots();
+
+ for (int i = 0; i < SLOT_COUNT; i++) {
+ if (storedFluids[i] == null) {
+ setSavedFluid(i, null);
+ continue;
+ }
+
+ FluidStack fluidStackWithAmount = storedInformationFluids[i];
+ // Nothing in stock, no need to save anything
+ if (fluidStackWithAmount == null) continue;
+
+ setSavedFluid(i, fluidStackWithAmount);
+ }
+
+ return shadowStoredFluids;
+ }
+
+ @Override
+ public FluidStack drain(ForgeDirection side, FluidStack aFluid, boolean doDrain) {
+ // this is an ME input hatch. allowing draining via logistics would be very wrong (and against
+ // canTankBeEmptied()) but we do need to support draining from controller, which uses the UNKNOWN direction.
+ if (side != ForgeDirection.UNKNOWN) return null;
+ FluidStack stored = getMatchingFluidStack(aFluid);
+ if (stored == null) return null;
+ FluidStack drained = GT_Utility.copyAmount(Math.min(stored.amount, aFluid.amount), stored);
+ if (doDrain) {
+ stored.amount -= drained.amount;
+ }
+ return drained;
+ }
+
+ @Override
+ public void startRecipeProcessing() {
+ processingRecipe = true;
+ updateAllInformationSlots();
+ }
+
+ @Override
+ public CheckRecipeResult endRecipeProcessing(GT_MetaTileEntity_MultiBlockBase controller) {
+ CheckRecipeResult checkRecipeResult = CheckRecipeResultRegistry.SUCCESSFUL;
+ AENetworkProxy proxy = getProxy();
+
+ for (int i = 0; i < SLOT_COUNT; ++i) {
+ FluidStack oldStack = shadowStoredFluids[i];
+ int toExtract = savedStackSizes[i] - (oldStack != null ? oldStack.amount : 0);
+ if (toExtract <= 0) continue;
+
+ try {
+ IMEMonitor<IAEFluidStack> sg = proxy.getStorage()
+ .getFluidInventory();
+
+ IAEFluidStack request = AEFluidStack.create(storedFluids[i]);
+ request.setStackSize(toExtract);
+ IAEFluidStack extractionResult = sg.extractItems(request, Actionable.MODULATE, getRequestSource());
+ proxy.getEnergy()
+ .extractAEPower(toExtract, Actionable.MODULATE, PowerMultiplier.CONFIG);
+
+ if (extractionResult == null || extractionResult.getStackSize() != toExtract) {
+ controller.stopMachine(ShutDownReasonRegistry.CRITICAL_NONE);
+ checkRecipeResult = SimpleCheckRecipeResult
+ .ofFailurePersistOnShutdown("stocking_hatch_fail_extraction");
+ }
+ } catch (GridAccessException ignored) {
+ controller.stopMachine(ShutDownReasonRegistry.CRITICAL_NONE);
+ checkRecipeResult = SimpleCheckRecipeResult
+ .ofFailurePersistOnShutdown("stocking_hatch_fail_extraction");
+ }
+ setSavedFluid(i, null);
+ if (storedInformationFluids[i] != null && storedInformationFluids[i].amount <= 0) {
+ storedInformationFluids[i] = null;
+ }
+ }
+
+ processingRecipe = false;
+ return checkRecipeResult;
+ }
+
+ @Override
+ public void onFirstTick(IGregTechTileEntity aBaseMetaTileEntity) {
+ super.onFirstTick(aBaseMetaTileEntity);
+ getProxy().onReady();
+ }
+
+ @Override
+ public AECableType getCableConnectionType(ForgeDirection forgeDirection) {
+ return isOutputFacing(forgeDirection) ? AECableType.SMART : AECableType.NONE;
+ }
+
+ private void updateValidGridProxySides() {
+ if (additionalConnection) {
+ getProxy().setValidSides(EnumSet.complementOf(EnumSet.of(ForgeDirection.UNKNOWN)));
+ } else {
+ getProxy().setValidSides(EnumSet.of(getBaseMetaTileEntity().getFrontFacing()));
+ }
+ }
+
+ @Override
+ public void onFacingChange() {
+ updateValidGridProxySides();
+ }
+
+ @Override
+ public boolean onWireCutterRightClick(ForgeDirection side, ForgeDirection wrenchingSide, EntityPlayer aPlayer,
+ float aX, float aY, float aZ) {
+ additionalConnection = !additionalConnection;
+ updateValidGridProxySides();
+ aPlayer.addChatComponentMessage(
+ new ChatComponentTranslation("GT5U.hatch.additionalConnection." + additionalConnection));
+ return true;
+ }
+
+ @Override
+ public AENetworkProxy getProxy() {
+ if (gridProxy == null) {
+ if (getBaseMetaTileEntity() instanceof IGridProxyable) {
+ gridProxy = new AENetworkProxy(
+ (IGridProxyable) getBaseMetaTileEntity(),
+ "proxy",
+ autoPullAvailable ? ItemList.Hatch_Input_ME_Advanced.get(1) : ItemList.Hatch_Input_ME.get(1),
+ true);
+ gridProxy.setFlags(GridFlags.REQUIRE_CHANNEL);
+ updateValidGridProxySides();
+ if (getBaseMetaTileEntity().getWorld() != null) gridProxy.setOwner(
+ getBaseMetaTileEntity().getWorld()
+ .getPlayerEntityByName(getBaseMetaTileEntity().getOwnerName()));
+ }
+ }
+ return this.gridProxy;
+ }
+
+ @Override
+ public boolean isPowered() {
+ return getProxy() != null && getProxy().isPowered();
+ }
+
+ @Override
+ public boolean isActive() {
+ return getProxy() != null && getProxy().isActive();
+ }
+
+ private void setAutoPullFluidList(boolean pullFluidList) {
+ if (!autoPullAvailable) {
+ return;
+ }
+
+ autoPullFluidList = pullFluidList;
+ if (!autoPullFluidList) {
+ Arrays.fill(storedFluids, null);
+ } else {
+ refreshFluidList();
+ }
+ updateAllInformationSlots();
+ }
+
+ private void updateAllInformationSlots() {
+ for (int index = 0; index < SLOT_COUNT; index++) {
+ updateInformationSlot(index);
+ }
+ }
+
+ public void updateInformationSlot(int index) {
+ if (index < 0 || index >= SLOT_COUNT) {
+ return;
+ }
+
+ FluidStack fluidStack = storedFluids[index];
+ if (fluidStack == null) {
+ storedInformationFluids[index] = null;
+ return;
+ }
+
+ AENetworkProxy proxy = getProxy();
+ if (proxy == null || !proxy.isActive()) {
+ storedInformationFluids[index] = null;
+ return;
+ }
+
+ try {
+ IMEMonitor<IAEFluidStack> sg = proxy.getStorage()
+ .getFluidInventory();
+ IAEFluidStack request = AEFluidStack.create(fluidStack);
+ request.setStackSize(Integer.MAX_VALUE);
+ IAEFluidStack result = sg.extractItems(request, Actionable.SIMULATE, getRequestSource());
+ FluidStack resultFluid = (result != null) ? result.getFluidStack() : null;
+ storedInformationFluids[index] = resultFluid;
+ } catch (final GridAccessException ignored) {}
+ }
+
+ private BaseActionSource getRequestSource() {
+ if (requestSource == null) requestSource = new MachineSource((IActionHost) getBaseMetaTileEntity());
+ return requestSource;
+ }
+
+ public FluidStack getMatchingFluidStack(FluidStack fluidStack) {
+ if (fluidStack == null) return null;
+
+ AENetworkProxy proxy = getProxy();
+ if (proxy == null || !proxy.isActive()) {
+ return null;
+ }
+
+ for (int i = 0; i < storedFluids.length; i++) {
+ if (storedFluids[i] == null) {
+ continue;
+ }
+
+ if (GT_Utility.areFluidsEqual(fluidStack, storedFluids[i], false)) {
+ updateInformationSlot(i);
+ if (storedInformationFluids[i] != null) {
+ setSavedFluid(i, storedInformationFluids[i]);
+ return shadowStoredFluids[i];
+ }
+
+ setSavedFluid(i, null);
+ return null;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Used to avoid slot update.
+ */
+ public FluidStack getShadowFluidStack(int index) {
+ if (index < 0 || index >= storedFluids.length) {
+ return null;
+ }
+
+ return shadowStoredFluids[index];
+ }
+
+ public int getFluidSlot(FluidStack fluidStack) {
+ if (fluidStack == null) return -1;
+
+ for (int i = 0; i < storedFluids.length; i++) {
+ if (storedFluids[i] == null) {
+ continue;
+ }
+
+ if (GT_Utility.areFluidsEqual(fluidStack, storedFluids[i], false)) {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ @Override
+ public boolean canTankBeEmptied() {
+ return false;
+ }
+
+ @Override
+ public boolean canTankBeFilled() {
+ return false;
+ }
+
+ @Override
+ public boolean doesEmptyContainers() {
+ return false;
+ }
+
+ @Override
+ public boolean isValidSlot(int aIndex) {
+ return false;
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+
+ NBTTagList nbtTagList = new NBTTagList();
+ for (int i = 0; i < SLOT_COUNT; i++) {
+ FluidStack fluidStack = storedFluids[i];
+ if (fluidStack == null) {
+ continue;
+ }
+ NBTTagCompound fluidTag = fluidStack.writeToNBT(new NBTTagCompound());
+ if (storedInformationFluids[i] != null)
+ fluidTag.setInteger("informationAmount", storedInformationFluids[i].amount);
+ nbtTagList.appendTag(fluidTag);
+ }
+
+ aNBT.setTag("storedFluids", nbtTagList);
+ aNBT.setBoolean("autoPull", autoPullFluidList);
+ aNBT.setInteger("minAmount", minAutoPullAmount);
+ aNBT.setBoolean("additionalConnection", additionalConnection);
+ aNBT.setInteger("refreshTime", autoPullRefreshTime);
+ getProxy().writeToNBT(aNBT);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ if (aNBT.hasKey("storedFluids")) {
+ NBTTagList nbtTagList = aNBT.getTagList("storedFluids", 10);
+ int c = Math.min(nbtTagList.tagCount(), SLOT_COUNT);
+ for (int i = 0; i < c; i++) {
+ NBTTagCompound nbtTagCompound = nbtTagList.getCompoundTagAt(i);
+ FluidStack fluidStack = GT_Utility.loadFluid(nbtTagCompound);
+ storedFluids[i] = fluidStack;
+
+ if (nbtTagCompound.hasKey("informationAmount")) {
+ int informationAmount = nbtTagCompound.getInteger("informationAmount");
+ storedInformationFluids[i] = GT_Utility.copyAmount(informationAmount, fluidStack);
+ }
+ }
+ }
+
+ minAutoPullAmount = aNBT.getInteger("minAmount");
+ autoPullFluidList = aNBT.getBoolean("autoPull");
+ additionalConnection = aNBT.getBoolean("additionalConnection");
+ if (aNBT.hasKey("refreshTime")) {
+ autoPullRefreshTime = aNBT.getInteger("refreshTime");
+ }
+ getProxy().readFromNBT(aNBT);
+ }
+
+ @Override
+ public void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ if (!autoPullAvailable) {
+ return;
+ }
+
+ setAutoPullFluidList(!autoPullFluidList);
+ aPlayer.addChatMessage(
+ new ChatComponentTranslation(
+ "GT5U.machines.stocking_hatch.auto_pull_toggle." + (autoPullFluidList ? "enabled" : "disabled")));
+ }
+
+ @Override
+ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer, ForgeDirection side,
+ float aX, float aY, float aZ) {
+ if (!(aPlayer instanceof EntityPlayerMP))
+ return super.onRightclick(aBaseMetaTileEntity, aPlayer, side, aX, aY, aZ);
+ ItemStack dataStick = aPlayer.inventory.getCurrentItem();
+ if (!ItemList.Tool_DataStick.isStackEqual(dataStick, false, true))
+ return super.onRightclick(aBaseMetaTileEntity, aPlayer, side, aX, aY, aZ);
+ if (!dataStick.hasTagCompound() || !"stockingHatch".equals(dataStick.stackTagCompound.getString("type")))
+ return false;
+
+ NBTTagCompound nbt = dataStick.stackTagCompound;
+
+ if (autoPullAvailable) {
+ setAutoPullFluidList(nbt.getBoolean("autoPull"));
+ minAutoPullAmount = nbt.getInteger("minAmount");
+ autoPullRefreshTime = nbt.getInteger("refreshTime");
+ }
+ additionalConnection = nbt.getBoolean("additionalConnection");
+
+ if (!autoPullFluidList) {
+ NBTTagList stockingFluids = nbt.getTagList("fluidsToStock", 10);
+ for (int i = 0; i < stockingFluids.tagCount(); i++) {
+ storedFluids[i] = GT_Utility.loadFluid(stockingFluids.getCompoundTagAt(i));
+ }
+ }
+
+ updateValidGridProxySides();
+ aPlayer.addChatMessage(new ChatComponentTranslation("GT5U.machines.stocking_bus.loaded"));
+ return true;
+ }
+
+ @Override
+ public void onLeftclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) {
+ if (!(aPlayer instanceof EntityPlayerMP)) return;
+
+ ItemStack dataStick = aPlayer.inventory.getCurrentItem();
+ if (!ItemList.Tool_DataStick.isStackEqual(dataStick, false, true)) return;
+
+ NBTTagCompound tag = new NBTTagCompound();
+ tag.setString("type", "stockingHatch");
+ tag.setBoolean("autoPull", autoPullFluidList);
+ tag.setInteger("minAmount", minAutoPullAmount);
+ tag.setBoolean("additionalConnection", additionalConnection);
+ tag.setInteger("refreshTime", autoPullRefreshTime);
+
+ NBTTagList stockingFluids = new NBTTagList();
+ if (!autoPullFluidList) {
+ for (int index = 0; index < SLOT_COUNT; index++) {
+ FluidStack fluidStack = storedFluids[index];
+ if (fluidStack == null) {
+ continue;
+ }
+ stockingFluids.appendTag(fluidStack.writeToNBT(new NBTTagCompound()));
+ }
+ tag.setTag("fluidsToStock", stockingFluids);
+ }
+ dataStick.stackTagCompound = tag;
+ dataStick.setStackDisplayName("Stocking Input Hatch Configuration");
+ aPlayer.addChatMessage(new ChatComponentTranslation("GT5U.machines.stocking_bus.saved"));
+ }
+
+ @Override
+ public void onExplosion() {
+ for (int i = 0; i < SLOT_COUNT; i++) {
+ mInventory[i] = null;
+ }
+ }
+
+ public boolean containsSuchStack(FluidStack tStack) {
+ for (int i = 0; i < 16; ++i) {
+ if (GT_Utility.areFluidsEqual(storedFluids[i], tStack, false)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int getGUIHeight() {
+ return 179;
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ if (autoPullAvailable) {
+ buildContext.addSyncedWindow(CONFIG_WINDOW_ID, this::createStackSizeConfigurationWindow);
+ }
+
+ builder.widget(
+ SlotGroup.ofFluidTanks(
+ IntStream.range(0, SLOT_COUNT)
+ .mapToObj(index -> createTankForFluidStack(storedFluids, index, 1))
+ .collect(Collectors.toList()),
+ 4)
+ .phantom(true)
+ .widgetCreator((slotIndex, h) -> (FluidSlotWidget) new FluidSlotWidget(h) {
+
+ @Override
+ protected void tryClickPhantom(ClickData clickData, ItemStack cursorStack) {
+ if (clickData.mouseButton != 0 || autoPullFluidList) return;
+
+ FluidStack heldFluid = getFluidForPhantomItem(cursorStack);
+ if (cursorStack == null) {
+ storedFluids[slotIndex] = null;
+ } else {
+ if (containsSuchStack(heldFluid)) return;
+ storedFluids[slotIndex] = heldFluid;
+ }
+ if (getBaseMetaTileEntity().isServerSide()) {
+ updateInformationSlot(slotIndex);
+ detectAndSendChanges(false);
+ }
+ }
+
+ @Override
+ protected void tryScrollPhantom(int direction) {}
+
+ @Override
+ public IDrawable[] getBackground() {
+ IDrawable slot;
+ if (autoPullFluidList) {
+ slot = GT_UITextures.SLOT_DARK_GRAY;
+ } else {
+ slot = ModularUITextures.FLUID_SLOT;
+ }
+ return new IDrawable[] { slot, GT_UITextures.OVERLAY_SLOT_ARROW_ME };
+ }
+
+ @Override
+ public void buildTooltip(List<Text> tooltip) {
+ FluidStack fluid = getContent();
+ if (fluid != null) {
+ addFluidNameInfo(tooltip, fluid);
+
+ if (!autoPullFluidList) {
+ tooltip.add(Text.localised("modularui.phantom.single.clear"));
+ }
+ } else {
+ tooltip.add(
+ Text.localised("modularui.fluid.empty")
+ .format(EnumChatFormatting.WHITE));
+ }
+
+ if (autoPullFluidList) {
+ tooltip.add(Text.localised("GT5U.machines.stocking_bus.cannot_set_slot"));
+ }
+ }
+ }.setUpdateTooltipEveryTick(true))
+ .build()
+ .setPos(new Pos2d(7, 9)));
+
+ builder.widget(
+ SlotGroup.ofFluidTanks(
+ IntStream.range(0, SLOT_COUNT)
+ .mapToObj(index -> createTankForFluidStack(storedInformationFluids, index, Integer.MAX_VALUE))
+ .collect(Collectors.toList()),
+ 4)
+ .phantom(true)
+ .widgetCreator((slotIndex, h) -> (FluidSlotWidget) new FluidSlotWidget(h) {
+
+ @Override
+ protected void tryClickPhantom(ClickData clickData, ItemStack cursorStack) {}
+
+ @Override
+ protected void tryScrollPhantom(int direction) {}
+
+ @Override
+ public void buildTooltip(List<Text> tooltip) {
+ FluidStack fluid = getContent();
+ if (fluid != null) {
+ addFluidNameInfo(tooltip, fluid);
+ tooltip.add(Text.localised("modularui.fluid.phantom.amount", fluid.amount));
+ addAdditionalFluidInfo(tooltip, fluid);
+ if (!Interactable.hasShiftDown()) {
+ tooltip.add(Text.EMPTY);
+ tooltip.add(Text.localised("modularui.tooltip.shift"));
+ }
+ } else {
+ tooltip.add(
+ Text.localised("modularui.fluid.empty")
+ .format(EnumChatFormatting.WHITE));
+ }
+ }
+ }.setUpdateTooltipEveryTick(true))
+ .background(GT_UITextures.SLOT_DARK_GRAY)
+ .controlsAmount(true)
+ .build()
+ .setPos(new Pos2d(97, 9)));
+
+ if (autoPullAvailable) {
+ builder.widget(new ButtonWidget().setOnClick((clickData, widget) -> {
+ if (clickData.mouseButton == 0) {
+ setAutoPullFluidList(!autoPullFluidList);
+ } else if (clickData.mouseButton == 1 && !widget.isClient()) {
+ widget.getContext()
+ .openSyncedWindow(CONFIG_WINDOW_ID);
+ }
+ })
+ .setPlayClickSound(true)
+ .setBackground(() -> {
+ if (autoPullFluidList) {
+ return new IDrawable[] { GT_UITextures.BUTTON_STANDARD_PRESSED,
+ GT_UITextures.OVERLAY_BUTTON_AUTOPULL_ME };
+ } else {
+ return new IDrawable[] { GT_UITextures.BUTTON_STANDARD,
+ GT_UITextures.OVERLAY_BUTTON_AUTOPULL_ME_DISABLED };
+ }
+ })
+ .addTooltips(
+ Arrays.asList(
+ StatCollector.translateToLocal("GT5U.machines.stocking_hatch.auto_pull.tooltip.1"),
+ StatCollector.translateToLocal("GT5U.machines.stocking_hatch.auto_pull.tooltip.2")))
+ .setSize(16, 16)
+ .setPos(80, 10))
+ .widget(new FakeSyncWidget.BooleanSyncer(() -> autoPullFluidList, this::setAutoPullFluidList));
+ }
+
+ builder.widget(
+ new DrawableWidget().setDrawable(GT_UITextures.PICTURE_ARROW_DOUBLE)
+ .setPos(82, 30)
+ .setSize(12, 12))
+ .widget(TextWidget.dynamicString(() -> {
+ boolean isActive = isActive();
+ boolean isPowered = isPowered();
+ boolean isBooting = isBooting();
+ EnumChatFormatting color = (isActive && isPowered) ? EnumChatFormatting.GREEN
+ : EnumChatFormatting.DARK_RED;
+ return color + WailaText.getPowerState(isActive, isPowered, isBooting);
+ })
+ .setTextAlignment(Alignment.Center)
+ .setSize(90, 9)
+ .setPos(43, 84));
+ }
+
+ private FluidStackTank createTankForFluidStack(FluidStack[] fluidStacks, int slotIndex, int capacity) {
+ return new FluidStackTank(() -> fluidStacks[slotIndex], (stack) -> {
+ if (getBaseMetaTileEntity().isServerSide()) {
+ return;
+ }
+
+ fluidStacks[slotIndex] = stack;
+ }, capacity);
+ }
+
+ protected ModularWindow createStackSizeConfigurationWindow(final EntityPlayer player) {
+ final int WIDTH = 78;
+ final int HEIGHT = 80;
+ final int PARENT_WIDTH = getGUIWidth();
+ final int PARENT_HEIGHT = getGUIHeight();
+ ModularWindow.Builder builder = ModularWindow.builder(WIDTH, HEIGHT);
+ builder.setBackground(GT_UITextures.BACKGROUND_SINGLEBLOCK_DEFAULT);
+ builder.setGuiTint(getGUIColorization());
+ builder.setDraggable(true);
+ builder.setPos(
+ (size, window) -> Alignment.Center.getAlignedPos(size, new Size(PARENT_WIDTH, PARENT_HEIGHT))
+ .add(
+ Alignment.TopRight.getAlignedPos(new Size(PARENT_WIDTH, PARENT_HEIGHT), new Size(WIDTH, HEIGHT))
+ .add(WIDTH - 3, 0)));
+ builder.widget(
+ TextWidget.localised("GT5U.machines.stocking_hatch.min_amount")
+ .setPos(3, 2)
+ .setSize(74, 14))
+ .widget(
+ new NumericWidget().setSetter(val -> minAutoPullAmount = (int) val)
+ .setGetter(() -> minAutoPullAmount)
+ .setBounds(1, Integer.MAX_VALUE)
+ .setScrollValues(1, 4, 64)
+ .setTextAlignment(Alignment.Center)
+ .setTextColor(Color.WHITE.normal)
+ .setSize(70, 18)
+ .setPos(3, 18)
+ .setBackground(GT_UITextures.BACKGROUND_TEXT_FIELD));
+ builder.widget(
+ TextWidget.localised("GT5U.machines.stocking_bus.refresh_time")
+ .setPos(3, 42)
+ .setSize(74, 14))
+ .widget(
+ new NumericWidget().setSetter(val -> autoPullRefreshTime = (int) val)
+ .setGetter(() -> autoPullRefreshTime)
+ .setBounds(1, Integer.MAX_VALUE)
+ .setScrollValues(1, 4, 64)
+ .setTextAlignment(Alignment.Center)
+ .setTextColor(Color.WHITE.normal)
+ .setSize(70, 18)
+ .setPos(3, 58)
+ .setBackground(GT_UITextures.BACKGROUND_TEXT_FIELD));
+ return builder.build();
+ }
+
+ @Override
+ public void addGregTechLogo(ModularWindow.Builder builder) {
+ builder.widget(
+ new DrawableWidget().setDrawable(getGUITextureSet().getGregTechLogo())
+ .setSize(17, 17)
+ .setPos(80, 63));
+ }
+
+ @Override
+ public void getWailaBody(ItemStack itemStack, List<String> currenttip, IWailaDataAccessor accessor,
+ IWailaConfigHandler config) {
+ if (!autoPullAvailable) {
+ super.getWailaBody(itemStack, currenttip, accessor, config);
+ return;
+ }
+
+ NBTTagCompound tag = accessor.getNBTData();
+ boolean autopull = tag.getBoolean("autoPull");
+ int minSize = tag.getInteger("minAmount");
+ currenttip.add(
+ StatCollector.translateToLocal("GT5U.waila.stocking_bus.auto_pull." + (autopull ? "enabled" : "disabled")));
+ if (autopull) {
+ currenttip.add(
+ StatCollector.translateToLocalFormatted(
+ "GT5U.waila.stocking_hatch.min_amount",
+ GT_Utility.formatNumbers(minSize)));
+ }
+ super.getWailaBody(itemStack, currenttip, accessor, config);
+ }
+
+ @Override
+ public void getWailaNBTData(EntityPlayerMP player, TileEntity tile, NBTTagCompound tag, World world, int x, int y,
+ int z) {
+ if (!autoPullAvailable) {
+ super.getWailaNBTData(player, tile, tag, world, x, y, z);
+ return;
+ }
+
+ tag.setBoolean("autoPull", autoPullFluidList);
+ tag.setInteger("minAmount", minAutoPullAmount);
+ super.getWailaNBTData(player, tile, tag, world, x, y, z);
+ }
+
+ private static String[] getDescriptionArray(boolean autoPullAvailable) {
+ List<String> strings = new ArrayList<>(8);
+ strings.add("Advanced fluid input for Multiblocks");
+ strings.add("Hatch Tier: " + TIER_COLORS[autoPullAvailable ? 10 : 8] + VN[autoPullAvailable ? 10 : 8]);
+ strings.add("Retrieves directly from ME");
+ strings.add("Keeps 16 fluid types in stock");
+
+ if (autoPullAvailable) {
+ strings.add(
+ "Auto-Pull from ME mode will automatically stock the first 16 fluid in the ME system, updated every 5 seconds.");
+ strings.add("Toggle by right-clicking with screwdriver, or use the GUI.");
+ strings
+ .add("Use the GUI to limit the minimum stack size for Auto-Pulling and adjust the slot refresh timer.");
+ }
+
+ strings.add("Change ME connection behavior by right-clicking with wire cutter.");
+ strings.add("Configuration data can be copy+pasted using a data stick.");
+ return strings.toArray(new String[0]);
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_Hatch_OutputBus_ME.java b/src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_Hatch_OutputBus_ME.java
new file mode 100644
index 0000000000..16817e1a9c
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_Hatch_OutputBus_ME.java
@@ -0,0 +1,327 @@
+package gregtech.common.tileentities.machines;
+
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_ME_HATCH;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_ME_HATCH_ACTIVE;
+
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTBase;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraft.util.ChatComponentTranslation;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import appeng.api.AEApi;
+import appeng.api.implementations.IPowerChannelState;
+import appeng.api.networking.GridFlags;
+import appeng.api.networking.security.BaseActionSource;
+import appeng.api.networking.security.IActionHost;
+import appeng.api.networking.security.MachineSource;
+import appeng.api.storage.IMEMonitor;
+import appeng.api.storage.data.IAEItemStack;
+import appeng.api.storage.data.IItemList;
+import appeng.api.util.AECableType;
+import appeng.me.GridAccessException;
+import appeng.me.helpers.AENetworkProxy;
+import appeng.me.helpers.IGridProxyable;
+import appeng.util.IWideReadableNumberConverter;
+import appeng.util.Platform;
+import appeng.util.ReadableNumberConverter;
+import gregtech.GT_Mod;
+import gregtech.api.enums.ItemList;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_OutputBus;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_Hatch_OutputBus_ME extends GT_MetaTileEntity_Hatch_OutputBus
+ implements IPowerChannelState {
+
+ private BaseActionSource requestSource = null;
+ private @Nullable AENetworkProxy gridProxy = null;
+ final IItemList<IAEItemStack> itemCache = AEApi.instance()
+ .storage()
+ .createItemList();
+ long lastOutputTick = 0;
+ long tickCounter = 0;
+ boolean lastOutputFailed = false;
+ boolean infiniteCache = true;
+ boolean additionalConnection = false;
+
+ public GT_MetaTileEntity_Hatch_OutputBus_ME(int aID, String aName, String aNameRegional) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ 3,
+ new String[] { "Item Output for Multiblocks", "Stores directly into ME",
+ "Can cache infinite amount of items.", "Change cache behavior by right-clicking with screwdriver.",
+ "Change ME connection behavior by right-clicking with wire cutter" },
+ 0);
+ }
+
+ public GT_MetaTileEntity_Hatch_OutputBus_ME(String aName, int aTier, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, 0, aDescription, aTextures);
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Hatch_OutputBus_ME(mName, mTier, mDescriptionArray, mTextures);
+ }
+
+ @Override
+ public ITexture[] getTexturesActive(ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture, TextureFactory.of(OVERLAY_ME_HATCH_ACTIVE) };
+ }
+
+ @Override
+ public ITexture[] getTexturesInactive(ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture, TextureFactory.of(OVERLAY_ME_HATCH) };
+ }
+
+ @Override
+ public void onFirstTick(IGregTechTileEntity aBaseMetaTileEntity) {
+ super.onFirstTick(aBaseMetaTileEntity);
+ getProxy().onReady();
+ }
+
+ @Override
+ public boolean storeAll(ItemStack aStack) {
+ aStack.stackSize = store(aStack);
+ return aStack.stackSize == 0;
+ }
+
+ /**
+ * Attempt to store items in connected ME network. Returns how many items did not fit (if the network was down e.g.)
+ *
+ * @param stack input stack
+ * @return amount of items left over
+ */
+ public int store(final ItemStack stack) {
+ if (!infiniteCache && lastOutputFailed) return stack.stackSize;
+ itemCache.add(
+ AEApi.instance()
+ .storage()
+ .createItemStack(stack));
+ return 0;
+ }
+
+ private BaseActionSource getRequest() {
+ if (requestSource == null) requestSource = new MachineSource((IActionHost) getBaseMetaTileEntity());
+ return requestSource;
+ }
+
+ @Override
+ public AECableType getCableConnectionType(ForgeDirection forgeDirection) {
+ return isOutputFacing(forgeDirection) ? AECableType.SMART : AECableType.NONE;
+ }
+
+ private void updateValidGridProxySides() {
+ if (additionalConnection) {
+ getProxy().setValidSides(EnumSet.complementOf(EnumSet.of(ForgeDirection.UNKNOWN)));
+ } else {
+ getProxy().setValidSides(EnumSet.of(getBaseMetaTileEntity().getFrontFacing()));
+ }
+ }
+
+ @Override
+ public void onFacingChange() {
+ updateValidGridProxySides();
+ }
+
+ @Override
+ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) {
+ return false;
+ }
+
+ @Override
+ public void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ if (!getBaseMetaTileEntity().getCoverInfoAtSide(side)
+ .isGUIClickable()) return;
+ infiniteCache = !infiniteCache;
+ aPlayer.addChatComponentMessage(new ChatComponentTranslation("GT5U.hatch.infiniteCache." + infiniteCache));
+ }
+
+ @Override
+ public boolean onWireCutterRightClick(ForgeDirection side, ForgeDirection wrenchingSide, EntityPlayer aPlayer,
+ float aX, float aY, float aZ) {
+ additionalConnection = !additionalConnection;
+ updateValidGridProxySides();
+ aPlayer.addChatComponentMessage(
+ new ChatComponentTranslation("GT5U.hatch.additionalConnection." + additionalConnection));
+ return true;
+ }
+
+ @Override
+ public AENetworkProxy getProxy() {
+ if (gridProxy == null) {
+ if (getBaseMetaTileEntity() instanceof IGridProxyable) {
+ gridProxy = new AENetworkProxy(
+ (IGridProxyable) getBaseMetaTileEntity(),
+ "proxy",
+ ItemList.Hatch_Output_Bus_ME.get(1),
+ true);
+ gridProxy.setFlags(GridFlags.REQUIRE_CHANNEL);
+ updateValidGridProxySides();
+ if (getBaseMetaTileEntity().getWorld() != null) gridProxy.setOwner(
+ getBaseMetaTileEntity().getWorld()
+ .getPlayerEntityByName(getBaseMetaTileEntity().getOwnerName()));
+ }
+ }
+ return this.gridProxy;
+ }
+
+ private void flushCachedStack() {
+ lastOutputFailed = false;
+ AENetworkProxy proxy = getProxy();
+ if (proxy == null) {
+ lastOutputFailed = true;
+ return;
+ }
+ try {
+ IMEMonitor<IAEItemStack> sg = proxy.getStorage()
+ .getItemInventory();
+ for (IAEItemStack s : itemCache) {
+ if (s.getStackSize() == 0) continue;
+ IAEItemStack rest = Platform.poweredInsert(proxy.getEnergy(), sg, s, getRequest());
+ if (rest != null && rest.getStackSize() > 0) {
+ lastOutputFailed = true;
+ s.setStackSize(rest.getStackSize());
+ break;
+ }
+ s.setStackSize(0);
+ }
+ } catch (final GridAccessException ignored) {
+ lastOutputFailed = true;
+ }
+ lastOutputTick = tickCounter;
+ }
+
+ @Override
+ public boolean isPowered() {
+ return getProxy() != null && getProxy().isPowered();
+ }
+
+ @Override
+ public boolean isActive() {
+ return getProxy() != null && getProxy().isActive();
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ if (getBaseMetaTileEntity().isServerSide()) {
+ tickCounter = aTick;
+ if (tickCounter > (lastOutputTick + 40)) flushCachedStack();
+ if (tickCounter % 20 == 0) getBaseMetaTileEntity().setActive(isActive());
+ }
+ super.onPostTick(aBaseMetaTileEntity, aTick);
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+
+ NBTTagList items = new NBTTagList();
+ for (IAEItemStack s : itemCache) {
+ if (s.getStackSize() == 0) continue;
+ NBTTagCompound tag = new NBTTagCompound();
+ tag.setTag("itemStack", GT_Utility.saveItem(s.getItemStack()));
+ tag.setLong("size", s.getStackSize());
+ items.appendTag(tag);
+ }
+ aNBT.setBoolean("infiniteCache", infiniteCache);
+ aNBT.setBoolean("additionalConnection", additionalConnection);
+ aNBT.setTag("cachedItems", items);
+ getProxy().writeToNBT(aNBT);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+
+ NBTBase t = aNBT.getTag("cachedStack"); // legacy
+ if (t instanceof NBTTagCompound) itemCache.add(
+ AEApi.instance()
+ .storage()
+ .createItemStack(GT_Utility.loadItem((NBTTagCompound) t)));
+ t = aNBT.getTag("cachedItems");
+ if (t instanceof NBTTagList l) {
+ for (int i = 0; i < l.tagCount(); ++i) {
+ NBTTagCompound tag = l.getCompoundTagAt(i);
+ if (!tag.hasKey("itemStack")) { // legacy #868
+ itemCache.add(
+ AEApi.instance()
+ .storage()
+ .createItemStack(GT_Utility.loadItem(l.getCompoundTagAt(i))));
+ continue;
+ }
+ NBTTagCompound tagItemStack = tag.getCompoundTag("itemStack");
+ final IAEItemStack s = AEApi.instance()
+ .storage()
+ .createItemStack(GT_Utility.loadItem(tagItemStack));
+ if (s != null) {
+ s.setStackSize(tag.getLong("size"));
+ itemCache.add(s);
+ } else {
+ GT_Mod.GT_FML_LOGGER.warn(
+ "An error occurred while loading contents of ME Output Bus. This item has been voided: "
+ + tagItemStack);
+ }
+ }
+ }
+ if (aNBT.hasKey("infiniteCache")) {
+ infiniteCache = aNBT.getBoolean("infiniteCache");
+ }
+ additionalConnection = aNBT.getBoolean("additionalConnection");
+ getProxy().readFromNBT(aNBT);
+ }
+
+ public boolean isLastOutputFailed() {
+ return lastOutputFailed;
+ }
+
+ @Override
+ public boolean isGivingInformation() {
+ return true;
+ }
+
+ @Override
+ public String[] getInfoData() {
+ List<String> ss = new ArrayList<>();
+ ss.add(
+ "The bus is " + ((getProxy() != null && getProxy().isActive()) ? EnumChatFormatting.GREEN + "online"
+ : EnumChatFormatting.RED + "offline" + getAEDiagnostics()) + EnumChatFormatting.RESET);
+ if (itemCache.isEmpty()) {
+ ss.add("The bus has no cached items");
+ } else {
+ IWideReadableNumberConverter nc = ReadableNumberConverter.INSTANCE;
+ ss.add(String.format("The bus contains %d cached stacks: ", itemCache.size()));
+ int counter = 0;
+ for (IAEItemStack s : itemCache) {
+ ss.add(
+ s.getItem()
+ .getItemStackDisplayName(s.getItemStack()) + ": "
+ + EnumChatFormatting.GOLD
+ + nc.toWideReadableForm(s.getStackSize())
+ + EnumChatFormatting.RESET);
+ if (++counter > 100) break;
+ }
+ }
+ return ss.toArray(new String[itemCache.size() + 2]);
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return false;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_Hatch_Output_ME.java b/src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_Hatch_Output_ME.java
new file mode 100644
index 0000000000..4df8ff68c5
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/GT_MetaTileEntity_Hatch_Output_ME.java
@@ -0,0 +1,383 @@
+package gregtech.common.tileentities.machines;
+
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_ME_FLUID_HATCH;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_ME_FLUID_HATCH_ACTIVE;
+
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.nbt.NBTBase;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraft.util.ChatComponentTranslation;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidStack;
+
+import appeng.api.AEApi;
+import appeng.api.config.Actionable;
+import appeng.api.config.PowerMultiplier;
+import appeng.api.implementations.IPowerChannelState;
+import appeng.api.networking.GridFlags;
+import appeng.api.networking.energy.IEnergySource;
+import appeng.api.networking.security.BaseActionSource;
+import appeng.api.networking.security.IActionHost;
+import appeng.api.networking.security.MachineSource;
+import appeng.api.networking.security.PlayerSource;
+import appeng.api.storage.IMEInventory;
+import appeng.api.storage.IMEMonitor;
+import appeng.api.storage.data.IAEFluidStack;
+import appeng.api.storage.data.IItemList;
+import appeng.api.util.AECableType;
+import appeng.core.stats.Stats;
+import appeng.me.GridAccessException;
+import appeng.me.helpers.AENetworkProxy;
+import appeng.me.helpers.IGridProxyable;
+import appeng.util.IWideReadableNumberConverter;
+import appeng.util.ReadableNumberConverter;
+import gregtech.GT_Mod;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.enums.ItemList;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Output;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_Hatch_Output_ME extends GT_MetaTileEntity_Hatch_Output implements IPowerChannelState {
+
+ private BaseActionSource requestSource = null;
+ private @Nullable AENetworkProxy gridProxy = null;
+ final IItemList<IAEFluidStack> fluidCache = AEApi.instance()
+ .storage()
+ .createFluidList();
+ long lastOutputTick = 0;
+ long tickCounter = 0;
+ boolean lastOutputFailed = false;
+ boolean infiniteCache = true;
+ boolean additionalConnection = false;
+
+ public GT_MetaTileEntity_Hatch_Output_ME(int aID, String aName, String aNameRegional) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ 3,
+ new String[] { "Fluid Output for Multiblocks", "Stores directly into ME",
+ "Can cache infinite amount of fluids.", "Change cache behavior by right-clicking with screwdriver.",
+ "Change ME connection behavior by right-clicking with wire cutter" },
+ 0);
+ }
+
+ public GT_MetaTileEntity_Hatch_Output_ME(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, 0, aDescription, aTextures);
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Hatch_Output_ME(mName, mTier, mDescriptionArray, mTextures);
+ }
+
+ @Override
+ public ITexture[] getTexturesActive(ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture, TextureFactory.of(OVERLAY_ME_FLUID_HATCH_ACTIVE) };
+ }
+
+ @Override
+ public ITexture[] getTexturesInactive(ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture, TextureFactory.of(OVERLAY_ME_FLUID_HATCH) };
+ }
+
+ @Override
+ public byte getTierForStructure() {
+ return (byte) (GT_Values.V.length - 2);
+ }
+
+ @Override
+ public void onFirstTick(IGregTechTileEntity aBaseMetaTileEntity) {
+ super.onFirstTick(aBaseMetaTileEntity);
+ getProxy().onReady();
+ }
+
+ @Override
+ public int fill(FluidStack aFluid, boolean doFill) {
+ if (doFill) {
+ return tryFillAE(aFluid);
+ } else {
+ if ((!infiniteCache && lastOutputFailed) || aFluid == null) return 0;
+ return aFluid.amount;
+ }
+ }
+
+ /**
+ * Attempt to store fluid in connected ME network. Returns how much fluid is accepted (if the network was down e.g.)
+ *
+ * @param aFluid input fluid
+ * @return amount of fluid filled
+ */
+ public int tryFillAE(final FluidStack aFluid) {
+ if ((!infiniteCache && lastOutputFailed) || aFluid == null) return 0;
+ fluidCache.add(
+ AEApi.instance()
+ .storage()
+ .createFluidStack(aFluid));
+ return aFluid.amount;
+ }
+
+ private BaseActionSource getRequest() {
+ if (requestSource == null) requestSource = new MachineSource((IActionHost) getBaseMetaTileEntity());
+ return requestSource;
+ }
+
+ @Override
+ public AECableType getCableConnectionType(ForgeDirection side) {
+ return isOutputFacing(side) ? AECableType.SMART : AECableType.NONE;
+ }
+
+ private void updateValidGridProxySides() {
+ if (additionalConnection) {
+ getProxy().setValidSides(EnumSet.complementOf(EnumSet.of(ForgeDirection.UNKNOWN)));
+ } else {
+ getProxy().setValidSides(EnumSet.of(getBaseMetaTileEntity().getFrontFacing()));
+ }
+ }
+
+ @Override
+ public void onFacingChange() {
+ updateValidGridProxySides();
+ }
+
+ @Override
+ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) {
+ return false;
+ }
+
+ @Override
+ public boolean isValidSlot(int aIndex) {
+ return true;
+ }
+
+ @Override
+ public boolean doesFillContainers() {
+ return false;
+ }
+
+ @Override
+ public void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ // Don't allow to lock fluid in me fluid hatch
+ if (!getBaseMetaTileEntity().getCoverInfoAtSide(side)
+ .isGUIClickable()) return;
+ infiniteCache = !infiniteCache;
+ aPlayer.addChatComponentMessage(new ChatComponentTranslation("GT5U.hatch.infiniteCacheFluid." + infiniteCache));
+ }
+
+ @Override
+ public boolean onWireCutterRightClick(ForgeDirection side, ForgeDirection wrenchingSide, EntityPlayer aPlayer,
+ float aX, float aY, float aZ) {
+ additionalConnection = !additionalConnection;
+ updateValidGridProxySides();
+ aPlayer.addChatComponentMessage(
+ new ChatComponentTranslation("GT5U.hatch.additionalConnection." + additionalConnection));
+ return true;
+ }
+
+ @Override
+ public AENetworkProxy getProxy() {
+ if (gridProxy == null) {
+ if (getBaseMetaTileEntity() instanceof IGridProxyable) {
+ gridProxy = new AENetworkProxy(
+ (IGridProxyable) getBaseMetaTileEntity(),
+ "proxy",
+ ItemList.Hatch_Output_ME.get(1),
+ true);
+ gridProxy.setFlags(GridFlags.REQUIRE_CHANNEL);
+ updateValidGridProxySides();
+ if (getBaseMetaTileEntity().getWorld() != null) gridProxy.setOwner(
+ getBaseMetaTileEntity().getWorld()
+ .getPlayerEntityByName(getBaseMetaTileEntity().getOwnerName()));
+ }
+ }
+ return this.gridProxy;
+ }
+
+ private void flushCachedStack() {
+ if (fluidCache.isEmpty()) return;
+ lastOutputFailed = true;
+ AENetworkProxy proxy = getProxy();
+ if (proxy == null) {
+ lastOutputFailed = true;
+ return;
+ }
+ try {
+ IMEMonitor<IAEFluidStack> sg = proxy.getStorage()
+ .getFluidInventory();
+ for (IAEFluidStack s : fluidCache) {
+ if (s.getStackSize() == 0) continue;
+ IAEFluidStack rest = fluidAEInsert(proxy.getEnergy(), sg, s, getRequest());
+ if (rest != null && rest.getStackSize() > 0) {
+ s.setStackSize(rest.getStackSize());
+ continue;
+ }
+ lastOutputFailed = false;
+ s.setStackSize(0);
+ }
+ } catch (final GridAccessException ignored) {
+ lastOutputFailed = true;
+ }
+ lastOutputTick = tickCounter;
+ }
+
+ @Override
+ public boolean isPowered() {
+ return getProxy() != null && getProxy().isPowered();
+ }
+
+ @Override
+ public boolean isActive() {
+ return getProxy() != null && getProxy().isActive();
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ if (getBaseMetaTileEntity().isServerSide()) {
+ tickCounter = aTick;
+ if (tickCounter > (lastOutputTick + 40)) flushCachedStack();
+ if (tickCounter % 20 == 0) getBaseMetaTileEntity().setActive(isActive());
+ }
+ super.onPostTick(aBaseMetaTileEntity, aTick);
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ NBTTagList fluids = new NBTTagList();
+ for (IAEFluidStack s : fluidCache) {
+ if (s.getStackSize() == 0) continue;
+ NBTTagCompound tag = new NBTTagCompound();
+ NBTTagCompound tagFluidStack = new NBTTagCompound();
+ s.getFluidStack()
+ .writeToNBT(tagFluidStack);
+ tag.setTag("fluidStack", tagFluidStack);
+ tag.setLong("size", s.getStackSize());
+ fluids.appendTag(tag);
+ }
+ aNBT.setTag("cachedFluids", fluids);
+ aNBT.setBoolean("infiniteCache", infiniteCache);
+ aNBT.setBoolean("additionalConnection", additionalConnection);
+ getProxy().writeToNBT(aNBT);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ NBTBase t = aNBT.getTag("cachedFluids");
+ if (t instanceof NBTTagList l) {
+ for (int i = 0; i < l.tagCount(); ++i) {
+ NBTTagCompound tag = l.getCompoundTagAt(i);
+ NBTTagCompound tagFluidStack = tag.getCompoundTag("fluidStack");
+ final IAEFluidStack s = AEApi.instance()
+ .storage()
+ .createFluidStack(GT_Utility.loadFluid(tagFluidStack));
+ if (s != null) {
+ s.setStackSize(tag.getLong("size"));
+ fluidCache.add(s);
+ } else {
+ GT_Mod.GT_FML_LOGGER.warn(
+ "An error occurred while loading contents of ME Output Hatch. This fluid has been voided: "
+ + tagFluidStack);
+ }
+ }
+ }
+ if (aNBT.hasKey("infiniteCache")) {
+ infiniteCache = aNBT.getBoolean("infiniteCache");
+ }
+ additionalConnection = aNBT.getBoolean("additionalConnection");
+ getProxy().readFromNBT(aNBT);
+ }
+
+ public boolean isLastOutputFailed() {
+ return lastOutputFailed;
+ }
+
+ @Override
+ public boolean isGivingInformation() {
+ return true;
+ }
+
+ @Override
+ public String[] getInfoData() {
+ List<String> ss = new ArrayList<>();
+ ss.add(
+ "The hatch is " + ((getProxy() != null && getProxy().isActive()) ? EnumChatFormatting.GREEN + "online"
+ : EnumChatFormatting.RED + "offline" + getAEDiagnostics()) + EnumChatFormatting.RESET);
+ if (fluidCache.isEmpty()) {
+ ss.add("The bus has no cached fluids");
+ } else {
+ IWideReadableNumberConverter nc = ReadableNumberConverter.INSTANCE;
+ ss.add(String.format("The hatch contains %d cached fluids: ", fluidCache.size()));
+ int counter = 0;
+ for (IAEFluidStack s : fluidCache) {
+ ss.add(
+ s.getFluidStack()
+ .getLocalizedName() + ": "
+ + EnumChatFormatting.GOLD
+ + nc.toWideReadableForm(s.getStackSize())
+ + " mB"
+ + EnumChatFormatting.RESET);
+ if (++counter > 100) break;
+ }
+ }
+ return ss.toArray(new String[fluidCache.size() + 2]);
+ }
+
+ public static IAEFluidStack fluidAEInsert(final IEnergySource energy, final IMEInventory<IAEFluidStack> cell,
+ final IAEFluidStack input, final BaseActionSource src) {
+ final IAEFluidStack possible = cell.injectItems(input.copy(), Actionable.SIMULATE, src);
+
+ long stored = input.getStackSize();
+ if (possible != null) {
+ stored -= possible.getStackSize();
+ }
+ // 1000 mb fluid will be considered as 1 item
+ long power = Math.max(1, stored / 1000);
+
+ final double availablePower = energy.extractAEPower(power, Actionable.SIMULATE, PowerMultiplier.CONFIG);
+
+ final long itemToAdd = Math.min((long) (availablePower + 0.9) * 1000, stored);
+
+ if (itemToAdd > 0) {
+ energy.extractAEPower(power, Actionable.MODULATE, PowerMultiplier.CONFIG);
+
+ if (itemToAdd < input.getStackSize()) {
+ final long original = input.getStackSize();
+ final IAEFluidStack split = input.copy();
+ split.decStackSize(itemToAdd);
+ input.setStackSize(itemToAdd);
+ split.add(cell.injectItems(input, Actionable.MODULATE, src));
+
+ if (src.isPlayer()) {
+ final long diff = original - split.getStackSize();
+ Stats.ItemsInserted.addToPlayer(((PlayerSource) src).player, (int) diff);
+ }
+
+ return split;
+ }
+
+ final IAEFluidStack ret = cell.injectItems(input, Actionable.MODULATE, src);
+
+ if (src.isPlayer()) {
+ final long diff = ret == null ? input.getStackSize() : input.getStackSize() - ret.getStackSize();
+ Stats.ItemsInserted.addToPlayer(((PlayerSource) src).player, (int) diff);
+ }
+
+ return ret;
+ }
+
+ return input;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/IDualInputHatch.java b/src/main/java/gregtech/common/tileentities/machines/IDualInputHatch.java
new file mode 100644
index 0000000000..c89aaaff40
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/IDualInputHatch.java
@@ -0,0 +1,21 @@
+package gregtech.common.tileentities.machines;
+
+import java.util.Iterator;
+import java.util.Optional;
+
+import net.minecraft.item.ItemStack;
+
+public interface IDualInputHatch {
+
+ boolean justUpdated();
+
+ Iterator<? extends IDualInputInventory> inventories();
+
+ void updateTexture(int id);
+
+ void updateCraftingIcon(ItemStack icon);
+
+ Optional<IDualInputInventory> getFirstNonEmptyInventory();
+
+ public boolean supportsFluids();
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/IDualInputInventory.java b/src/main/java/gregtech/common/tileentities/machines/IDualInputInventory.java
new file mode 100644
index 0000000000..01649fe181
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/IDualInputInventory.java
@@ -0,0 +1,11 @@
+package gregtech.common.tileentities.machines;
+
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.fluids.FluidStack;
+
+public interface IDualInputInventory {
+
+ ItemStack[] getItemInputs();
+
+ FluidStack[] getFluidInputs();
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/IRecipeProcessingAwareHatch.java b/src/main/java/gregtech/common/tileentities/machines/IRecipeProcessingAwareHatch.java
new file mode 100644
index 0000000000..c7a97ce969
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/IRecipeProcessingAwareHatch.java
@@ -0,0 +1,26 @@
+package gregtech.common.tileentities.machines;
+
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_MultiBlockBase;
+import gregtech.api.recipe.check.CheckRecipeResult;
+
+/**
+ * Implement this interface for {@link gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch}
+ * if it does special stuff while multiblock controller is processing recipe.
+ */
+public interface IRecipeProcessingAwareHatch {
+
+ /**
+ * Called when multiblock controller starts processing.
+ * {@link #endRecipeProcessing} is called on the same tick.
+ */
+ void startRecipeProcessing();
+
+ /**
+ * Called when multiblock controller ends processing. {@link #startRecipeProcessing} is called on the same tick.
+ *
+ * @param controller Caller of this method.
+ * @return Result of the process of this method. {@code !wasSuccessful()} means the returned result should
+ * overwrite the result calculated on multiblock whatever the reason is.
+ */
+ CheckRecipeResult endRecipeProcessing(GT_MetaTileEntity_MultiBlockBase controller);
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_AdvSeismicProspector.java b/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_AdvSeismicProspector.java
new file mode 100644
index 0000000000..78ed9982fc
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_AdvSeismicProspector.java
@@ -0,0 +1,309 @@
+package gregtech.common.tileentities.machines.basic;
+
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_ROCK_BREAKER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_ROCK_BREAKER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_ROCK_BREAKER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_ROCK_BREAKER_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ROCK_BREAKER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ROCK_BREAKER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ROCK_BREAKER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ROCK_BREAKER_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_ROCK_BREAKER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_ROCK_BREAKER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_ROCK_BREAKER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_ROCK_BREAKER_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_ROCK_BREAKER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_ROCK_BREAKER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_ROCK_BREAKER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_ROCK_BREAKER_GLOW;
+import static gregtech.common.GT_UndergroundOil.undergroundOilReadInformation;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.world.ChunkCoordIntPair;
+import net.minecraft.world.chunk.Chunk;
+import net.minecraftforge.fluids.FluidStack;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Materials;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachine;
+import gregtech.api.objects.ItemData;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_OreDictUnificator;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.blocks.GT_Block_Ores_Abstract;
+import gregtech.common.blocks.GT_TileEntity_Ores;
+import ic2.core.Ic2Items;
+
+public class GT_MetaTileEntity_AdvSeismicProspector extends GT_MetaTileEntity_BasicMachine {
+
+ boolean ready = false;
+ final int radius;
+ final int step;
+ int cX;
+ int cZ;
+
+ public GT_MetaTileEntity_AdvSeismicProspector(int aID, String aName, String aNameRegional, int aTier, int aRadius,
+ int aStep) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ 1, // amperage
+ "",
+ 1, // input slot count
+ 1, // output slot count
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_SIDE_ROCK_BREAKER_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_ROCK_BREAKER_ACTIVE_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_SIDE_ROCK_BREAKER),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_ROCK_BREAKER_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_TOP_ROCK_BREAKER_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_ROCK_BREAKER_ACTIVE_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_TOP_ROCK_BREAKER),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_ROCK_BREAKER_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_FRONT_ROCK_BREAKER_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_ROCK_BREAKER_ACTIVE_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_FRONT_ROCK_BREAKER),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_ROCK_BREAKER_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_BOTTOM_ROCK_BREAKER_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_ROCK_BREAKER_ACTIVE_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_BOTTOM_ROCK_BREAKER),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_ROCK_BREAKER_GLOW)
+ .glow()
+ .build()));
+ radius = aRadius;
+ step = aStep;
+ }
+
+ @Override
+ public String[] getDescription() {
+ return new String[] { "Place, activate with explosives",
+ "2 Powderbarrels, " + "4 Glyceryl Trinitrate, " + "16 TNT, or " + "8 ITNT",
+ "Use Data Stick, Scan Data Stick, Print Data Stick, Bind Pages into Book",
+ "Ore prospecting area = " + radius * 2 + "x" + radius * 2 + " ONLY blocks below prospector",
+ "Oil prospecting area 3x3 oilfields, each is 8x8 chunks" };
+ }
+
+ protected GT_MetaTileEntity_AdvSeismicProspector(String aName, int aTier, String[] aDescription,
+ ITexture[][][] aTextures, int aRadius, int aStep) {
+ super(aName, aTier, 1, aDescription, aTextures, 1, 1);
+ radius = aRadius;
+ step = aStep;
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_AdvSeismicProspector(
+ this.mName,
+ this.mTier,
+ this.mDescriptionArray,
+ this.mTextures,
+ this.radius,
+ this.step);
+ }
+
+ @Override
+ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) {
+ if (aBaseMetaTileEntity.isServerSide()) {
+ ItemStack aStack = aPlayer.getCurrentEquippedItem();
+
+ if (!ready && (GT_Utility.consumeItems(aPlayer, aStack, Item.getItemFromBlock(Blocks.tnt), 16)
+ || GT_Utility.consumeItems(aPlayer, aStack, Ic2Items.industrialTnt.getItem(), 8)
+ || GT_Utility.consumeItems(aPlayer, aStack, Materials.Glyceryl, 4)
+ || GT_Utility.consumeItems(aPlayer, aStack, ItemList.Block_Powderbarrel.getItem(), 2))) {
+
+ this.ready = true;
+ this.mMaxProgresstime = (aPlayer.capabilities.isCreativeMode ? 20 : 800);
+
+ } else if (ready && mMaxProgresstime == 0
+ && aStack != null
+ && aStack.stackSize == 1
+ && aStack.getItem() == ItemList.Tool_DataStick.getItem()) {
+ this.ready = false;
+
+ // prospecting ores
+ HashMap<String, Integer> tOres = new HashMap<>(36);
+
+ prospectOres(tOres);
+
+ // prospecting oils
+ ArrayList<String> tOils = new ArrayList<>();
+ prospectOils(tOils);
+
+ GT_Utility.ItemNBT.setAdvancedProspectionData(
+ mTier,
+ aStack,
+ this.getBaseMetaTileEntity()
+ .getXCoord(),
+ this.getBaseMetaTileEntity()
+ .getYCoord(),
+ this.getBaseMetaTileEntity()
+ .getZCoord(),
+ this.getBaseMetaTileEntity()
+ .getWorld().provider.dimensionId,
+ tOils,
+ GT_Utility.sortByValueToList(tOres),
+ radius);
+ }
+ }
+
+ return true;
+ }
+
+ private void prospectOils(ArrayList<String> aOils) {
+
+ int xChunk = (getBaseMetaTileEntity().getXCoord() >> 7) << 3; // oil field aligned chunk coords
+ int zChunk = (getBaseMetaTileEntity().getZCoord() >> 7) << 3;
+
+ LinkedHashMap<ChunkCoordIntPair, FluidStack> tFluids = new LinkedHashMap<>();
+ int oilFieldCount = 0;
+
+ try {
+ final int oilfieldSize = 8;
+ for (int z = -1; z <= 1; ++z) {
+ for (int x = -1; x <= 1; ++x) {
+ ChunkCoordIntPair cInts = new ChunkCoordIntPair(x, z);
+ int min = Integer.MAX_VALUE;
+ int max = Integer.MIN_VALUE;
+
+ for (int i = 0; i < oilfieldSize; i++) {
+ for (int j = 0; j < oilfieldSize; j++) {
+ Chunk tChunk = getBaseMetaTileEntity().getWorld()
+ .getChunkFromChunkCoords(xChunk + i + x * oilfieldSize, zChunk + j + z * oilfieldSize);
+ FluidStack tFluid = undergroundOilReadInformation(tChunk);
+ if (tFluid != null) {
+ if (tFluid.amount > max) max = tFluid.amount;
+ if (tFluid.amount < min) min = tFluid.amount;
+ if (!tFluids.containsKey(cInts)) {
+ tFluids.put(cInts, tFluid);
+ }
+ }
+ }
+ }
+
+ aOils.add(
+ ++oilFieldCount + ","
+ + min
+ + "-"
+ + max
+ + ","
+ + tFluids.get(cInts)
+ .getLocalizedName());
+ }
+ }
+ } catch (Exception ignored) {}
+ }
+
+ private void prospectOres(Map<String, Integer> aOres) {
+ int tLeftXBound = this.getBaseMetaTileEntity()
+ .getXCoord() - radius;
+ int tRightXBound = tLeftXBound + 2 * radius;
+
+ int tLeftZBound = this.getBaseMetaTileEntity()
+ .getZCoord() - radius;
+ int tRightZBound = tLeftZBound + 2 * radius;
+
+ for (int i = tLeftXBound; i <= tRightXBound; i += step) {
+ if (Math.abs(i >> 4) % 3 != 1) continue;
+ for (int k = tLeftZBound; k <= tRightZBound; k += step) {
+ if (Math.abs(k >> 4) % 3 != 1) continue;
+
+ cX = (i >> 4) << 4;
+ cZ = (k >> 4) << 4;
+
+ String separator = (cX + 8) + "," + (cZ + 8) + " --------";
+ aOres.put(separator, 1);
+ prospectHole(i, k, aOres);
+ }
+ }
+ }
+
+ private void prospectHole(int i, int k, Map<String, Integer> aOres) {
+ String tFoundOre;
+ for (int j = this.getBaseMetaTileEntity()
+ .getYCoord(); j > 0; j--) {
+ tFoundOre = checkForOre(i, j, k);
+ if (tFoundOre != null) countOre(aOres, tFoundOre, cX, cZ);
+ }
+ }
+
+ private String checkForOre(int x, int y, int z) {
+ Block tBlock = this.getBaseMetaTileEntity()
+ .getBlock(x, y, z);
+
+ if (tBlock instanceof GT_Block_Ores_Abstract) {
+ TileEntity tTileEntity = getBaseMetaTileEntity().getWorld()
+ .getTileEntity(x, y, z);
+
+ if ((tTileEntity instanceof GT_TileEntity_Ores) && (((GT_TileEntity_Ores) tTileEntity).mMetaData < 16000)) { // Filtering
+ // small
+ // ores
+ Materials tMaterial = GregTech_API.sGeneratedMaterials[((GT_TileEntity_Ores) tTileEntity).mMetaData
+ % 1000];
+
+ if ((tMaterial != null) && (tMaterial != Materials._NULL)) return tMaterial.mDefaultLocalName;
+ }
+ } else {
+ int tMetaID = getBaseMetaTileEntity().getWorld()
+ .getBlockMetadata(x, y, z);
+ ItemStack is = new ItemStack(tBlock, 1, tMetaID);
+ ItemData association = GT_OreDictUnificator.getAssociation(is);
+ if ((association != null) && (association.mPrefix.toString()
+ .startsWith("ore"))) return association.mMaterial.mMaterial.mDefaultLocalName;
+ else if (GT_Utility.isOre(tBlock, tMetaID)) return tBlock.getLocalizedName();
+ }
+ return null;
+ }
+
+ private static void countOre(Map<String, Integer> map, String ore, int cCX, int cCZ) {
+ ore = (cCX + 8) + "," + (cCZ + 8) + " has " + ore;
+ Integer oldCount = map.get(ore);
+ oldCount = (oldCount == null) ? 0 : oldCount;
+
+ map.put(ore, oldCount + 1);
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Boxinator.java b/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Boxinator.java
new file mode 100644
index 0000000000..6c908aadac
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Boxinator.java
@@ -0,0 +1,231 @@
+package gregtech.common.tileentities.machines.basic;
+
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_BOXINATOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_BOXINATOR_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_BOXINATOR_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_BOXINATOR_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_BOXINATOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_BOXINATOR_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_BOXINATOR_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_BOXINATOR_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_BOXINATOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_BOXINATOR_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_BOXINATOR_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_BOXINATOR_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_BOXINATOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_BOXINATOR_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_BOXINATOR_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_BOXINATOR_GLOW;
+
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.MachineType;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachine;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_Boxinator extends GT_MetaTileEntity_BasicMachine {
+
+ ItemStack aInputCache;
+ ItemStack aOutputCache;
+ int aTypeCache = 0;
+
+ public GT_MetaTileEntity_Boxinator(int aID, String aName, String aNameRegional, int aTier) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ 1,
+ MachineType.PACKAGER.tooltipDescription(),
+ 2,
+ 1,
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_SIDE_BOXINATOR_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_BOXINATOR_ACTIVE_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_SIDE_BOXINATOR),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_BOXINATOR_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_FRONT_BOXINATOR_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_BOXINATOR_ACTIVE_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_FRONT_BOXINATOR),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_BOXINATOR_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_TOP_BOXINATOR_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_BOXINATOR_ACTIVE_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_TOP_BOXINATOR),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_BOXINATOR_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_BOTTOM_BOXINATOR_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_BOXINATOR_ACTIVE_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_BOTTOM_BOXINATOR),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_BOXINATOR_GLOW)
+ .glow()
+ .build()));
+ }
+
+ public GT_MetaTileEntity_Boxinator(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, 1, aDescription, aTextures, 2, 1);
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Boxinator(this.mName, this.mTier, this.mDescriptionArray, this.mTextures);
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.packagerRecipes;
+ }
+
+ private boolean hasValidCache(ItemStack mItem, int mType, boolean mClearOnFailure) {
+ if (aInputCache != null && aOutputCache != null
+ && aTypeCache == mType
+ && aInputCache.isItemEqual(mItem)
+ && ItemStack.areItemStackTagsEqual(mItem, aInputCache)) return true;
+ // clear cache if it was invalid
+ if (mClearOnFailure) {
+ aInputCache = null;
+ aOutputCache = null;
+ aTypeCache = 0;
+ }
+ return false;
+ }
+
+ private void cacheItem(ItemStack mInputItem, ItemStack mOutputItem, int mType) {
+ aTypeCache = mType;
+ aOutputCache = mOutputItem.copy();
+ aInputCache = mInputItem.copy();
+ }
+
+ @Override
+ public int checkRecipe() {
+ int tCheck = super.checkRecipe();
+ if (tCheck != DID_NOT_FIND_RECIPE) {
+ return tCheck;
+ }
+ ItemStack tSlot0 = getInputAt(0);
+ ItemStack tSlot1 = getInputAt(1);
+ if ((GT_Utility.isStackValid(tSlot0)) && (GT_Utility.isStackValid(tSlot1))
+ && (GT_Utility.getContainerItem(tSlot0, true) == null)) {
+ if ((ItemList.Schematic_1by1.isStackEqual(tSlot1)) && (tSlot0.stackSize >= 1)) {
+ boolean tIsCached = hasValidCache(tSlot0, 1, true);
+ this.mOutputItems[0] = tIsCached ? aOutputCache.copy() : GT_ModHandler.getRecipeOutput(tSlot0);
+ if (this.mOutputItems[0] != null) {
+ if (canOutput(this.mOutputItems[0])) {
+ tSlot0.stackSize -= 1;
+ calculateOverclockedNess(30, 16);
+ // In case recipe is too OP for that machine
+ if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1)
+ return FOUND_RECIPE_BUT_DID_NOT_MEET_REQUIREMENTS;
+ if (!tIsCached) cacheItem(tSlot0, this.mOutputItems[0], 1);
+ return FOUND_AND_SUCCESSFULLY_USED_RECIPE;
+ }
+ }
+ return DID_NOT_FIND_RECIPE;
+ }
+ if ((ItemList.Schematic_2by2.isStackEqual(tSlot1)) && (getInputAt(0).stackSize >= 4)) {
+ boolean tIsCached = hasValidCache(tSlot0, 2, true);
+ this.mOutputItems[0] = tIsCached ? aOutputCache.copy()
+ : GT_ModHandler.getRecipeOutput(tSlot0, tSlot0, null, tSlot0, tSlot0);
+ if (this.mOutputItems[0] != null) {
+ if (canOutput(this.mOutputItems[0])) {
+ getInputAt(0).stackSize -= 4;
+ calculateOverclockedNess(30, 32);
+ // In case recipe is too OP for that machine
+ if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1)
+ return FOUND_RECIPE_BUT_DID_NOT_MEET_REQUIREMENTS;
+ if (!tIsCached) cacheItem(tSlot0, this.mOutputItems[0], 2);
+ return FOUND_AND_SUCCESSFULLY_USED_RECIPE;
+ }
+ }
+ return DID_NOT_FIND_RECIPE;
+ }
+ if ((ItemList.Schematic_3by3.isStackEqual(tSlot1)) && (getInputAt(0).stackSize >= 9)) {
+ boolean tIsCached = hasValidCache(tSlot0, 3, true);
+ this.mOutputItems[0] = tIsCached ? aOutputCache.copy()
+ : GT_ModHandler
+ .getRecipeOutput(tSlot0, tSlot0, tSlot0, tSlot0, tSlot0, tSlot0, tSlot0, tSlot0, tSlot0);
+ if (this.mOutputItems[0] != null) {
+ if (canOutput(this.mOutputItems[0])) {
+ getInputAt(0).stackSize -= 9;
+ calculateOverclockedNess(30, 64);
+ // In case recipe is too OP for that machine
+ if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1)
+ return FOUND_RECIPE_BUT_DID_NOT_MEET_REQUIREMENTS;
+ if (!tIsCached) cacheItem(tSlot0, this.mOutputItems[0], 3);
+ return FOUND_AND_SUCCESSFULLY_USED_RECIPE;
+ }
+ }
+ return DID_NOT_FIND_RECIPE;
+ }
+ }
+ return DID_NOT_FIND_RECIPE;
+ }
+
+ @Override
+ protected boolean allowPutStackValidated(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ if (!super.allowPutStackValidated(aBaseMetaTileEntity, aIndex, side, aStack)) {
+ return false;
+ }
+ ItemStack tInput1 = getInputAt(1);
+ if ((ItemList.Schematic_1by1.isStackEqual(tInput1)) || (ItemList.Schematic_2by2.isStackEqual(tInput1))
+ || (ItemList.Schematic_3by3.isStackEqual(tInput1))) {
+ if (hasValidCache(aStack, aTypeCache, false)) return true;
+ if (RecipeMaps.packagerRecipes.findRecipe(
+ getBaseMetaTileEntity(),
+ true,
+ gregtech.api.enums.GT_Values.V[mTier],
+ null,
+ GT_Utility.copyAmount(64, aStack),
+ tInput1) != null) {
+ return true;
+ }
+ if (ItemList.Schematic_1by1.isStackEqual(getInputAt(1)) && GT_ModHandler.getRecipeOutput(aStack) != null)
+ return true;
+ if (ItemList.Schematic_2by2.isStackEqual(getInputAt(1))
+ && GT_ModHandler.getRecipeOutput(aStack, aStack, null, aStack, aStack) != null) {
+ return true;
+ }
+ return ItemList.Schematic_3by3.isStackEqual(getInputAt(1)) && (GT_ModHandler
+ .getRecipeOutput(aStack, aStack, aStack, aStack, aStack, aStack, aStack, aStack, aStack) != null);
+ } else {
+ return RecipeMaps.packagerRecipes.containsInput(aStack);
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Charger.java b/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Charger.java
new file mode 100644
index 0000000000..de43fd715e
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Charger.java
@@ -0,0 +1,110 @@
+package gregtech.common.tileentities.machines.basic;
+
+import static gregtech.api.enums.GT_Values.V;
+
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.BaseMetaTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicBatteryBuffer;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_Charger extends GT_MetaTileEntity_BasicBatteryBuffer {
+
+ public GT_MetaTileEntity_Charger(int aID, String aName, String aNameRegional, int aTier, String aDescription,
+ int aSlotCount) {
+ super(aID, aName, aNameRegional, aTier, aDescription, aSlotCount);
+ }
+
+ public GT_MetaTileEntity_Charger(String aName, int aTier, String aDescription, ITexture[][][] aTextures,
+ int aSlotCount) {
+ super(aName, aTier, aDescription, aTextures, aSlotCount);
+ }
+
+ public GT_MetaTileEntity_Charger(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures,
+ int aSlotCount) {
+ super(aName, aTier, aDescription, aTextures, aSlotCount);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Charger(mName, mTier, mDescriptionArray, mTextures, mInventory.length);
+ }
+
+ @Override
+ public long getMinimumStoredEU() {
+ return V[mTier] * 64L * mInventory.length;
+ }
+
+ @Override
+ public long maxEUStore() {
+ return V[mTier] * 256L * mInventory.length;
+ }
+
+ @Override
+ public long maxAmperesIn() {
+ return Math.max(mChargeableCount * 8L, 4L);
+ }
+
+ @Override
+ public long maxAmperesOut() {
+ return Math.max(mBatteryCount * 4L, 2L);
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ if (aBaseMetaTileEntity.isServerSide()) {
+ super.onPostTick(aBaseMetaTileEntity, aTick);
+ if (this.getBaseMetaTileEntity() instanceof BaseMetaTileEntity) {
+ BaseMetaTileEntity mBaseMetaTileEntity = (BaseMetaTileEntity) getBaseMetaTileEntity();
+ if (mBaseMetaTileEntity.getMetaTileEntity() instanceof MetaTileEntity mMetaTileEntity) {
+ // for (int t = 0; t < 6; t++) {
+ if (mMetaTileEntity.dechargerSlotCount() > 0
+ && mBaseMetaTileEntity.getStoredEU() < mBaseMetaTileEntity.getEUCapacity()) {
+ for (int i = mMetaTileEntity.dechargerSlotStartIndex(),
+ k = mMetaTileEntity.dechargerSlotCount() + i; i < k; i++) {
+ if (mMetaTileEntity.mInventory[i] != null
+ && mBaseMetaTileEntity.getStoredEU() < mBaseMetaTileEntity.getEUCapacity()) {
+ mBaseMetaTileEntity.increaseStoredEnergyUnits(
+ GT_ModHandler.dischargeElectricItem(
+ mMetaTileEntity.mInventory[i],
+ GT_Utility.safeInt(
+ Math.min(
+ V[mTier] * 15,
+ mBaseMetaTileEntity.getEUCapacity()
+ - mBaseMetaTileEntity.getStoredEU())),
+ (int) Math.min(Integer.MAX_VALUE, mMetaTileEntity.getInputTier()),
+ true,
+ false,
+ false),
+ true);
+ if (mMetaTileEntity.mInventory[i].stackSize <= 0) mMetaTileEntity.mInventory[i] = null;
+ }
+ }
+ }
+ if (mMetaTileEntity.rechargerSlotCount() > 0 && mBaseMetaTileEntity.getStoredEU() > 0) {
+ for (int i = mMetaTileEntity.rechargerSlotStartIndex(),
+ k = mMetaTileEntity.rechargerSlotCount() + i; i < k; i++) {
+ if (mBaseMetaTileEntity.getStoredEU() > 0 && mMetaTileEntity.mInventory[i] != null) {
+ mBaseMetaTileEntity
+ .decreaseStoredEU(
+ GT_ModHandler.chargeElectricItem(
+ mMetaTileEntity.mInventory[i],
+ GT_Utility
+ .safeInt(Math.min(V[mTier] * 15, mBaseMetaTileEntity.getStoredEU())),
+ (int) Math.min(Integer.MAX_VALUE, mMetaTileEntity.getOutputTier()),
+ true,
+ false),
+ true);
+ if (mMetaTileEntity.mInventory[i].stackSize <= 0) mMetaTileEntity.mInventory[i] = null;
+ }
+ }
+ // }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_IndustrialApiary.java b/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_IndustrialApiary.java
new file mode 100644
index 0000000000..50f544334c
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_IndustrialApiary.java
@@ -0,0 +1,1560 @@
+package gregtech.common.tileentities.machines.basic;
+
+import static gregtech.api.enums.GT_Values.AuthorKuba;
+import static gregtech.api.enums.GT_Values.V;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_INDUSTRIAL_APIARY;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_INDUSTRIAL_APIARY_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_INDUSTRIAL_APIARY_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_INDUSTRIAL_APIARY_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_INDUSTRIAL_APIARY;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_INDUSTRIAL_APIARY_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_INDUSTRIAL_APIARY_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_INDUSTRIAL_APIARY_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_INDUSTRIAL_APIARY;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_INDUSTRIAL_APIARY_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_INDUSTRIAL_APIARY_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_INDUSTRIAL_APIARY_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_INDUSTRIAL_APIARY;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_INDUSTRIAL_APIARY_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_INDUSTRIAL_APIARY_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_INDUSTRIAL_APIARY_GLOW;
+import static gregtech.api.metatileentity.BaseTileEntity.STALLED_STUTTERING_TOOLTIP;
+import static gregtech.api.metatileentity.BaseTileEntity.TOOLTIP_DELAY;
+import static gregtech.api.util.GT_Utility.moveMultipleItemStacks;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.inventory.Slot;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.ChunkCoordinates;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.StatCollector;
+import net.minecraft.util.Vec3;
+import net.minecraft.world.World;
+import net.minecraft.world.biome.BiomeGenBase;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.google.common.collect.ImmutableSet;
+import com.gtnewhorizons.modularui.api.drawable.FallbackableUITexture;
+import com.gtnewhorizons.modularui.api.drawable.IDrawable;
+import com.gtnewhorizons.modularui.api.forge.IItemHandlerModifiable;
+import com.gtnewhorizons.modularui.api.math.Pos2d;
+import com.gtnewhorizons.modularui.api.screen.ModularUIContext;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.common.builder.UIInfo;
+import com.gtnewhorizons.modularui.common.internal.wrapper.BaseSlot;
+import com.gtnewhorizons.modularui.common.internal.wrapper.ModularUIContainer;
+import com.gtnewhorizons.modularui.common.widget.ButtonWidget;
+import com.gtnewhorizons.modularui.common.widget.CycleButtonWidget;
+import com.gtnewhorizons.modularui.common.widget.DrawableWidget;
+import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget;
+import com.gtnewhorizons.modularui.common.widget.SlotGroup;
+import com.gtnewhorizons.modularui.common.widget.SlotWidget;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+import com.mojang.authlib.GameProfile;
+
+import forestry.api.apiculture.BeeManager;
+import forestry.api.apiculture.EnumBeeChromosome;
+import forestry.api.apiculture.EnumBeeType;
+import forestry.api.apiculture.FlowerManager;
+import forestry.api.apiculture.IAlleleBeeAcceleratableEffect;
+import forestry.api.apiculture.IAlleleBeeEffect;
+import forestry.api.apiculture.IAlleleBeeSpecies;
+import forestry.api.apiculture.IApiaristTracker;
+import forestry.api.apiculture.IBee;
+import forestry.api.apiculture.IBeeGenome;
+import forestry.api.apiculture.IBeeHousing;
+import forestry.api.apiculture.IBeeHousingInventory;
+import forestry.api.apiculture.IBeeListener;
+import forestry.api.apiculture.IBeeModifier;
+import forestry.api.apiculture.IBeeRoot;
+import forestry.api.apiculture.IBeekeepingLogic;
+import forestry.api.apiculture.IBeekeepingMode;
+import forestry.api.arboriculture.EnumGermlingType;
+import forestry.api.core.BiomeHelper;
+import forestry.api.core.EnumHumidity;
+import forestry.api.core.EnumTemperature;
+import forestry.api.core.ForestryAPI;
+import forestry.api.core.IErrorLogic;
+import forestry.api.core.IErrorState;
+import forestry.api.genetics.AlleleManager;
+import forestry.api.genetics.IEffectData;
+import forestry.api.genetics.IIndividual;
+import forestry.apiculture.genetics.Bee;
+import forestry.apiculture.genetics.alleles.AlleleEffectThrottled;
+import forestry.core.errors.EnumErrorCode;
+import forestry.plugins.PluginApiculture;
+import gregtech.GT_Mod;
+import gregtech.api.gui.modularui.GT_UIInfos;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.modularui.IAddUIWidgets;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachine;
+import gregtech.api.recipe.BasicUIProperties;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_ApiaryModifier;
+import gregtech.api.util.GT_ApiaryUpgrade;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.GT_Client;
+import mcp.mobius.waila.api.IWailaConfigHandler;
+import mcp.mobius.waila.api.IWailaDataAccessor;
+
+public class GT_MetaTileEntity_IndustrialApiary extends GT_MetaTileEntity_BasicMachine
+ implements IBeeHousing, IBeeHousingInventory, IErrorLogic, IBeeModifier, IBeeListener, IAddUIWidgets {
+
+ public static final int beeCycleLength = 550;
+ public static final int baseEUtUsage = 37;
+ private static final int queen = 5;
+ private static final int drone = 6;
+ private static final int upgradeSlot = drone + 1;
+ private static final int upgradeSlotCount = 4;
+ private static Field AlleleBeeEffectThrottledField;
+
+ final IBeeRoot beeRoot = (IBeeRoot) AlleleManager.alleleRegistry.getSpeciesRoot("rootBees");
+
+ public int mSpeed = 0;
+ public boolean mLockedSpeed = true;
+ public boolean mAutoQueen = true;
+
+ private ItemStack usedQueen = null;
+ private IBee usedQueenBee = null;
+ private IEffectData[] effectData = new IEffectData[2];
+
+ public GT_MetaTileEntity_IndustrialApiary(int aID, String aName, String aNameRegional, int aTier) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ 4,
+ new String[] { "BEES GOES BRRRR", EnumChatFormatting.GRAY + AuthorKuba,
+ "Effective production chance as a percent is", "2.8 * b^0.52 * (p + t)^0.52 * s^0.37",
+ "where b is the base production chance as a percent,",
+ "p is the production modifier (2 w/o upgrades, or 4 * 1.2^n with n production upgrades),",
+ "t is 8 for the industrial apiary, and", "s is the speed value for the bee",
+ "Outputs are generated at the end of every bee tick (...)",
+ "Primary outputs are rolled once with base chance, once with half base" },
+ 6,
+ 9,
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_SIDE_INDUSTRIAL_APIARY_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_INDUSTRIAL_APIARY_ACTIVE_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_SIDE_INDUSTRIAL_APIARY),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_INDUSTRIAL_APIARY_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_FRONT_INDUSTRIAL_APIARY_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_INDUSTRIAL_APIARY_ACTIVE_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_FRONT_INDUSTRIAL_APIARY),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_INDUSTRIAL_APIARY_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_TOP_INDUSTRIAL_APIARY_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_INDUSTRIAL_APIARY_ACTIVE_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_TOP_INDUSTRIAL_APIARY),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_INDUSTRIAL_APIARY_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_BOTTOM_INDUSTRIAL_APIARY_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_INDUSTRIAL_APIARY_ACTIVE_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_BOTTOM_INDUSTRIAL_APIARY),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_INDUSTRIAL_APIARY_GLOW)
+ .glow()
+ .build()));
+ }
+
+ public GT_MetaTileEntity_IndustrialApiary(String aName, int aTier, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, 4, aDescription, aTextures, 6, 9);
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_IndustrialApiary(this.mName, this.mTier, this.mDescriptionArray, this.mTextures);
+ }
+
+ @Override
+ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) {
+ if (aBaseMetaTileEntity.isClientSide()) return true;
+ if (!GT_Mod.gregtechproxy.mForceFreeFace) {
+ openGUI(aBaseMetaTileEntity, aPlayer);
+ return true;
+ }
+ for (final ForgeDirection side : ForgeDirection.VALID_DIRECTIONS) {
+ if (aBaseMetaTileEntity.getAirAtSide(side)) {
+ openGUI(aBaseMetaTileEntity, aPlayer);
+ return true;
+ }
+ }
+ GT_Utility.sendChatToPlayer(aPlayer, "No free Side!");
+ return true;
+ }
+
+ private void openGUI(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) {
+ IndustrialApiaryUI.open(
+ aPlayer,
+ aBaseMetaTileEntity.getWorld(),
+ aBaseMetaTileEntity.getXCoord(),
+ aBaseMetaTileEntity.getYCoord(),
+ aBaseMetaTileEntity.getZCoord());
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ aNBT.setInteger("mSpeed", mSpeed);
+ aNBT.setBoolean("mLockedSpeed", mLockedSpeed);
+ aNBT.setBoolean("mAutoQueen", mAutoQueen);
+ if (usedQueen != null) aNBT.setTag("usedQueen", usedQueen.writeToNBT(new NBTTagCompound()));
+ aNBT.setBoolean("retrievingPollenInThisOperation", retrievingPollenInThisOperation);
+ aNBT.setInteger("pollinationDelay", pollinationDelay);
+ aNBT.setFloat("usedBeeLife", usedBeeLife);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ mSpeed = aNBT.getInteger("mSpeed");
+ mLockedSpeed = aNBT.getBoolean("mLockedSpeed");
+ if (aNBT.hasKey("mAutoQueen")) mAutoQueen = aNBT.getBoolean("mAutoQueen");
+ if (aNBT.hasKey("usedQueen")) usedQueen = ItemStack.loadItemStackFromNBT(aNBT.getCompoundTag("usedQueen"));
+ retrievingPollenInThisOperation = aNBT.getBoolean("retrievingPollenInThisOperation");
+ pollinationDelay = aNBT.getInteger("pollinationDelay");
+ usedBeeLife = aNBT.getFloat("usedBeeLife");
+ }
+
+ boolean retrievingPollenInThisOperation = false;
+ IIndividual retrievedpollen = null;
+ int pollinationDelay = 100;
+ float usedBeeLife = 0f;
+
+ @Override
+ public int checkRecipe() {
+ updateModifiers();
+ if (canWork()) {
+
+ final ItemStack queen = getQueen();
+ usedQueen = queen.copy();
+ if (beeRoot.getType(queen) == EnumBeeType.QUEEN) {
+ final IBee bee = beeRoot.getMember(queen);
+ usedQueenBee = bee;
+
+ // LIFE CYCLES
+
+ float mod = this.getLifespanModifier(null, null, 1.f);
+ final IBeekeepingMode mode = beeRoot.getBeekeepingMode(this.getWorld());
+ final IBeeModifier beemodifier = mode.getBeeModifier();
+ mod *= beemodifier.getLifespanModifier(null, null, 1.f);
+ final int h = bee.getHealth();
+ mod = 1.f / mod;
+ final float cycles = h / mod;
+
+ // PRODUCTS
+
+ final HashMap<GT_Utility.ItemId, ItemStack> pollen = new HashMap<>();
+
+ if (isRetrievingPollen && floweringMod > 0f) {
+ final int icycles = (int) cycles
+ + (getWorld().rand.nextFloat() < (cycles - (float) ((int) cycles)) ? 1 : 0);
+ for (int z = 0; z < icycles; z++) {
+ final IIndividual p = bee.retrievePollen(this);
+ if (p != null) {
+ final ItemStack s = p.getGenome()
+ .getSpeciesRoot()
+ .getMemberStack(p, EnumGermlingType.POLLEN.ordinal());
+ if (s != null) {
+ final GT_Utility.ItemId id = GT_Utility.ItemId.createNoCopy(s);
+ pollen.computeIfAbsent(id, k -> {
+ final ItemStack ns = s.copy();
+ ns.stackSize = 0;
+ return ns;
+ });
+ pollen.get(id).stackSize += s.stackSize;
+ }
+ }
+ }
+ }
+
+ retrievedpollen = null;
+ retrievingPollenInThisOperation = isRetrievingPollen;
+
+ final IBeeGenome genome = bee.getGenome();
+ final IAlleleBeeSpecies primary = genome.getPrimary();
+ final IAlleleBeeSpecies secondary = genome.getSecondary();
+
+ final float speed = genome.getSpeed();
+ final float prodMod = getProductionModifier(null, 0f) + beemodifier.getProductionModifier(null, 0f);
+
+ final HashMap<GT_Utility.ItemId, Float> drops = new HashMap<>();
+ final HashMap<GT_Utility.ItemId, ItemStack> dropstacks = new HashMap<>();
+
+ for (Map.Entry<ItemStack, Float> entry : primary.getProductChances()
+ .entrySet()) {
+ final GT_Utility.ItemId id = GT_Utility.ItemId.createNoCopy(entry.getKey());
+ drops.merge(
+ id,
+ Bee.getFinalChance(entry.getValue(), speed, prodMod, 8f) * (float) entry.getKey().stackSize
+ * cycles,
+ Float::sum);
+ dropstacks.computeIfAbsent(id, k -> entry.getKey());
+ }
+ for (Map.Entry<ItemStack, Float> entry : secondary.getProductChances()
+ .entrySet()) {
+ final GT_Utility.ItemId id = GT_Utility.ItemId.createNoCopy(entry.getKey());
+ drops.merge(
+ id,
+ Bee.getFinalChance(entry.getValue() / 2f, speed, prodMod, 8f) * (float) entry.getKey().stackSize
+ * cycles,
+ Float::sum);
+ dropstacks.computeIfAbsent(id, k -> entry.getKey());
+ }
+ if (primary.isJubilant(genome, this) && secondary.isJubilant(genome, this))
+ for (Map.Entry<ItemStack, Float> entry : primary.getSpecialtyChances()
+ .entrySet()) {
+ final GT_Utility.ItemId id = GT_Utility.ItemId.createNoCopy(entry.getKey());
+ drops.merge(
+ id,
+ Bee.getFinalChance(entry.getValue(), speed, prodMod, 8f)
+ * (float) entry.getKey().stackSize
+ * cycles,
+ Float::sum);
+ dropstacks.computeIfAbsent(id, k -> entry.getKey());
+ }
+
+ int i = 0;
+ final int imax = mOutputItems.length;
+
+ final IApiaristTracker breedingTracker = beeRoot.getBreedingTracker(getWorld(), getOwner());
+
+ if (!bee.canSpawn()) {
+ final ItemStack convert = new ItemStack(PluginApiculture.items.beePrincessGE);
+ final NBTTagCompound nbttagcompound = new NBTTagCompound();
+ queen.writeToNBT(nbttagcompound);
+ convert.setTagCompound(nbttagcompound);
+ this.mOutputItems[i++] = convert;
+ } else {
+ final IBee b = bee.spawnPrincess(this);
+ if (b != null) {
+ final ItemStack princess = beeRoot.getMemberStack(b, EnumBeeType.PRINCESS.ordinal());
+ breedingTracker.registerPrincess(b);
+ this.mOutputItems[i++] = princess;
+ }
+ final IBee[] d = bee.spawnDrones(this);
+ if (d != null && d.length > 0) {
+ final HashMap<GT_Utility.ItemId, ItemStack> drones = new HashMap<>(d.length);
+ for (IBee dr : d) {
+ final ItemStack drone = beeRoot.getMemberStack(dr, EnumBeeType.DRONE.ordinal());
+ breedingTracker.registerDrone(dr);
+ final GT_Utility.ItemId drid = GT_Utility.ItemId.createNoCopy(drone);
+ if (drones.containsKey(drid)) drones.get(drid).stackSize += drone.stackSize;
+ else {
+ this.mOutputItems[i++] = drone;
+ drones.put(drid, drone);
+ }
+ }
+ }
+ }
+
+ final int imin = i;
+
+ setQueen(null);
+
+ for (Map.Entry<GT_Utility.ItemId, Float> entry : drops.entrySet()) {
+ final ItemStack s = dropstacks.get(entry.getKey())
+ .copy();
+ s.stackSize = entry.getValue()
+ .intValue()
+ + (getWorld().rand.nextFloat() < (entry.getValue() - (float) entry.getValue()
+ .intValue()) ? 1 : 0);
+ if (s.stackSize > 0 && i < imax) while (true) {
+ if (s.stackSize <= s.getMaxStackSize()) {
+ this.mOutputItems[i++] = s;
+ break;
+ } else this.mOutputItems[i++] = s.splitStack(s.getMaxStackSize());
+ if (i >= imax) break;
+ }
+ }
+
+ for (ItemStack s : pollen.values()) if (i < imax) this.mOutputItems[i++] = s;
+ else break;
+
+ // Overclock
+
+ usedBeeLife = cycles * (float) beeCycleLength;
+ this.mMaxProgresstime = (int) usedBeeLife;
+ final int timemaxdivider = this.mMaxProgresstime / 100;
+ final int useddivider = 1 << this.mSpeed;
+ int actualdivider = useddivider;
+ this.mMaxProgresstime /= Math.min(actualdivider, timemaxdivider);
+ actualdivider /= Math.min(actualdivider, timemaxdivider);
+ for (i--; i >= imin; i--) this.mOutputItems[i].stackSize *= actualdivider;
+
+ pollinationDelay = Math.max((int) (this.mMaxProgresstime / cycles), 20); // don't run too often
+
+ this.mProgresstime = 0;
+ this.mEUt = (int) ((float) baseEUtUsage * this.energyMod * useddivider);
+ if (useddivider == 2) this.mEUt += 32;
+ else if (useddivider > 2) this.mEUt += (32 * (useddivider << (this.mSpeed - 2)));
+ } else {
+ // Breeding time
+
+ retrievingPollenInThisOperation = true; // Don't pollinate when breeding
+
+ this.mMaxProgresstime = 100;
+ this.mProgresstime = 0;
+ final int useddivider = Math.min(100, 1 << this.mSpeed);
+ this.mMaxProgresstime /= useddivider;
+ this.mEUt = (int) ((float) baseEUtUsage * this.energyMod * useddivider);
+ if (useddivider == 2) this.mEUt += 32;
+ else if (useddivider > 2) this.mEUt += (32 * (useddivider << (this.mSpeed - 2)));
+
+ final IBee princess = beeRoot.getMember(getQueen());
+ usedQueenBee = princess;
+ final IBee drone = beeRoot.getMember(getDrone());
+ princess.mate(drone);
+ final NBTTagCompound nbttagcompound = new NBTTagCompound();
+ princess.writeToNBT(nbttagcompound);
+ this.mOutputItems[0] = new ItemStack(PluginApiculture.items.beeQueenGE);
+ this.mOutputItems[0].setTagCompound(nbttagcompound);
+ beeRoot.getBreedingTracker(getWorld(), getOwner())
+ .registerQueen(princess);
+
+ setQueen(null);
+ getDrone().stackSize -= 1;
+ if (getDrone().stackSize == 0) setDrone(null);
+ }
+
+ return FOUND_AND_SUCCESSFULLY_USED_RECIPE;
+ }
+
+ return DID_NOT_FIND_RECIPE;
+ }
+
+ @Override
+ public void onFirstTick(IGregTechTileEntity aBaseMetaTileEntity) {
+ updateModifiers();
+ }
+
+ @Override
+ protected boolean hasEnoughEnergyToCheckRecipe() {
+ return getBaseMetaTileEntity().isUniversalEnergyStored(V[mSpeed] * 8L);
+ }
+
+ @Override
+ public long maxAmperesIn() {
+ return 4L;
+ }
+
+ private void doEffect() {
+ final IBeeGenome genome = usedQueenBee.getGenome();
+ final IAlleleBeeEffect effect = genome.getEffect();
+ if (!(effect instanceof IAlleleBeeAcceleratableEffect)) {
+ effectData[0] = effect.validateStorage(effectData[0]);
+ effect.doEffect(genome, effectData[0], this);
+ }
+
+ if (!effect.isCombinable()) return;
+
+ final IAlleleBeeEffect secondary = (IAlleleBeeEffect) genome.getInactiveAllele(EnumBeeChromosome.EFFECT);
+ if (!secondary.isCombinable()) return;
+
+ if (!(secondary instanceof IAlleleBeeAcceleratableEffect)) {
+ effectData[1] = secondary.validateStorage(effectData[1]);
+ secondary.doEffect(genome, effectData[1], this);
+ }
+ }
+
+ private void doAcceleratedEffects() {
+ final IBeeGenome genome = usedQueenBee.getGenome();
+ final IAlleleBeeEffect effect = genome.getEffect();
+ try {
+ if (AlleleBeeEffectThrottledField == null) {
+ AlleleBeeEffectThrottledField = AlleleEffectThrottled.class.getDeclaredField("throttle");
+ AlleleBeeEffectThrottledField.setAccessible(true);
+ }
+ if (effect instanceof IAlleleBeeAcceleratableEffect) {
+ effectData[0] = effect.validateStorage(effectData[0]);
+ effectData[0] = ((IAlleleBeeAcceleratableEffect) effect).doEffectAccelerated(
+ genome,
+ effectData[0],
+ this,
+ usedBeeLife / (effect instanceof AlleleEffectThrottled
+ ? (float) AlleleBeeEffectThrottledField.getInt(effect)
+ : 1f));
+ }
+
+ if (!effect.isCombinable()) return;
+
+ final IAlleleBeeEffect secondary = (IAlleleBeeEffect) genome.getInactiveAllele(EnumBeeChromosome.EFFECT);
+ if (!secondary.isCombinable()) return;
+
+ if (secondary instanceof IAlleleBeeAcceleratableEffect) {
+ effectData[1] = secondary.validateStorage(effectData[1]);
+ effectData[1] = ((IAlleleBeeAcceleratableEffect) secondary).doEffectAccelerated(
+ genome,
+ effectData[0],
+ this,
+ usedBeeLife / (secondary instanceof AlleleEffectThrottled
+ ? (float) AlleleBeeEffectThrottledField.getInt(secondary)
+ : 1f));
+ }
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ if (aBaseMetaTileEntity.isClientSide()) {
+ if (GT_Client.changeDetected == 4) {
+ /*
+ * Client tick counter that is set to 5 on hiding pipes and covers. It triggers a texture update next
+ * client tick when reaching 4, with provision for 3 more update tasks, spreading client change
+ * detection related work and network traffic on different ticks, until it reaches 0.
+ */
+ aBaseMetaTileEntity.issueTextureUpdate();
+ }
+ if (aBaseMetaTileEntity.isActive()) {
+ if (usedQueen != null) {
+ if (aTick % 2 == 0) {
+ // FX on client, effect on server
+ final IBee bee = beeRoot.getMember(usedQueen);
+ effectData = bee.doFX(effectData, this);
+ }
+ }
+ }
+ }
+ if (aBaseMetaTileEntity.isServerSide()) {
+
+ mCharge = aBaseMetaTileEntity.getStoredEU() / 2 > aBaseMetaTileEntity.getEUCapacity() / 3;
+ mDecharge = aBaseMetaTileEntity.getStoredEU() < aBaseMetaTileEntity.getEUCapacity() / 3;
+
+ doDisplayThings();
+
+ if (!aBaseMetaTileEntity.isActive()) {
+ if (aBaseMetaTileEntity.isAllowedToWork()
+ && (aBaseMetaTileEntity.hasInventoryBeenModified() || aTick % 600 == 0
+ || aBaseMetaTileEntity.hasWorkJustBeenEnabled())
+ && hasEnoughEnergyToCheckRecipe()) {
+ final int check = checkRecipe();
+ if (check == FOUND_AND_SUCCESSFULLY_USED_RECIPE) {
+ aBaseMetaTileEntity.setActive(true);
+ }
+ }
+ } else {
+
+ if (this.mProgresstime < 0) {
+ this.mProgresstime++;
+ return;
+ }
+ if (this.mStuttering) {
+ if (!aBaseMetaTileEntity.isAllowedToWork()) return;
+ if (aTick % 100 == 0) this.mStuttering = false;
+ return;
+ }
+ if (this.hasErrors()) {
+ if (!aBaseMetaTileEntity.isAllowedToWork()) return;
+ if (aTick % 100 == 0) if (!canWork(usedQueen)) this.stutterProcess();
+ return;
+ }
+
+ if (!drainEnergyForProcess(this.mEUt)) {
+ this.mStuttering = true;
+ this.stutterProcess();
+ return;
+ }
+ this.mProgresstime++;
+ if (usedQueen != null) {
+ if (usedQueenBee == null) usedQueenBee = beeRoot.getMember(usedQueen);
+ doEffect();
+ if (!retrievingPollenInThisOperation && floweringMod > 0f
+ && this.mProgresstime % pollinationDelay == 0) {
+ if (retrievedpollen == null) retrievedpollen = usedQueenBee.retrievePollen(this);
+ if (retrievedpollen != null && (usedQueenBee.pollinateRandom(this, retrievedpollen)
+ || this.mProgresstime % (pollinationDelay * 5) == 0)) retrievedpollen = null;
+ }
+ }
+
+ if (this.mProgresstime % 100 == 0) {
+ if (!canWork(usedQueen)) {
+ this.stutterProcess();
+ return;
+ }
+ }
+
+ if (this.mProgresstime >= this.mMaxProgresstime) {
+ if (usedQueenBee != null) doAcceleratedEffects();
+ updateModifiers();
+ for (int i = 0; i < mOutputItems.length; i++)
+ if (mOutputItems[i] != null) for (int j = 0; j < mOutputItems.length; j++) {
+ if (j == 0 && isAutomated) {
+ if (beeRoot.isMember(mOutputItems[i], EnumBeeType.QUEEN.ordinal())
+ || beeRoot.isMember(mOutputItems[i], EnumBeeType.PRINCESS.ordinal())) {
+ if (aBaseMetaTileEntity.addStackToSlot(queen, mOutputItems[i])) break;
+ } else if (beeRoot.isMember(mOutputItems[i], EnumBeeType.DRONE.ordinal()))
+ if (aBaseMetaTileEntity.addStackToSlot(drone, mOutputItems[i])) break;
+ } else if (mAutoQueen && i == 0
+ && j == 0
+ && beeRoot.isMember(mOutputItems[0], EnumBeeType.QUEEN.ordinal())
+ && aBaseMetaTileEntity.addStackToSlot(queen, mOutputItems[0])) break;
+ if (aBaseMetaTileEntity
+ .addStackToSlot(getOutputSlot() + ((j + i) % mOutputItems.length), mOutputItems[i]))
+ break;
+ }
+ Arrays.fill(mOutputItems, null);
+ mEUt = 0;
+ mProgresstime = 0;
+ mMaxProgresstime = 0;
+ mStuttering = false;
+ aBaseMetaTileEntity.setActive(false);
+
+ if (doesAutoOutput() && !isOutputEmpty() && aBaseMetaTileEntity.getFrontFacing() != mMainFacing) {
+ final TileEntity tTileEntity2 = aBaseMetaTileEntity
+ .getTileEntityAtSide(aBaseMetaTileEntity.getFrontFacing());
+ final long tStoredEnergy = aBaseMetaTileEntity.getUniversalEnergyStored();
+ int tMaxStacks = (int) (tStoredEnergy / 64L);
+ if (tMaxStacks > mOutputItems.length) tMaxStacks = mOutputItems.length;
+
+ moveMultipleItemStacks(
+ aBaseMetaTileEntity,
+ tTileEntity2,
+ aBaseMetaTileEntity.getFrontFacing(),
+ aBaseMetaTileEntity.getBackFacing(),
+ null,
+ false,
+ (byte) 64,
+ (byte) 1,
+ (byte) 64,
+ (byte) 1,
+ tMaxStacks);
+ }
+
+ if (aBaseMetaTileEntity.isAllowedToWork() && checkRecipe() == FOUND_AND_SUCCESSFULLY_USED_RECIPE)
+ aBaseMetaTileEntity.setActive(true);
+ }
+ }
+ }
+ }
+
+ public void cancelProcess() {
+ if (this.getBaseMetaTileEntity()
+ .isActive()
+ && this.getBaseMetaTileEntity()
+ .isServerSide()
+ && usedQueen != null
+ && beeRoot.isMember(usedQueen, EnumBeeType.QUEEN.ordinal())) {
+ Arrays.fill(mOutputItems, null);
+ mEUt = 0;
+ mProgresstime = 0;
+ mMaxProgresstime = 0;
+ mStuttering = false;
+ this.getBaseMetaTileEntity()
+ .setActive(false);
+ setQueen(usedQueen);
+ this.getBaseMetaTileEntity()
+ .disableWorking();
+ }
+ }
+
+ @Override
+ public boolean isItemValidForSlot(int aIndex, ItemStack aStack) {
+ if (aStack == null) return false;
+ if (aIndex < getInputSlot()) return true;
+ if (aIndex == queen) return beeRoot.isMember(aStack, EnumBeeType.QUEEN.ordinal())
+ || beeRoot.isMember(aStack, EnumBeeType.PRINCESS.ordinal());
+ else if (aIndex == drone) return beeRoot.isMember(aStack, EnumBeeType.DRONE.ordinal());
+ else if (aIndex < getOutputSlot()) {
+ if (!GT_ApiaryUpgrade.isUpgrade(aStack)) return false;
+ for (int i = upgradeSlot; i < upgradeSlot + upgradeSlotCount; i++) {
+ if (aIndex == i) continue;
+ final ItemStack s = getStackInSlot(i);
+ if (s == null) continue;
+ if (GT_Utility.areStacksEqual(getStackInSlot(i), aStack)) return false;
+ if (GT_ApiaryUpgrade.isUpgrade(aStack)) {
+ if (!GT_ApiaryUpgrade.getUpgrade(aStack)
+ .isAllowedToWorkWith(getStackInSlot(i))) return false;
+ } else if (GT_ApiaryUpgrade.isUpgrade(s)) {
+ if (!GT_ApiaryUpgrade.getUpgrade(s)
+ .isAllowedToWorkWith(aStack)) return false;
+ }
+ }
+ return true;
+ } else return false;
+ }
+
+ @Override
+ public boolean allowPutStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ if (!super.allowPutStack(aBaseMetaTileEntity, aIndex, side, aStack)) return false;
+ return isItemValidForSlot(aIndex, aStack);
+ }
+
+ @Override
+ public void setInventorySlotContents(int aIndex, ItemStack aStack) {
+ if (aIndex == queen && aStack != null && getBaseMetaTileEntity().isClientSide()) usedQueen = aStack.copy();
+ super.setInventorySlotContents(aIndex, aStack);
+ }
+
+ // Gets called on slot click //
+ public void onInventoryUpdate(int aIndex) {
+ if (aIndex > drone && aIndex < getOutputSlot()) updateModifiers();
+ }
+
+ public ItemStack getUsedQueen() {
+ return usedQueen;
+ }
+
+ // region IBeeHousing
+
+ @Override
+ public Iterable<IBeeModifier> getBeeModifiers() {
+ return Collections.singletonList(this);
+ }
+
+ @Override
+ public Iterable<IBeeListener> getBeeListeners() {
+ return Collections.singletonList(this);
+ }
+
+ @Override
+ public IBeeHousingInventory getBeeInventory() {
+ return this;
+ }
+
+ @Override
+ public IBeekeepingLogic getBeekeepingLogic() {
+ return dummylogic;
+ }
+
+ @Override
+ public int getBlockLightValue() {
+ return this.getBaseMetaTileEntity()
+ .getLightLevelAtSide(ForgeDirection.UP);
+ }
+
+ @Override
+ public boolean canBlockSeeTheSky() {
+ return this.getBaseMetaTileEntity()
+ .getSkyAtSide(ForgeDirection.UP);
+ }
+
+ @Override
+ public World getWorld() {
+ return this.getBaseMetaTileEntity()
+ .getWorld();
+ }
+
+ GameProfile owner = null;
+
+ @Override
+ public GameProfile getOwner() {
+ if (owner == null) owner = new GameProfile(
+ this.getBaseMetaTileEntity()
+ .getOwnerUuid(),
+ this.getBaseMetaTileEntity()
+ .getOwnerName());
+ return owner;
+ }
+
+ @Override
+ public Vec3 getBeeFXCoordinates() {
+ return Vec3.createVectorHelper(
+ getBaseMetaTileEntity().getXCoord() + 0.5,
+ getBaseMetaTileEntity().getYCoord() + 0.5,
+ getBaseMetaTileEntity().getZCoord() + 0.5);
+ }
+
+ @Override
+ public BiomeGenBase getBiome() {
+ if (biomeOverride == null) return this.getBaseMetaTileEntity()
+ .getBiome();
+ return biomeOverride;
+ }
+
+ @Override
+ public EnumTemperature getTemperature() {
+ if (BiomeHelper.isBiomeHellish(getBiome())) return EnumTemperature.HELLISH;
+ return EnumTemperature.getFromValue(getBiome().temperature + temperatureMod);
+ }
+
+ @Override
+ public EnumHumidity getHumidity() {
+ return EnumHumidity.getFromValue(getBiome().rainfall + humidityMod);
+ }
+
+ @Override
+ public IErrorLogic getErrorLogic() {
+ return this;
+ }
+
+ @Override
+ public ChunkCoordinates getCoordinates() {
+ return this.getBaseMetaTileEntity()
+ .getCoords();
+ }
+
+ // endregion
+
+ // region IBeeHousingInventory
+ @Override
+ public ItemStack getQueen() {
+ return getStackInSlot(queen);
+ }
+
+ @Override
+ public ItemStack getDrone() {
+ return getStackInSlot(drone);
+ }
+
+ @Override
+ public void setQueen(ItemStack itemStack) {
+ setInventorySlotContents(queen, itemStack);
+ }
+
+ @Override
+ public void setDrone(ItemStack itemStack) {
+ setInventorySlotContents(drone, itemStack);
+ }
+
+ @Override
+ public boolean addProduct(ItemStack itemStack, boolean b) {
+ throw new RuntimeException("Should not happen :F");
+ }
+ // endregion
+
+ // region IErrorLogic
+
+ public HashSet<IErrorState> mErrorStates = new HashSet<>();
+
+ @Override
+ public boolean setCondition(boolean b, IErrorState iErrorState) {
+ if (b) mErrorStates.add(iErrorState);
+ else mErrorStates.remove(iErrorState);
+ return b;
+ }
+
+ @Override
+ public boolean contains(IErrorState iErrorState) {
+ return mErrorStates.contains(iErrorState);
+ }
+
+ @Override
+ public boolean hasErrors() {
+ return !mErrorStates.isEmpty();
+ }
+
+ @Override
+ public void clearErrors() {
+ mErrorStates.clear();
+ }
+
+ @Override
+ public void writeData(DataOutputStream dataOutputStream) throws IOException {
+ dataOutputStream.write(mErrorStates.size());
+ for (IErrorState s : mErrorStates) dataOutputStream.writeUTF(s.getUniqueName());
+ }
+
+ @Override
+ public void readData(DataInputStream dataInputStream) throws IOException {
+ for (int i = dataInputStream.readInt(); i > 0; i--)
+ mErrorStates.add(ForestryAPI.errorStateRegistry.getErrorState(dataInputStream.readUTF()));
+ }
+
+ @Override
+ public ImmutableSet<IErrorState> getErrorStates() {
+ return ImmutableSet.copyOf(mErrorStates);
+ }
+
+ private String flowerType = "";
+ private ChunkCoordinates flowercoords = null;
+ private Block flowerBlock;
+ private int flowerBlockMeta;
+
+ private boolean checkFlower(IBee bee) {
+ final String flowerType = bee.getGenome()
+ .getFlowerProvider()
+ .getFlowerType();
+ if (!this.flowerType.equals(flowerType)) flowercoords = null;
+ if (flowercoords != null) {
+ if (getWorld().getBlock(flowercoords.posX, flowercoords.posY, flowercoords.posZ) != flowerBlock
+ || getWorld().getBlockMetadata(flowercoords.posX, flowercoords.posY, flowercoords.posZ)
+ != flowerBlockMeta)
+ if (!FlowerManager.flowerRegistry
+ .isAcceptedFlower(flowerType, getWorld(), flowercoords.posX, flowercoords.posY, flowercoords.posZ))
+ flowercoords = null;
+ else {
+ flowerBlock = getWorld().getBlock(flowercoords.posX, flowercoords.posY, flowercoords.posZ);
+ flowerBlockMeta = getWorld()
+ .getBlockMetadata(flowercoords.posX, flowercoords.posY, flowercoords.posZ);
+ }
+ }
+ if (flowercoords == null) {
+ flowercoords = FlowerManager.flowerRegistry.getAcceptedFlowerCoordinates(this, bee, flowerType);
+ if (flowercoords != null) {
+ flowerBlock = getWorld().getBlock(flowercoords.posX, flowercoords.posY, flowercoords.posZ);
+ flowerBlockMeta = getWorld().getBlockMetadata(flowercoords.posX, flowercoords.posY, flowercoords.posZ);
+ this.flowerType = flowerType;
+ }
+ }
+ return flowercoords != null;
+ }
+
+ private boolean canWork(ItemStack queen) {
+ clearErrors();
+ if (queen == null) return true; // Reloaded the chunk ?
+ if (beeRoot.isMember(queen, EnumBeeType.PRINCESS.ordinal())) return true;
+ final IBee bee = beeRoot.getMember(queen);
+ for (IErrorState err : bee.getCanWork(this)) setCondition(true, err);
+ setCondition(!checkFlower(bee), EnumErrorCode.NO_FLOWER);
+ return !hasErrors();
+ }
+
+ private boolean canWork() {
+ clearErrors();
+ final EnumBeeType beeType = beeRoot.getType(getQueen());
+ if (beeType == EnumBeeType.PRINCESS) {
+ setCondition(!beeRoot.isDrone(getDrone()), EnumErrorCode.NO_DRONE);
+ return !hasErrors();
+ }
+ if (beeType == EnumBeeType.QUEEN) {
+ final IBee bee = beeRoot.getMember(getQueen());
+ for (IErrorState err : bee.getCanWork(this)) setCondition(true, err);
+ setCondition(!checkFlower(bee), EnumErrorCode.NO_FLOWER);
+ return !hasErrors();
+ } else {
+ setCondition(true, EnumErrorCode.NO_QUEEN);
+ return false;
+ }
+ }
+
+ // endregion
+
+ // region IBeeModifier
+
+ private float terrorityMod = 1f;
+ private float mutationMod = 1f;
+ private float lifespanMod = 1f;
+ private float productionMod = 2f;
+ private float floweringMod = 1f;
+ private float geneticDecayMod = 1f;
+ private float energyMod = 1f;
+ private boolean sealedMod = false;
+ private boolean selfLightedMod = false;
+ private boolean selfUnlightedMod = false;
+ private boolean sunlightSimulatedMod = false;
+ private BiomeGenBase biomeOverride = null;
+ private float humidityMod = 0f;
+ private float temperatureMod = 0f;
+ private boolean isAutomated = false;
+ private boolean isRetrievingPollen = false;
+ private int maxspeed = 0;
+
+ public void updateModifiers() {
+ final GT_ApiaryModifier mods = new GT_ApiaryModifier();
+ for (int i = 0; i < upgradeSlotCount; i++) {
+ final ItemStack s = getStackInSlot(upgradeSlot + i);
+ if (s == null) continue;
+ if (GT_ApiaryUpgrade.isUpgrade(s)) {
+ final GT_ApiaryUpgrade upgrade = GT_ApiaryUpgrade.getUpgrade(s);
+ upgrade.applyModifiers(mods, s);
+ }
+ }
+
+ terrorityMod = mods.territory;
+ mutationMod = mods.mutation;
+ lifespanMod = mods.lifespan;
+ productionMod = mods.production;
+ floweringMod = mods.flowering;
+ geneticDecayMod = mods.geneticDecay;
+ energyMod = mods.energy;
+ sealedMod = mods.isSealed;
+ selfLightedMod = mods.isSelfLighted;
+ selfUnlightedMod = mods.isSelfUnlighted;
+ sunlightSimulatedMod = mods.isSunlightSimulated;
+ biomeOverride = mods.biomeOverride;
+ humidityMod = mods.humidity;
+ temperatureMod = mods.temperature;
+ isAutomated = mods.isAutomated;
+ isRetrievingPollen = mods.isCollectingPollen;
+ maxspeed = mods.maxSpeed;
+
+ if (mLockedSpeed) mSpeed = maxspeed;
+ else mSpeed = Math.min(mSpeed, maxspeed);
+ }
+
+ /** Tries to move as much of [stack] into a possible upgrade slot */
+ public void addUpgrade(ItemStack stack) {
+ if (stack == null || !GT_ApiaryUpgrade.isUpgrade(stack)) return;
+
+ int amount = stack.stackSize;
+ for (int i = upgradeSlot; i < upgradeSlot + upgradeSlotCount; i++) {
+ if (!isItemValidForSlot(i, stack)) continue;
+
+ int maxStackSize = GT_ApiaryUpgrade.getUpgrade(stack)
+ .getMaxNumber();
+ ItemStack stackInSlot = getStackInSlot(i);
+
+ // Push into empty slot
+ if (stackInSlot == null) {
+ amount = Math.min(amount, maxStackSize);
+ setInventorySlotContents(i, stack.splitStack(amount));
+ return;
+ }
+
+ if (!GT_Utility.areStacksEqual(stack, stackInSlot)) continue;
+ amount = Math.max(Math.min(amount, maxStackSize - stackInSlot.stackSize), 0);
+ if (amount == 0) return;
+ stackInSlot.stackSize += amount;
+ stack.stackSize -= amount;
+ return;
+ }
+ }
+
+ /** Returns installed upgrade in slot 0 <= [index] < getMaxUpgradeCount() */
+ public ItemStack getUpgrade(int index) {
+ if (index < 0 || index >= upgradeSlotCount) return null;
+ return getStackInSlot(upgradeSlot + index);
+ }
+
+ /** Tries to remove [amount] or less of the upgrade installed in slot [index]. Returns the removed ItemStack */
+ public ItemStack removeUpgrade(int index, int amount) {
+ if (index < 0 || index >= upgradeSlotCount || amount <= 0) return null;
+
+ ItemStack stackInSlot = getUpgrade(index);
+ if (stackInSlot == null) return null;
+
+ amount = Math.min(amount, stackInSlot.stackSize);
+ ItemStack result = stackInSlot.splitStack(amount);
+ if (stackInSlot.stackSize <= 0) setInventorySlotContents(upgradeSlot + index, null);
+ return result;
+ }
+
+ public static int getMaxUpgradeCount() {
+ return upgradeSlotCount;
+ }
+
+ @Override
+ public float getTerritoryModifier(IBeeGenome iBeeGenome, float v) {
+ return Math.min(5, terrorityMod);
+ }
+
+ @Override
+ public float getMutationModifier(IBeeGenome iBeeGenome, IBeeGenome iBeeGenome1, float v) {
+ return mutationMod;
+ }
+
+ @Override
+ public float getLifespanModifier(IBeeGenome iBeeGenome, IBeeGenome iBeeGenome1, float v) {
+ return lifespanMod;
+ }
+
+ @Override
+ public float getProductionModifier(IBeeGenome iBeeGenome, float v) {
+ return productionMod;
+ }
+
+ @Override
+ public float getFloweringModifier(IBeeGenome iBeeGenome, float v) {
+ return floweringMod;
+ }
+
+ @Override
+ public float getGeneticDecay(IBeeGenome iBeeGenome, float v) {
+ return geneticDecayMod;
+ }
+
+ public float getEnergyModifier() {
+ return energyMod;
+ }
+
+ @Override
+ public boolean isSealed() {
+ return sealedMod;
+ }
+
+ @Override
+ public boolean isSelfLighted() {
+ return selfLightedMod;
+ }
+
+ @Override
+ public boolean isSelfUnlighted() {
+ return selfUnlightedMod;
+ }
+
+ @Override
+ public boolean isSunlightSimulated() {
+ return sunlightSimulatedMod;
+ }
+
+ @Override
+ public boolean isHellish() {
+ return getBiome() == BiomeGenBase.hell;
+ }
+
+ public int getMaxSpeed() {
+ return maxspeed;
+ }
+
+ // endregion
+
+ // region IBeeListener
+
+ @Override
+ public void wearOutEquipment(int i) {}
+
+ @Override
+ public void onQueenDeath() {}
+
+ @Override
+ public boolean onPollenRetrieved(IIndividual iIndividual) {
+ return false;
+ }
+
+ // endregion
+
+ static final IBeekeepingLogic dummylogic = new IBeekeepingLogic() {
+
+ @Override
+ public boolean canWork() {
+ return true;
+ }
+
+ @Override
+ public void doWork() {}
+
+ @Override
+ public void syncToClient() {}
+
+ @Override
+ public void syncToClient(EntityPlayerMP entityPlayerMP) {}
+
+ @Override
+ public int getBeeProgressPercent() {
+ return 0;
+ }
+
+ @Override
+ public boolean canDoBeeFX() {
+ return false;
+ }
+
+ @Override
+ public void doBeeFX() {}
+
+ @Override
+ public void readFromNBT(NBTTagCompound nbtTagCompound) {}
+
+ @Override
+ public void writeToNBT(NBTTagCompound nbtTagCompound) {}
+ };
+
+ private static final String POWER_SOURCE_POWER = "GT5U.machines.powersource.power",
+ CANCEL_PROCESS_TOOLTIP = "GT5U.machines.industrialapiary.cancel.tooltip",
+ SPEED_TOOLTIP = "GT5U.machines.industrialapiary.speed.tooltip",
+ SPEED_LOCKED_TOOLTIP = "GT5U.machines.industrialapiary.speedlocked.tooltip",
+ INFO_TOOLTIP = "GT5U.machines.industrialapiary.info.tooltip",
+ INFO_WITH_BEE_TOOLTIP = "GT5U.machines.industrialapiary.infoextended.tooltip",
+ UPGRADE_TOOLTIP = "GT5U.machines.industrialapiary.upgradeslot.tooltip",
+ AUTOQUEEN_TOOLTIP = "GT5U.machines.industrialapiary.autoqueen.tooltip";
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ builder
+ .widget(
+ new SlotWidget(new ApiarySlot(inventoryHandler, queen))
+ .setBackground(getGUITextureSet().getItemSlot(), GT_UITextures.OVERLAY_SLOT_BEE_QUEEN)
+ .setPos(36, 21))
+ .widget(
+ new SlotWidget(new ApiarySlot(inventoryHandler, drone))
+ .setBackground(getGUITextureSet().getItemSlot(), GT_UITextures.OVERLAY_SLOT_BEE_DRONE)
+ .setPos(36, 41))
+ .widget(
+ SlotGroup.ofItemHandler(inventoryHandler, 2)
+ .startFromSlot(7)
+ .endAtSlot(10)
+ .slotCreator(i -> new ApiarySlot(inventoryHandler, i))
+ .applyForWidget(
+ widget -> widget.setGTTooltip(() -> mTooltipCache.getData(UPGRADE_TOOLTIP))
+ .setTooltipShowUpDelay(TOOLTIP_DELAY))
+ .build()
+ .setPos(61, 23));
+
+ super.addUIWidgets(builder, buildContext);
+
+ builder.widget(
+ new ButtonWidget().setOnClick((clickData, widget) -> cancelProcess())
+ .setBackground(GT_UITextures.BUTTON_STANDARD, GT_UITextures.OVERLAY_BUTTON_CROSS)
+ .setGTTooltip(() -> mTooltipCache.getData(CANCEL_PROCESS_TOOLTIP))
+ .setTooltipShowUpDelay(TOOLTIP_DELAY)
+ .setPos(7, 26)
+ .setSize(18, 18))
+ .widget(
+ new CycleButtonWidget().setToggle(() -> mAutoQueen, x -> mAutoQueen = x)
+ .setTextureGetter(
+ i -> i == 0 ? GT_UITextures.OVERLAY_BUTTON_CROSS : GT_UITextures.OVERLAY_BUTTON_CHECKMARK)
+ .setGTTooltip(() -> mTooltipCache.getData(AUTOQUEEN_TOOLTIP))
+ .setTooltipShowUpDelay(TOOLTIP_DELAY)
+ .setPos(7, 44)
+ .setSize(18, 18)
+ .setBackground(GT_UITextures.BUTTON_STANDARD, GT_UITextures.OVERLAY_SLOT_BEE_QUEEN))
+ .widget(
+ new DrawableWidget().setDrawable(GT_UITextures.PICTURE_INFORMATION)
+ .setGTTooltip(() -> {
+ final String energyreq = GT_Utility.formatNumbers(
+ (int) ((float) GT_MetaTileEntity_IndustrialApiary.baseEUtUsage * getEnergyModifier()
+ * getAcceleration()) + getAdditionalEnergyUsage());
+ final String Temp = StatCollector.translateToLocal(getTemperature().getName());
+ final String Hum = StatCollector.translateToLocal(getHumidity().getName());
+ if (getUsedQueen() != null
+ && BeeManager.beeRoot.isMember(getUsedQueen(), EnumBeeType.QUEEN.ordinal())) {
+ final IBee bee = BeeManager.beeRoot.getMember(getUsedQueen());
+ if (bee.isAnalyzed()) {
+ final IBeeGenome genome = bee.getGenome();
+ final IBeeModifier mod = BeeManager.beeRoot.getBeekeepingMode(getWorld())
+ .getBeeModifier();
+ final float tmod = getTerritoryModifier(null, 1f) * mod.getTerritoryModifier(null, 1f);
+ final int[] t = Arrays.stream(genome.getTerritory())
+ .map(i -> (int) ((float) i * tmod))
+ .toArray();
+ return mTooltipCache.getUncachedTooltipData(
+ INFO_WITH_BEE_TOOLTIP,
+ energyreq,
+ Temp,
+ Hum,
+ genome.getSpeed(),
+ getProductionModifier(null, 0f) + mod.getProductionModifier(null, 0f),
+ Math.round(
+ getFloweringModifier(null, 1f) * genome.getFlowering()
+ * mod.getFloweringModifier(null, 1f)),
+ Math.round(
+ getLifespanModifier(null, null, 1f) * genome.getLifespan()
+ * mod.getLifespanModifier(null, null, 1f)),
+ t[0],
+ t[1],
+ t[2]);
+ }
+ }
+ return mTooltipCache.getUncachedTooltipData(INFO_TOOLTIP, energyreq, Temp, Hum);
+ })
+ .attachSyncer(
+ new FakeSyncWidget.ItemStackSyncer(() -> usedQueen, val -> usedQueen = val),
+ builder,
+ (widget, val) -> widget.notifyTooltipChange())
+ .setPos(163, 5)
+ .setSize(7, 18))
+ .widget(new ButtonWidget().setOnClick((clickData, widget) -> {
+ if (clickData.mouseButton == 0) {
+ if (mLockedSpeed) return;
+ if (!clickData.shift) {
+ mSpeed++;
+ if (mSpeed > getMaxSpeed()) mSpeed = 0;
+ } else {
+ mSpeed--;
+ if (mSpeed < 0) mSpeed = getMaxSpeed();
+ }
+ } else if (clickData.mouseButton == 1) {
+ mLockedSpeed = !mLockedSpeed;
+ if (mLockedSpeed) mSpeed = getMaxSpeed();
+ }
+ })
+ .setGTTooltip(
+ () -> mTooltipCache.getUncachedTooltipData(
+ mLockedSpeed ? SPEED_LOCKED_TOOLTIP : SPEED_TOOLTIP,
+ getAcceleration(),
+ GT_Utility.formatNumbers(getAdditionalEnergyUsage())))
+ .attachSyncer(
+ new FakeSyncWidget.IntegerSyncer(() -> mSpeed, val -> mSpeed = val),
+ builder,
+ (widget, val) -> widget.notifyTooltipChange())
+ .attachSyncer(
+ new FakeSyncWidget.BooleanSyncer(() -> mLockedSpeed, val -> mLockedSpeed = val),
+ builder,
+ (widget, val) -> widget.notifyTooltipChange())
+ .setTooltipShowUpDelay(TOOLTIP_DELAY)
+ .setBackground(GT_UITextures.PICTURE_SQUARE_LIGHT_GRAY)
+ .setPos(25, 62)
+ .setSize(18, 18))
+ .widget(
+ new TextWidget("x").setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(30, 63))
+ .widget(
+ TextWidget.dynamicString(() -> String.valueOf(1 << mSpeed))
+ // mSpeed is already synced
+ .setSynced(false)
+ .setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(26, 72));
+ }
+
+ private static final FallbackableUITexture progressBarTexture = GT_UITextures
+ .fallbackableProgressbar("iapiary", GT_UITextures.PROGRESSBAR_ARROW);
+
+ @Override
+ protected BasicUIProperties getUIProperties() {
+ return super.getUIProperties().toBuilder()
+ .progressBarTexture(progressBarTexture)
+ .progressBarPos(new Pos2d(70, 3))
+ .build();
+ }
+
+ @Override
+ protected SlotWidget createItemInputSlot(int index, IDrawable[] backgrounds, Pos2d pos) {
+ // we have custom input slots
+ return null;
+ }
+
+ @Override
+ protected CycleButtonWidget createItemAutoOutputButton() {
+ return (CycleButtonWidget) super.createItemAutoOutputButton().setPos(7, 62);
+ }
+
+ @Override
+ protected CycleButtonWidget createFluidAutoOutputButton() {
+ return null;
+ }
+
+ @Override
+ protected SlotWidget createChargerSlot(int x, int y, String tooltipKey, Object[] tooltipArgs) {
+ return (SlotWidget) super.createChargerSlot(x, y, tooltipKey, tooltipArgs).setPos(79, 62);
+ }
+
+ @Override
+ protected DrawableWidget createErrorStatusArea(ModularWindow.Builder builder, IDrawable picture) {
+ return (DrawableWidget) super.createErrorStatusArea(builder, picture).setPos(100, 62)
+ .attachSyncer(
+ new FakeSyncWidget.ListSyncer<>(() -> Arrays.asList(mErrorStates.toArray(new IErrorState[0])), val -> {
+ mErrorStates.clear();
+ mErrorStates.addAll(new HashSet<>(val));
+ },
+ (buffer, val) -> buffer.writeShort(val.getID()),
+ buffer -> ForestryAPI.errorStateRegistry.getErrorState(buffer.readShort())),
+ builder,
+ (widget, val) -> widget.notifyTooltipChange());
+ }
+
+ @Override
+ protected List<String> getErrorDescriptions() {
+ if (!mErrorStates.isEmpty()) {
+ return mErrorStates.stream()
+ .map(state -> EnumChatFormatting.RED + StatCollector.translateToLocal("for." + state.getDescription()))
+ .collect(Collectors.toList());
+ } else if (mStuttering) {
+ return mTooltipCache
+ .getData(STALLED_STUTTERING_TOOLTIP, StatCollector.translateToLocal(POWER_SOURCE_POWER)).text;
+ } else {
+ return Collections.emptyList();
+ }
+ }
+
+ @Override
+ protected List<String> getErrorDescriptionsShift() {
+ // Don't show shift tooltip of "Progress was lost"
+ // as this machine does not lose progress
+ return getErrorDescriptions();
+ }
+
+ private int getAcceleration() {
+ return 1 << mSpeed;
+ }
+
+ private int getAdditionalEnergyUsage() {
+ final int accelerated = getAcceleration();
+ int energyusage = 0;
+ if (accelerated == 2) energyusage = 32;
+ else if (accelerated > 2) energyusage = 32 * accelerated << (mSpeed - 2);
+ return energyusage;
+ }
+
+ private class ApiarySlot extends BaseSlot {
+
+ public ApiarySlot(IItemHandlerModifiable inventory, int index) {
+ super(inventory, index);
+ }
+
+ @Override
+ public boolean isItemValidPhantom(ItemStack stack) {
+ return super.isItemValidPhantom(stack) && getBaseMetaTileEntity().isItemValidForSlot(getSlotIndex(), stack);
+ }
+
+ @Override
+ public void onSlotChanged() {
+ super.onSlotChanged();
+ onInventoryUpdate(getSlotIndex());
+ }
+ }
+
+ private static final UIInfo<?, ?> IndustrialApiaryUI = GT_UIInfos.GTTileEntityUIFactory
+ .apply(GT_ModularUIContainer_IndustrialApiary::new);
+
+ private static class GT_ModularUIContainer_IndustrialApiary extends ModularUIContainer {
+
+ public GT_ModularUIContainer_IndustrialApiary(ModularUIContext context, ModularWindow mainWindow) {
+ super(context, mainWindow);
+ }
+
+ private final int playerInventorySlot = 36;
+
+ @Override
+ public ItemStack slotClick(int aSlotNumber, int aMouseclick, int aShifthold, EntityPlayer aPlayer) {
+ if (!(aSlotNumber >= playerInventorySlot + 2 && aSlotNumber < playerInventorySlot + 2 + 4))
+ return super.slotClick(aSlotNumber, aMouseclick, aShifthold, aPlayer);
+ if (aShifthold == 5) return null;
+ if (aShifthold != 0) return super.slotClick(aSlotNumber, aMouseclick, aShifthold, aPlayer);
+ if (aMouseclick > 1) return super.slotClick(aSlotNumber, aMouseclick, aShifthold, aPlayer);
+ final ItemStack s = aPlayer.inventory.getItemStack();
+ if (s == null) return super.slotClick(aSlotNumber, aMouseclick, aShifthold, aPlayer);
+ final Slot slot = getSlot(aSlotNumber);
+ final ItemStack slotStack = slot.getStack();
+ if (slotStack != null && !GT_Utility.areStacksEqual(slotStack, s)) return null; // super would replace item
+ if (slotStack == null && !slot.isItemValid(s))
+ return super.slotClick(aSlotNumber, aMouseclick, aShifthold, aPlayer);
+ if (!GT_ApiaryUpgrade.isUpgrade(s)) return super.slotClick(aSlotNumber, aMouseclick, aShifthold, aPlayer);
+ int max = GT_ApiaryUpgrade.getUpgrade(s)
+ .getMaxNumber();
+ if (slotStack != null) max = Math.max(0, max - slotStack.stackSize);
+ max = Math.min(max, s.stackSize);
+ if (max == 0) return null;
+ if (aMouseclick == 1) max = 1;
+ if (max == s.stackSize) return super.slotClick(aSlotNumber, aMouseclick, aShifthold, aPlayer);
+ final ItemStack newStack = s.splitStack(s.stackSize - max);
+ final ItemStack result = super.slotClick(aSlotNumber, aMouseclick, aShifthold, aPlayer);
+ aPlayer.inventory.setItemStack(newStack);
+ return result;
+ }
+
+ @Override
+ public ItemStack transferStackInSlot(EntityPlayer aPlayer, int aSlotIndex) {
+ final Slot s = getSlot(aSlotIndex);
+ if (s == null) return super.transferStackInSlot(aPlayer, aSlotIndex);
+ if (aSlotIndex >= playerInventorySlot) return super.transferStackInSlot(aPlayer, aSlotIndex);
+ final ItemStack aStack = s.getStack();
+ if (aStack == null) return super.transferStackInSlot(aPlayer, aSlotIndex);
+ if (!GT_ApiaryUpgrade.isUpgrade(aStack)) return super.transferStackInSlot(aPlayer, aSlotIndex);
+ for (int i = playerInventorySlot + 2; i < playerInventorySlot + 2 + 4; i++) {
+ final Slot iSlot = getSlot(i);
+ final ItemStack iStack = iSlot.getStack();
+ if (iStack == null) {
+ if (!iSlot.isItemValid(aStack)) continue;
+ } else {
+ if (!GT_Utility.areStacksEqual(aStack, iStack)) continue;
+ }
+ int max = GT_ApiaryUpgrade.getUpgrade(aStack)
+ .getMaxNumber();
+ if (iStack == null) {
+ max = Math.min(max, aStack.stackSize);
+ final ItemStack newstack = aStack.splitStack(max);
+ iSlot.putStack(newstack);
+ } else {
+ max = Math.max(0, max - iStack.stackSize);
+ max = Math.min(max, aStack.stackSize);
+ iStack.stackSize += max;
+ aStack.stackSize -= max;
+ iSlot.onSlotChanged();
+ }
+ if (aStack.stackSize == 0) s.putStack(null);
+ else s.onSlotChanged();
+ break;
+ }
+ return null;
+ }
+ }
+
+ @Override
+ public void getWailaBody(ItemStack itemStack, List<String> currenttip, IWailaDataAccessor accessor,
+ IWailaConfigHandler config) {
+ super.getWailaBody(itemStack, currenttip, accessor, config);
+ final NBTTagCompound tag = accessor.getNBTData();
+ if (tag.hasKey("queen")) {
+ currenttip.add(
+ "Current Queen: " + EnumChatFormatting.GREEN + StatCollector.translateToLocal(tag.getString("queen")));
+ }
+ if (tag.hasKey("dummyProduction")) {
+ currenttip.add(
+ "Effective Production: " + EnumChatFormatting.AQUA
+ + String.format("b^0.52 * %.2f", tag.getFloat("dummyProduction")));
+ }
+ if (tag.hasKey("errors")) {
+ NBTTagCompound errorNbt = tag.getCompoundTag("errors");
+ for (int i = 0; i < errorNbt.getInteger("size"); i++) {
+ currenttip.add(
+ "Error: " + EnumChatFormatting.RED
+ + StatCollector.translateToLocal("for." + errorNbt.getString("e" + i)));
+ }
+ }
+ }
+
+ @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);
+ if (usedQueen != null) {
+ IBeeGenome genome = beeRoot.getMember(usedQueen)
+ .getGenome();
+ tag.setString(
+ "queen",
+ genome.getPrimary()
+ .getUnlocalizedName());
+ float prodModifier = getProductionModifier(genome, 0f);
+ prodModifier += beeRoot.getBeekeepingMode(world)
+ .getBeeModifier()
+ .getProductionModifier(genome, prodModifier);
+ float dummyProduction = 100f * Bee.getFinalChance(0.01f, genome.getSpeed(), prodModifier, 8f);
+ tag.setFloat("dummyProduction", dummyProduction);
+ }
+ if (hasErrors()) {
+ NBTTagCompound errorNbt = new NBTTagCompound();
+ int errorCounter = 0;
+ for (IErrorState error : mErrorStates) {
+ errorNbt.setString("e" + errorCounter++, error.getDescription());
+ }
+ errorNbt.setInteger("size", errorCounter);
+ tag.setTag("errors", errorNbt);
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Massfabricator.java b/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Massfabricator.java
new file mode 100644
index 0000000000..07e9977429
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Massfabricator.java
@@ -0,0 +1,243 @@
+package gregtech.common.tileentities.machines.basic;
+
+import static gregtech.api.enums.GT_Values.V;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_MASSFAB;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_MASSFAB_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_MASSFAB_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_MASSFAB_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_MASSFAB;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_MASSFAB_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_MASSFAB_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_MASSFAB_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_MASSFAB;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_MASSFAB_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_MASSFAB_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_MASSFAB_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_MASSFAB;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_MASSFAB_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_MASSFAB_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_MASSFAB_GLOW;
+
+import java.util.Arrays;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+
+import net.minecraftforge.fluids.FluidStack;
+
+import com.google.common.primitives.Ints;
+
+import gregtech.api.enums.ConfigCategories;
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.MachineType;
+import gregtech.api.enums.Materials;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachine;
+import gregtech.api.objects.overclockdescriber.EUOverclockDescriber;
+import gregtech.api.objects.overclockdescriber.OverclockDescriber;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Config;
+import gregtech.api.util.GT_OverclockCalculator;
+import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.MethodsReturnNonnullByDefault;
+
+public class GT_MetaTileEntity_Massfabricator extends GT_MetaTileEntity_BasicMachine {
+
+ public static int sUUAperUUM = 1;
+ public static int sUUASpeedBonus = 4;
+ public static int sDurationMultiplier = 3215;
+ public static boolean sRequiresUUA = false;
+ public static int BASE_EUT = 256;
+ public static GT_Recipe nonUUARecipe;
+ public static GT_Recipe uuaRecipe;
+
+ public GT_MetaTileEntity_Massfabricator(int aID, String aName, String aNameRegional, int aTier) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ 8,
+ MachineType.MATTER_FABRICATOR.tooltipDescription(),
+ 1,
+ 1,
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_SIDE_MASSFAB_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_MASSFAB_ACTIVE_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_SIDE_MASSFAB),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_MASSFAB_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_FRONT_MASSFAB_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_MASSFAB_ACTIVE_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_FRONT_MASSFAB),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_MASSFAB_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_TOP_MASSFAB_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_MASSFAB_ACTIVE_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_TOP_MASSFAB),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_MASSFAB_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_BOTTOM_MASSFAB_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_MASSFAB_ACTIVE_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_BOTTOM_MASSFAB),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_MASSFAB_GLOW)
+ .glow()
+ .build()));
+ }
+
+ public GT_MetaTileEntity_Massfabricator(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, 8, aDescription, aTextures, 1, 1);
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Massfabricator(this.mName, this.mTier, this.mDescriptionArray, this.mTextures);
+ }
+
+ @Override
+ public boolean allowSelectCircuit() {
+ return true;
+ }
+
+ @Override
+ protected OverclockDescriber createOverclockDescriber() {
+ return new MassfabricatorOverclockDescriber(mTier, mAmperage);
+ }
+
+ @Override
+ public void onConfigLoad(GT_Config aConfig) {
+ super.onConfigLoad(aConfig);
+ sDurationMultiplier = aConfig
+ .get(ConfigCategories.machineconfig, "Massfabricator.UUM_Duration_Multiplier", sDurationMultiplier);
+ sUUAperUUM = aConfig.get(ConfigCategories.machineconfig, "Massfabricator.UUA_per_UUM", sUUAperUUM);
+ sUUASpeedBonus = aConfig.get(ConfigCategories.machineconfig, "Massfabricator.UUA_Speed_Bonus", sUUASpeedBonus);
+ sRequiresUUA = aConfig.get(ConfigCategories.machineconfig, "Massfabricator.UUA_Requirement", sRequiresUUA);
+ Materials.UUAmplifier.mChemicalFormula = ("Mass Fabricator Eff/Speed Bonus: x" + sUUASpeedBonus);
+ }
+
+ @Override
+ public long maxAmperesIn() {
+ return 10;
+ }
+
+ @Override
+ public long maxEUStore() {
+ return V[mTier] * 512L;
+ }
+
+ @Override
+ public int checkRecipe() {
+ FluidStack tFluid = getDrainableStack();
+ if ((tFluid == null) || (tFluid.amount < getCapacity())) {
+ this.mOutputFluid = Materials.UUMatter.getFluid(1L);
+ calculateCustomOverclock(containsUUA(getFillableStack()) ? uuaRecipe : nonUUARecipe);
+ // In case recipe is too OP for that machine
+ if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1)
+ return FOUND_RECIPE_BUT_DID_NOT_MEET_REQUIREMENTS;
+ if (containsUUA(tFluid = getFillableStack())) {
+ tFluid.amount -= sUUAperUUM;
+ return FOUND_AND_SUCCESSFULLY_USED_RECIPE;
+ }
+ return sRequiresUUA || Arrays.stream(getAllInputs())
+ .anyMatch(s -> ItemList.Circuit_Integrated.isStackEqual(s, true, true))
+ ? FOUND_RECIPE_BUT_DID_NOT_MEET_REQUIREMENTS
+ : FOUND_AND_SUCCESSFULLY_USED_RECIPE;
+ }
+ return DID_NOT_FIND_RECIPE;
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.massFabFakeRecipes;
+ }
+
+ @Override
+ public boolean isFluidInputAllowed(FluidStack aFluid) {
+ return aFluid.isFluidEqual(Materials.UUAmplifier.getFluid(1L));
+ }
+
+ @Override
+ public int getCapacity() {
+ return Math.max(sUUAperUUM, 1000);
+ }
+
+ private boolean containsUUA(FluidStack aFluid) {
+ return aFluid != null && aFluid.amount >= sUUAperUUM && aFluid.isFluidEqual(Materials.UUAmplifier.getFluid(1L));
+ }
+
+ @ParametersAreNonnullByDefault
+ @MethodsReturnNonnullByDefault
+ protected class MassfabricatorOverclockDescriber extends EUOverclockDescriber {
+
+ protected MassfabricatorOverclockDescriber(byte tier, int amperage) {
+ super(tier, amperage);
+ }
+
+ @Override
+ public GT_OverclockCalculator createCalculator(GT_OverclockCalculator template, GT_Recipe recipe) {
+ return super.createCalculator(template, recipe).setEUt(Ints.saturatedCast(V[tier] * amperage))
+ .setEUtIncreasePerOC(1)
+ .limitOverclockCount(tier - 1)
+ .setOneTickDiscount(false);
+ }
+
+ @Override
+ protected boolean shouldShowAmperage(GT_OverclockCalculator calculator) {
+ return true;
+ }
+
+ @Override
+ protected String getVoltageString(GT_OverclockCalculator calculator) {
+ // standard amperage calculation doesn't work here
+ return decorateWithOverclockLabel(GT_Utility.formatNumbers(V[mTier]) + " EU/t", calculator)
+ + GT_Utility.getTierNameWithParentheses(V[mTier]);
+ }
+
+ @Override
+ protected String getAmperageString(GT_OverclockCalculator calculator) {
+ int amperage = this.amperage;
+ int denominator = 1;
+ for (int i = 1; i < mTier; i++) {
+ amperage >>= 1;
+ if (amperage == 0) {
+ denominator <<= 1;
+ }
+ }
+ if (amperage > 0) {
+ return GT_Utility.formatNumbers(amperage);
+ } else {
+ return "1/" + denominator;
+ }
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_MicrowaveEnergyTransmitter.java b/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_MicrowaveEnergyTransmitter.java
new file mode 100644
index 0000000000..fc6afbd06f
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_MicrowaveEnergyTransmitter.java
@@ -0,0 +1,501 @@
+package gregtech.common.tileentities.machines.basic;
+
+import static gregtech.api.enums.GT_Values.V;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASINGS;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TELEPORTER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TELEPORTER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TELEPORTER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TELEPORTER_GLOW;
+
+import java.util.function.Consumer;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.world.World;
+import net.minecraftforge.common.DimensionManager;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidStack;
+
+import com.gtnewhorizons.modularui.api.NumberFormatMUI;
+import com.gtnewhorizons.modularui.api.drawable.IDrawable;
+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.DrawableWidget;
+import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.ConfigCategories;
+import gregtech.api.enums.Materials;
+import gregtech.api.gui.modularui.GT_UIInfos;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.gui.modularui.GUITextureSet;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.modularui.IAddGregtechLogo;
+import gregtech.api.interfaces.modularui.IAddUIWidgets;
+import gregtech.api.interfaces.tileentity.IEnergyConnected;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.BaseMetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicTank;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Config;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_MicrowaveEnergyTransmitter extends GT_MetaTileEntity_BasicTank
+ implements IAddGregtechLogo, IAddUIWidgets {
+
+ private static boolean sInterDimensionalTeleportAllowed = true;
+ private static int mMaxLoss = 50;
+ private static int mMaxLossDistance = 10000;
+ private static boolean mPassiveEnergyUse = true;
+ public int mTargetX = 0;
+ public int mTargetY = 0;
+ public int mTargetZ = 0;
+ public int mTargetD = 0;
+ public boolean mDebug = false;
+ public boolean hasBlock = false;
+ public int tTargetX = 0;
+ public int tTargetY = 0;
+ public int tTargetZ = 0;
+ public int tTargetD = 0;
+ public TileEntity tTile = null;
+
+ public GT_MetaTileEntity_MicrowaveEnergyTransmitter(int aID, String aName, String aNameRegional, int aTier) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ 3,
+ new String[] { "Transmits Energy Wirelessly", "Use Nitrogen Plasma", "for Inter-dimensional transmission",
+ "0.004EU Loss per 100 Blocks" });
+ }
+
+ public GT_MetaTileEntity_MicrowaveEnergyTransmitter(String aName, int aTier, String aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, 3, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_MicrowaveEnergyTransmitter(String aName, int aTier, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, 3, aDescription, aTextures);
+ }
+
+ @Override
+ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) {
+ if (aBaseMetaTileEntity.isClientSide()) return true;
+ this.hasBlock = checkForBlock();
+ GT_UIInfos.openGTTileEntityUI(aBaseMetaTileEntity, aPlayer);
+ return true;
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_MicrowaveEnergyTransmitter(
+ this.mName,
+ this.mTier,
+ this.mDescriptionArray,
+ this.mTextures);
+ }
+
+ @Override
+ public String[] getInfoData() {
+ return new String[] { "Coordinates:",
+ "X: " + EnumChatFormatting.GREEN + GT_Utility.formatNumbers(this.mTargetX) + EnumChatFormatting.RESET,
+ "Y: " + EnumChatFormatting.GREEN + GT_Utility.formatNumbers(this.mTargetY) + EnumChatFormatting.RESET,
+ "Z: " + EnumChatFormatting.GREEN + GT_Utility.formatNumbers(this.mTargetZ) + EnumChatFormatting.RESET,
+ "Dimension: " + EnumChatFormatting.GREEN + this.mTargetD + EnumChatFormatting.RESET,
+ "Dimension Valid: " + (GT_Utility.isRealDimension(this.mTargetD)
+ ? EnumChatFormatting.GREEN + "Yes" + EnumChatFormatting.RESET
+ : EnumChatFormatting.RED + "No" + EnumChatFormatting.RESET),
+ "Dimension Registered: " + (DimensionManager.isDimensionRegistered(this.mTargetD)
+ ? EnumChatFormatting.GREEN + "Yes" + EnumChatFormatting.RESET
+ : EnumChatFormatting.RED + "No" + EnumChatFormatting.RESET) };
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection aFacing,
+ int colorIndex, boolean aActive, boolean redstoneLevel) {
+ if (side == ForgeDirection.DOWN) return new ITexture[] { MACHINE_CASINGS[mTier][colorIndex + 1] };
+ if (aActive) return new ITexture[] { MACHINE_CASINGS[mTier][colorIndex + 1],
+ TextureFactory.of(OVERLAY_TELEPORTER_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_TELEPORTER_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ return new ITexture[] { MACHINE_CASINGS[mTier][colorIndex + 1], TextureFactory.of(OVERLAY_TELEPORTER),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_TELEPORTER_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ if (mFluid != null) aNBT.setTag("mFluid", mFluid.writeToNBT(new NBTTagCompound()));
+ aNBT.setInteger("mTargetX", this.mTargetX);
+ aNBT.setInteger("mTargetY", this.mTargetY);
+ aNBT.setInteger("mTargetZ", this.mTargetZ);
+ aNBT.setInteger("mTargetD", this.mTargetD);
+ aNBT.setBoolean("mDebug", this.mDebug);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ mFluid = FluidStack.loadFluidStackFromNBT(aNBT.getCompoundTag("mFluid"));
+ this.mTargetX = aNBT.getInteger("mTargetX");
+ this.mTargetY = aNBT.getInteger("mTargetY");
+ this.mTargetZ = aNBT.getInteger("mTargetZ");
+ this.mTargetD = aNBT.getInteger("mTargetD");
+ this.mDebug = aNBT.getBoolean("mDebug");
+ }
+
+ @Override
+ public void onConfigLoad(GT_Config aConfig) {
+ sInterDimensionalTeleportAllowed = aConfig
+ .get(ConfigCategories.machineconfig, "Teleporter.Interdimensional", true);
+ mMaxLoss = Math.max(aConfig.get(ConfigCategories.machineconfig, "MicrowaveTransmitter.MaxLoss", 50), 11);
+ mMaxLossDistance = aConfig.get(ConfigCategories.machineconfig, "MicrowaveTransmitter.MaxLossDistance", 10000);
+ mPassiveEnergyUse = aConfig.get(ConfigCategories.machineconfig, "MicrowaveTransmitter.PassiveEnergy", true);
+ }
+
+ @Override
+ public void onFirstTick(IGregTechTileEntity aBaseMetaTileEntity) {
+ if (aBaseMetaTileEntity.isServerSide()) {
+ if ((this.mTargetX == 0) && (this.mTargetY == 0) && (this.mTargetZ == 0) && (this.mTargetD == 0)) {
+ this.mTargetX = aBaseMetaTileEntity.getXCoord();
+ this.mTargetY = aBaseMetaTileEntity.getYCoord();
+ this.mTargetZ = aBaseMetaTileEntity.getZCoord();
+ this.mTargetD = aBaseMetaTileEntity.getWorld().provider.dimensionId;
+ }
+ this.hasBlock = checkForBlock();
+ }
+ }
+
+ public boolean checkForBlock() {
+ for (byte i = -5; i <= 5; i = (byte) (i + 1)) {
+ for (byte j = -5; j <= 5; j = (byte) (j + 1)) {
+ for (byte k = -5; k <= 5; k = (byte) (k + 1)) {
+ if (getBaseMetaTileEntity().getBlockOffset(i, j, k) == GregTech_API.sBlockMetal5
+ && getBaseMetaTileEntity().getMetaIDOffset(i, j, k) == 8) { // require osmiridium block
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ public boolean hasDimensionalTeleportCapability() {
+ return this.mDebug || (sInterDimensionalTeleportAllowed && (this.hasBlock
+ || mFluid != null && mFluid.isFluidEqual(Materials.Nitrogen.getPlasma(1)) && mFluid.amount >= 1000));
+ }
+
+ public boolean isDimensionalTeleportAvailable() {
+ return this.mDebug || (hasDimensionalTeleportCapability() && GT_Utility.isRealDimension(this.mTargetD)
+ && GT_Utility.isRealDimension(getBaseMetaTileEntity().getWorld().provider.dimensionId));
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ if (mFluid == null) {
+ mFluid = Materials.Nitrogen.getPlasma(0);
+ }
+ super.onPostTick(aBaseMetaTileEntity, aTick);
+ if (getBaseMetaTileEntity().isServerSide()) {
+ if (getBaseMetaTileEntity().getTimer() % 100L == 50L) {
+ this.hasBlock = checkForBlock();
+ }
+ if ((getBaseMetaTileEntity().isAllowedToWork()) && (getBaseMetaTileEntity().getRedstone())) {
+ if (getBaseMetaTileEntity().getStoredEU() > (V[mTier] * 16)) {
+ if (mPassiveEnergyUse) {
+ getBaseMetaTileEntity().decreaseStoredEnergyUnits(2L << (mTier - 1), false);
+ }
+ if (hasDimensionalTeleportCapability()
+ && this.mTargetD != getBaseMetaTileEntity().getWorld().provider.dimensionId
+ && mFluid.isFluidEqual(Materials.Nitrogen.getPlasma(1))) {
+ mFluid.amount--;
+ if (mFluid.amount < 1) {
+ mFluid = null;
+ }
+ }
+ if (tTargetD != mTargetD || tTargetX != mTargetX || tTargetY != mTargetY || tTargetZ != mTargetZ) {
+ tTargetD = mTargetD;
+ tTargetX = mTargetX;
+ tTargetY = mTargetY;
+ tTargetZ = mTargetZ;
+ if (this.mTargetD == getBaseMetaTileEntity().getWorld().provider.dimensionId) {
+ tTile = getBaseMetaTileEntity().getTileEntity(this.mTargetX, this.mTargetY, this.mTargetZ);
+ } else {
+ World tWorld = DimensionManager.getWorld(this.mTargetD);
+ if (tWorld != null) {
+ tTile = tWorld.getTileEntity(this.mTargetX, this.mTargetY, this.mTargetZ);
+ }
+ }
+ }
+ int tDistance = distanceCalculation();
+ if (tTile != null) {
+ if (tTile instanceof IEnergyConnected) {
+ long packetSize = V[mTier];
+ if (tTile instanceof IGregTechTileEntity) {
+ IMetaTileEntity mte = ((IGregTechTileEntity) tTile).getMetaTileEntity();
+ if (mte instanceof BaseMetaTileEntity) {
+ packetSize = ((BaseMetaTileEntity) mte).getMaxSafeInput();
+ }
+ }
+ long energyUse = 10;
+ if (mMaxLossDistance != 0) {
+ energyUse = GT_Utility
+ .safeInt(10L + (tDistance * Math.max(mMaxLoss - 10L, 0) / mMaxLossDistance));
+ }
+ energyUse = packetSize + ((V[mTier] * energyUse) / 100);
+ if (getBaseMetaTileEntity().isUniversalEnergyStored(energyUse)) {
+ if (((IEnergyConnected) tTile).injectEnergyUnits(ForgeDirection.UNKNOWN, packetSize, 1)
+ > 0) {
+ getBaseMetaTileEntity().decreaseStoredEnergyUnits(energyUse, false);
+ }
+ }
+ }
+ }
+ }
+ getBaseMetaTileEntity().setActive(true);
+ } else {
+ getBaseMetaTileEntity().setActive(false);
+ }
+ }
+ }
+
+ private int distanceCalculation() {
+ return Math.abs(
+ ((this.mTargetD != getBaseMetaTileEntity().getWorld().provider.dimensionId)
+ && (isDimensionalTeleportAvailable()) ? 100 : 1)
+ * (int) Math.sqrt(
+ Math.pow(getBaseMetaTileEntity().getXCoord() - this.mTargetX, 2.0D)
+ + Math.pow(getBaseMetaTileEntity().getYCoord() - this.mTargetY, 2.0D)
+ + Math.pow(getBaseMetaTileEntity().getZCoord() - this.mTargetZ, 2.0D)));
+ }
+
+ @Override
+ public boolean isSimpleMachine() {
+ return false;
+ }
+
+ @Override
+ public boolean isOverclockerUpgradable() {
+ return false;
+ }
+
+ @Override
+ public boolean isTransformerUpgradable() {
+ return false;
+ }
+
+ @Override
+ public boolean isElectric() {
+ return true;
+ }
+
+ @Override
+ public boolean isFacingValid(ForgeDirection facing) {
+ return true;
+ }
+
+ @Override
+ public boolean isEnetInput() {
+ return true;
+ }
+
+ @Override
+ public boolean isInputFacing(ForgeDirection side) {
+ return true;
+ }
+
+ @Override
+ public boolean isOutputFacing(ForgeDirection side) {
+ return false;
+ }
+
+ @Override
+ public boolean isTeleporterCompatible() {
+ return false;
+ }
+
+ @Override
+ public long getMinimumStoredEU() {
+ return V[mTier] * 16;
+ }
+
+ @Override
+ public long maxEUStore() {
+ return V[mTier] * 256;
+ }
+
+ @Override
+ public long maxEUInput() {
+ return V[mTier];
+ }
+
+ @Override
+ public long maxSteamStore() {
+ return maxEUStore();
+ }
+
+ @Override
+ public long maxAmperesIn() {
+ return 3;
+ }
+
+ @Override
+ public int getStackDisplaySlot() {
+ return 2;
+ }
+
+ @Override
+ public boolean isAccessAllowed(EntityPlayer aPlayer) {
+ return true;
+ }
+
+ @Override
+ public int getInputSlot() {
+ return 0;
+ }
+
+ @Override
+ public int getOutputSlot() {
+ return 0;
+ }
+
+ @Override
+ public int getCapacity() {
+ return 64000;
+ }
+
+ @Override
+ public boolean doesFillContainers() {
+ return false;
+ }
+
+ @Override
+ public boolean doesEmptyContainers() {
+ return false;
+ }
+
+ @Override
+ public boolean canTankBeFilled() {
+ return true;
+ }
+
+ @Override
+ public boolean canTankBeEmptied() {
+ return true;
+ }
+
+ @Override
+ public boolean displaysItemStack() {
+ return false;
+ }
+
+ @Override
+ public boolean displaysStackSize() {
+ return false;
+ }
+
+ @Override
+ public ITexture[][][] getTextureSet(ITexture[] aTextures) {
+ return null;
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ protected static final NumberFormatMUI numberFormat = new NumberFormatMUI();
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ builder.widget(
+ new DrawableWidget().setDrawable(GT_UITextures.PICTURE_SCREEN_BLACK)
+ .setSize(90, 72)
+ .setPos(43, 4))
+ .widget(
+ new TextWidget().setStringSupplier(() -> "X: " + numberFormat.format(mTargetX))
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setPos(46, 8))
+ .widget(
+ new TextWidget().setStringSupplier(() -> "Y: " + numberFormat.format(mTargetY))
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setPos(46, 16))
+ .widget(
+ new TextWidget().setStringSupplier(() -> "Z: " + numberFormat.format(mTargetZ))
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setPos(46, 24))
+ .widget(
+ new TextWidget().setStringSupplier(() -> "Dim: " + numberFormat.format(mTargetD))
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setPos(46, 32))
+ .widget(
+ TextWidget.dynamicString(() -> "Dim Valid: " + (GT_Utility.isRealDimension(mTargetD) ? "Yes" : "No"))
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setEnabled(widget -> hasDimensionalTeleportCapability())
+ .setPos(46, 40))
+ .widget(new FakeSyncWidget.FluidStackSyncer(() -> mFluid, val -> mFluid = val));
+
+ addChangeNumberButtons(builder, GT_UITextures.OVERLAY_BUTTON_MINUS_LARGE, -512, -64, 7);
+ addChangeNumberButtons(builder, GT_UITextures.OVERLAY_BUTTON_MINUS_SMALL, -16, -1, 25);
+ addChangeNumberButtons(builder, GT_UITextures.OVERLAY_BUTTON_PLUS_SMALL, 16, 1, 133);
+ addChangeNumberButtons(builder, GT_UITextures.OVERLAY_BUTTON_PLUS_LARGE, 512, 64, 151);
+
+ addChangeNumberButton(
+ builder,
+ GT_UITextures.OVERLAY_BUTTON_MINUS_LARGE,
+ val -> mTargetD += val,
+ -16,
+ -8,
+ 7,
+ 58);
+ addChangeNumberButton(
+ builder,
+ GT_UITextures.OVERLAY_BUTTON_MINUS_SMALL,
+ val -> mTargetD += val,
+ -4,
+ -1,
+ 25,
+ 58);
+ addChangeNumberButton(builder, GT_UITextures.OVERLAY_BUTTON_PLUS_SMALL, val -> mTargetD += val, 4, 1, 133, 58);
+ addChangeNumberButton(builder, GT_UITextures.OVERLAY_BUTTON_PLUS_LARGE, val -> mTargetD += val, 16, 8, 151, 58);
+ }
+
+ private void addChangeNumberButtons(ModularWindow.Builder builder, IDrawable overlay, int addNumberShift,
+ int addNumber, int xPos) {
+ addChangeNumberButton(builder, overlay, val -> mTargetX += val, addNumberShift, addNumber, xPos, 4);
+ addChangeNumberButton(builder, overlay, val -> mTargetY += val, addNumberShift, addNumber, xPos, 22);
+ addChangeNumberButton(builder, overlay, val -> mTargetZ += val, addNumberShift, addNumber, xPos, 40);
+ }
+
+ private void addChangeNumberButton(ModularWindow.Builder builder, IDrawable overlay, Consumer<Integer> setter,
+ int addNumberShift, int addNumber, int xPos, int yPos) {
+ builder.widget(
+ new ButtonWidget()
+ .setOnClick((clickData, widget) -> setter.accept(clickData.shift ? addNumberShift : addNumber))
+ .setBackground(GT_UITextures.BUTTON_STANDARD, overlay)
+ .setSize(18, 18)
+ .setPos(xPos, yPos));
+ }
+
+ @Override
+ public GUITextureSet getGUITextureSet() {
+ return new GUITextureSet().setGregTechLogo(GT_UITextures.PICTURE_GT_LOGO_17x17_TRANSPARENT_GRAY);
+ }
+
+ @Override
+ public void addGregTechLogo(ModularWindow.Builder builder) {
+ builder.widget(
+ new DrawableWidget().setDrawable(getGUITextureSet().getGregTechLogo())
+ .setSize(17, 17)
+ .setPos(113, 56));
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Miner.java b/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Miner.java
new file mode 100644
index 0000000000..2acaea8050
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Miner.java
@@ -0,0 +1,412 @@
+package gregtech.common.tileentities.machines.basic;
+
+import static gregtech.api.enums.GT_Values.V;
+import static gregtech.api.enums.GT_Values.debugBlockMiner;
+
+import java.util.ArrayList;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.Item;
+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.ChunkPosition;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.gtnewhorizons.modularui.api.drawable.FallbackableUITexture;
+
+import gregtech.api.enums.Textures;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.modularui.IAddUIWidgets;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachine;
+import gregtech.api.recipe.BasicUIProperties;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Log;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.blocks.GT_Block_Ores_Abstract;
+import gregtech.common.blocks.GT_TileEntity_Ores;
+import gregtech.common.misc.GT_DrillingLogicDelegate;
+import gregtech.common.misc.GT_IDrillingLogicDelegateOwner;
+
+public class GT_MetaTileEntity_Miner extends GT_MetaTileEntity_BasicMachine
+ implements GT_IDrillingLogicDelegateOwner, IAddUIWidgets {
+
+ static final int[] RADIUS = { 8, 8, 16, 24, 32 }; // Miner radius per tier
+ static final int[] SPEED = { 160, 160, 80, 40, 20 }; // Miner cycle time per tier
+ static final int[] ENERGY = { 8, 8, 32, 128, 512 }; // Miner energy consumption per tier
+
+ /** Miner configured radius */
+ private int radiusConfig;
+ /** Found ore blocks cache of current drill depth */
+ private final ArrayList<ChunkPosition> oreBlockPositions = new ArrayList<>();
+
+ /** General pipe accessor */
+ private final GT_DrillingLogicDelegate pipe = new GT_DrillingLogicDelegate(this);
+
+ private final int mSpeed;
+
+ public GT_MetaTileEntity_Miner(int aID, String aName, String aNameRegional, int aTier) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ 1,
+ new String[] { "Digging ore instead of you", "Use Screwdriver to regulate work area",
+ "Use Soft Mallet to disable and retract the pipe",
+ String.format("%d EU/t, %d sec per block, no stuttering", ENERGY[aTier], SPEED[aTier] / 20),
+ String.format("Maximum work area %dx%d", (RADIUS[aTier] * 2 + 1), (RADIUS[aTier] * 2 + 1)),
+ String.format("Fortune bonus of %d", aTier) },
+ 2,
+ 2,
+ TextureFactory.of(
+ TextureFactory.of(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_SIDE_ACTIVE")),
+ TextureFactory.builder()
+ .addIcon(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_SIDE_ACTIVE_GLOW"))
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_SIDE")),
+ TextureFactory.builder()
+ .addIcon(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_SIDE_GLOW"))
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_FRONT_ACTIVE")),
+ TextureFactory.builder()
+ .addIcon(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_FRONT_ACTIVE_GLOW"))
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_FRONT")),
+ TextureFactory.builder()
+ .addIcon(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_FRONT_GLOW"))
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_TOP_ACTIVE")),
+ TextureFactory.builder()
+ .addIcon(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_TOP_ACTIVE_GLOW"))
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_TOP")),
+ TextureFactory.builder()
+ .addIcon(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_TOP_GLOW"))
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_BOTTOM_ACTIVE")),
+ TextureFactory.builder()
+ .addIcon(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_BOTTOM_ACTIVE_GLOW"))
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_BOTTOM")),
+ TextureFactory.builder()
+ .addIcon(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_BOTTOM_GLOW"))
+ .glow()
+ .build()));
+ mSpeed = SPEED[aTier];
+ radiusConfig = RADIUS[mTier];
+ }
+
+ public GT_MetaTileEntity_Miner(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, 1, aDescription, aTextures, 2, 2);
+ mSpeed = SPEED[aTier];
+ radiusConfig = RADIUS[mTier];
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Miner(mName, mTier, mDescriptionArray, mTextures);
+ }
+
+ @Override
+ public void onFirstTick(IGregTechTileEntity aBaseMetaTileEntity) {
+ pipe.findTipDepth();
+ fillOreList(aBaseMetaTileEntity);
+ }
+
+ @Override
+ protected boolean allowPutStackValidated(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return super.allowPutStackValidated(aBaseMetaTileEntity, aIndex, side, aStack) //
+ && aStack.getItem() == GT_DrillingLogicDelegate.MINING_PIPE_STACK.getItem();
+ }
+
+ /** Both output slots must be free to work */
+ public boolean hasFreeSpace() {
+ for (int i = getOutputSlot(); i < getOutputSlot() + 2; i++) {
+ if (mInventory[i] != null) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ super.onScrewdriverRightClick(side, aPlayer, aX, aY, aZ);
+ if (side != getBaseMetaTileEntity().getFrontFacing() && side != mMainFacing) {
+ if (aPlayer.isSneaking()) {
+ if (radiusConfig >= 0) {
+ radiusConfig--;
+ }
+ if (radiusConfig < 0) {
+ radiusConfig = RADIUS[mTier];
+ }
+ } else {
+ if (radiusConfig <= RADIUS[mTier]) {
+ radiusConfig++;
+ }
+ if (radiusConfig > RADIUS[mTier]) {
+ radiusConfig = 0;
+ }
+ }
+
+ GT_Utility.sendChatToPlayer(
+ aPlayer,
+ String.format(
+ "%s %dx%d",
+ StatCollector.translateToLocal("GT5U.machines.workareaset"),
+ (radiusConfig * 2 + 1),
+ (radiusConfig * 2 + 1)));
+
+ // Rebuild ore cache after change config
+ fillOreList(getBaseMetaTileEntity());
+ }
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ super.onPostTick(aBaseMetaTileEntity, aTick);
+
+ if (!aBaseMetaTileEntity.isServerSide()) {
+ return;
+ }
+
+ // Pipe workaround
+ pipe.onOwnerPostTick(aBaseMetaTileEntity, aTick);
+
+ if (!aBaseMetaTileEntity.isAllowedToWork()) {
+ mMaxProgresstime = 0;
+ if (debugBlockMiner) {
+ GT_Log.out.println("MINER: Disabled");
+ }
+ return;
+ }
+
+ if (!hasFreeSpace()) {
+ mMaxProgresstime = 0;
+ if (debugBlockMiner) {
+ GT_Log.out.println("MINER: No free space");
+ }
+ return;
+ }
+
+ if (!aBaseMetaTileEntity.isUniversalEnergyStored((long) ENERGY[mTier] * (mSpeed - mProgresstime))) {
+ mMaxProgresstime = 0;
+ if (debugBlockMiner) {
+ GT_Log.out.println(
+ "MINER: Not enough energy yet, want " + (ENERGY[mTier] * mSpeed)
+ + " have "
+ + aBaseMetaTileEntity.getUniversalEnergyStored());
+ }
+ return;
+ }
+
+ /* Checks if machine are waiting new mining pipe item */
+ if (!pipe.canContinueDrilling(aTick)) {
+ mMaxProgresstime = 0;
+ return;
+ }
+
+ mMaxProgresstime = mSpeed;
+
+ aBaseMetaTileEntity.decreaseStoredEnergyUnits(ENERGY[mTier], true);
+
+ // Real working only when progress done. TODO some legacy code... refactorings needed
+ if (mProgresstime == mSpeed - 1) {
+ if (pipe.getTipDepth() == 0 || oreBlockPositions.isEmpty()) {
+ boolean descends = pipe.descent(aBaseMetaTileEntity);
+ if (descends) {
+ fillOreList(aBaseMetaTileEntity);
+ }
+ } else {
+ int x;
+ int y;
+ int z;
+ Block oreBlock;
+ boolean isOre;
+ do {
+ ChunkPosition oreBlockPos = oreBlockPositions.remove(0);
+ oreBlock = aBaseMetaTileEntity
+ .getBlockOffset(oreBlockPos.chunkPosX, oreBlockPos.chunkPosY, oreBlockPos.chunkPosZ);
+ x = aBaseMetaTileEntity.getXCoord() + oreBlockPos.chunkPosX;
+ y = aBaseMetaTileEntity.getYCoord() + oreBlockPos.chunkPosY;
+ z = aBaseMetaTileEntity.getZCoord() + oreBlockPos.chunkPosZ;
+ isOre = GT_Utility.isOre(
+ oreBlock,
+ aBaseMetaTileEntity.getWorld()
+ .getBlockMetadata(x, y, z));
+ } // someone else might have removed the block
+ while (!isOre && !oreBlockPositions.isEmpty());
+
+ if (isOre) {
+ pipe.mineBlock(aBaseMetaTileEntity, oreBlock, x, y, z);
+ }
+ }
+ }
+ }
+
+ /** Finds the ores in current drill Y level */
+ private void fillOreList(IGregTechTileEntity aBaseMetaTileEntity) {
+ if (pipe.getTipDepth() == 0) {
+ return;
+ }
+ oreBlockPositions.clear();
+ for (int z = -radiusConfig; z <= radiusConfig; ++z) {
+ for (int x = -radiusConfig; x <= radiusConfig; ++x) {
+ Block block = aBaseMetaTileEntity.getBlockOffset(x, pipe.getTipDepth(), z);
+ int blockMeta = aBaseMetaTileEntity.getMetaIDOffset(x, pipe.getTipDepth(), z);
+
+ // todo some weird checks. refactorings needed
+ if (block instanceof GT_Block_Ores_Abstract) {
+ TileEntity oreEntity = aBaseMetaTileEntity.getTileEntityOffset(x, pipe.getTipDepth(), z);
+ if (oreEntity instanceof GT_TileEntity_Ores && ((GT_TileEntity_Ores) oreEntity).mNatural) {
+ oreBlockPositions.add(new ChunkPosition(x, pipe.getTipDepth(), z));
+ }
+ } else if (GT_Utility.isOre(block, blockMeta)) {
+ oreBlockPositions.add(new ChunkPosition(x, pipe.getTipDepth(), z));
+ }
+ }
+ }
+ }
+
+ /** Pulls (or check can pull) items from an input slots. */
+ @Override
+ public boolean pullInputs(Item item, int count, boolean simulate) {
+ for (int i = 0; i < mInputSlotCount; i++) {
+ ItemStack stack = getInputAt(i);
+ if (stack != null && stack.getItem() == item && stack.stackSize >= count) {
+ if (simulate) {
+ return true;
+ }
+ stack.stackSize -= count;
+ if (stack.stackSize == 0) {
+ mInventory[getInputSlot() + i] = null;
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /** Pushes (or check can push) item to output slots. */
+ @Override
+ public boolean pushOutputs(ItemStack stack, int count, boolean simulate, boolean allowInputSlots) {
+ return allowInputSlots && pushOutput(getInputSlot(), getInputSlot() + mInputSlotCount, stack, count, simulate)
+ || pushOutput(getOutputSlot(), getOutputSlot() + mOutputItems.length, stack, count, simulate);
+ }
+
+ private boolean pushOutput(int startIndex, int endIndex, ItemStack stack, int count, boolean simulate) {
+ for (int i = startIndex; i < endIndex; i++) {
+ ItemStack slot = mInventory[i];
+ if (slot == null || slot.stackSize == 0) {
+ if (!simulate) {
+ ItemStack copy = stack.copy();
+ copy.stackSize = count;
+ mInventory[i] = copy;
+ }
+ return true;
+ } else if (GT_Utility.areStacksEqual(slot, stack) && slot.stackSize <= slot.getMaxStackSize() - count) {
+ if (!simulate) {
+ slot.stackSize += count;
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public long maxEUStore() {
+ return Math.max(V[mTier] * 64, 4096);
+ }
+
+ @Override
+ public void setItemNBT(NBTTagCompound aNBT) {
+ super.setItemNBT(aNBT);
+ aNBT.setInteger("radiusConfig", radiusConfig);
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ aNBT.setInteger("radiusConfig", radiusConfig);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ if (aNBT.hasKey("radiusConfig")) {
+ int newRadius = aNBT.getInteger("radiusConfig");
+ if (RADIUS[mTier] <= newRadius && newRadius > 0) {
+ radiusConfig = newRadius;
+ }
+ }
+ }
+
+ @Override
+ public String[] getInfoData() {
+ return new String[] {
+ String.format(
+ "%s%s%s",
+ EnumChatFormatting.BLUE,
+ StatCollector.translateToLocal("GT5U.machines.miner"),
+ EnumChatFormatting.RESET),
+ String.format(
+ "%s: %s%d%s %s",
+ StatCollector.translateToLocal("GT5U.machines.workarea"),
+ EnumChatFormatting.GREEN,
+ (radiusConfig * 2 + 1),
+ EnumChatFormatting.RESET,
+ StatCollector.translateToLocal("GT5U.machines.blocks")) };
+ }
+
+ @Override
+ public int getMachineTier() {
+ return mTier;
+ }
+
+ @Override
+ public int getMachineSpeed() {
+ return mSpeed;
+ }
+
+ public GT_DrillingLogicDelegate getPipe() {
+ return pipe;
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ private static final FallbackableUITexture progressBarTexture = GT_UITextures
+ .fallbackableProgressbar("miner", GT_UITextures.PROGRESSBAR_CANNER);
+
+ @Override
+ protected BasicUIProperties getUIProperties() {
+ return super.getUIProperties().toBuilder()
+ .progressBarTexture(progressBarTexture)
+ .build();
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_MonsterRepellent.java b/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_MonsterRepellent.java
new file mode 100644
index 0000000000..fde78cfa2e
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_MonsterRepellent.java
@@ -0,0 +1,182 @@
+package gregtech.common.tileentities.machines.basic;
+
+import static gregtech.api.enums.GT_Values.V;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASINGS;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TELEPORTER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TELEPORTER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TELEPORTER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TELEPORTER_GLOW;
+
+import java.util.Arrays;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_TieredMachineBlock;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_SpawnEventHandler;
+
+public class GT_MetaTileEntity_MonsterRepellent extends GT_MetaTileEntity_TieredMachineBlock {
+
+ public int mRange = 16;
+
+ public GT_MetaTileEntity_MonsterRepellent(int aID, String aName, String aNameRegional, int aTier) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ 0,
+ "Repels nasty Creatures. Range: " + (4 + (12 * aTier))
+ + " unpowered / "
+ + (16 + (48 * aTier))
+ + " powered. Costs "
+ + (1L << (aTier * 2))
+ + " EU/t");
+ }
+
+ public GT_MetaTileEntity_MonsterRepellent(String aName, int aTier, int aInvSlotCount, String aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aInvSlotCount, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_MonsterRepellent(String aName, int aTier, int aInvSlotCount, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aInvSlotCount, aDescription, aTextures);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_MonsterRepellent(
+ this.mName,
+ this.mTier,
+ this.mInventory.length,
+ this.mDescriptionArray,
+ this.mTextures);
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity baseMetaTileEntity, ForgeDirection sideDirection,
+ ForgeDirection facingDirection, int colorIndex, boolean active, boolean redstoneLevel) {
+ if (sideDirection != ForgeDirection.UP) return new ITexture[] { MACHINE_CASINGS[mTier][colorIndex + 1] };
+ if (active) return new ITexture[] { MACHINE_CASINGS[mTier][colorIndex + 1],
+ TextureFactory.of(OVERLAY_TELEPORTER_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_TELEPORTER_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ return new ITexture[] { MACHINE_CASINGS[mTier][colorIndex + 1], TextureFactory.of(OVERLAY_TELEPORTER),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_TELEPORTER_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTimer) {
+ if (aBaseMetaTileEntity.isAllowedToWork() && aBaseMetaTileEntity.isServerSide()) {
+ int[] tCoords = { aBaseMetaTileEntity.getXCoord(), aBaseMetaTileEntity.getYCoord(),
+ aBaseMetaTileEntity.getZCoord(), aBaseMetaTileEntity.getWorld().provider.dimensionId };
+ if ((aTimer % 600 == 0) && !GT_SpawnEventHandler.mobReps.contains(tCoords)) {
+ GT_SpawnEventHandler.mobReps.add(tCoords);
+ }
+ if (aBaseMetaTileEntity.isUniversalEnergyStored(getMinimumStoredEU())
+ && aBaseMetaTileEntity.decreaseStoredEnergyUnits(1L << (this.mTier * 2), false)) {
+ mRange = GT_SpawnEventHandler.getPoweredRepellentRange(mTier);
+ } else {
+ mRange = GT_SpawnEventHandler.getUnpoweredRepellentRange(mTier);
+ }
+ }
+ }
+
+ @Override
+ public void onFirstTick(IGregTechTileEntity aBaseMetaTileEntity) {
+ int[] tCoords = { aBaseMetaTileEntity.getXCoord(), aBaseMetaTileEntity.getYCoord(),
+ aBaseMetaTileEntity.getZCoord(), aBaseMetaTileEntity.getWorld().provider.dimensionId };
+ GT_SpawnEventHandler.mobReps.add(tCoords);
+ }
+
+ @Override
+ public void onRemoval() {
+ int[] tCoords = { this.getBaseMetaTileEntity()
+ .getXCoord(),
+ this.getBaseMetaTileEntity()
+ .getYCoord(),
+ this.getBaseMetaTileEntity()
+ .getZCoord(),
+ this.getBaseMetaTileEntity()
+ .getWorld().provider.dimensionId };
+ GT_SpawnEventHandler.mobReps.removeIf(coords -> Arrays.equals(coords, tCoords));
+ }
+
+ @Override
+ public boolean isSimpleMachine() {
+ return false;
+ }
+
+ @Override
+ public boolean isFacingValid(ForgeDirection facing) {
+ return true;
+ }
+
+ @Override
+ public boolean isEnetInput() {
+ return true;
+ }
+
+ @Override
+ public boolean isInputFacing(ForgeDirection side) {
+ return true;
+ }
+
+ @Override
+ public boolean isTeleporterCompatible() {
+ return false;
+ }
+
+ @Override
+ public long getMinimumStoredEU() {
+ return 512L;
+ }
+
+ @Override
+ public long maxEUStore() {
+ return 512L + V[mTier] * 50;
+ }
+
+ @Override
+ public long maxEUInput() {
+ return V[mTier];
+ }
+
+ @Override
+ public long maxAmperesIn() {
+ return 2;
+ }
+
+ @Override
+ public boolean allowPullStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public boolean allowPutStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public ITexture[][][] getTextureSet(ITexture[] aTextures) {
+ return null;
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {}
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {}
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_PotionBrewer.java b/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_PotionBrewer.java
new file mode 100644
index 0000000000..15150abf67
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_PotionBrewer.java
@@ -0,0 +1,235 @@
+package gregtech.common.tileentities.machines.basic;
+
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_POTIONBREWER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_POTIONBREWER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_POTIONBREWER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_POTIONBREWER_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_POTIONBREWER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_POTIONBREWER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_POTIONBREWER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_POTIONBREWER_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_POTIONBREWER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_POTIONBREWER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_POTIONBREWER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_POTIONBREWER_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_POTIONBREWER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_POTIONBREWER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_POTIONBREWER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_POTIONBREWER_GLOW;
+
+import net.minecraft.init.Items;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidRegistry;
+import net.minecraftforge.fluids.FluidStack;
+
+import gregtech.api.enums.MachineType;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachine;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_OreDictUnificator;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_PotionBrewer extends GT_MetaTileEntity_BasicMachine {
+
+ public GT_MetaTileEntity_PotionBrewer(int aID, String aName, String aNameRegional, int aTier) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ 1,
+ MachineType.BREWERY.tooltipDescription(),
+ 1,
+ 0,
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_SIDE_POTIONBREWER_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_POTIONBREWER_ACTIVE_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_SIDE_POTIONBREWER),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_POTIONBREWER_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_FRONT_POTIONBREWER_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_POTIONBREWER_ACTIVE_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_FRONT_POTIONBREWER),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_POTIONBREWER_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_TOP_POTIONBREWER_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_POTIONBREWER_ACTIVE_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_TOP_POTIONBREWER),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_POTIONBREWER_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_BOTTOM_POTIONBREWER_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_POTIONBREWER_ACTIVE_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_BOTTOM_POTIONBREWER),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_POTIONBREWER_GLOW)
+ .glow()
+ .build()));
+ }
+
+ public GT_MetaTileEntity_PotionBrewer(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, 1, aDescription, aTextures, 1, 0);
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_PotionBrewer(this.mName, this.mTier, this.mDescriptionArray, this.mTextures);
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.brewingRecipes;
+ }
+
+ @Override
+ public int checkRecipe() {
+ int tCheck = super.checkRecipe();
+ if (tCheck != DID_NOT_FIND_RECIPE) {
+ return tCheck;
+ }
+
+ calculateOverclockedNess(4, 128);
+ // In case recipe is too OP for that machine
+ if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1)
+ return FOUND_RECIPE_BUT_DID_NOT_MEET_REQUIREMENTS;
+
+ FluidStack aFluid = getFillableStack();
+ if ((getDrainableStack() == null) && (aFluid != null) && (getInputAt(0) != null)) {
+ String tInputName = aFluid.getFluid()
+ .getName();
+ if (tInputName.startsWith("potion.")) {
+ tInputName = tInputName.replaceFirst("potion.", "");
+ int tFirstDot = tInputName.indexOf('.') + 1;
+ String tModifier = tFirstDot <= 0 ? "" : tInputName.substring(tFirstDot);
+ if (!tModifier.isEmpty()) {
+ tInputName = tInputName.replaceFirst("." + tModifier, "");
+ }
+ if (GT_Utility.areStacksEqual(new ItemStack(Items.fermented_spider_eye, 1, 0), getInputAt(0))) {
+ if (tInputName.equals("poison")) {
+ return setOutput("potion.damage" + tModifier);
+ }
+ if (tInputName.equals("health")) {
+ return setOutput("potion.damage" + tModifier);
+ }
+ if (tInputName.equals("waterbreathing")) {
+ return setOutput("potion.damage" + tModifier);
+ }
+ if (tInputName.equals("nightvision")) {
+ return setOutput("potion.invisibility" + tModifier);
+ }
+ if (tInputName.equals("fireresistance")) {
+ return setOutput("potion.slowness" + tModifier);
+ }
+ if (tInputName.equals("speed")) {
+ return setOutput("potion.slowness" + tModifier);
+ }
+ if (tInputName.equals("strength")) {
+ return setOutput("potion.weakness" + tModifier);
+ }
+ if (tInputName.equals("regen")) {
+ return setOutput("potion.poison" + tModifier);
+ }
+ return setOutput("potion.weakness");
+ }
+ if (GT_Utility.areStacksEqual(
+ GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Glowstone, 1L),
+ getInputAt(0))) {
+ if (!tModifier.startsWith("strong")) {
+ return setOutput(
+ "potion." + tInputName + ".strong" + (tModifier.isEmpty() ? "" : "." + tModifier));
+ }
+ if (tModifier.startsWith("long")) {
+ return setOutput("potion." + tInputName + tModifier.replaceFirst("long", ""));
+ }
+ return setOutput("potion.thick");
+ }
+ if (GT_Utility.areStacksEqual(
+ GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Redstone, 1L),
+ getInputAt(0))) {
+ if (!tModifier.startsWith("long")) {
+ return setOutput(
+ "potion." + tInputName + ".long" + (tModifier.isEmpty() ? "" : "." + tModifier));
+ }
+ if (tModifier.startsWith("strong")) {
+ return setOutput("potion." + tInputName + tModifier.replaceFirst("strong", ""));
+ }
+ return setOutput("potion.mundane");
+ }
+ if (GT_Utility.areStacksEqual(
+ GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Gunpowder, 1L),
+ getInputAt(0))) {
+ if (!tInputName.endsWith(".splash")) {
+ return setOutput("potion." + tInputName + ".splash");
+ }
+ return setOutput("potion.mundane");
+ }
+ }
+ }
+ return 0;
+ }
+
+ private int setOutput(String aFluidName) {
+ if (getFillableStack().amount < 750) {
+ return 0;
+ }
+
+ this.mOutputFluid = FluidRegistry.getFluidStack(aFluidName, 750);
+ if (this.mOutputFluid == null) {
+ this.mOutputFluid = FluidRegistry.getFluidStack("potion.mundane", getFillableStack().amount);
+ }
+
+ getInputAt(0).stackSize -= 1;
+ getFillableStack().amount -= 750;
+ return 2;
+ }
+
+ @Override
+ public boolean allowPutStackValidated(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return super.allowPutStackValidated(aBaseMetaTileEntity, aIndex, side, aStack)
+ && getRecipeMap().containsInput(aStack);
+ }
+
+ @Override
+ public boolean isFluidInputAllowed(FluidStack aFluid) {
+ return (aFluid.getFluid()
+ .getName()
+ .startsWith("potion.")) || (super.isFluidInputAllowed(aFluid));
+ }
+
+ @Override
+ public int getCapacity() {
+ return getCapacityForTier(mTier);
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Pump.java b/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Pump.java
new file mode 100644
index 0000000000..8cac0c3df7
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Pump.java
@@ -0,0 +1,851 @@
+package gregtech.common.tileentities.machines.basic;
+
+import static gregtech.api.enums.GT_Values.debugBlockPump;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.StatCollector;
+import net.minecraft.world.ChunkPosition;
+import net.minecraftforge.common.util.FakePlayer;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.IFluidBlock;
+
+import com.gtnewhorizons.modularui.api.drawable.FallbackableUITexture;
+
+import gregtech.api.enums.Textures;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.BaseTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachine;
+import gregtech.api.recipe.BasicUIProperties;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Log;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.misc.GT_DrillingLogicDelegate;
+
+public class GT_MetaTileEntity_Pump extends GT_MetaTileEntity_BasicMachine {
+
+ private static final ItemStack MINING_PIPE = GT_ModHandler.getIC2Item("miningPipe", 0);
+
+ private static final ItemStack MINING_PIPE_ONE = GT_ModHandler.getIC2Item("miningPipe", 1);
+ private static final Block MINING_PIPE_BLOCK = GT_Utility.getBlockFromStack(MINING_PIPE);
+ private static final Block MINING_PIPE_TIP_BLOCK = GT_Utility
+ .getBlockFromStack(GT_ModHandler.getIC2Item("miningPipeTip", 0));
+
+ public static int getMaxDistanceForTier(int aTier) {
+ return (10 * ((int) Math.pow(1.6D, aTier)));
+ }
+
+ public static long getEuUsagePerTier(int aTier) {
+ return (16 * ((long) Math.pow(4, aTier)));
+ }
+
+ public ArrayDeque<ChunkPosition> mPumpList = new ArrayDeque<>();
+ public boolean wasPumping = false;
+ public int mPumpTimer = 0;
+ public int mPumpCountBelow = 0;
+ public Block mPrimaryPumpedBlock = null;
+ public Block mSecondaryPumpedBlock = null;
+
+ private int radiusConfig; // Pump configured radius
+ private boolean mRetractDone = false;
+
+ private boolean mDisallowRetract = true;
+
+ public GT_MetaTileEntity_Pump(int aID, String aName, String aNameRegional, int aTier) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ 1,
+ new String[] { "The best way to empty Oceans!",
+ getEuUsagePerTier(aTier) + " EU/operation, "
+ + GT_Utility.safeInt(160 / 20 / (long) Math.pow(2, aTier))
+ + " sec per bucket, no stuttering",
+ "Maximum pumping area: " + (getMaxDistanceForTier(aTier) * 2 + 1)
+ + "x"
+ + (getMaxDistanceForTier(aTier) * 2 + 1),
+ "Use Screwdriver to regulate pumping area", "Use Soft Mallet to disable and retract the pipe",
+ "Disable the bottom pump to retract the pipe!",
+ "Use Soldering Iron to auto retract the pipe when hitting a rock", },
+ 2,
+ 2,
+ TextureFactory.of(
+ TextureFactory.of(new Textures.BlockIcons.CustomIcon("basicmachines/pump/OVERLAY_SIDE_ACTIVE")),
+ TextureFactory.builder()
+ .addIcon(new Textures.BlockIcons.CustomIcon("basicmachines/pump/OVERLAY_SIDE_ACTIVE_GLOW"))
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(new Textures.BlockIcons.CustomIcon("basicmachines/pump/OVERLAY_SIDE")),
+ TextureFactory.builder()
+ .addIcon(new Textures.BlockIcons.CustomIcon("basicmachines/pump/OVERLAY_SIDE_GLOW"))
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(new Textures.BlockIcons.CustomIcon("basicmachines/pump/OVERLAY_FRONT_ACTIVE")),
+ TextureFactory.builder()
+ .addIcon(new Textures.BlockIcons.CustomIcon("basicmachines/pump/OVERLAY_FRONT_ACTIVE_GLOW"))
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(new Textures.BlockIcons.CustomIcon("basicmachines/pump/OVERLAY_FRONT")),
+ TextureFactory.builder()
+ .addIcon(new Textures.BlockIcons.CustomIcon("basicmachines/pump/OVERLAY_FRONT_GLOW"))
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(new Textures.BlockIcons.CustomIcon("basicmachines/pump/OVERLAY_TOP_ACTIVE")),
+ TextureFactory.builder()
+ .addIcon(new Textures.BlockIcons.CustomIcon("basicmachines/pump/OVERLAY_TOP_ACTIVE_GLOW"))
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(new Textures.BlockIcons.CustomIcon("basicmachines/pump/OVERLAY_TOP")),
+ TextureFactory.builder()
+ .addIcon(new Textures.BlockIcons.CustomIcon("basicmachines/pump/OVERLAY_TOP_GLOW"))
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(new Textures.BlockIcons.CustomIcon("basicmachines/pump/OVERLAY_BOTTOM_ACTIVE")),
+ TextureFactory.builder()
+ .addIcon(new Textures.BlockIcons.CustomIcon("basicmachines/pump/OVERLAY_BOTTOM_ACTIVE_GLOW"))
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(new Textures.BlockIcons.CustomIcon("basicmachines/pump/OVERLAY_BOTTOM")),
+ TextureFactory.builder()
+ .addIcon(new Textures.BlockIcons.CustomIcon("basicmachines/pump/OVERLAY_BOTTOM_GLOW"))
+ .glow()
+ .build()));
+
+ radiusConfig = getMaxDistanceForTier(mTier);
+ }
+
+ public GT_MetaTileEntity_Pump(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, 1, aDescription, aTextures, 2, 2);
+ radiusConfig = getMaxDistanceForTier(mTier);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Pump(this.mName, this.mTier, this.mDescriptionArray, this.mTextures);
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ private static final FallbackableUITexture progressBarTexture = GT_UITextures
+ .fallbackableProgressbar("pump", GT_UITextures.PROGRESSBAR_CANNER);
+
+ @Override
+ protected BasicUIProperties getUIProperties() {
+ return BasicUIProperties.builder()
+ .maxItemInputs(2)
+ .maxItemOutputs(2)
+ .slotOverlays((index, isFluid, isOutput, isSpecial) -> {
+ if (!isFluid && !isOutput && !isSpecial) {
+ return GT_UITextures.OVERLAY_SLOT_MINING_PIPE;
+ } else {
+ return null;
+ }
+ })
+ .maxFluidInputs(0)
+ .maxFluidOutputs(1)
+ .progressBarTexture(progressBarTexture)
+ .build();
+ }
+
+ @Override
+ public int getCapacity() {
+ return getCapacityForTier(mTier);
+ }
+
+ @Override
+ protected boolean allowPutStackValidated(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return super.allowPutStackValidated(aBaseMetaTileEntity, aIndex, side, aStack)
+ && aStack.getItem() == GT_DrillingLogicDelegate.MINING_PIPE_STACK.getItem();
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ boolean wasPumping = this.wasPumping || !this.mPumpList.isEmpty();
+ if (debugBlockPump) {
+ GT_Log.out.println(
+ "PUMP: NBT:Save - WasPumping - " + wasPumping
+ + " blocks ("
+ + this.mPrimaryPumpedBlock
+ + ", "
+ + this.mSecondaryPumpedBlock
+ + ")");
+ }
+ super.saveNBTData(aNBT);
+ aNBT.setString(
+ "mPumpedBlock1",
+ this.mPrimaryPumpedBlock == null ? "" : Block.blockRegistry.getNameForObject(this.mPrimaryPumpedBlock));
+ aNBT.setString(
+ "mPumpedBlock2",
+ this.mSecondaryPumpedBlock == null ? "" : Block.blockRegistry.getNameForObject(this.mSecondaryPumpedBlock));
+ aNBT.setBoolean("wasPumping", wasPumping);
+ aNBT.setInteger("radiusConfig", radiusConfig);
+ aNBT.setBoolean("mRetractDone", mRetractDone);
+ aNBT.setBoolean("mDisallowRetract", mDisallowRetract);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ this.wasPumping = aNBT.getBoolean("wasPumping");
+ if (aNBT.hasKey("radiusConfig")) this.radiusConfig = aNBT.getInteger("radiusConfig");
+ this.mPrimaryPumpedBlock = Block.getBlockFromName(aNBT.getString("mPumpedBlock1"));
+ this.mSecondaryPumpedBlock = Block.getBlockFromName(aNBT.getString("mPumpedBlock2"));
+ this.mRetractDone = aNBT.getBoolean("mRetractDone");
+ this.mDisallowRetract = aNBT.getBoolean("mDisallowRetract");
+
+ // Transition from old TE which was derived from GT_MetaTileEntity_Hatch
+ if (!aNBT.hasKey("mEUt")) {
+ // Output of old pump always faces up.
+ getBaseMetaTileEntity().setFrontFacing(ForgeDirection.UP);
+
+ // Automatic output on.
+ mFluidTransfer = true;
+
+ // Fluid was stored in the hatch, now needs to go to the output.
+ if (mFluid != null && mFluid.amount > 0) {
+ fluidOutputTank.fill(mFluid, true);
+ mFluid = null;
+ }
+
+ // Move pipes (or other things) from old slots to new ones.
+ if (mInventory[1] != null && mInventory[1].stackSize > 0) {
+ mInventory[getInputSlot() + 1] = mInventory[1];
+ mInventory[1] = null;
+ }
+
+ if (mInventory[0] != null && mInventory[0].stackSize > 0) {
+ mInventory[getInputSlot()] = mInventory[0];
+ mInventory[0] = null;
+ }
+ }
+
+ if (debugBlockPump) {
+ GT_Log.out.println(
+ "PUMP: NBT:Load - WasPumping - " + this.wasPumping
+ + "("
+ + aNBT.getString("mPumpedBlock1")
+ + ") "
+ + this.mPrimaryPumpedBlock);
+ }
+ }
+
+ @Override
+ public void setItemNBT(NBTTagCompound aNBT) {
+ super.setItemNBT(aNBT);
+ aNBT.setInteger("radiusConfig", radiusConfig);
+ aNBT.setBoolean("mDisallowRetract", mDisallowRetract);
+ }
+
+ @Override
+ public void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ super.onScrewdriverRightClick(side, aPlayer, aX, aY, aZ);
+
+ if (side == getBaseMetaTileEntity().getFrontFacing() || side == mMainFacing) {
+ // Configuring "input from output side allowed".
+ return;
+ }
+
+ int max = getMaxPumpableDistance();
+ if (aPlayer.isSneaking()) {
+ if (radiusConfig >= 0) {
+ radiusConfig--;
+ }
+ if (radiusConfig < 0) radiusConfig = max;
+ } else {
+ if (radiusConfig <= max) {
+ radiusConfig++;
+ }
+ if (radiusConfig > max) radiusConfig = 0;
+ }
+ GT_Utility.sendChatToPlayer(
+ aPlayer,
+ StatCollector.translateToLocal("GT5U.machines.workareaset") + " "
+ + (radiusConfig * 2 + 1)
+ + "x"
+ + (radiusConfig * 2 + 1)); // TODO Add translation support
+
+ clearQueue(false);
+ }
+
+ @Override
+ public boolean onSolderingToolRightClick(ForgeDirection side, ForgeDirection wrenchingSide,
+ EntityPlayer entityPlayer, float aX, float aY, float aZ) {
+ if (super.onSolderingToolRightClick(side, wrenchingSide, entityPlayer, aX, aY, aZ)) return true;
+ mDisallowRetract = !mDisallowRetract;
+ GT_Utility.sendChatToPlayer(
+ entityPlayer,
+ StatCollector.translateToLocal(
+ mDisallowRetract ? "GT5U.machines.autoretract.disabled" : "GT5U.machines.autoretract.enabled"));
+ return true;
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ super.onPostTick(aBaseMetaTileEntity, aTick);
+
+ if (getBaseMetaTileEntity().isServerSide()) {
+ this.mPumpTimer -= 1;
+ if ((getBaseMetaTileEntity() instanceof BaseTileEntity)) {
+ ((BaseTileEntity) getBaseMetaTileEntity()).ignoreUnloadedChunks = false;
+ }
+ this.doTickProfilingInThisTick = true;
+ this.mPumpCountBelow = 0;
+
+ IGregTechTileEntity tTileEntity;
+ for (int i = 1; (i < 21)
+ && ((tTileEntity = getBaseMetaTileEntity()
+ .getIGregTechTileEntityAtSideAndDistance(ForgeDirection.DOWN, i)) != null)
+ && ((tTileEntity.getMetaTileEntity() instanceof GT_MetaTileEntity_Pump)); i++) {
+ // Apparently someone might stack 21 pumps on top of each other, so let's check for that
+ getBaseMetaTileEntity().setActive(tTileEntity.isActive());
+ this.mPumpCountBelow += 1;
+ // The more pumps we have stacked, the faster the ones below go
+ ((GT_MetaTileEntity_Pump) tTileEntity.getMetaTileEntity()).mPumpTimer -= 1;
+ ((GT_MetaTileEntity_Pump) tTileEntity.getMetaTileEntity()).mProgresstime += 1;
+ }
+ if (debugBlockPump && (this.mPumpCountBelow != 0)) {
+ GT_Log.out.println("PUMP: Detected " + this.mPumpCountBelow + " pumps below this pump.");
+ }
+ if (this.mPumpCountBelow <= 0) {
+ // Only the bottom most pump does anything
+ if (getBaseMetaTileEntity().isAllowedToWork()) {
+ mRetractDone = false;
+ if ((getBaseMetaTileEntity().isUniversalEnergyStored(this.getEuUsagePerAction()))
+ && (fluidOutputTank.getFluidAmount() + 1000 <= fluidOutputTank.getCapacity())) {
+ boolean tMovedOneDown = false;
+ if ((this.mPumpList.isEmpty()) && (getBaseMetaTileEntity().getTimer() % 100L == 0L)) {
+ if (!this.wasPumping) {
+ tMovedOneDown = moveOneDown();
+ if (!tMovedOneDown) {
+ if (canMoveDown(
+ getBaseMetaTileEntity().getXCoord(),
+ Math.max(getYOfPumpHead() - 1, 1),
+ getBaseMetaTileEntity().getZCoord())) {
+ if (debugBlockPump) {
+ GT_Log.out.println("PUMP: No pipe left. Idle for a little longer.");
+ }
+ this.mPumpTimer = 160;
+ } else {
+ getBaseMetaTileEntity().disableWorking();
+ if (debugBlockPump) {
+ GT_Log.out.println("PUMP: Can't move. Retracting in next few ticks");
+ }
+ }
+ } else if (debugBlockPump) {
+ GT_Log.out.println("PUMP: Moved down");
+ }
+ } else if (debugBlockPump) {
+ GT_Log.out.println("PUMP: Was pumping, didn't move down");
+ }
+ }
+ int x = getBaseMetaTileEntity().getXCoord(), z = getBaseMetaTileEntity().getZCoord();
+
+ if (!this.hasValidFluid()) {
+ // We don't have a valid block, let's try to find one
+ int y = getYOfPumpHead();
+
+ if (debugBlockPump && this.mPrimaryPumpedBlock != null) {
+ GT_Log.out.println(
+ "PUMP: Had an invalid pump block. Trying to find a fluid at Y: " + y
+ + " Previous blocks 1: "
+ + this.mPrimaryPumpedBlock
+ + " 2: "
+ + this.mSecondaryPumpedBlock);
+ }
+ // First look down
+ checkForFluidToPump(x, y - 1, z);
+
+ // Then look all around
+ checkForFluidToPump(x, y, z + 1);
+ checkForFluidToPump(x, y, z - 1);
+ checkForFluidToPump(x + 1, y, z);
+ checkForFluidToPump(x - 1, y, z);
+ this.clearQueue(false);
+
+ if (this.hasValidFluid()) {
+ // Don't move down and rebuild the queue if we now have a valid fluid
+ this.wasPumping = true;
+ }
+
+ } else if (getYOfPumpHead() < getBaseMetaTileEntity().getYCoord()) {
+ // We didn't just look for a block, and the pump head is below the pump
+ if ((tMovedOneDown) || this.wasPumping
+ || ((this.mPumpList.isEmpty()) && (getBaseMetaTileEntity().getTimer() % 200L == 100L))
+ || (getBaseMetaTileEntity().getTimer() % 72000L == 100L)) {
+ // Rebuild the list to pump if any of the following conditions are true:
+ // 1) We just moved down
+ // 2) We were previously pumping (and possibly just reloaded)
+ // 3) We have an empty queue and enough time has passed
+ // 4) A long while has passed
+ if (debugBlockPump) {
+ GT_Log.out.println(
+ "PUMP: Rebuilding pump list - Size " + this.mPumpList.size()
+ + " WasPumping: "
+ + this.wasPumping
+ + " Timer "
+ + getBaseMetaTileEntity().getTimer());
+ }
+ int yPump = getBaseMetaTileEntity().getYCoord() - 1, yHead = getYOfPumpHead();
+
+ this.rebuildPumpQueue(x, yPump, z, yHead);
+
+ if (debugBlockPump) {
+ GT_Log.out.println("PUMP: Rebuilt pump list - Size " + this.mPumpList.size());
+ }
+ }
+ if ((!tMovedOneDown) && (this.mPumpTimer <= 0)) {
+ while ((!this.mPumpList.isEmpty())) {
+ ChunkPosition pos = this.mPumpList.pollLast();
+ if (consumeFluid(pos.chunkPosX, pos.chunkPosY, pos.chunkPosZ)) {
+ // Keep trying until we consume something, or the list is empty
+ break;
+ }
+ }
+ this.mPumpTimer = GT_Utility.safeInt(160 / (long) Math.pow(2, this.mTier));
+ this.mPumpTimer = mPumpTimer == 0 ? 1 : mPumpTimer;
+
+ mMaxProgresstime = mPumpTimer;
+ mProgresstime = 0;
+ }
+ } else {
+ // We somehow have a valid fluid, but the head of the pump isn't below the pump. Perhaps
+ // someone broke some pipes
+ // -- Clear the queue and we should try to move down until we can find a valid fluid
+ this.clearQueue(false);
+ }
+ } else if (debugBlockPump) {
+ GT_Log.out.println("PUMP: Not enough energy? Free space?");
+ }
+ } else {
+ mMaxProgresstime = 0;
+
+ if (!mRetractDone && ((aTick % 5) == 0) && canOutput(MINING_PIPE_ONE)) {
+ // try retract if all of these conditions are met
+ // 1. not retracted yet
+ // 2. once per 5 tick
+ // 3. can hold retracted pipe in inventory
+ int tHeadY = getYOfPumpHead();
+ if (tHeadY < this.getBaseMetaTileEntity()
+ .getYCoord()) {
+ final int tXCoord = this.getBaseMetaTileEntity()
+ .getXCoord();
+ final int tZCoord = this.getBaseMetaTileEntity()
+ .getZCoord();
+ this.getBaseMetaTileEntity()
+ .getWorld()
+ .setBlockToAir(tXCoord, tHeadY, tZCoord);
+ if (tHeadY < this.getBaseMetaTileEntity()
+ .getYCoord() - 1) {
+ getBaseMetaTileEntity().getWorld()
+ .setBlock(tXCoord, tHeadY + 1, tZCoord, MINING_PIPE_TIP_BLOCK);
+ }
+
+ for (int i = 0; i < mOutputItems.length; ++i) {
+ if (aBaseMetaTileEntity.addStackToSlot(getOutputSlot() + i, MINING_PIPE_ONE.copy())) {
+ break;
+ }
+ }
+
+ if (debugBlockPump) {
+ GT_Log.out.println("PUMP: Retracted one pipe");
+ }
+ } else {
+ mRetractDone = true;
+ if (debugBlockPump) {
+ GT_Log.out.println("PUMP: Retract done");
+ }
+ }
+ }
+ }
+ if (!mDisallowRetract) getBaseMetaTileEntity().setActive(!this.mPumpList.isEmpty());
+ }
+ }
+ }
+
+ private int getMaxPumpableDistance() {
+ return getMaxDistanceForTier(this.mTier);
+ }
+
+ private long getEuUsagePerAction() {
+ return getEuUsagePerTier(this.mTier);
+ }
+
+ private boolean hasValidFluid() {
+ return mPrimaryPumpedBlock != null && mSecondaryPumpedBlock != null;
+ }
+
+ private boolean moveOneDown() {
+ boolean foundPipe = false;
+
+ for (int i = 0; i < mInputSlotCount; i++) {
+ ItemStack stack = getInputAt(i);
+ if (stack != null && GT_Utility.areStacksEqual(stack, MINING_PIPE) && stack.stackSize > 0) {
+ foundPipe = true;
+ break;
+ }
+ }
+
+ if (!foundPipe) {
+ // No mining pipes
+ if (debugBlockPump) {
+ GT_Log.out.println("PUMP: No mining pipes");
+ }
+ return false;
+ }
+
+ int yHead = getYOfPumpHead();
+ if (yHead <= 1) {
+ // Let's not punch through bedrock
+ if (debugBlockPump) {
+ GT_Log.out.println("PUMP: At bottom");
+ }
+ return false;
+ }
+
+ int x = getBaseMetaTileEntity().getXCoord(), z = getBaseMetaTileEntity().getZCoord();
+
+ Block aBlock = getBaseMetaTileEntity().getBlock(x, yHead - 1, z);
+ boolean canReplaceBlock = aBlock.isReplaceable(getBaseMetaTileEntity().getWorld(), x, yHead - 1, z);
+
+ // We specifically allow replacing water even if we can't consume it
+ // (e.g. pump holds a different fluid) to help avoid getting stuck on random water pockets.
+ if (!canReplaceBlock || (isFluid(aBlock) && !consumeFluid(x, yHead - 1, z) && !isWater(aBlock))) {
+ // Either we didn't consume a fluid, or it's a non-replaceable block, or it's water.
+ if (debugBlockPump) {
+ GT_Log.out.println("PUMP: Did not consume fluid, or non-replaceable block found");
+ }
+ return false;
+ }
+ // Try to set the block below us to a tip
+ if (!GT_Utility.setBlockByFakePlayer(
+ getFakePlayer(getBaseMetaTileEntity()),
+ x,
+ yHead - 1,
+ z,
+ MINING_PIPE_TIP_BLOCK,
+ 0,
+ false)) {
+ if (debugBlockPump) {
+ GT_Log.out.println("PUMP: Could not set block below to new tip");
+ }
+ return false;
+ }
+ // And change the previous block to a pipe -- as long as it isn't the pump itself!
+ if (yHead != getBaseMetaTileEntity().getYCoord()) {
+ getBaseMetaTileEntity().getWorld()
+ .setBlock(x, yHead, z, MINING_PIPE_BLOCK);
+ }
+
+ // Remove pipe from inputs.
+ foundPipe = false;
+
+ for (int i = 0; i < mInputSlotCount; i++) {
+ ItemStack stack = getInputAt(i);
+ if (stack != null && GT_Utility.areStacksEqual(stack, MINING_PIPE) && stack.stackSize > 0) {
+ foundPipe = true;
+ stack.stackSize -= 1;
+ if (stack.stackSize == 0) {
+ mInventory[getInputSlot() + i] = null;
+ }
+ break;
+ }
+ }
+
+ if (debugBlockPump) {
+ if (foundPipe) {
+ GT_Log.out.println("PUMP: Using 1 pipe");
+ } else {
+ GT_Log.err.println("PUMP: Lowered pipe but could not find pipe in input");
+ }
+ }
+
+ return true;
+ }
+
+ private int getYOfPumpHead() {
+ // Let's play find the pump head!
+
+ // TODO: Handle pipe|pipe|head|pipe|pipe
+ int y = getBaseMetaTileEntity().getYCoord() - 1, x = getBaseMetaTileEntity().getXCoord(),
+ z = getBaseMetaTileEntity().getZCoord();
+
+ while (y > 0) {
+ Block curBlock = getBaseMetaTileEntity().getBlock(x, y, z);
+ if (curBlock == MINING_PIPE_BLOCK) {
+ y--;
+ } else if (curBlock == MINING_PIPE_TIP_BLOCK) {
+ Block nextBlock = getBaseMetaTileEntity().getBlock(x, y - 1, z);
+ if (nextBlock == MINING_PIPE_BLOCK || nextBlock == MINING_PIPE_TIP_BLOCK) {
+ // We're running into an existing set of pipes -- Turn this block into a pipe and keep going
+ this.clearQueue(true);
+ getBaseMetaTileEntity().getWorld()
+ .setBlock(x, y, z, MINING_PIPE_BLOCK);
+ if (debugBlockPump) {
+ GT_Log.out.println("PUMP: Hit pipes already in place, trying to merge");
+ }
+ }
+ y--;
+
+ } else {
+ break;
+ }
+ }
+
+ if (getBaseMetaTileEntity().getBlock(x, y, z) != MINING_PIPE_TIP_BLOCK) {
+ if (y != getBaseMetaTileEntity().getYCoord() - 1
+ && getBaseMetaTileEntity().getBlock(x, y + 1, z) == MINING_PIPE_BLOCK) {
+ // We're below the pump at the bottom of the pipes, we haven't found a tip; make the previous pipe a
+ // tip!
+ this.clearQueue(true);
+ getBaseMetaTileEntity().getWorld()
+ .setBlock(x, y + 1, z, MINING_PIPE_TIP_BLOCK);
+ if (debugBlockPump) {
+ GT_Log.out.println("PUMP: Did not find a tip at bottom, setting last pipe as tip");
+ }
+ }
+ return y + 1;
+ }
+ return y;
+ }
+
+ private void clearQueue(boolean checkPumping) {
+ if (checkPumping) {
+ this.wasPumping = !this.mPumpList.isEmpty();
+ } else {
+ this.wasPumping = false;
+ }
+ this.mPumpList.clear();
+ }
+
+ private void rebuildPumpQueue(int aX, int yStart, int aZ, int yEnd) {
+ int mDist = this.radiusConfig;
+ doTickProfilingInThisTick = false;
+ ArrayDeque<ChunkPosition> fluidsToSearch = new ArrayDeque<>();
+ ArrayDeque<ChunkPosition> fluidsFound = new ArrayDeque<>();
+ Set<ChunkPosition> checked = new HashSet<>();
+ this.clearQueue(false);
+
+ for (int aY = yStart; this.mPumpList.isEmpty() && aY >= yEnd; aY--) {
+ // Start at the top (presumably the block below the pump), and work our way down to the end (presumably the
+ // location of the pump Head)
+ // and build up a queue of fluids to pump
+ fluidsToSearch.add(new ChunkPosition(aX, aY, aZ));
+
+ while (!fluidsToSearch.isEmpty()) {
+ for (ChunkPosition tPos : fluidsToSearch) {
+ // Look all around
+ if (tPos.chunkPosX < aX + mDist)
+ queueFluid(tPos.chunkPosX + 1, tPos.chunkPosY, tPos.chunkPosZ, fluidsFound, checked);
+ if (tPos.chunkPosX > aX - mDist)
+ queueFluid(tPos.chunkPosX - 1, tPos.chunkPosY, tPos.chunkPosZ, fluidsFound, checked);
+ if (tPos.chunkPosZ < aZ + mDist)
+ queueFluid(tPos.chunkPosX, tPos.chunkPosY, tPos.chunkPosZ + 1, fluidsFound, checked);
+ if (tPos.chunkPosZ > aZ - mDist)
+ queueFluid(tPos.chunkPosX, tPos.chunkPosY, tPos.chunkPosZ - 1, fluidsFound, checked);
+
+ // And then look up
+ queueFluid(tPos.chunkPosX, tPos.chunkPosY + 1, tPos.chunkPosZ, this.mPumpList, checked);
+ }
+ this.mPumpList.addAll(fluidsFound);
+ fluidsToSearch = fluidsFound;
+ fluidsFound = new ArrayDeque<>();
+ }
+
+ // Make sure we don't have the pipe location in the queue
+ this.mPumpList.remove(new ChunkPosition(aX, aY, aZ));
+ }
+ }
+
+ private boolean queueFluid(int aX, int aY, int aZ, ArrayDeque<ChunkPosition> fluidsFound,
+ Set<ChunkPosition> checked) {
+ // If we haven't already looked at this coordinate set, and it's not already in the list of fluids found, see if
+ // there is
+ // a valid fluid and add it to the fluids found
+ ChunkPosition tCoordinate = new ChunkPosition(aX, aY, aZ);
+ if (checked.add(tCoordinate) && !fluidsFound.contains(tCoordinate)) {
+ Block aBlock = getBaseMetaTileEntity().getBlock(aX, aY, aZ);
+ if ((this.mPrimaryPumpedBlock == aBlock) || (this.mSecondaryPumpedBlock == aBlock)) {
+ fluidsFound.addFirst(tCoordinate);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void checkForFluidToPump(int aX, int aY, int aZ) {
+ // If we don't currently have a valid fluid to pump, try pumping the fluid at the given coordinates
+ if (this.hasValidFluid()) return;
+
+ Block aBlock = getBaseMetaTileEntity().getBlock(aX, aY, aZ);
+ if (aBlock != null) {
+ if (isWater(aBlock)) {
+ this.mPrimaryPumpedBlock = Blocks.water;
+ this.mSecondaryPumpedBlock = Blocks.flowing_water;
+ return;
+ }
+ if (isLava(aBlock)) {
+ this.mPrimaryPumpedBlock = Blocks.lava;
+ this.mSecondaryPumpedBlock = Blocks.flowing_lava;
+ return;
+ }
+ if ((aBlock instanceof IFluidBlock)) {
+ this.mPrimaryPumpedBlock = aBlock;
+ this.mSecondaryPumpedBlock = aBlock;
+ return;
+ }
+ }
+ this.mPrimaryPumpedBlock = null;
+ this.mSecondaryPumpedBlock = null;
+ }
+
+ /** only check if block below can be replaced with pipe tip. pipe stockpile condition is ignored */
+ private boolean canMoveDown(int aX, int aY, int aZ) {
+ if (!GT_Utility.eraseBlockByFakePlayer(getFakePlayer(getBaseMetaTileEntity()), aX, aY, aZ, true)) return false;
+
+ Block aBlock = getBaseMetaTileEntity().getBlock(aX, aY, aZ);
+
+ return aBlock != null && aBlock.isReplaceable(getBaseMetaTileEntity().getWorld(), aX, aY, aZ);
+ }
+
+ private boolean consumeFluid(int aX, int aY, int aZ) {
+ // Try to consume a fluid at a location
+ // Returns true if something was consumed, otherwise false
+ if (!GT_Utility.eraseBlockByFakePlayer(getFakePlayer(getBaseMetaTileEntity()), aX, aY, aZ, true)) return false;
+
+ Block aBlock = getBaseMetaTileEntity().getBlock(aX, aY, aZ);
+ if (!isFluid(aBlock)) {
+ return false;
+ }
+
+ if (aBlock != null && ((this.mPrimaryPumpedBlock == aBlock) || (this.mSecondaryPumpedBlock == aBlock))) {
+ boolean isWaterOrLava = ((this.mPrimaryPumpedBlock == Blocks.water
+ || this.mPrimaryPumpedBlock == Blocks.lava));
+
+ if (isWaterOrLava && getBaseMetaTileEntity().getMetaID(aX, aY, aZ) != 0) {
+ // Water/Lava that isn't a source block - do nothing here, but set the block to air and consume energy
+ // below
+ if (debugBlockPump) {
+ GT_Log.out.println("PUMP: Water/Lava - Not a source block");
+ }
+
+ } else if (getDrainableStack() == null) {
+ // The pump has no internal fluid
+ if (this.mPrimaryPumpedBlock == Blocks.water) setDrainableStack(GT_ModHandler.getWater(1000L));
+ else if (this.mPrimaryPumpedBlock == Blocks.lava) setDrainableStack(GT_ModHandler.getLava(1000L));
+ else {
+ // Not water or lava; try to drain and set to air
+ setDrainableStack(
+ ((IFluidBlock) aBlock).drain(getBaseMetaTileEntity().getWorld(), aX, aY, aZ, true));
+ }
+
+ } else if (GT_ModHandler.isWater(getDrainableStack()) || GT_ModHandler.isLava(getDrainableStack())
+ || getDrainableStack().isFluidEqual(
+ ((IFluidBlock) aBlock).drain(getBaseMetaTileEntity().getWorld(), aX, aY, aZ, false))) {
+ if (!isWaterOrLava) {
+ // Only set Block to Air for non lava/water fluids
+ this.getBaseMetaTileEntity()
+ .getWorld()
+ .setBlockToAir(aX, aY, aZ);
+ }
+ getDrainableStack().amount += 1000;
+
+ } else {
+ if (debugBlockPump) {
+ GT_Log.out.println("PUMP: Couldn't consume " + aBlock);
+ }
+ // We didn't do anything
+ return false;
+ }
+
+ getBaseMetaTileEntity().decreaseStoredEnergyUnits(this.getEuUsagePerAction(), true);
+ getBaseMetaTileEntity().getWorld()
+ .setBlock(aX, aY, aZ, Blocks.air, 0, 2);
+ return true;
+ }
+ return false;
+ }
+
+ private static boolean isWater(Block aBlock) {
+ return aBlock == Blocks.water || aBlock == Blocks.flowing_water;
+ }
+
+ private static boolean isLava(Block aBlock) {
+ return aBlock == Blocks.lava || aBlock == Blocks.flowing_lava;
+ }
+
+ private static boolean isFluid(Block aBlock) {
+ return isWater(aBlock) || isLava(aBlock) || aBlock instanceof IFluidBlock;
+ }
+
+ @Override
+ public ArrayList<String> getSpecialDebugInfo(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer,
+ int aLogLevel, ArrayList<String> aList) {
+ aList.addAll(
+ Arrays.asList(
+ EnumChatFormatting.BLUE + StatCollector.translateToLocal("GT5U.machines.pump")
+ + EnumChatFormatting.RESET,
+ StatCollector.translateToLocal("GT5U.machines.workarea") + ": "
+ + EnumChatFormatting.GREEN
+ + (radiusConfig * 2 + 1)
+ + EnumChatFormatting.RESET
+ + " "
+ + StatCollector.translateToLocal("GT5U.machines.blocks"),
+ "Primary pumping fluid: "
+ + (this.mPrimaryPumpedBlock != null ? this.mPrimaryPumpedBlock.getLocalizedName() : "None"),
+ "Secondary pumping fluid: "
+ + (this.mSecondaryPumpedBlock != null ? this.mSecondaryPumpedBlock.getLocalizedName() : "None"),
+ "Pumps below: " + mPumpCountBelow,
+ "Queue size: " + mPumpList.size(),
+ "Pump head at Y: " + getYOfPumpHead(),
+ "Pump timer: " + mPumpTimer,
+ "Meta Entity Timer: " + getBaseMetaTileEntity().getTimer()));
+ return aList;
+ }
+
+ private FakePlayer mFakePlayer = null;
+
+ protected FakePlayer getFakePlayer(IGregTechTileEntity aBaseTile) {
+ if (mFakePlayer == null) mFakePlayer = GT_Utility.getFakePlayer(aBaseTile);
+ mFakePlayer.setWorld(aBaseTile.getWorld());
+ mFakePlayer.setPosition(aBaseTile.getXCoord(), aBaseTile.getYCoord(), aBaseTile.getZCoord());
+ return mFakePlayer;
+ }
+
+ @Override
+ public String[] getInfoData() {
+ return new String[] {
+ EnumChatFormatting.BLUE + StatCollector.translateToLocal("GT5U.machines.pump") + EnumChatFormatting.RESET,
+ StatCollector.translateToLocal("GT5U.machines.workarea") + ": "
+ + EnumChatFormatting.GREEN
+ + (radiusConfig * 2 + 1)
+ + EnumChatFormatting.RESET
+ + " "
+ + StatCollector.translateToLocal("GT5U.machines.blocks") };
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Replicator.java b/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Replicator.java
new file mode 100644
index 0000000000..a15d5b7f6d
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Replicator.java
@@ -0,0 +1,127 @@
+package gregtech.common.tileentities.machines.basic;
+
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_REPLICATOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_REPLICATOR_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_REPLICATOR_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_REPLICATOR_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_REPLICATOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_REPLICATOR_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_REPLICATOR_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_REPLICATOR_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_REPLICATOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_REPLICATOR_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_REPLICATOR_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_REPLICATOR_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_REPLICATOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_REPLICATOR_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_REPLICATOR_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_REPLICATOR_GLOW;
+
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidStack;
+
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.MachineType;
+import gregtech.api.enums.Materials;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachine;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.render.TextureFactory;
+
+public class GT_MetaTileEntity_Replicator extends GT_MetaTileEntity_BasicMachine {
+
+ public GT_MetaTileEntity_Replicator(int aID, String aName, String aNameRegional, int aTier) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ 1,
+ MachineType.REPLICATOR.tooltipDescription(),
+ 1,
+ 1,
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_SIDE_REPLICATOR_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_REPLICATOR_ACTIVE_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_SIDE_REPLICATOR),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_REPLICATOR_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_FRONT_REPLICATOR_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_REPLICATOR_ACTIVE_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_FRONT_REPLICATOR),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_REPLICATOR_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_TOP_REPLICATOR_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_REPLICATOR_ACTIVE_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_TOP_REPLICATOR),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_REPLICATOR_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_BOTTOM_REPLICATOR_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_REPLICATOR_ACTIVE_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_BOTTOM_REPLICATOR),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_REPLICATOR_GLOW)
+ .glow()
+ .build()));
+ }
+
+ public GT_MetaTileEntity_Replicator(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, 1, aDescription, aTextures, 1, 1);
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Replicator(this.mName, this.mTier, this.mDescriptionArray, this.mTextures);
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.replicatorRecipes;
+ }
+
+ @Override
+ protected boolean allowPutStackValidated(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return super.allowPutStackValidated(aBaseMetaTileEntity, aIndex, side, aStack)
+ && ItemList.Cell_Empty.isStackEqual(aStack);
+ }
+
+ @Override
+ public boolean isFluidInputAllowed(FluidStack aFluid) {
+ return aFluid.isFluidEqual(Materials.UUMatter.getFluid(1L));
+ }
+
+ @Override
+ public int getCapacity() {
+ return 3000;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_RockBreaker.java b/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_RockBreaker.java
new file mode 100644
index 0000000000..e632f4eeda
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_RockBreaker.java
@@ -0,0 +1,169 @@
+package gregtech.common.tileentities.machines.basic;
+
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_ROCK_BREAKER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_ROCK_BREAKER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_ROCK_BREAKER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_ROCK_BREAKER_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ROCK_BREAKER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ROCK_BREAKER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ROCK_BREAKER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ROCK_BREAKER_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_ROCK_BREAKER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_ROCK_BREAKER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_ROCK_BREAKER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_ROCK_BREAKER_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_ROCK_BREAKER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_ROCK_BREAKER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_ROCK_BREAKER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_ROCK_BREAKER_GLOW;
+
+import net.minecraft.init.Blocks;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.enums.MachineType;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachine;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_OreDictUnificator;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_RockBreaker extends GT_MetaTileEntity_BasicMachine {
+
+ public GT_MetaTileEntity_RockBreaker(int aID, String aName, String aNameRegional, int aTier) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ 1,
+ MachineType.ROCKBREAKER.tooltipDescription(),
+ 1,
+ 1,
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_SIDE_ROCK_BREAKER_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_ROCK_BREAKER_ACTIVE_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_SIDE_ROCK_BREAKER),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_ROCK_BREAKER_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_FRONT_ROCK_BREAKER_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_ROCK_BREAKER_ACTIVE_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_FRONT_ROCK_BREAKER),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_ROCK_BREAKER_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_TOP_ROCK_BREAKER_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_ROCK_BREAKER_ACTIVE_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_TOP_ROCK_BREAKER),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_ROCK_BREAKER_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_BOTTOM_ROCK_BREAKER_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_ROCK_BREAKER_ACTIVE_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_BOTTOM_ROCK_BREAKER),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_ROCK_BREAKER_GLOW)
+ .glow()
+ .build()));
+ }
+
+ public GT_MetaTileEntity_RockBreaker(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, 1, aDescription, aTextures, 1, 1);
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_RockBreaker(this.mName, this.mTier, this.mDescriptionArray, this.mTextures);
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.rockBreakerFakeRecipes;
+ }
+
+ @Override
+ protected boolean allowPutStackValidated(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return super.allowPutStackValidated(aBaseMetaTileEntity, aIndex, side, aStack)
+ && getRecipeMap().containsInput(aStack);
+ }
+
+ @Override
+ public boolean allowSelectCircuit() {
+ return true;
+ }
+
+ @Override
+ public int checkRecipe() {
+ IGregTechTileEntity aBaseMetaTileEntity = getBaseMetaTileEntity();
+ if ((aBaseMetaTileEntity.getBlockOffset(0, 0, 1) == Blocks.water)
+ || (aBaseMetaTileEntity.getBlockOffset(0, 0, -1) == Blocks.water)
+ || (aBaseMetaTileEntity.getBlockOffset(-1, 0, 0) == Blocks.water)
+ || (aBaseMetaTileEntity.getBlockOffset(1, 0, 0) == Blocks.water)) {
+ ItemStack tOutput = null;
+ if (aBaseMetaTileEntity.getBlockOffset(0, 1, 0) == Blocks.lava) {
+ tOutput = new ItemStack(Blocks.stone, 1);
+ } else if ((aBaseMetaTileEntity.getBlockOffset(0, 0, 1) == Blocks.lava)
+ || (aBaseMetaTileEntity.getBlockOffset(0, 0, -1) == Blocks.lava)
+ || (aBaseMetaTileEntity.getBlockOffset(-1, 0, 0) == Blocks.lava)
+ || (aBaseMetaTileEntity.getBlockOffset(1, 0, 0) == Blocks.lava)) {
+ tOutput = new ItemStack(Blocks.cobblestone, 1);
+ }
+ if (tOutput != null) {
+ if (GT_Utility.areStacksEqual(getStackInSlot(getCircuitSlot()), GT_Utility.getIntegratedCircuit(1))) {
+ if (GT_Utility.areStacksEqual(
+ getInputAt(0),
+ GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Redstone, 1L))) {
+ tOutput = new ItemStack(Blocks.obsidian, 1);
+ if (canOutput(tOutput)) {
+ getInputAt(0).stackSize -= 1;
+ calculateOverclockedNess(30, 128);
+ // In case recipe is too OP for that machine
+ if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1)
+ return FOUND_RECIPE_BUT_DID_NOT_MEET_REQUIREMENTS;
+ this.mOutputItems[0] = tOutput;
+ return 2;
+ }
+ }
+ } else if (canOutput(tOutput)) {
+ calculateOverclockedNess(30, 16);
+ // In case recipe is too OP for that machine
+ if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1)
+ return FOUND_RECIPE_BUT_DID_NOT_MEET_REQUIREMENTS;
+ this.mOutputItems[0] = tOutput;
+ return 2;
+ }
+ }
+ }
+ return 0;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Scanner.java b/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Scanner.java
new file mode 100644
index 0000000000..ba00be67f8
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Scanner.java
@@ -0,0 +1,425 @@
+package gregtech.common.tileentities.machines.basic;
+
+import static gregtech.api.enums.GT_Values.D1;
+import static gregtech.api.enums.Mods.GalacticraftCore;
+import static gregtech.api.enums.Mods.GalacticraftMars;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_SCANNER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_SCANNER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_SCANNER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_SCANNER_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_SCANNER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_SCANNER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_SCANNER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_SCANNER_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_SCANNER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_SCANNER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_SCANNER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_SCANNER_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_SCANNER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_SCANNER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_SCANNER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_SCANNER_GLOW;
+import static gregtech.api.recipe.RecipeMaps.scannerFakeRecipes;
+
+import java.util.Objects;
+
+import net.minecraft.init.Items;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import forestry.api.genetics.AlleleManager;
+import forestry.api.genetics.IIndividual;
+import gregtech.GT_Mod;
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.MachineType;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.enums.SoundResource;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachine;
+import gregtech.api.objects.ItemData;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_AssemblyLineUtils;
+import gregtech.api.util.GT_Log;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_OreDictUnificator;
+import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.items.behaviors.Behaviour_DataOrb;
+
+public class GT_MetaTileEntity_Scanner extends GT_MetaTileEntity_BasicMachine {
+
+ public GT_MetaTileEntity_Scanner(int aID, String aName, String aNameRegional, int aTier) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ 1,
+ MachineType.SCANNER.tooltipDescription(),
+ 1,
+ 1,
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_SIDE_SCANNER_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_SCANNER_ACTIVE_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_SIDE_SCANNER),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_SCANNER_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_FRONT_SCANNER_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_SCANNER_ACTIVE_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_FRONT_SCANNER),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_SCANNER_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_TOP_SCANNER_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_SCANNER_ACTIVE_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_TOP_SCANNER),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_SCANNER_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_BOTTOM_SCANNER_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_SCANNER_ACTIVE_GLOW)
+ .glow()
+ .build()),
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_BOTTOM_SCANNER),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_SCANNER_GLOW)
+ .glow()
+ .build()));
+ }
+
+ public GT_MetaTileEntity_Scanner(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, 1, aDescription, aTextures, 1, 1);
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Scanner(this.mName, this.mTier, this.mDescriptionArray, this.mTextures);
+ }
+
+ @Override
+ public int checkRecipe() {
+ ItemStack aStack = getInputAt(0);
+ if (getOutputAt(0) != null) {
+ this.mOutputBlocked += 1;
+ } else if ((GT_Utility.isStackValid(aStack)) && (aStack.stackSize > 0)) {
+ if ((getFillableStack() != null) && (getFillableStack().containsFluid(Materials.Honey.getFluid(100L)))) {
+ try {
+ IIndividual tIndividual = AlleleManager.alleleRegistry.getIndividual(aStack);
+ if (tIndividual != null) {
+ if (tIndividual.analyze()) {
+ getFillableStack().amount -= 100;
+ this.mOutputItems[0] = GT_Utility.copyOrNull(aStack);
+ aStack.stackSize = 0;
+ NBTTagCompound tNBT = new NBTTagCompound();
+ tIndividual.writeToNBT(tNBT);
+ this.mOutputItems[0].setTagCompound(tNBT);
+ calculateOverclockedNess(2, 500);
+ // In case recipe is too OP for that machine
+ if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1)
+ return FOUND_RECIPE_BUT_DID_NOT_MEET_REQUIREMENTS;
+ return 2;
+ }
+ this.mOutputItems[0] = GT_Utility.copyOrNull(aStack);
+ aStack.stackSize = 0;
+ this.mMaxProgresstime = 1;
+ this.mEUt = 1;
+ return 2;
+ }
+ } catch (Throwable e) {
+ if (D1) {
+ e.printStackTrace(GT_Log.err);
+ }
+ }
+ }
+ if (ItemList.IC2_Crop_Seeds.isStackEqual(aStack, true, true)) {
+ NBTTagCompound tNBT = aStack.getTagCompound();
+ if (tNBT == null) {
+ tNBT = new NBTTagCompound();
+ }
+ if (tNBT.getByte("scan") < 4) {
+ tNBT.setByte("scan", (byte) 4);
+ calculateOverclockedNess(8, 160);
+ // In case recipe is too OP for that machine
+ if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1)
+ return FOUND_RECIPE_BUT_DID_NOT_MEET_REQUIREMENTS;
+ } else {
+ this.mMaxProgresstime = 1;
+ this.mEUt = 1;
+ }
+ aStack.stackSize -= 1;
+ this.mOutputItems[0] = GT_Utility.copyAmount(1, aStack);
+ assert this.mOutputItems[0] != null;
+ this.mOutputItems[0].setTagCompound(tNBT);
+ return 2;
+ }
+ if (ItemList.Tool_DataOrb.isStackEqual(getSpecialSlot(), false, true)) {
+ if (ItemList.Tool_DataOrb.isStackEqual(aStack, false, true)) {
+ aStack.stackSize -= 1;
+ this.mOutputItems[0] = GT_Utility.copyAmount(1, getSpecialSlot());
+ calculateOverclockedNess(30, 512);
+ // In case recipe is too OP for that machine
+ if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1)
+ return FOUND_RECIPE_BUT_DID_NOT_MEET_REQUIREMENTS;
+ return 2;
+ }
+ ItemData tData = GT_OreDictUnificator.getAssociation(aStack);
+ if ((tData != null) && ((tData.mPrefix == OrePrefixes.dust) || (tData.mPrefix == OrePrefixes.cell))
+ && (tData.mMaterial.mMaterial.mElement != null)
+ && (!tData.mMaterial.mMaterial.mElement.mIsIsotope)
+ && (tData.mMaterial.mMaterial != Materials.Magic)
+ && (tData.mMaterial.mMaterial.getMass() > 0L)) {
+ getSpecialSlot().stackSize -= 1;
+ aStack.stackSize -= 1;
+
+ this.mOutputItems[0] = ItemList.Tool_DataOrb.get(1L);
+ Behaviour_DataOrb.setDataTitle(this.mOutputItems[0], "Elemental-Scan");
+ Behaviour_DataOrb.setDataName(this.mOutputItems[0], tData.mMaterial.mMaterial.mElement.name());
+ calculateOverclockedNess(30, GT_Utility.safeInt(tData.mMaterial.mMaterial.getMass() * 8192L));
+ // In case recipe is too OP for that machine
+ if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1)
+ return FOUND_RECIPE_BUT_DID_NOT_MEET_REQUIREMENTS;
+ return 2;
+ }
+ }
+ if (ItemList.Tool_DataStick.isStackEqual(getSpecialSlot(), false, true)) {
+ if (ItemList.Tool_DataStick.isStackEqual(aStack, false, true)) {
+ aStack.stackSize -= 1;
+ this.mOutputItems[0] = GT_Utility.copyAmount(1, getSpecialSlot());
+ calculateOverclockedNess(30, 128);
+ // In case recipe is too OP for that machine
+ if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1)
+ return FOUND_RECIPE_BUT_DID_NOT_MEET_REQUIREMENTS;
+ return 2;
+ }
+ if (aStack.getItem() == Items.written_book) {
+ getSpecialSlot().stackSize -= 1;
+ aStack.stackSize -= 1;
+
+ this.mOutputItems[0] = GT_Utility.copyAmount(1, getSpecialSlot());
+ assert this.mOutputItems[0] != null;
+ this.mOutputItems[0].setTagCompound(aStack.getTagCompound());
+ calculateOverclockedNess(30, 128);
+ // In case recipe is too OP for that machine
+ if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1)
+ return FOUND_RECIPE_BUT_DID_NOT_MEET_REQUIREMENTS;
+ return 2;
+ }
+ if (aStack.getItem() == Items.filled_map) {
+ getSpecialSlot().stackSize -= 1;
+ aStack.stackSize -= 1;
+
+ this.mOutputItems[0] = GT_Utility.copyAmount(1, getSpecialSlot());
+ assert this.mOutputItems[0] != null;
+ this.mOutputItems[0].setTagCompound(
+ GT_Utility
+ .getNBTContainingShort(new NBTTagCompound(), "map_id", (short) aStack.getItemDamage()));
+ calculateOverclockedNess(30, 128);
+ // In case recipe is too OP for that machine
+ if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1)
+ return FOUND_RECIPE_BUT_DID_NOT_MEET_REQUIREMENTS;
+ return 2;
+ }
+
+ if ((aStack.getItem()
+ .getUnlocalizedName()
+ .contains("Schematic")
+ || aStack.getItem()
+ .getUnlocalizedName()
+ .contains("schematic"))
+ && !aStack.getItem()
+ .getUnlocalizedName()
+ .contains("Schematics")) {
+ if (mTier < 3) return FOUND_RECIPE_BUT_DID_NOT_MEET_REQUIREMENTS;
+ String sTier = "";
+
+ int stackItemID = Item.getIdFromItem(aStack.getItem());
+ int stackItemDamage = aStack.getItemDamage();
+ if (stackItemID == Item.getIdFromItem(
+ Objects.requireNonNull(GT_ModHandler.getModItem(GalacticraftCore.ID, "item.schematic", 1L, 0))
+ .getItem())) {
+ if (stackItemDamage == 0 && aStack.toString()
+ .equals(
+ Objects
+ .requireNonNull(
+ GT_ModHandler.getModItem(GalacticraftCore.ID, "item.schematic", 1L, 0))
+ .copy()
+ .toString()))
+ sTier = "100";
+ else if (stackItemDamage == 1 && aStack.toString()
+ .equals(
+ Objects
+ .requireNonNull(
+ GT_ModHandler.getModItem(GalacticraftCore.ID, "item.schematic", 1L, 1))
+ .copy()
+ .toString()))
+ sTier = "2";
+ } else {
+ if (stackItemID == Item.getIdFromItem(
+ Objects
+ .requireNonNull(GT_ModHandler.getModItem(GalacticraftMars.ID, "item.schematic", 1L, 0))
+ .getItem())) {
+ if (stackItemDamage == 0 && aStack.toString()
+ .equals(
+ Objects
+ .requireNonNull(
+ GT_ModHandler.getModItem(GalacticraftMars.ID, "item.schematic", 1L, 0))
+ .copy()
+ .toString()))
+ sTier = "3";
+ else if (stackItemDamage == 1 && aStack.toString()
+ .equals(
+ Objects
+ .requireNonNull(
+ GT_ModHandler.getModItem(GalacticraftMars.ID, "item.schematic", 1L, 1))
+ .copy()
+ .toString()))
+ sTier = "101";
+ else if (stackItemDamage == 2 && aStack.toString()
+ .equals(
+ Objects
+ .requireNonNull(
+ GT_ModHandler.getModItem(GalacticraftMars.ID, "item.schematic", 1L, 2))
+ .copy()
+ .toString()))
+ sTier = "102";
+ } else if (aStack.getUnlocalizedName()
+ .matches(".*\\d+.*"))
+ sTier = aStack.getUnlocalizedName()
+ .split("(?<=\\D)(?=\\d)")[1].substring(0, 1);
+ else sTier = "1";
+ }
+
+ getSpecialSlot().stackSize -= 1;
+ aStack.stackSize -= 1;
+
+ this.mOutputItems[0] = GT_Utility.copyAmount(1, getSpecialSlot());
+ assert this.mOutputItems[0] != null;
+ this.mOutputItems[0].setTagCompound(
+ GT_Utility.getNBTContainingShort(new NBTTagCompound(), "rocket_tier", Short.parseShort(sTier)));
+
+ calculateOverclockedNess(480, 36000);
+ // In case recipe is too OP for that machine
+ if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1)
+ return FOUND_RECIPE_BUT_DID_NOT_MEET_REQUIREMENTS;
+ return 2;
+ }
+ }
+ if (getSpecialSlot() == null && ItemList.Tool_DataStick.isStackEqual(aStack, false, true)) {
+ if (GT_Utility.ItemNBT.getBookTitle(aStack)
+ .equals("Raw Prospection Data")) {
+ GT_Utility.ItemNBT.setBookTitle(aStack, "Analyzed Prospection Data");
+ GT_Utility.ItemNBT.convertProspectionData(aStack);
+ aStack.stackSize -= 1;
+
+ this.mOutputItems[0] = GT_Utility.copyAmount(1, aStack);
+ calculateOverclockedNess(30, 1000);
+ // In case recipe is too OP for that machine
+ if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1)
+ return FOUND_RECIPE_BUT_DID_NOT_MEET_REQUIREMENTS;
+ return 2;
+ }
+ }
+ if (ItemList.Tool_DataStick.isStackEqual(getSpecialSlot(), false, true)) {
+ for (GT_Recipe.GT_Recipe_AssemblyLine tRecipe : GT_Recipe.GT_Recipe_AssemblyLine.sAssemblylineRecipes) {
+ if (GT_Utility.areStacksEqual(tRecipe.mResearchItem, aStack, true)) {
+ boolean failScanner = true;
+ for (GT_Recipe scannerRecipe : scannerFakeRecipes.getAllRecipes()) {
+ if (GT_Utility.areStacksEqual(scannerRecipe.mInputs[0], aStack, true)) {
+ failScanner = false;
+ break;
+ }
+ }
+ if (failScanner) {
+ return FOUND_RECIPE_BUT_DID_NOT_MEET_REQUIREMENTS;
+ }
+
+ this.mOutputItems[0] = GT_Utility.copyAmount(1, getSpecialSlot());
+
+ // Use Assline Utils
+ if (GT_AssemblyLineUtils.setAssemblyLineRecipeOnDataStick(this.mOutputItems[0], tRecipe)) {
+ aStack.stackSize -= 1;
+ calculateOverclockedNess(30, tRecipe.mResearchTime);
+ // In case recipe is too OP for that machine
+ if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1)
+ return FOUND_RECIPE_BUT_DID_NOT_MEET_REQUIREMENTS;
+ getSpecialSlot().stackSize -= 1;
+ return 2;
+ }
+ }
+ }
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ if (mProgresstime >= (mMaxProgresstime - 1)) {
+ if ((this.mOutputItems[0] != null) && (this.mOutputItems[0].getUnlocalizedName()
+ .equals("gt.metaitem.01.32707"))) {
+ GT_Mod.achievements.issueAchievement(
+ aBaseMetaTileEntity.getWorld()
+ .getPlayerEntityByName(aBaseMetaTileEntity.getOwnerName()),
+ "scanning");
+ }
+ }
+ super.onPostTick(aBaseMetaTileEntity, aTick);
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return scannerFakeRecipes;
+ }
+
+ @Override
+ public int getCapacity() {
+ return 1000;
+ }
+
+ @Override
+ protected boolean allowPutStackValidated(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return super.allowPutStackValidated(aBaseMetaTileEntity, aIndex, side, aStack)
+ && getRecipeMap().containsInput(aStack);
+ }
+
+ @Override
+ public void startSoundLoop(byte aIndex, double aX, double aY, double aZ) {
+ super.startSoundLoop(aIndex, aX, aY, aZ);
+ if (aIndex == 1) {
+ GT_Utility.doSoundAtClient(SoundResource.IC2_MACHINES_MAGNETIZER_LOOP, 10, 1.0F, aX, aY, aZ);
+ }
+ }
+
+ @Override
+ public void startProcess() {
+ sendLoopStart((byte) 1);
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Teleporter.java b/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Teleporter.java
new file mode 100644
index 0000000000..0666c55ac4
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Teleporter.java
@@ -0,0 +1,609 @@
+package gregtech.common.tileentities.machines.basic;
+
+import static gregtech.api.enums.GT_Values.V;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASINGS;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TELEPORTER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TELEPORTER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TELEPORTER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TELEPORTER_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TELEPORTER_SIDES;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TELEPORTER_SIDES_GLOW;
+
+import java.util.List;
+import java.util.function.Consumer;
+
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.EntityHanging;
+import net.minecraft.entity.EntityLiving;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.boss.EntityDragonPart;
+import net.minecraft.entity.effect.EntityWeatherEffect;
+import net.minecraft.entity.item.EntityBoat;
+import net.minecraft.entity.item.EntityEnderCrystal;
+import net.minecraft.entity.item.EntityEnderEye;
+import net.minecraft.entity.item.EntityFireworkRocket;
+import net.minecraft.entity.item.EntityItem;
+import net.minecraft.entity.item.EntityMinecart;
+import net.minecraft.entity.item.EntityTNTPrimed;
+import net.minecraft.entity.item.EntityXPOrb;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.projectile.EntityArrow;
+import net.minecraft.entity.projectile.EntityFireball;
+import net.minecraft.entity.projectile.EntityFishHook;
+import net.minecraft.entity.projectile.EntityThrowable;
+import net.minecraft.inventory.IInventory;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.AxisAlignedBB;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.world.World;
+import net.minecraftforge.common.DimensionManager;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidStack;
+
+import com.gtnewhorizons.modularui.api.NumberFormatMUI;
+import com.gtnewhorizons.modularui.api.drawable.IDrawable;
+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.DrawableWidget;
+import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.api.enums.ConfigCategories;
+import gregtech.api.gui.modularui.GT_UIInfos;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.gui.modularui.GUITextureSet;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.modularui.IAddGregtechLogo;
+import gregtech.api.interfaces.modularui.IAddUIWidgets;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicTank;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Config;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_Teleporter extends GT_MetaTileEntity_BasicTank
+ implements IAddGregtechLogo, IAddUIWidgets {
+
+ private static boolean sInterDimensionalTeleportAllowed = true;
+ private static int sPassiveEnergyDrain = 2048;
+ private static int sPowerMultiplyer = 100;
+ private static double sFPowerMultiplyer = 1.0;
+ public int mTargetX = 0;
+ public int mTargetY = 0;
+ public int mTargetZ = 0;
+ public int mTargetD = Integer.MIN_VALUE;
+ public boolean mDebug = false;
+
+ public GT_MetaTileEntity_Teleporter(int aID, String aName, String aNameRegional, int aTier) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ 3,
+ new String[] { "Teleport long distances with this little device.", "Use a Dragon Egg or Nitrogen Plasma",
+ "for Inter-dimensional transmission" });
+ }
+
+ public GT_MetaTileEntity_Teleporter(String aName, int aTier, String aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, 3, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_Teleporter(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, 3, aDescription, aTextures);
+ }
+
+ private static float calculateWeight(Entity aEntity) {
+ if ((aEntity instanceof EntityFishHook)) {
+ return -1.0F;
+ }
+ if ((aEntity instanceof EntityDragonPart)) {
+ return -1.0F;
+ }
+ if ((aEntity instanceof EntityWeatherEffect)) {
+ return -1.0F;
+ }
+ if ((aEntity instanceof EntityPlayer tPlayer)) {
+ int tCount = 64;
+ for (int i = 0; i < 36; i++) {
+ if (tPlayer.inventory.getStackInSlot(i) != null) {
+ tCount += (tPlayer.inventory.getStackInSlot(i)
+ .getMaxStackSize() > 1 ? tPlayer.inventory.getStackInSlot(i).stackSize : 64);
+ }
+ }
+ for (int i = 0; i < 4; i++) {
+ if (tPlayer.inventory.armorInventory[i] != null) {
+ tCount += 256;
+ }
+ }
+ return Math.min(5.0F, tCount / 666.6F);
+ }
+ if (GT_Utility.getClassName(aEntity)
+ .equals("EntityItnt")) {
+ return 5.0F;
+ }
+ if (GT_Utility.getClassName(aEntity)
+ .equals("EntityNuke")) {
+ return 50.0F;
+ }
+ if ((aEntity instanceof EntityArrow)) {
+ return 0.001F;
+ }
+ if ((aEntity instanceof EntityBoat)) {
+ return 0.1F;
+ }
+ if ((aEntity instanceof EntityEnderCrystal)) {
+ return 2.0F;
+ }
+ if ((aEntity instanceof EntityEnderEye)) {
+ return 0.001F;
+ }
+ if ((aEntity instanceof EntityFireball)) {
+ return 0.001F;
+ }
+ if ((aEntity instanceof EntityFireworkRocket)) {
+ return 0.001F;
+ }
+ if ((aEntity instanceof EntityHanging)) {
+ return 0.005F;
+ }
+ if ((aEntity instanceof EntityItem)) {
+ return 0.001F;
+ }
+ if ((aEntity instanceof EntityLiving)) {
+ return 0.5F;
+ }
+ if ((aEntity instanceof EntityMinecart)) {
+ return 0.1F;
+ }
+ if ((aEntity instanceof EntityThrowable)) {
+ return 0.001F;
+ }
+ if ((aEntity instanceof EntityTNTPrimed)) {
+ return 5.0F;
+ }
+ if ((aEntity instanceof EntityXPOrb)) {
+ return 0.001F;
+ }
+ return -1.0F;
+ }
+
+ @Override
+ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) {
+ if (aBaseMetaTileEntity.isClientSide()) return true;
+ GT_UIInfos.openGTTileEntityUI(aBaseMetaTileEntity, aPlayer);
+ return true;
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Teleporter(this.mName, this.mTier, this.mDescriptionArray, this.mTextures);
+ }
+
+ @Override
+ public boolean isGivingInformation() {
+ return true;
+ }
+
+ @Override
+ public String[] getInfoData() {
+ return new String[] { "Coordinates:",
+ "X: " + EnumChatFormatting.GREEN + GT_Utility.formatNumbers(this.mTargetX) + EnumChatFormatting.RESET,
+ "Y: " + EnumChatFormatting.GREEN + GT_Utility.formatNumbers(this.mTargetY) + EnumChatFormatting.RESET,
+ "Z: " + EnumChatFormatting.GREEN + GT_Utility.formatNumbers(this.mTargetZ) + EnumChatFormatting.RESET,
+ "Dimension: " + EnumChatFormatting.GREEN + this.mTargetD + EnumChatFormatting.RESET,
+ "Dimension Valid: " + (GT_Utility.isRealDimension(this.mTargetD)
+ ? EnumChatFormatting.GREEN + "Yes" + EnumChatFormatting.RESET
+ : EnumChatFormatting.RED + "No" + EnumChatFormatting.RESET),
+ "Dimension Registered: " + (DimensionManager.isDimensionRegistered(this.mTargetD)
+ ? EnumChatFormatting.GREEN + "Yes" + EnumChatFormatting.RESET
+ : EnumChatFormatting.RED + "No" + EnumChatFormatting.RESET) };
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection aFacing,
+ int colorIndex, boolean aActive, boolean redstoneLevel) {
+ if (side != this.getBaseMetaTileEntity()
+ .getFrontFacing())
+ return new ITexture[] { MACHINE_CASINGS[mTier][colorIndex + 1], TextureFactory.of(OVERLAY_TELEPORTER_SIDES),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_TELEPORTER_SIDES_GLOW)
+ .glow()
+ .build() };
+ if (aActive) return new ITexture[] { MACHINE_CASINGS[mTier][colorIndex + 1],
+ TextureFactory.of(OVERLAY_TELEPORTER_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_TELEPORTER_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ return new ITexture[] { MACHINE_CASINGS[mTier][colorIndex + 1], TextureFactory.of(OVERLAY_TELEPORTER),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_TELEPORTER_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ if (mFluid != null) aNBT.setTag("mFluid", mFluid.writeToNBT(new NBTTagCompound()));
+ aNBT.setInteger("mTargetX", this.mTargetX);
+ aNBT.setInteger("mTargetY", this.mTargetY);
+ aNBT.setInteger("mTargetZ", this.mTargetZ);
+ aNBT.setInteger("mTargetD", this.mTargetD);
+ aNBT.setBoolean("mDebug", this.mDebug);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ mFluid = FluidStack.loadFluidStackFromNBT(aNBT.getCompoundTag("mFluid"));
+ this.mTargetX = aNBT.getInteger("mTargetX");
+ this.mTargetY = aNBT.getInteger("mTargetY");
+ this.mTargetZ = aNBT.getInteger("mTargetZ");
+ this.mTargetD = aNBT.getInteger("mTargetD");
+ this.mDebug = aNBT.getBoolean("mDebug");
+ }
+
+ @Override
+ public void onConfigLoad(GT_Config aConfig) {
+ sInterDimensionalTeleportAllowed = aConfig
+ .get(ConfigCategories.machineconfig, "Teleporter.Interdimensional", true);
+ sPassiveEnergyDrain = aConfig
+ .get(ConfigCategories.machineconfig, "Teleporter.PassiveDrain", sPassiveEnergyDrain);
+ sPowerMultiplyer = aConfig.get(ConfigCategories.machineconfig, "Teleporter.PowerMultipler", sPowerMultiplyer);
+ sFPowerMultiplyer = sPowerMultiplyer / 100.0;
+ }
+
+ @Override
+ public void onFirstTick(IGregTechTileEntity aBaseMetaTileEntity) {
+ if (getBaseMetaTileEntity().isServerSide()) {
+ if ((this.mTargetX == 0) && (this.mTargetY == 0)
+ && (this.mTargetZ == 0)
+ && (this.mTargetD == Integer.MIN_VALUE)) {
+ this.mTargetX = aBaseMetaTileEntity.getXCoord();
+ this.mTargetY = aBaseMetaTileEntity.getYCoord();
+ this.mTargetZ = aBaseMetaTileEntity.getZCoord();
+ this.mTargetD = aBaseMetaTileEntity.getWorld().provider.dimensionId;
+ }
+ }
+ }
+
+ public boolean hasDimensionalTeleportCapability() {
+ return this.mDebug || sInterDimensionalTeleportAllowed;
+ }
+
+ public boolean isDimensionalTeleportAvailable() {
+ return this.mDebug || (hasDimensionalTeleportCapability() && GT_Utility.isRealDimension(this.mTargetD)
+ && GT_Utility.isRealDimension(getBaseMetaTileEntity().getWorld().provider.dimensionId));
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+
+ if (mFluid != null) { // Was if null -> Materials.Nitrogen.getPlasma(0);
+ mFluid = null;
+ }
+ super.onPostTick(aBaseMetaTileEntity, aTick);
+ if (getBaseMetaTileEntity().isServerSide()) {
+ if ((getBaseMetaTileEntity().isAllowedToWork()) && (getBaseMetaTileEntity().getRedstone())) {
+ if (getBaseMetaTileEntity().decreaseStoredEnergyUnits(sPassiveEnergyDrain, false)) {
+ int tDistance = distanceCalculation();
+ if (mInventory[0] != null) {
+ TileEntity tTile = null;
+ if (this.mTargetD == getBaseMetaTileEntity().getWorld().provider.dimensionId) {
+ tTile = getBaseMetaTileEntity().getTileEntity(this.mTargetX, this.mTargetY, this.mTargetZ);
+ } else {
+ World tWorld = DimensionManager.getWorld(this.mTargetD);
+ if (tWorld != null) {
+ tTile = tWorld.getTileEntity(this.mTargetX, this.mTargetY, this.mTargetZ);
+ }
+ }
+ if (tTile instanceof IInventory) {
+ int tStacksize = mInventory[0].stackSize;
+ GT_Utility.moveOneItemStack(
+ this,
+ tTile,
+ ForgeDirection.DOWN,
+ ForgeDirection.DOWN,
+ null,
+ false,
+ (byte) 64,
+ (byte) 1,
+ (byte) 64,
+ (byte) 1);
+ if (mInventory[0] == null || mInventory[0].stackSize < tStacksize) {
+ getBaseMetaTileEntity().decreaseStoredEnergyUnits(
+ (long) (Math.pow(tDistance, 1.5) * tDistance
+ * (tStacksize - (mInventory[0] == null ? 0 : mInventory[0].stackSize))
+ * sFPowerMultiplyer),
+ false);
+ }
+ }
+ }
+ List<Entity> entities_in_box = getBaseMetaTileEntity().getWorld()
+ .getEntitiesWithinAABB(
+ Entity.class,
+ AxisAlignedBB.getBoundingBox(
+ getBaseMetaTileEntity().getOffsetX(getBaseMetaTileEntity().getFrontFacing(), 2) - 1,
+ getBaseMetaTileEntity().getOffsetY(getBaseMetaTileEntity().getFrontFacing(), 2) - 1,
+ getBaseMetaTileEntity().getOffsetZ(getBaseMetaTileEntity().getFrontFacing(), 2) - 1,
+ getBaseMetaTileEntity().getOffsetX(getBaseMetaTileEntity().getFrontFacing(), 2) + 2,
+ getBaseMetaTileEntity().getOffsetY(getBaseMetaTileEntity().getFrontFacing(), 2) + 2,
+ getBaseMetaTileEntity().getOffsetZ(getBaseMetaTileEntity().getFrontFacing(), 2) + 2));
+
+ for (Object tObject : entities_in_box) {
+ if (((tObject instanceof Entity tEntity)) && (!((Entity) tObject).isDead)) {
+ if (getBaseMetaTileEntity().decreaseStoredEnergyUnits(
+ (long) (Math.pow(tDistance, 1.5) * calculateWeight(tEntity) * sFPowerMultiplyer),
+ false)) {
+
+ if (tEntity.ridingEntity != null) {
+ tEntity.mountEntity(null);
+ }
+ if (tEntity.riddenByEntity != null) {
+ tEntity.riddenByEntity.mountEntity(null);
+ }
+ if ((this.mTargetD == getBaseMetaTileEntity().getWorld().provider.dimensionId)
+ || (!isDimensionalTeleportAvailable())
+ || (!GT_Utility.moveEntityToDimensionAtCoords(
+ tEntity,
+ this.mTargetD,
+ this.mTargetX + 0.5D,
+ this.mTargetY + 0.5D,
+ this.mTargetZ + 0.5D))) {
+ if ((tEntity instanceof EntityLivingBase)) {
+ ((EntityLivingBase) tEntity).setPositionAndUpdate(
+ this.mTargetX + 0.5D,
+ this.mTargetY + 0.5D,
+ this.mTargetZ + 0.5D);
+ } else {
+ tEntity.setPosition(
+ this.mTargetX + 0.5D,
+ this.mTargetY + 0.5D,
+ this.mTargetZ + 0.5D);
+ }
+ }
+ }
+ }
+ }
+ }
+ getBaseMetaTileEntity().setActive(true);
+ } else {
+ getBaseMetaTileEntity().setActive(false);
+ }
+ }
+ }
+
+ private int distanceCalculation() {
+ return Math.abs(
+ ((this.mTargetD != getBaseMetaTileEntity().getWorld().provider.dimensionId)
+ && (isDimensionalTeleportAvailable())
+ ? 4000
+ : (int) Math.sqrt(
+ Math.pow(getBaseMetaTileEntity().getXCoord() - this.mTargetX, 2.0D)
+ + Math.pow(getBaseMetaTileEntity().getYCoord() - this.mTargetY, 2.0D)
+ + Math.pow(getBaseMetaTileEntity().getZCoord() - this.mTargetZ, 2.0D))));
+ }
+
+ @Override
+ public boolean isSimpleMachine() {
+ return false;
+ }
+
+ @Override
+ public boolean isOverclockerUpgradable() {
+ return false;
+ }
+
+ @Override
+ public boolean isTransformerUpgradable() {
+ return false;
+ }
+
+ @Override
+ public boolean isElectric() {
+ return true;
+ }
+
+ @Override
+ public boolean isFacingValid(ForgeDirection facing) {
+ return true;
+ }
+
+ @Override
+ public boolean isEnetInput() {
+ return true;
+ }
+
+ @Override
+ public boolean isInputFacing(ForgeDirection side) {
+ return true;
+ }
+
+ @Override
+ public boolean isOutputFacing(ForgeDirection side) {
+ return false;
+ }
+
+ @Override
+ public boolean isTeleporterCompatible() {
+ return false;
+ }
+
+ @Override
+ public long getMinimumStoredEU() {
+ return V[mTier] * 16;
+ }
+
+ @Override
+ public long maxEUStore() {
+ return 100000000;
+ }
+
+ @Override
+ public long maxEUInput() {
+ return V[mTier];
+ }
+
+ @Override
+ public long maxSteamStore() {
+ return maxEUStore();
+ }
+
+ @Override
+ public long maxAmperesIn() {
+ return 2;
+ }
+
+ @Override
+ public int getStackDisplaySlot() {
+ return 2;
+ }
+
+ @Override
+ public boolean isAccessAllowed(EntityPlayer aPlayer) {
+ return true;
+ }
+
+ @Override
+ public int getInputSlot() {
+ return 0;
+ }
+
+ @Override
+ public int getOutputSlot() {
+ return 0;
+ }
+
+ @Override
+ public int getCapacity() {
+ return 64000;
+ }
+
+ @Override
+ public boolean doesFillContainers() {
+ return false;
+ }
+
+ @Override
+ public boolean doesEmptyContainers() {
+ return false;
+ }
+
+ @Override
+ public boolean canTankBeFilled() {
+ return true;
+ }
+
+ @Override
+ public boolean canTankBeEmptied() {
+ return true;
+ }
+
+ @Override
+ public boolean displaysItemStack() {
+ return false;
+ }
+
+ @Override
+ public boolean displaysStackSize() {
+ return false;
+ }
+
+ @Override
+ public ITexture[][][] getTextureSet(ITexture[] aTextures) {
+ return null;
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ protected static final NumberFormatMUI numberFormat = new NumberFormatMUI();
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ builder.widget(
+ new DrawableWidget().setDrawable(GT_UITextures.PICTURE_SCREEN_BLACK)
+ .setSize(90, 72)
+ .setPos(43, 4))
+ .widget(
+ new TextWidget().setStringSupplier(() -> "X: " + numberFormat.format(mTargetX))
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setPos(46, 8))
+ .widget(
+ new TextWidget().setStringSupplier(() -> "Y: " + numberFormat.format(mTargetY))
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setPos(46, 16))
+ .widget(
+ new TextWidget().setStringSupplier(() -> "Z: " + numberFormat.format(mTargetZ))
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setPos(46, 24))
+ .widget(
+ new TextWidget().setStringSupplier(() -> "Dim: " + numberFormat.format(mTargetD))
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setPos(46, 32))
+ .widget(
+ TextWidget.dynamicString(() -> "Dim Valid: " + (GT_Utility.isRealDimension(mTargetD) ? "Yes" : "No"))
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setEnabled(widget -> hasDimensionalTeleportCapability())
+ .setPos(46, 40))
+ .widget(new FakeSyncWidget.FluidStackSyncer(() -> mFluid, val -> mFluid = val));
+
+ addChangeNumberButtons(builder, GT_UITextures.OVERLAY_BUTTON_MINUS_LARGE, -512, -64, 7);
+ addChangeNumberButtons(builder, GT_UITextures.OVERLAY_BUTTON_MINUS_SMALL, -16, -1, 25);
+ addChangeNumberButtons(builder, GT_UITextures.OVERLAY_BUTTON_PLUS_SMALL, 16, 1, 133);
+ addChangeNumberButtons(builder, GT_UITextures.OVERLAY_BUTTON_PLUS_LARGE, 512, 64, 151);
+
+ addChangeNumberButton(
+ builder,
+ GT_UITextures.OVERLAY_BUTTON_MINUS_LARGE,
+ val -> mTargetD += val,
+ -16,
+ -8,
+ 7,
+ 58);
+ addChangeNumberButton(
+ builder,
+ GT_UITextures.OVERLAY_BUTTON_MINUS_SMALL,
+ val -> mTargetD += val,
+ -4,
+ -1,
+ 25,
+ 58);
+ addChangeNumberButton(builder, GT_UITextures.OVERLAY_BUTTON_PLUS_SMALL, val -> mTargetD += val, 4, 1, 133, 58);
+ addChangeNumberButton(builder, GT_UITextures.OVERLAY_BUTTON_PLUS_LARGE, val -> mTargetD += val, 16, 8, 151, 58);
+ }
+
+ private void addChangeNumberButtons(ModularWindow.Builder builder, IDrawable overlay, int addNumberShift,
+ int addNumber, int xPos) {
+ addChangeNumberButton(builder, overlay, val -> mTargetX += val, addNumberShift, addNumber, xPos, 4);
+ addChangeNumberButton(builder, overlay, val -> mTargetY += val, addNumberShift, addNumber, xPos, 22);
+ addChangeNumberButton(builder, overlay, val -> mTargetZ += val, addNumberShift, addNumber, xPos, 40);
+ }
+
+ private void addChangeNumberButton(ModularWindow.Builder builder, IDrawable overlay, Consumer<Integer> setter,
+ int addNumberShift, int addNumber, int xPos, int yPos) {
+ builder.widget(
+ new ButtonWidget()
+ .setOnClick((clickData, widget) -> setter.accept(clickData.shift ? addNumberShift : addNumber))
+ .setBackground(GT_UITextures.BUTTON_STANDARD, overlay)
+ .setSize(18, 18)
+ .setPos(xPos, yPos));
+ }
+
+ @Override
+ public GUITextureSet getGUITextureSet() {
+ return new GUITextureSet().setGregTechLogo(GT_UITextures.PICTURE_GT_LOGO_17x17_TRANSPARENT_GRAY);
+ }
+
+ @Override
+ public void addGregTechLogo(ModularWindow.Builder builder) {
+ builder.widget(
+ new DrawableWidget().setDrawable(getGUITextureSet().getGregTechLogo())
+ .setSize(17, 17)
+ .setPos(113, 56));
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/long_distance/GT_MetaTileEntity_LongDistancePipelineBase.java b/src/main/java/gregtech/common/tileentities/machines/long_distance/GT_MetaTileEntity_LongDistancePipelineBase.java
new file mode 100644
index 0000000000..ff3048f4b2
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/long_distance/GT_MetaTileEntity_LongDistancePipelineBase.java
@@ -0,0 +1,415 @@
+/**
+ *
+ * Inspired/ported from GregTech 6 under the LGPL license
+ *
+ * Copyright (c) 2020 GregTech-6 Team
+ *
+ * This file is part of GregTech.
+ *
+ * GregTech is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * GregTech is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with GregTech. If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+package gregtech.common.tileentities.machines.long_distance;
+
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASINGS;
+import static mcp.mobius.waila.api.SpecialChars.BLUE;
+import static mcp.mobius.waila.api.SpecialChars.GOLD;
+import static mcp.mobius.waila.api.SpecialChars.GREEN;
+import static mcp.mobius.waila.api.SpecialChars.RED;
+import static mcp.mobius.waila.api.SpecialChars.RESET;
+import static mcp.mobius.waila.api.SpecialChars.YELLOW;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+
+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.tileentity.TileEntity;
+import net.minecraft.util.ChunkCoordinates;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.items.GT_Block_LongDistancePipe;
+import gregtech.api.metatileentity.BaseMetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicHull_NonElectric;
+import gregtech.api.util.GT_Utility;
+import mcp.mobius.waila.api.IWailaConfigHandler;
+import mcp.mobius.waila.api.IWailaDataAccessor;
+
+public abstract class GT_MetaTileEntity_LongDistancePipelineBase extends GT_MetaTileEntity_BasicHull_NonElectric {
+
+ protected static final int INPUT_INDEX = 0;
+ protected static final int OUTPUT_INDEX = 1;
+ protected static final int SIDE_UP_DOWN_INDEX = 2;
+ protected static final int SIDE_LEFT_RIGHT_INDEX = 3;
+
+ public static int minimalDistancePoints = 64;
+
+ protected GT_MetaTileEntity_LongDistancePipelineBase mTarget = null;
+ // these two are updated by machine block update thread, so must be volatile
+ protected volatile GT_MetaTileEntity_LongDistancePipelineBase mSender = null;
+ protected volatile ChunkCoordinates mTargetPos = null;
+ protected GT_MetaTileEntity_LongDistancePipelineBase mTooCloseTarget = null, mTooCloseSender = null;
+
+ public GT_MetaTileEntity_LongDistancePipelineBase(int aID, String aName, String aNameRegional, int aTier,
+ String aDescription) {
+ super(aID, aName, aNameRegional, aTier, aDescription);
+ }
+
+ public GT_MetaTileEntity_LongDistancePipelineBase(String aName, int aTier, String aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ }
+
+ @Override
+ public String[] getDescription() {
+ return new String[] { "Only one Input and Output are allowed per pipeline",
+ "Only Input and Output have to be chunkloaded", "Transfer rate is solely limited by input rate",
+ "Minimum distance: " + minimalDistancePoints + " blocks" };
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ if (mTargetPos != null && mTarget != this) {
+ aNBT.setBoolean("target", true);
+ aNBT.setInteger("target.x", mTargetPos.posX);
+ aNBT.setInteger("target.y", mTargetPos.posY);
+ aNBT.setInteger("target.z", mTargetPos.posZ);
+ }
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ if (aNBT.hasKey("target")) {
+ mTargetPos = new ChunkCoordinates(
+ aNBT.getInteger("target.x"),
+ aNBT.getInteger("target.y"),
+ aNBT.getInteger("target.z"));
+ if (getDistanceToSelf(mTargetPos) < minimalDistancePoints) mTargetPos = null;
+ }
+ }
+
+ public boolean isSameClass(GT_MetaTileEntity_LongDistancePipelineBase other) {
+ return false;
+ }
+
+ @Override
+ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) {
+ if (aBaseMetaTileEntity.isClientSide()) return true;
+ ItemStack tCurrentItem = aPlayer.inventory.getCurrentItem();
+ if (tCurrentItem != null) {
+ if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sSoftHammerList)) {
+ scanPipes();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean isDead() {
+ return getBaseMetaTileEntity() == null || getBaseMetaTileEntity().isDead();
+ }
+
+ public boolean checkTarget() {
+ final IGregTechTileEntity gt_tile = getBaseMetaTileEntity();
+ if (gt_tile == null || !gt_tile.isAllowedToWork() || gt_tile.isClientSide()) return false;
+ World world = gt_tile.getWorld();
+ if (world == null) return false;
+
+ if (mTargetPos == null) {
+ // We don't have a target position, scan the pipes
+ scanPipes();
+ } else if (mTarget == null || mTarget.isDead()) {
+ // We don't have a target, or it's dead. Try checking the target position
+ mTarget = null;
+ if (world.blockExists(mTargetPos.posX, mTargetPos.posY, mTargetPos.posZ)) {
+ // Only check if the target position is loaded
+ TileEntity te = world.getTileEntity(mTargetPos.posX, mTargetPos.posY, mTargetPos.posZ);
+ final IMetaTileEntity tMeta;
+ if (te instanceof BaseMetaTileEntity
+ && ((tMeta = ((BaseMetaTileEntity) te)
+ .getMetaTileEntity()) instanceof GT_MetaTileEntity_LongDistancePipelineBase)
+ && isSameClass((GT_MetaTileEntity_LongDistancePipelineBase) tMeta)) {
+ // It's the right type!
+ mTarget = (GT_MetaTileEntity_LongDistancePipelineBase) tMeta;
+ } else if (te != null) {
+ // It isn't the right type, kill the target position
+ mTargetPos = null;
+ }
+ }
+ }
+ if (mTooCloseTarget != null && mTooCloseTarget.mSender == null) mTooCloseTarget.mTooCloseSender = this;
+ if (mTooCloseSender != null && (mTooCloseSender.isDead() || mTooCloseSender.mTarget != null))
+ mTooCloseSender = null;
+ if (mTarget == null || mTarget == this) return false;
+ if (mTarget.mSender == null || mTarget.mSender.isDead()
+ || mTarget.mSender.mTarget == null
+ || mTarget.mSender.mTarget.isDead()) {
+ mTarget.mSender = this;
+ mTarget.mTooCloseSender = null;
+ }
+
+ return mTarget.mSender == this;
+ }
+
+ @Override
+ public ArrayList<String> getSpecialDebugInfo(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer,
+ int aLogLevel, ArrayList<String> aList) {
+ if (mSender != null && !mSender.isDead() && mSender.mTarget == this) {
+ final ChunkCoordinates coords = mSender.getCoords();
+ aList.addAll(
+ Arrays.asList(
+ "Is Pipeline Output",
+ "Pipeline Input is at: X: " + coords.posX + " Y: " + coords.posY + " Z: " + coords.posZ));
+ } else {
+ aList.addAll(
+ Arrays.asList(
+ checkTarget() ? "Is connected to Pipeline Output" : "Pipeline Output is not connected/chunkloaded",
+ "Pipeline Output should be around: X: " + mTargetPos.posX
+ + " Y: "
+ + mTargetPos.posY
+ + " Z: "
+ + mTargetPos.posZ));
+ }
+
+ return aList;
+ }
+
+ // What meta should the pipes for this pipeline have
+ public abstract int getPipeMeta();
+
+ protected void scanPipes() {
+ if (mSender != null && !mSender.isDead() && mSender.mTarget == this) return;
+
+ // Check if we need to scan anything
+ final IGregTechTileEntity gtTile = getBaseMetaTileEntity();
+ if (gtTile == null) return;
+
+ final World world = gtTile.getWorld();
+ if (world == null) return;
+
+ mTargetPos = getCoords();
+ mTarget = this;
+ mSender = null;
+
+ // Start scanning from the output side
+ Block aBlock = gtTile.getBlockAtSide(gtTile.getBackFacing());
+
+ if (aBlock instanceof GT_Block_LongDistancePipe) {
+ byte aMetaData = gtTile.getMetaIDAtSide(gtTile.getBackFacing());
+ if (aMetaData != getPipeMeta()) return;
+
+ HashSet<ChunkCoordinates> tVisited = new HashSet<>(Collections.singletonList(getCoords())),
+ tWires = new HashSet<>();
+ Queue<ChunkCoordinates> tQueue = new LinkedList<>(
+ Collections.singletonList(getFacingOffset(gtTile, gtTile.getBackFacing())));
+
+ while (!tQueue.isEmpty()) {
+ final ChunkCoordinates aCoords = tQueue.poll();
+
+ if (world.getBlock(aCoords.posX, aCoords.posY, aCoords.posZ) == aBlock
+ && world.getBlockMetadata(aCoords.posX, aCoords.posY, aCoords.posZ) == aMetaData) {
+ // We've got another pipe/wire block
+ // TODO: Make sure it's the right type of pipe/wire via meta
+ ChunkCoordinates tCoords;
+ tWires.add(aCoords);
+
+ // For each direction, if we haven't already visited that coordinate, add it to the end of the
+ // queue
+ if (tVisited.add(tCoords = new ChunkCoordinates(aCoords.posX + 1, aCoords.posY, aCoords.posZ)))
+ tQueue.add(tCoords);
+ if (tVisited.add(tCoords = new ChunkCoordinates(aCoords.posX - 1, aCoords.posY, aCoords.posZ)))
+ tQueue.add(tCoords);
+ if (tVisited.add(tCoords = new ChunkCoordinates(aCoords.posX, aCoords.posY + 1, aCoords.posZ)))
+ tQueue.add(tCoords);
+ if (tVisited.add(tCoords = new ChunkCoordinates(aCoords.posX, aCoords.posY - 1, aCoords.posZ)))
+ tQueue.add(tCoords);
+ if (tVisited.add(tCoords = new ChunkCoordinates(aCoords.posX, aCoords.posY, aCoords.posZ + 1)))
+ tQueue.add(tCoords);
+ if (tVisited.add(tCoords = new ChunkCoordinates(aCoords.posX, aCoords.posY, aCoords.posZ - 1)))
+ tQueue.add(tCoords);
+ } else {
+ // It's not a block - let's see if it's a tile entity
+ TileEntity tTileEntity = world.getTileEntity(aCoords.posX, aCoords.posY, aCoords.posZ);
+ if (tTileEntity != gtTile && tTileEntity instanceof BaseMetaTileEntity
+ && ((BaseMetaTileEntity) tTileEntity)
+ .getMetaTileEntity() instanceof GT_MetaTileEntity_LongDistancePipelineBase tGtTile) {
+ if (isSameClass(tGtTile) && tWires.contains(
+ tGtTile.getFacingOffset(
+ (BaseMetaTileEntity) tTileEntity,
+ ((BaseMetaTileEntity) tTileEntity).getFrontFacing()))) {
+ // If it's the same class, and we've scanned a wire in front of it (the input side), we've
+ // found our target
+ // still need to check if it's distant enough
+ int distance = getDistanceToSelf(aCoords);
+ if (distance > minimalDistancePoints) {
+ mTarget = tGtTile;
+ mTargetPos = tGtTile.getCoords();
+ mTooCloseTarget = null;
+ return;
+ } else {
+ if (mTooCloseTarget == null) {
+ mTooCloseTarget = tGtTile;
+ }
+ }
+ }
+
+ // Remove this block from the visited because we might end up back here from another wire that
+ // IS connected to the
+ // input side
+ tVisited.remove(aCoords);
+ }
+ }
+ }
+ }
+ }
+
+ protected int getDistanceToSelf(ChunkCoordinates aCoords) {
+ return Math.abs(getBaseMetaTileEntity().getXCoord() - aCoords.posX)
+ + Math.abs(getBaseMetaTileEntity().getYCoord() - aCoords.posY) / 2
+ + Math.abs(getBaseMetaTileEntity().getZCoord() - aCoords.posZ);
+ }
+
+ public ChunkCoordinates getFacingOffset(IGregTechTileEntity gt_tile, ForgeDirection side) {
+ return new ChunkCoordinates(
+ gt_tile.getOffsetX(side, 1),
+ gt_tile.getOffsetY(side, 1),
+ gt_tile.getOffsetZ(side, 1));
+ }
+
+ public ChunkCoordinates getCoords() {
+ final IGregTechTileEntity gt_tile = getBaseMetaTileEntity();
+ return new ChunkCoordinates(gt_tile.getXCoord(), gt_tile.getYCoord(), gt_tile.getZCoord());
+ }
+
+ @Override
+ public void onMachineBlockUpdate() {
+ mTargetPos = null;
+ mSender = null;
+ }
+
+ @Override
+ public boolean shouldTriggerBlockUpdate() {
+ return true;
+ }
+
+ abstract public ITexture[] getTextureOverlays();
+
+ @Override
+ public ITexture[][][] getTextureSet(ITexture[] aTextures) {
+ ITexture[][][] rTextures = new ITexture[4][17][];
+ ITexture[] overlays = getTextureOverlays();
+ for (int i = 0; i < rTextures[0].length; i++) {
+ rTextures[INPUT_INDEX][i] = new ITexture[] { MACHINE_CASINGS[mTier][i], overlays[INPUT_INDEX] };
+ rTextures[OUTPUT_INDEX][i] = new ITexture[] { MACHINE_CASINGS[mTier][i], overlays[OUTPUT_INDEX] };
+ rTextures[SIDE_UP_DOWN_INDEX][i] = new ITexture[] { MACHINE_CASINGS[mTier][i],
+ overlays[SIDE_UP_DOWN_INDEX] };
+ rTextures[SIDE_LEFT_RIGHT_INDEX][i] = new ITexture[] { MACHINE_CASINGS[mTier][i],
+ overlays[SIDE_LEFT_RIGHT_INDEX] };
+ }
+ return rTextures;
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity baseMetaTileEntity, ForgeDirection sideDirection,
+ ForgeDirection facingDirection, int colorIndex, boolean active, boolean redstoneLevel) {
+ colorIndex += 1;
+ if (sideDirection == facingDirection) return mTextures[INPUT_INDEX][colorIndex];
+ else if (sideDirection == facingDirection.getOpposite()) return mTextures[OUTPUT_INDEX][colorIndex];
+ else {
+ switch (facingDirection) {
+ case UP, DOWN -> {
+ return mTextures[SIDE_UP_DOWN_INDEX][colorIndex];
+ }
+ case NORTH -> {
+ switch (sideDirection) {
+ case DOWN, UP -> {
+ return mTextures[SIDE_UP_DOWN_INDEX][colorIndex];
+ }
+ case EAST, WEST -> {
+ return mTextures[SIDE_LEFT_RIGHT_INDEX][colorIndex];
+ }
+ default -> {}
+ }
+ }
+ case SOUTH -> {
+ switch (sideDirection) {
+ case DOWN, UP -> {
+ return mTextures[SIDE_UP_DOWN_INDEX][colorIndex];
+ }
+ case EAST, WEST -> {
+ return mTextures[SIDE_LEFT_RIGHT_INDEX][colorIndex];
+ }
+ default -> {}
+ }
+ }
+ case EAST, WEST -> {
+ return mTextures[SIDE_LEFT_RIGHT_INDEX][colorIndex];
+ }
+ default -> {}
+ }
+ }
+ return mTextures[INPUT_INDEX][colorIndex]; // dummy
+ }
+
+ @Override
+ public void getWailaBody(ItemStack itemStack, List<String> currentTip, IWailaDataAccessor accessor,
+ IWailaConfigHandler config) {
+ final ForgeDirection facing = getBaseMetaTileEntity().getFrontFacing();
+ final ForgeDirection side = accessor.getSide();
+
+ final NBTTagCompound tag = accessor.getNBTData();
+ final boolean hasInput = tag.getBoolean("hasInput");
+ final boolean hasInputTooClose = tag.getBoolean("hasInputTooClose");
+ final boolean hasOutput = tag.getBoolean("hasOutput");
+ final boolean hasOutputTooClose = tag.getBoolean("hasOutputTooClose");
+
+ if (side == facing) currentTip.add(GOLD + "Pipeline Input" + RESET);
+ else if (side == facing.getOpposite()) currentTip.add(BLUE + "Pipeline Output" + RESET);
+ else currentTip.add("Pipeline Side");
+
+ if (!hasInput && !hasInputTooClose && !hasOutput && !hasOutputTooClose) {
+ currentTip.add(YELLOW + "Not connected" + RESET);
+ }
+
+ if (hasInput) currentTip.add(GREEN + "Connected to " + GOLD + "Input" + RESET);
+ else if (hasInputTooClose) currentTip.add(RED + "Connected Input too close" + RESET);
+ else if (hasOutput) currentTip.add(GREEN + "Connected to " + BLUE + "Output" + RESET);
+ else if (hasOutputTooClose) currentTip.add(RED + "Connected Output too close" + RESET);
+
+ super.getWailaBody(itemStack, currentTip, accessor, config);
+ }
+
+ @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("hasInput", mSender != null);
+ tag.setBoolean("hasInputTooClose", mTooCloseSender != null);
+ tag.setBoolean("hasOutput", mTarget != null && mTarget != this);
+ tag.setBoolean("hasOutputTooClose", mTooCloseTarget != null);
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/long_distance/GT_MetaTileEntity_LongDistancePipelineFluid.java b/src/main/java/gregtech/common/tileentities/machines/long_distance/GT_MetaTileEntity_LongDistancePipelineFluid.java
new file mode 100644
index 0000000000..70e295f3ad
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/long_distance/GT_MetaTileEntity_LongDistancePipelineFluid.java
@@ -0,0 +1,125 @@
+/**
+ *
+ * Inspired/ported from GregTech 6 under the LGPL license
+ *
+ * Copyright (c) 2020 GregTech-6 Team
+ *
+ * This file is part of GregTech.
+ *
+ * GregTech is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * GregTech is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with GregTech. If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+package gregtech.common.tileentities.machines.long_distance;
+
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_PIPELINE_FLUID_BACK;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_PIPELINE_FLUID_FRONT;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_PIPELINE_FLUID_SIDE_LEFT_RIGHT;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_PIPELINE_FLUID_SIDE_LEFT_RIGHT_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_PIPELINE_FLUID_SIDE_UP_DOWN;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_PIPELINE_FLUID_SIDE_UP_DOWN_GLOW;
+
+import net.minecraft.tileentity.TileEntity;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidStack;
+import net.minecraftforge.fluids.FluidTankInfo;
+import net.minecraftforge.fluids.IFluidHandler;
+
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.render.TextureFactory;
+
+public class GT_MetaTileEntity_LongDistancePipelineFluid extends GT_MetaTileEntity_LongDistancePipelineBase {
+
+ static final FluidTankInfo[] emptyTank = { new FluidTankInfo(null, Integer.MAX_VALUE) };
+
+ public GT_MetaTileEntity_LongDistancePipelineFluid(int aID, String aName, String aNameRegional, int aTier) {
+ super(aID, aName, aNameRegional, aTier, "Sends fluids over long distances");
+ }
+
+ public GT_MetaTileEntity_LongDistancePipelineFluid(String aName, int aTier, String aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ }
+
+ @Override
+ public boolean isSameClass(GT_MetaTileEntity_LongDistancePipelineBase other) {
+ return other instanceof GT_MetaTileEntity_LongDistancePipelineFluid;
+ }
+
+ @Override
+ public int getPipeMeta() {
+ return 0;
+ }
+
+ public IFluidHandler getTank() {
+ final IGregTechTileEntity tTile = mTarget.getBaseMetaTileEntity();
+ TileEntity tankTile = tTile.getTileEntityAtSide(tTile.getBackFacing());
+ if (tankTile instanceof IFluidHandler) return (IFluidHandler) tankTile;
+ else return null;
+ }
+
+ @Override
+ public FluidTankInfo[] getTankInfo(ForgeDirection side) {
+ if (checkTarget()) {
+ final IFluidHandler tankTile = getTank();
+ if (tankTile != null) return tankTile.getTankInfo(side);
+ }
+
+ return emptyTank;
+ }
+
+ @Override
+ public int fill(ForgeDirection side, FluidStack aFluid, boolean aDoFill) {
+ if (checkTarget()) {
+ final IGregTechTileEntity tTile = mTarget.getBaseMetaTileEntity();
+ final IFluidHandler tankTile = getTank();
+ if (tankTile != null) return tankTile.fill(tTile.getFrontFacing(), aFluid, aDoFill);
+ }
+ return 0;
+ }
+
+ @Override
+ public FluidStack drain(ForgeDirection side, FluidStack aFluid, boolean aDoDrain) {
+ return null;
+ }
+
+ @Override
+ public FluidStack drain(ForgeDirection side, int aMaxDrain, boolean aDoDrain) {
+ return null;
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_LongDistancePipelineFluid(mName, mTier, getDescription()[0], mTextures);
+ }
+
+ @Override
+ public ITexture[] getTextureOverlays() {
+ ITexture[] overlays = new ITexture[4];
+ overlays[INPUT_INDEX] = TextureFactory.of(OVERLAY_PIPELINE_FLUID_FRONT);
+ overlays[OUTPUT_INDEX] = TextureFactory.of(OVERLAY_PIPELINE_FLUID_BACK);
+ overlays[SIDE_UP_DOWN_INDEX] = TextureFactory.of(
+ TextureFactory.of(OVERLAY_PIPELINE_FLUID_SIDE_UP_DOWN),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_PIPELINE_FLUID_SIDE_UP_DOWN_GLOW)
+ .glow()
+ .build());
+ overlays[SIDE_LEFT_RIGHT_INDEX] = TextureFactory.of(
+ TextureFactory.of(OVERLAY_PIPELINE_FLUID_SIDE_LEFT_RIGHT),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_PIPELINE_FLUID_SIDE_LEFT_RIGHT_GLOW)
+ .glow()
+ .build());
+
+ return overlays;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/long_distance/GT_MetaTileEntity_LongDistancePipelineItem.java b/src/main/java/gregtech/common/tileentities/machines/long_distance/GT_MetaTileEntity_LongDistancePipelineItem.java
new file mode 100644
index 0000000000..e1510f4d3d
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/long_distance/GT_MetaTileEntity_LongDistancePipelineItem.java
@@ -0,0 +1,214 @@
+/**
+ *
+ * Inspired/ported from GregTech 6 under the LGPL license
+ *
+ * Copyright (c) 2020 GregTech-6 Team
+ *
+ * This file is part of GregTech.
+ *
+ * GregTech is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * GregTech is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with GregTech. If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+package gregtech.common.tileentities.machines.long_distance;
+
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_PIPELINE_ITEM_BACK;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_PIPELINE_ITEM_FRONT;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_PIPELINE_ITEM_SIDE_LEFT_RIGHT;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_PIPELINE_ITEM_SIDE_LEFT_RIGHT_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_PIPELINE_ITEM_SIDE_UP_DOWN;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_PIPELINE_ITEM_SIDE_UP_DOWN_GLOW;
+
+import net.minecraft.inventory.IInventory;
+import net.minecraft.inventory.ISidedInventory;
+import net.minecraft.item.ItemStack;
+import net.minecraft.tileentity.TileEntity;
+
+import gregtech.api.enums.GT_Values;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.render.TextureFactory;
+
+public class GT_MetaTileEntity_LongDistancePipelineItem extends GT_MetaTileEntity_LongDistancePipelineBase {
+
+ public GT_MetaTileEntity_LongDistancePipelineItem(int aID, String aName, String aNameRegional, int aTier) {
+ super(aID, aName, aNameRegional, aTier, "Sends Items over long distances");
+ }
+
+ public GT_MetaTileEntity_LongDistancePipelineItem(String aName, int aTier, String aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ }
+
+ @Override
+ public boolean isSameClass(GT_MetaTileEntity_LongDistancePipelineBase other) {
+ return other instanceof GT_MetaTileEntity_LongDistancePipelineItem;
+ }
+
+ @Override
+ public int getPipeMeta() {
+ return 1;
+ }
+
+ public IInventory getInventory() {
+ final IGregTechTileEntity tTile = mTarget.getBaseMetaTileEntity();
+ TileEntity invTile = tTile.getTileEntityAtSide(tTile.getBackFacing());
+ if (invTile instanceof IInventory) return (IInventory) invTile;
+ else return null;
+ }
+
+ @Override
+ public ItemStack decrStackSize(int aSlot, int aDecrement) {
+ if (checkTarget()) {
+ IInventory iInventory = getInventory();
+ if (iInventory != null) return iInventory.decrStackSize(aSlot, aDecrement);
+ }
+ return null;
+ }
+
+ @Override
+ public ItemStack getStackInSlotOnClosing(int aSlot) {
+ if (checkTarget()) {
+ IInventory iInventory = getInventory();
+ if (iInventory != null) return iInventory.getStackInSlotOnClosing(aSlot);
+ }
+ return null;
+ }
+
+ @Override
+ public ItemStack getStackInSlot(int aSlot) {
+ if (checkTarget()) {
+ IInventory iInventory = getInventory();
+ if (iInventory != null) return iInventory.getStackInSlot(aSlot);
+ }
+ return null;
+ }
+
+ @Override
+ public String getInventoryName() {
+ if (checkTarget()) {
+ IInventory iInventory = getInventory();
+ if (iInventory != null) return iInventory.getInventoryName();
+ }
+ return super.getInventoryName();
+ }
+
+ @Override
+ public int getSizeInventory() {
+ if (checkTarget()) {
+ IInventory iInventory = getInventory();
+ if (iInventory != null) return iInventory.getSizeInventory();
+ }
+ return 0;
+ }
+
+ @Override
+ public int getInventoryStackLimit() {
+ if (checkTarget()) {
+ IInventory iInventory = getInventory();
+ if (iInventory != null) return iInventory.getInventoryStackLimit();
+ }
+ return 0;
+ }
+
+ @Override
+ public void setInventorySlotContents(int aSlot, ItemStack aStack) {
+ if (checkTarget()) {
+ IInventory iInventory = getInventory();
+ if (iInventory != null) iInventory.setInventorySlotContents(aSlot, aStack);
+ }
+ }
+
+ @Override
+ public boolean hasCustomInventoryName() {
+ if (checkTarget()) {
+ IInventory iInventory = getInventory();
+ if (iInventory != null) return iInventory.hasCustomInventoryName();
+ }
+ return false;
+ }
+
+ @Override
+ public boolean isItemValidForSlot(int aSlot, ItemStack aStack) {
+ if (checkTarget()) {
+ IInventory iInventory = getInventory();
+ if (iInventory != null) return iInventory.isItemValidForSlot(aSlot, aStack);
+ }
+ return false;
+ }
+
+ // // Relay Sided Inventories
+ //
+
+ @Override
+ public int[] getAccessibleSlotsFromSide(int ordinalSide) {
+ if (checkTarget()) {
+ final IGregTechTileEntity tTile = mTarget.getBaseMetaTileEntity();
+ final IInventory iInventory = getInventory();
+ if (iInventory instanceof ISidedInventory inv) return inv.getAccessibleSlotsFromSide(
+ tTile.getFrontFacing()
+ .ordinal());
+ if (iInventory != null) {
+ final int[] tReturn = new int[iInventory.getSizeInventory()];
+ for (int i = 0; i < tReturn.length; i++) tReturn[i] = i;
+ return tReturn;
+ }
+ }
+
+ return GT_Values.emptyIntArray;
+ }
+
+ @Override
+ public boolean canInsertItem(int aSlot, ItemStack aStack, int ordinalSide) {
+ if (checkTarget()) {
+ final IGregTechTileEntity tTile = mTarget.getBaseMetaTileEntity();
+ IInventory iInventory = getInventory();
+ if (iInventory instanceof ISidedInventory iSidedInventory) return iSidedInventory.canInsertItem(
+ aSlot,
+ aStack,
+ tTile.getFrontFacing()
+ .ordinal());
+ return iInventory != null;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean canExtractItem(int aSlot, ItemStack aStack, int ordinalSide) {
+ return false;
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_LongDistancePipelineItem(mName, mTier, getDescription()[0], mTextures);
+ }
+
+ @Override
+ public ITexture[] getTextureOverlays() {
+ ITexture[] overlays = new ITexture[4];
+ overlays[INPUT_INDEX] = TextureFactory.of(OVERLAY_PIPELINE_ITEM_FRONT);
+ overlays[OUTPUT_INDEX] = TextureFactory.of(OVERLAY_PIPELINE_ITEM_BACK);
+ overlays[SIDE_UP_DOWN_INDEX] = TextureFactory.of(
+ TextureFactory.of(OVERLAY_PIPELINE_ITEM_SIDE_UP_DOWN),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_PIPELINE_ITEM_SIDE_UP_DOWN_GLOW)
+ .glow()
+ .build());
+ overlays[SIDE_LEFT_RIGHT_INDEX] = TextureFactory.of(
+ TextureFactory.of(OVERLAY_PIPELINE_ITEM_SIDE_LEFT_RIGHT),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_PIPELINE_ITEM_SIDE_LEFT_RIGHT_GLOW)
+ .glow()
+ .build());
+
+ return overlays;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_AbstractMultiFurnace.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_AbstractMultiFurnace.java
new file mode 100644
index 0000000000..0c91951e28
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_AbstractMultiFurnace.java
@@ -0,0 +1,48 @@
+package gregtech.common.tileentities.machines.multi;
+
+import net.minecraft.item.ItemStack;
+
+import gregtech.api.enums.HeatingCoilLevel;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_ExtendedPowerMultiBlockBase;
+
+public abstract class GT_MetaTileEntity_AbstractMultiFurnace<T extends GT_MetaTileEntity_AbstractMultiFurnace<T>>
+ extends GT_MetaTileEntity_ExtendedPowerMultiBlockBase<T> {
+
+ private HeatingCoilLevel mCoilLevel;
+
+ protected GT_MetaTileEntity_AbstractMultiFurnace(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ protected GT_MetaTileEntity_AbstractMultiFurnace(String aName) {
+ super(aName);
+ }
+
+ @Override
+ public boolean isCorrectMachinePart(ItemStack aStack) {
+ return true;
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack aStack) {
+ return 10000;
+ }
+
+ @Override
+ public int getDamageToComponent(ItemStack aStack) {
+ return 0;
+ }
+
+ @Override
+ public boolean explodesOnComponentBreak(ItemStack aStack) {
+ return false;
+ }
+
+ public HeatingCoilLevel getCoilLevel() {
+ return mCoilLevel;
+ }
+
+ public void setCoilLevel(HeatingCoilLevel aCoilLevel) {
+ mCoilLevel = aCoilLevel;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_AssemblyLine.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_AssemblyLine.java
new file mode 100644
index 0000000000..7c7c27c880
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_AssemblyLine.java
@@ -0,0 +1,505 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofChain;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.transpose;
+import static gregtech.GT_Mod.GT_FML_LOGGER;
+import static gregtech.api.enums.GT_HatchElement.Energy;
+import static gregtech.api.enums.GT_HatchElement.InputBus;
+import static gregtech.api.enums.GT_HatchElement.InputHatch;
+import static gregtech.api.enums.GT_HatchElement.Maintenance;
+import static gregtech.api.enums.GT_HatchElement.OutputBus;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ASSEMBLY_LINE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ASSEMBLY_LINE_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ASSEMBLY_LINE_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ASSEMBLY_LINE_GLOW;
+import static gregtech.api.util.GT_StructureUtility.buildHatchAdder;
+import static gregtech.api.util.GT_StructureUtility.ofHatchAdder;
+import static gregtech.api.util.GT_Utility.filterValidMTEs;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidStack;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Textures;
+import gregtech.api.enums.Textures.BlockIcons;
+import gregtech.api.enums.VoidingMode;
+import gregtech.api.interfaces.IHatchElement;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_ExtendedPowerMultiBlockBase;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_DataAccess;
+import gregtech.api.multitileentity.multiblock.casing.Glasses;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_AssemblyLineUtils;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_Recipe.GT_Recipe_AssemblyLine;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.IGT_HatchAdder;
+
+public class GT_MetaTileEntity_AssemblyLine extends
+ GT_MetaTileEntity_ExtendedPowerMultiBlockBase<GT_MetaTileEntity_AssemblyLine> implements ISurvivalConstructable {
+
+ public ArrayList<GT_MetaTileEntity_Hatch_DataAccess> mDataAccessHatches = new ArrayList<>();
+ private static final String STRUCTURE_PIECE_FIRST = "first";
+ private static final String STRUCTURE_PIECE_LATER = "later";
+ private static final String STRUCTURE_PIECE_LAST = "last";
+ private static final IStructureDefinition<GT_MetaTileEntity_AssemblyLine> STRUCTURE_DEFINITION = StructureDefinition
+ .<GT_MetaTileEntity_AssemblyLine>builder()
+ .addShape(
+ STRUCTURE_PIECE_FIRST,
+ transpose(new String[][] { { " ", "e", " " }, { "~", "l", "G" }, { "g", "m", "g" }, { "b", "i", "b" }, }))
+ .addShape(
+ STRUCTURE_PIECE_LATER,
+ transpose(new String[][] { { " ", "e", " " }, { "d", "l", "d" }, { "g", "m", "g" }, { "b", "I", "b" }, }))
+ .addShape(
+ STRUCTURE_PIECE_LAST,
+ transpose(new String[][] { { " ", "e", " " }, { "d", "l", "d" }, { "g", "m", "g" }, { "o", "i", "b" }, }))
+ .addElement('G', ofBlock(GregTech_API.sBlockCasings3, 10)) // grate machine casing
+ .addElement('l', ofBlock(GregTech_API.sBlockCasings2, 9)) // assembler machine casing
+ .addElement('m', ofBlock(GregTech_API.sBlockCasings2, 5)) // assembling line casing
+ .addElement('g', Glasses.chainAllGlasses())
+ .addElement(
+ 'e',
+ ofChain(
+ Energy.newAny(16, 1, ForgeDirection.UP, ForgeDirection.NORTH, ForgeDirection.SOUTH),
+ ofBlock(GregTech_API.sBlockCasings2, 0)))
+ .addElement(
+ 'd',
+ buildHatchAdder(GT_MetaTileEntity_AssemblyLine.class).atLeast(DataHatchElement.DataAccess)
+ .dot(2)
+ .casingIndex(42)
+ .allowOnly(ForgeDirection.NORTH)
+ .buildAndChain(GregTech_API.sBlockCasings3, 10))
+ .addElement(
+ 'b',
+ buildHatchAdder(GT_MetaTileEntity_AssemblyLine.class)
+ .atLeast(InputHatch, InputHatch, InputHatch, InputHatch, Maintenance)
+ .casingIndex(16)
+ .dot(3)
+ .allowOnly(ForgeDirection.DOWN)
+ .buildAndChain(
+ ofBlock(GregTech_API.sBlockCasings2, 0),
+ ofHatchAdder(GT_MetaTileEntity_AssemblyLine::addOutputToMachineList, 16, 4)))
+ .addElement(
+ 'I',
+ ofChain(
+ // all blocks nearby use solid steel casing, so let's use the texture of that
+ InputBus.newAny(16, 5, ForgeDirection.DOWN),
+ ofHatchAdder(GT_MetaTileEntity_AssemblyLine::addOutputToMachineList, 16, 4)))
+ .addElement('i', InputBus.newAny(16, 5, ForgeDirection.DOWN))
+ .addElement('o', OutputBus.newAny(16, 4, ForgeDirection.DOWN))
+ .build();
+
+ public GT_MetaTileEntity_AssemblyLine(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_AssemblyLine(String aName) {
+ super(aName);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_AssemblyLine(this.mName);
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Assembling Line")
+ .addInfo("Controller block for the Assembling Line")
+ .addInfo("Used to make complex machine parts (LuV+)")
+ .addInfo("Does not make Assembler items")
+ .addInfo("Recipe tier is at most Energy Hatch tier + 1.")
+ .addSeparator()
+ .beginVariableStructureBlock(5, 16, 4, 4, 3, 3, false) // ?
+ .addStructureInfo("From Bottom to Top, Left to Right")
+ .addStructureInfo(
+ "Layer 1 - Solid Steel Machine Casing, Input Bus (last can be Output Bus), Solid Steel Machine Casing")
+ .addStructureInfo(
+ "Layer 2 - Borosilicate Glass(any)/Warded Glass/Reinforced Glass, Assembling Line Casing, Reinforced Glass")
+ .addStructureInfo("Layer 3 - Grate Machine Casing, Assembler Machine Casing, Grate Machine Casing")
+ .addStructureInfo("Layer 4 - Empty, Solid Steel Machine Casing, Empty")
+ .addStructureInfo("Up to 16 repeating slices, each one allows for 1 more item in recipes")
+ .addController("Either Grate on layer 3 of the first slice")
+ .addEnergyHatch("Any layer 4 casing", 1)
+ .addMaintenanceHatch("Any layer 1 casing", 3)
+ .addInputBus("As specified on layer 1", 4, 5)
+ .addInputHatch("Any layer 1 casing", 3)
+ .addOutputBus("Replaces Input Bus on final slice or on any solid steel casing on layer 1", 4)
+ .addOtherStructurePart("Data Access Hatch", "Optional, next to controller", 2)
+ .toolTipFinisher("Gregtech");
+ return tt;
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity baseMetaTileEntity, ForgeDirection sideDirection,
+ ForgeDirection facingDirection, int colorIndex, boolean active, boolean redstoneLevel) {
+ if (sideDirection == facingDirection) {
+ if (active) return new ITexture[] { BlockIcons.casingTexturePages[0][16], TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_ASSEMBLY_LINE_ACTIVE)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_ASSEMBLY_LINE_ACTIVE_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ return new ITexture[] { BlockIcons.casingTexturePages[0][16], TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_ASSEMBLY_LINE)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_ASSEMBLY_LINE_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ }
+ return new ITexture[] { Textures.BlockIcons.casingTexturePages[0][16] };
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.assemblylineVisualRecipes;
+ }
+
+ @Override
+ public boolean isCorrectMachinePart(ItemStack aStack) {
+ return true;
+ }
+
+ @Override
+ @NotNull
+ public CheckRecipeResult checkProcessing() {
+ if (GT_Values.D1) {
+ GT_FML_LOGGER.info("Start ALine recipe check");
+ }
+ CheckRecipeResult result = CheckRecipeResultRegistry.NO_DATA_STICKS;
+
+ ArrayList<ItemStack> tDataStickList = getDataItems(2);
+ if (tDataStickList.isEmpty()) {
+ return result;
+ }
+ if (GT_Values.D1) {
+ GT_FML_LOGGER.info("Stick accepted, " + tDataStickList.size() + " Data Sticks found");
+ }
+
+ int[] tStacks = new int[0];
+ FluidStack[] tFluids = new FluidStack[0];
+ long averageVoltage = getAverageInputVoltage();
+ long maxAmp = mEnergyHatches.size() <= 1 ? 1 : getMaxInputAmps();
+ int maxParallel = 1;
+ Map<GT_Utility.ItemId, ItemStack> inputsFromME = getStoredInputsFromME();
+ Map<Fluid, FluidStack> fluidsFromME = getStoredFluidsFromME();
+
+ for (ItemStack tDataStick : tDataStickList) {
+ GT_AssemblyLineUtils.LookupResult tLookupResult = GT_AssemblyLineUtils
+ .findAssemblyLineRecipeFromDataStick(tDataStick, false);
+
+ if (tLookupResult.getType() == GT_AssemblyLineUtils.LookupResultType.INVALID_STICK) {
+ result = CheckRecipeResultRegistry.NO_RECIPE;
+ continue;
+ }
+
+ GT_Recipe_AssemblyLine tRecipe = tLookupResult.getRecipe();
+ // Check if the recipe on the data stick is the current recipe for it's given output, if not we update it
+ // and continue to next.
+ if (tLookupResult.getType() != GT_AssemblyLineUtils.LookupResultType.VALID_STACK_AND_VALID_HASH) {
+ tRecipe = GT_AssemblyLineUtils.processDataStick(tDataStick);
+ if (tRecipe == null) {
+ result = CheckRecipeResultRegistry.NO_RECIPE;
+ continue;
+ }
+ }
+
+ // Void protection check.
+ if (!canOutputAll(new ItemStack[] { tRecipe.mOutput })) {
+ result = CheckRecipeResultRegistry.ITEM_OUTPUT_FULL;
+ continue;
+ }
+
+ // So here we check against the recipe found on the data stick.
+ // If we run into missing buses/hatches or bad inputs, we go to the next data stick.
+ // This check only happens if we have a valid up-to-date data stick.
+
+ // first validate we have enough input busses and input hatches for this recipe
+ if (mInputBusses.size() < tRecipe.mInputs.length || mInputHatches.size() < tRecipe.mFluidInputs.length) {
+ if (GT_Values.D1) {
+ GT_FML_LOGGER.info(
+ "Not enough sources: Need ({}, {}), has ({}, {})",
+ mInputBusses.size(),
+ tRecipe.mInputs.length,
+ mInputHatches.size(),
+ tRecipe.mFluidInputs.length);
+ }
+ result = CheckRecipeResultRegistry.NO_RECIPE;
+ continue;
+ }
+
+ // Check Inputs allign
+ int[] itemConsumptions = GT_Recipe_AssemblyLine.getItemConsumptionAmountArray(mInputBusses, tRecipe);
+ if (itemConsumptions == null || itemConsumptions.length == 0) {
+ result = CheckRecipeResultRegistry.NO_RECIPE;
+ continue;
+ }
+ maxParallel = (int) GT_Recipe_AssemblyLine
+ .maxParallelCalculatedByInputItems(mInputBusses, maxParallel, itemConsumptions, inputsFromME);
+ if (maxParallel <= 0) {
+ result = CheckRecipeResultRegistry.NO_RECIPE;
+ continue;
+ }
+ tStacks = itemConsumptions;
+
+ if (GT_Values.D1) {
+ GT_FML_LOGGER.info("All Items accepted");
+ }
+
+ // Check Fluid Inputs allign
+ if (tRecipe.mFluidInputs.length > 0) {
+ maxParallel = (int) GT_Recipe_AssemblyLine
+ .maxParallelCalculatedByInputFluids(mInputHatches, maxParallel, tRecipe.mFluidInputs, fluidsFromME);
+ if (maxParallel <= 0) {
+ result = CheckRecipeResultRegistry.NO_RECIPE;
+ continue;
+ }
+ tFluids = tRecipe.mFluidInputs;
+ }
+
+ if (GT_Values.D1) {
+ GT_FML_LOGGER.info("All fluids accepted");
+ }
+
+ if (GT_Values.D1) {
+ GT_FML_LOGGER.info("Check overclock");
+ }
+
+ // Recipe tier is limited to hatch tier + 1.
+ if (tRecipe.mEUt > averageVoltage * 4) {
+ result = CheckRecipeResultRegistry.insufficientPower(tRecipe.mEUt);
+ continue;
+ }
+
+ // Insufficient power check.
+ if (tRecipe.mEUt > maxAmp * averageVoltage) {
+ result = CheckRecipeResultRegistry.insufficientPower(tRecipe.mEUt);
+ continue;
+ }
+
+ calculateOverclockedNessMultiInternal(tRecipe.mEUt, tRecipe.mDuration, (int) maxAmp, averageVoltage, false);
+ // In case recipe is too OP for that machine
+ if (lEUt == Long.MAX_VALUE) {
+ if (GT_Values.D1) {
+ GT_FML_LOGGER.info("Recipe too OP");
+ }
+ result = CheckRecipeResultRegistry.POWER_OVERFLOW;
+ continue;
+ }
+
+ if (mMaxProgresstime == Integer.MAX_VALUE) {
+ if (GT_Values.D1) {
+ GT_FML_LOGGER.info("Recipe too OP");
+ }
+ result = CheckRecipeResultRegistry.DURATION_OVERFLOW;
+ continue;
+ }
+
+ if (GT_Values.D1) {
+ GT_FML_LOGGER.info("Find available recipe");
+ }
+ result = CheckRecipeResultRegistry.SUCCESSFUL;
+ mOutputItems = new ItemStack[] { tRecipe.mOutput };
+ break;
+ }
+
+ if (!result.wasSuccessful()) {
+ return result;
+ }
+
+ // Must be something wrong here...
+ if (tStacks.length == 0 || maxParallel <= 0) {
+ return CheckRecipeResultRegistry.INTERNAL_ERROR;
+ }
+
+ if (GT_Values.D1) {
+ GT_FML_LOGGER.info("All checked start consuming inputs");
+ }
+
+ GT_Recipe_AssemblyLine.consumeInputItems(mInputBusses, maxParallel, tStacks, inputsFromME);
+ GT_Recipe_AssemblyLine.consumeInputFluids(mInputHatches, maxParallel, tFluids, fluidsFromME);
+
+ if (this.lEUt > 0) {
+ this.lEUt = -this.lEUt;
+ }
+ this.mEfficiency = (10000 - (getIdealStatus() - getRepairStatus()) * 1000);
+ this.mEfficiencyIncrease = 10000;
+ updateSlots();
+ if (GT_Values.D1) {
+ GT_FML_LOGGER.info("Recipe successful");
+ }
+ return result;
+ }
+
+ @Override
+ public boolean onRunningTick(ItemStack aStack) {
+ for (GT_MetaTileEntity_Hatch_DataAccess hatch_dataAccess : mDataAccessHatches) {
+ hatch_dataAccess.setActive(true);
+ }
+ return super.onRunningTick(aStack);
+ }
+
+ @Override
+ public IStructureDefinition<GT_MetaTileEntity_AssemblyLine> getStructureDefinition() {
+ return STRUCTURE_DEFINITION;
+ }
+
+ @Override
+ public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+ mDataAccessHatches.clear();
+ if (!checkPiece(STRUCTURE_PIECE_FIRST, 0, 1, 0)) return false;
+ return checkMachine(true) || checkMachine(false);
+ }
+
+ private boolean checkMachine(boolean leftToRight) {
+ for (int i = 1; i < 16; i++) {
+ if (!checkPiece(STRUCTURE_PIECE_LATER, leftToRight ? -i : i, 1, 0)) return false;
+ if (!mOutputBusses.isEmpty())
+ return !mEnergyHatches.isEmpty() && mMaintenanceHatches.size() == 1 && mDataAccessHatches.size() <= 1;
+ }
+ return false;
+ }
+
+ /**
+ * @param state using bitmask, 1 for IntegratedCircuit, 2 for DataStick, 4 for DataOrb
+ */
+ private boolean isCorrectDataItem(ItemStack aStack, int state) {
+ if ((state & 1) != 0 && ItemList.Circuit_Integrated.isStackEqual(aStack, true, true)) return true;
+ if ((state & 2) != 0 && ItemList.Tool_DataStick.isStackEqual(aStack, false, true)) return true;
+ return (state & 4) != 0 && ItemList.Tool_DataOrb.isStackEqual(aStack, false, true);
+ }
+
+ /**
+ * @param state using bitmask, 1 for IntegratedCircuit, 2 for DataStick, 4 for DataOrb
+ */
+ public ArrayList<ItemStack> getDataItems(int state) {
+ ArrayList<ItemStack> rList = new ArrayList<>();
+ if (GT_Utility.isStackValid(mInventory[1]) && isCorrectDataItem(mInventory[1], state)) {
+ rList.add(mInventory[1]);
+ }
+ for (GT_MetaTileEntity_Hatch_DataAccess tHatch : filterValidMTEs(mDataAccessHatches)) {
+ for (int i = 0; i < tHatch.getBaseMetaTileEntity()
+ .getSizeInventory(); i++) {
+ if (tHatch.getBaseMetaTileEntity()
+ .getStackInSlot(i) != null && isCorrectDataItem(
+ tHatch.getBaseMetaTileEntity()
+ .getStackInSlot(i),
+ state))
+ rList.add(
+ tHatch.getBaseMetaTileEntity()
+ .getStackInSlot(i));
+ }
+ }
+ return rList;
+ }
+
+ public boolean addDataAccessToMachineList(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
+ if (aTileEntity == null) return false;
+ IMetaTileEntity aMetaTileEntity = aTileEntity.getMetaTileEntity();
+ if (aMetaTileEntity == null) return false;
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_DataAccess) {
+ ((GT_MetaTileEntity_Hatch) aMetaTileEntity).updateTexture(aBaseCasingIndex);
+ return mDataAccessHatches.add((GT_MetaTileEntity_Hatch_DataAccess) aMetaTileEntity);
+ }
+ return false;
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack aStack) {
+ return 10000;
+ }
+
+ @Override
+ public int getDamageToComponent(ItemStack aStack) {
+ return 0;
+ }
+
+ @Override
+ public boolean explodesOnComponentBreak(ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public void construct(ItemStack stackSize, boolean hintsOnly) {
+ buildPiece(STRUCTURE_PIECE_FIRST, stackSize, hintsOnly, 0, 1, 0);
+ int tLength = Math.min(stackSize.stackSize + 1, 16);
+ for (int i = 1; i < tLength; i++) {
+ buildPiece(STRUCTURE_PIECE_LATER, stackSize, hintsOnly, -i, 1, 0);
+ }
+ }
+
+ @Override
+ public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
+ if (mMachine) return -1;
+ int build = survivialBuildPiece(STRUCTURE_PIECE_FIRST, stackSize, 0, 1, 0, elementBudget, env, false, true);
+ if (build >= 0) return build;
+ int tLength = Math.min(stackSize.stackSize + 1, 16);
+ for (int i = 1; i < tLength - 1; i++) {
+ build = survivialBuildPiece(STRUCTURE_PIECE_LATER, stackSize, -i, 1, 0, elementBudget, env, false, true);
+ if (build >= 0) return build;
+ }
+ return survivialBuildPiece(STRUCTURE_PIECE_LAST, stackSize, 1 - tLength, 1, 0, elementBudget, env, false, true);
+ }
+
+ @Override
+ public boolean supportsVoidProtection() {
+ return true;
+ }
+
+ @Override
+ public Set<VoidingMode> getAllowedVoidingModes() {
+ return VoidingMode.ITEM_ONLY_MODES;
+ }
+
+ private enum DataHatchElement implements IHatchElement<GT_MetaTileEntity_AssemblyLine> {
+
+ DataAccess;
+
+ @Override
+ public List<? extends Class<? extends IMetaTileEntity>> mteClasses() {
+ return Collections.singletonList(GT_MetaTileEntity_Hatch_DataAccess.class);
+ }
+
+ @Override
+ public IGT_HatchAdder<GT_MetaTileEntity_AssemblyLine> adder() {
+ return GT_MetaTileEntity_AssemblyLine::addDataAccessToMachineList;
+ }
+
+ @Override
+ public long count(GT_MetaTileEntity_AssemblyLine t) {
+ return t.mDataAccessHatches.size();
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_BrickedBlastFurnace.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_BrickedBlastFurnace.java
new file mode 100644
index 0000000000..a9cb7708cf
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_BrickedBlastFurnace.java
@@ -0,0 +1,155 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static gregtech.api.util.GT_Waila.getMachineProgressString;
+
+import java.util.List;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import org.lwjgl.input.Keyboard;
+
+import gregtech.GT_Mod;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.SteamVariant;
+import gregtech.api.enums.Textures;
+import gregtech.api.enums.Textures.BlockIcons;
+import gregtech.api.interfaces.ISecondaryDescribable;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import mcp.mobius.waila.api.IWailaConfigHandler;
+import mcp.mobius.waila.api.IWailaDataAccessor;
+
+public class GT_MetaTileEntity_BrickedBlastFurnace extends GT_MetaTileEntity_PrimitiveBlastFurnace
+ implements ISecondaryDescribable {
+
+ private static final ITexture[] FACING_SIDE = { TextureFactory.of(Textures.BlockIcons.MACHINE_CASING_DENSEBRICKS) };
+ private static final ITexture[] FACING_FRONT = {
+ TextureFactory.of(Textures.BlockIcons.MACHINE_CASING_BRICKEDBLASTFURNACE_INACTIVE) };
+ private static final ITexture[] FACING_ACTIVE = {
+ TextureFactory.of(Textures.BlockIcons.MACHINE_CASING_BRICKEDBLASTFURNACE_ACTIVE), TextureFactory.builder()
+ .addIcon(BlockIcons.MACHINE_CASING_BRICKEDBLASTFURNACE_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ private GT_Multiblock_Tooltip_Builder tooltipBuilder;
+
+ public GT_MetaTileEntity_BrickedBlastFurnace(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_BrickedBlastFurnace(String aName) {
+ super(aName);
+ }
+
+ @Override
+ public String[] getDescription() {
+ return getCurrentDescription();
+ }
+
+ @Override
+ public boolean isDisplaySecondaryDescription() {
+ return Keyboard.isKeyDown(Keyboard.KEY_LSHIFT);
+ }
+
+ public String[] getPrimaryDescription() {
+ return getTooltip().getInformation();
+ }
+
+ public String[] getSecondaryDescription() {
+ return getTooltip().getStructureInformation();
+ }
+
+ protected GT_Multiblock_Tooltip_Builder getTooltip() {
+ if (tooltipBuilder == null) {
+ tooltipBuilder = new GT_Multiblock_Tooltip_Builder();
+ tooltipBuilder.addMachineType("Blast Furnace")
+ .addInfo("Controller Block for the Bricked Blast Furnace")
+ .addInfo("Usable for Steel and general Pyrometallurgy")
+ .addInfo("Has a useful interface, unlike other gregtech multis")
+ .addPollutionAmount(GT_Mod.gregtechproxy.mPollutionPrimitveBlastFurnacePerSecond)
+ .addSeparator()
+ .beginStructureBlock(3, 4, 3, true)
+ .addController("Front center")
+ .addOtherStructurePart("Firebricks", "Everything except the controller")
+ .addStructureInfo("The top block is also empty")
+ .addStructureInfo("You can share the walls of GT multis, so")
+ .addStructureInfo("each additional one costs less, up to 4")
+ .toolTipFinisher("Gregtech");
+ }
+ return tooltipBuilder;
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection aFacing,
+ int colorIndex, boolean aActive, boolean redstoneLevel) {
+ if (side == aFacing) {
+ return aActive ? FACING_ACTIVE : FACING_FRONT;
+ }
+ return FACING_SIDE;
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_BrickedBlastFurnace(this.mName);
+ }
+
+ @Override
+ protected Block getCasingBlock() {
+ return GregTech_API.sBlockCasings4;
+ }
+
+ @Override
+ protected int getCasingMetaID() {
+ return 15;
+ }
+
+ @Override
+ public String getName() {
+ return "Bricked Blast Furnace";
+ }
+
+ @Override
+ public SteamVariant getSteamVariant() {
+ return SteamVariant.PRIMITIVE;
+ }
+
+ @Override
+ public void getWailaBody(ItemStack itemStack, List<String> currenttip, IWailaDataAccessor accessor,
+ IWailaConfigHandler config) {
+ super.getWailaBody(itemStack, currenttip, accessor, config);
+ if (!this.getBaseMetaTileEntity()
+ .isInvalidTileEntity()) {
+ NBTTagCompound nbt = accessor.getNBTData();
+ currenttip.add(
+ getMachineProgressString(
+ this.getBaseMetaTileEntity()
+ .isActive(),
+ nbt.getInteger("mMaxProgressTime"),
+ nbt.getInteger("mProgressTime")));
+ }
+ }
+
+ @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);
+ if (!this.getBaseMetaTileEntity()
+ .isInvalidTileEntity()) {
+ tag.setInteger("mProgressTime", this.getProgresstime());
+ tag.setInteger("mMaxProgressTime", this.maxProgresstime());
+ }
+ }
+
+ @Override
+ public String[] getStructureDescription(ItemStack stackSize) {
+ return getTooltip().getStructureHint();
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_Charcoal_Pit.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_Charcoal_Pit.java
new file mode 100644
index 0000000000..1af65465c1
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_Charcoal_Pit.java
@@ -0,0 +1,313 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ROCK_BREAKER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ROCK_BREAKER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ROCK_BREAKER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ROCK_BREAKER_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.casingTexturePages;
+import static gregtech.api.objects.XSTR.XSTR_INSTANCE;
+
+import java.util.ArrayList;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.material.Material;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.ItemStack;
+import net.minecraft.world.ChunkPosition;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.oredict.OreDictionary;
+
+import gregtech.GT_Mod;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.enums.ParticleFX;
+import gregtech.api.interfaces.ISecondaryDescribable;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_TooltipMultiBlockBase;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.WorldSpawnedEventBuilder;
+import gregtech.common.GT_Pollution;
+
+public class GT_MetaTileEntity_Charcoal_Pit extends GT_MetaTileEntity_TooltipMultiBlockBase
+ implements ISecondaryDescribable {
+
+ private boolean running = false;
+
+ public GT_MetaTileEntity_Charcoal_Pit(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_Charcoal_Pit(String aName) {
+ super(aName);
+ }
+
+ @Override
+ public boolean isFacingValid(ForgeDirection facing) {
+ return (facing.flag & (ForgeDirection.UP.flag | ForgeDirection.DOWN.flag)) == 0;
+ }
+
+ @Override
+ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) {
+ // No GUI, do not capture right-click so it does not interfere when placing logs
+ return false;
+ }
+
+ @Override
+ public boolean isCorrectMachinePart(ItemStack aStack) {
+ return true;
+ }
+
+ @Nonnull
+ @Override
+ public CheckRecipeResult checkProcessing() {
+ if (!checkRecursiveBlocks()) {
+ mEfficiency = 0;
+ mEfficiencyIncrease = 0;
+ mMaxProgresstime = 0;
+ running = false;
+ return CheckRecipeResultRegistry.NO_RECIPE;
+ }
+
+ if (mEfficiency == 0) {
+ mEfficiency = 10000;
+ mEfficiencyIncrease = 10000;
+ mMaxProgresstime = Math.max(1, mMaxProgresstime);
+
+ // adds all the pollution at once when the recipe starts
+ GT_Pollution.addPollution(getBaseMetaTileEntity(), mMaxProgresstime * getPollutionPerTick(null));
+ return CheckRecipeResultRegistry.SUCCESSFUL;
+ } else {
+ mEfficiency = 0;
+ mEfficiencyIncrease = 0;
+ mMaxProgresstime = 0;
+ return CheckRecipeResultRegistry.NO_RECIPE;
+ }
+ }
+
+ private boolean checkRecursiveBlocks() {
+ ArrayList<ChunkPosition> tList1 = new ArrayList<>();
+ ArrayList<ChunkPosition> tList2 = new ArrayList<>();
+
+ Block tBlock = getBaseMetaTileEntity().getBlockOffset(0, -1, 0);
+ if (isWoodLog(tBlock, getBaseMetaTileEntity().getMetaIDOffset(0, -1, 0))) {
+ tList2.add(new ChunkPosition(0, -1, 0));
+ } else return false;
+ while (!tList2.isEmpty()) {
+ ChunkPosition tPos = tList2.get(0);
+ tList2.remove(0);
+ if (!checkAllBlockSides(tPos.chunkPosX, tPos.chunkPosY, tPos.chunkPosZ, tList1, tList2)) {
+ return false;
+ }
+ }
+ if (running) {
+ for (ChunkPosition tPos : tList1) {
+ if (isWoodLog(
+ getBaseMetaTileEntity().getBlockOffset(tPos.chunkPosX, tPos.chunkPosY, tPos.chunkPosZ),
+ getBaseMetaTileEntity().getMetaIDOffset(tPos.chunkPosX, tPos.chunkPosY, tPos.chunkPosZ)))
+ getBaseMetaTileEntity().getWorld()
+ .setBlock(
+ getBaseMetaTileEntity().getXCoord() + tPos.chunkPosX,
+ getBaseMetaTileEntity().getYCoord() + tPos.chunkPosY,
+ getBaseMetaTileEntity().getZCoord() + tPos.chunkPosZ,
+ GregTech_API.sBlockReinforced,
+ 4,
+ 3);
+ }
+ running = false;
+ return false;
+ } else {
+ mMaxProgresstime = (int) Math.sqrt(tList1.size() * 240000);
+ }
+ running = true;
+ return true;
+ }
+
+ private boolean isWoodLog(Block log, int meta) {
+ for (int id : OreDictionary.getOreIDs(new ItemStack(log, 1, meta))) {
+ if (OreDictionary.getOreName(id)
+ .equals("logWood")) return true;
+ }
+ String tTool = log.getHarvestTool(meta);
+ return OrePrefixes.log.contains(new ItemStack(log, 1, meta)) && ("axe".equals(tTool))
+ && (log.getMaterial() == Material.wood);
+ }
+
+ private boolean checkAllBlockSides(int aX, int aY, int aZ, ArrayList<? super ChunkPosition> aList1,
+ ArrayList<? super ChunkPosition> aList2) {
+ boolean expandToChunkXPos = false;
+ boolean expandToChunkXNeg = false;
+ boolean expandToChunkYPos = false;
+ boolean expandToChunkYNeg = false;
+ boolean expandToChunkZPos = false;
+ boolean expandToChunkZNeg = false;
+
+ Block blockXPos = getBaseMetaTileEntity().getBlockOffset(aX + 1, aY, aZ);
+ if (aX + 1 < 6 && (isWoodLog(blockXPos, getBaseMetaTileEntity().getMetaIDOffset(aX + 1, aY, aZ)))) {
+ if (!aList1.contains(new ChunkPosition(aX + 1, aY, aZ))
+ && (!aList2.contains(new ChunkPosition(aX + 1, aY, aZ)))) expandToChunkXPos = true;
+ } else if (!(blockXPos == Blocks.dirt || blockXPos == Blocks.grass)) {
+ return false;
+ }
+
+ Block blockXNeg = getBaseMetaTileEntity().getBlockOffset(aX - 1, aY, aZ);
+ if (aX - 1 > -6 && (isWoodLog(blockXNeg, getBaseMetaTileEntity().getMetaIDOffset(aX - 1, aY, aZ)))) {
+ if (!aList1.contains(new ChunkPosition(aX - 1, aY, aZ))
+ && (!aList2.contains(new ChunkPosition(aX - 1, aY, aZ)))) expandToChunkXNeg = true;
+ } else if (!(blockXNeg == Blocks.dirt || blockXNeg == Blocks.grass)) {
+ return false;
+ }
+
+ Block blockYPos = getBaseMetaTileEntity().getBlockOffset(aX, aY + 1, aZ);
+ if (aY + 1 < 1 && (isWoodLog(blockYPos, getBaseMetaTileEntity().getMetaIDOffset(aX, aY + 1, aZ)))) {
+ if (!aList1.contains(new ChunkPosition(aX, aY + 1, aZ))
+ && (!aList2.contains(new ChunkPosition(aX, aY + 1, aZ)))) expandToChunkYPos = true;
+ } else if (!(blockYPos == Blocks.dirt || blockYPos == Blocks.grass
+ || (aX == 0 && aY == -1 && aZ == 0 && blockYPos == GregTech_API.sBlockMachines))) {
+ return false;
+ }
+
+ Block blockYNeg = getBaseMetaTileEntity().getBlockOffset(aX, aY - 1, aZ);
+ if (aY - 1 > -6 && (isWoodLog(blockYNeg, getBaseMetaTileEntity().getMetaIDOffset(aX, aY - 1, aZ)))) {
+ if (!aList1.contains(new ChunkPosition(aX, aY - 1, aZ))
+ && (!aList2.contains(new ChunkPosition(aX, aY - 1, aZ)))) expandToChunkYNeg = true;
+ } else if (blockYNeg != Blocks.brick_block) {
+ return false;
+ }
+
+ Block blockZPos = getBaseMetaTileEntity().getBlockOffset(aX, aY, aZ + 1);
+ if (aZ + 1 < 6 && (isWoodLog(blockZPos, getBaseMetaTileEntity().getMetaIDOffset(aX, aY, aZ + 1)))) {
+ if (!aList1.contains(new ChunkPosition(aX, aY, aZ + 1))
+ && (!aList2.contains(new ChunkPosition(aX, aY, aZ + 1)))) expandToChunkZPos = true;
+ } else if (!(blockZPos == Blocks.dirt || blockZPos == Blocks.grass)) {
+ return false;
+ }
+
+ Block blockZNeg = getBaseMetaTileEntity().getBlockOffset(aX, aY, aZ - 1);
+ if (aZ - 1 > -6 && (isWoodLog(blockZNeg, getBaseMetaTileEntity().getMetaIDOffset(aX, aY, aZ - 1)))) {
+ if (!aList1.contains(new ChunkPosition(aX, aY, aZ - 1))
+ && (!aList2.contains(new ChunkPosition(aX, aY, aZ - 1)))) expandToChunkZNeg = true;
+ } else if (!(blockZNeg == Blocks.dirt || blockZNeg == Blocks.grass)) {
+ return false;
+ }
+ aList1.add(new ChunkPosition(aX, aY, aZ));
+ if (expandToChunkXPos) aList2.add(new ChunkPosition(aX + 1, aY, aZ));
+ if (expandToChunkXNeg) aList2.add(new ChunkPosition(aX - 1, aY, aZ));
+ if (expandToChunkYPos) aList2.add(new ChunkPosition(aX, aY + 1, aZ));
+ if (expandToChunkYNeg) aList2.add(new ChunkPosition(aX, aY - 1, aZ));
+ if (expandToChunkZPos) aList2.add(new ChunkPosition(aX, aY, aZ + 1));
+ if (expandToChunkZNeg) aList2.add(new ChunkPosition(aX, aY, aZ - 1));
+ return true;
+ }
+
+ @Override
+ public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+ mWrench = true;
+ mScrewdriver = true;
+ mSoftHammer = true;
+ mHardHammer = true;
+ mSolderingTool = true;
+ mCrowbar = true;
+ return true;
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack aStack) {
+ return 10000;
+ }
+
+ @Override
+ public int getPollutionPerSecond(ItemStack aStack) {
+ return GT_Mod.gregtechproxy.mPollutionCharcoalPitPerSecond;
+ }
+
+ @Override
+ public int getDamageToComponent(ItemStack aStack) {
+ return 0;
+ }
+
+ @Override
+ public boolean explodesOnComponentBreak(ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return null;
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Charcoal_Pit(mName);
+ }
+
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Charcoal Pile Igniter")
+ .addInfo("Controller for the Charcoal Pit")
+ .addInfo("Converts Logs into Brittle Charcoal blocks")
+ .addInfo("Will automatically start when valid")
+ .addPollutionAmount(getPollutionPerSecond(null))
+ .addSeparator()
+ .beginVariableStructureBlock(3, 13, 3, 7, 3, 13, false)
+ .addStructureInfo("Can be up to 13x7x13 in size, including the dirt; shape doesn't matter")
+ .addOtherStructurePart("Controller", "Top layer, directly touching a wood log")
+ .addOtherStructurePart("Dirt/Grass", "Top and middle layers, covering wood logs")
+ .addOtherStructurePart("Bricks", "Bottom layer, under all wood logs")
+ .addOtherStructurePart("Wood Logs", "Up to 5 layers, inside the previously mentioned blocks")
+ .addStructureInfo("No air between logs allowed.")
+ .addStructureInfo(
+ "All logs must be within 6 x/z of the controller, so it must be dead-center for a full 11x11 square of wood.")
+ .toolTipFinisher("Gregtech");
+ return tt;
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection aFacing,
+ int colorIndex, boolean aActive, boolean redstoneLevel) {
+ if (side == ForgeDirection.UP) {
+ if (aActive) return new ITexture[] { casingTexturePages[0][10],
+ TextureFactory.of(OVERLAY_FRONT_ROCK_BREAKER_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_ROCK_BREAKER_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ return new ITexture[] { casingTexturePages[0][10], TextureFactory.of(OVERLAY_FRONT_ROCK_BREAKER),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_ROCK_BREAKER_GLOW)
+ .glow()
+ .build(), };
+ }
+ return new ITexture[] { casingTexturePages[0][10] };
+ }
+
+ @Override
+ public boolean polluteEnvironment(int aPollutionLevel) {
+ // Do nothing and don't choke on pollution. This is fine because we add
+ // all the pollution at once when the recipe starts
+ return true;
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTimer) {
+ super.onPostTick(aBaseMetaTileEntity, aTimer);
+ if ((aBaseMetaTileEntity.isClientSide()) && (aBaseMetaTileEntity.isActive())) {
+
+ new WorldSpawnedEventBuilder.ParticleEventBuilder().setMotion(0D, 0.3D, 0D)
+ .setIdentifier(ParticleFX.LARGE_SMOKE)
+ .setPosition(
+ aBaseMetaTileEntity.getOffsetX(ForgeDirection.UP, 1) + XSTR_INSTANCE.nextFloat(),
+ aBaseMetaTileEntity.getOffsetY(ForgeDirection.UP, 1),
+ aBaseMetaTileEntity.getOffsetZ(ForgeDirection.UP, 1) + XSTR_INSTANCE.nextFloat())
+ .setWorld(getBaseMetaTileEntity().getWorld())
+ .run();
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_Cleanroom.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_Cleanroom.java
new file mode 100644
index 0000000000..cd31b9cc1e
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_Cleanroom.java
@@ -0,0 +1,514 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static gregtech.api.enums.GT_Values.debugCleanroom;
+import static gregtech.api.enums.Textures.BlockIcons.BLOCK_PLASCRETE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_CLEANROOM;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_CLEANROOM_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_CLEANROOM_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_CLEANROOM_GLOW;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.block.Block;
+import net.minecraft.item.ItemStack;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.world.World;
+import net.minecraftforge.common.config.ConfigCategory;
+import net.minecraftforge.common.config.Configuration;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.gtnewhorizon.structurelib.StructureLibAPI;
+import com.gtnewhorizon.structurelib.alignment.constructable.IConstructable;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.enums.TierEU;
+import gregtech.api.interfaces.ICleanroom;
+import gregtech.api.interfaces.ICleanroomReceiver;
+import gregtech.api.interfaces.ISecondaryDescribable;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicHull;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_TooltipMultiBlockBase;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.recipe.check.SimpleCheckRecipeResult;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Log;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+
+public class GT_MetaTileEntity_Cleanroom extends GT_MetaTileEntity_TooltipMultiBlockBase
+ implements IConstructable, ISecondaryDescribable, ICleanroom {
+
+ private final Set<ICleanroomReceiver> cleanroomReceivers = new HashSet<>();
+ private int mHeight = -1;
+
+ public GT_MetaTileEntity_Cleanroom(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_Cleanroom(String aName) {
+ super(aName);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Cleanroom(mName);
+ }
+
+ @Override
+ public int getCleanness() {
+ return mEfficiency;
+ }
+
+ @Override
+ public boolean isValidCleanroom() {
+ return isValid() && mMachine;
+ }
+
+ @Override
+ public void pollute() {
+ mEfficiency = 0;
+ mWrench = false;
+ mScrewdriver = false;
+ mSoftHammer = false;
+ mHardHammer = false;
+ mSolderingTool = false;
+ mCrowbar = false;
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Cleanroom")
+ .addInfo("Controller block for the Cleanroom")
+ .addInfo("Consumes 40 EU/t when first turned on")
+ .addInfo("and 4 EU/t once at 100% efficiency")
+ .addInfo("If you use an LV energy hatch, it will actually accept 2A instead of just 1A.")
+ .addInfo(
+ "MV+ energy hatches just accept 1A as usual. For HV+ the cleanroom will overclock and gain efficiency faster.")
+ .addInfo("Time required to reach full efficiency is proportional to")
+ .addInfo("the height of empty space within")
+ .addInfo("Machines that cause pollution aren't allowed to be put in.")
+ .addSeparator()
+ .beginVariableStructureBlock(3, 15, 4, 15, 3, 15, true)
+ .addController("Top center")
+ .addCasingInfoRange("Plascrete", 20, 1007, false)
+ .addStructureInfo(
+ GT_Values.cleanroomGlass
+ + "% of the Plascrete can be replaced with Reinforced Glass (not counting the top layer)")
+ .addStructureInfo(
+ "Other material can be used in place of Plascrete, even in higher percentages. See config for detail")
+ .addOtherStructurePart("Filter Machine Casing", "Top besides controller and edges")
+ .addEnergyHatch("Any casing except top layer. Exactly one.")
+ .addMaintenanceHatch("Any casing except top layer")
+ .addStructureInfo("0-2x Reinforced Door (keep closed or efficiency will reduce)")
+ .addStructureInfo("Up to 1 Elevator, Rotating Elevator, and Travel Anchor each")
+ .addStructureInfo("Up to 10 Machine Hulls for Item & Energy transfer through walls")
+ .addStructureInfo("You can also use Diodes for more power")
+ .addStructureInfo("Diodes also count towards 10 Machine Hulls count limit")
+ .toolTipFinisher("Gregtech");
+ return tt;
+ }
+
+ @Override
+ public String[] getStructureDescription(ItemStack itemStack) {
+ return new String[] { "The base can be rectangular." };
+ }
+
+ @Nonnull
+ @Override
+ public CheckRecipeResult checkProcessing() {
+ mEfficiencyIncrease = 100;
+ final long inputVoltage = getMaxInputVoltage();
+
+ // only allow LV+ energy hatches
+ if (inputVoltage < TierEU.LV) {
+ return CheckRecipeResultRegistry.insufficientPower(40);
+ }
+
+ // use the standard overclock mechanism to determine duration and estimate a maximum consumption
+ // if the cleanroom is powered by an LV energy hatch, it will actually accept 2A instead of just 1A.
+ calculateOverclockedNessMultiInternal(
+ 40,
+ 45 * Math.max(1, mHeight - 1),
+ inputVoltage == TierEU.LV ? 2 : 1,
+ inputVoltage,
+ false);
+ // negate it to trigger the special energy consumption function. divide by 10 to get the actual final
+ // consumption.
+ mEUt /= -10;
+ return SimpleCheckRecipeResult.ofSuccess("cleanroom_running");
+ }
+
+ @Override
+ public boolean isFacingValid(ForgeDirection facing) {
+ return (facing.flag & (ForgeDirection.UP.flag | ForgeDirection.DOWN.flag)) == 0;
+ }
+
+ @Override
+ public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+ int x = 1;
+ int z = 1;
+ int y = 1;
+ int mDoorCount = 0;
+ int mHullCount = 0;
+ int mPlascreteCount = 0;
+ final HashMap<String, Integer> otherBlocks = new HashMap<>();
+ boolean doorState = false;
+ this.mUpdate = 100;
+ cleanroomReceivers.forEach(r -> r.setCleanroom(null));
+ cleanroomReceivers.clear();
+
+ if (debugCleanroom) {
+ GT_Log.out.println("Cleanroom: Checking machine");
+ }
+ for (int i = 1; i < 8; i++) {
+ final Block tBlock = aBaseMetaTileEntity.getBlockOffset(i, 0, 0);
+ final int tMeta = aBaseMetaTileEntity.getMetaIDOffset(i, 0, 0);
+ if (tBlock != GregTech_API.sBlockCasings3 || tMeta != 11) {
+ if (tBlock == GregTech_API.sBlockReinforced || tMeta == 2) {
+ x = i;
+ break;
+ } else {
+ if (debugCleanroom) {
+ GT_Log.out.println("Cleanroom: Unable to detect room X edge?");
+ }
+ return false;
+ }
+ }
+ }
+ for (int i = 1; i < 8; i++) {
+ final Block tBlock = aBaseMetaTileEntity.getBlockOffset(0, 0, i);
+ final int tMeta = aBaseMetaTileEntity.getMetaIDOffset(0, 0, i);
+ if (tBlock != GregTech_API.sBlockCasings3 || tMeta != 11) {
+ if (tBlock == GregTech_API.sBlockReinforced || tMeta == 2) {
+ z = i;
+ break;
+ } else {
+ if (debugCleanroom) {
+ GT_Log.out.println("Cleanroom: Unable to detect room Z edge?");
+ }
+ return false;
+ }
+ }
+ }
+ // detect rectangular area of filters
+ for (int i = -x + 1; i < x; i++) {
+ for (int j = -z + 1; j < z; j++) {
+ if (i == 0 && j == 0) continue;
+ final Block tBlock = aBaseMetaTileEntity.getBlockOffset(i, 0, j);
+ final int tMeta = aBaseMetaTileEntity.getMetaIDOffset(i, 0, j);
+ if (tBlock != GregTech_API.sBlockCasings3 && tMeta != 11) {
+ if (debugCleanroom) {
+ GT_Log.out.println("Cleanroom: This is not a filter.");
+ }
+ return false;
+ }
+ }
+ }
+
+ for (int i = -1; i > -16; i--) {
+ final Block tBlock = aBaseMetaTileEntity.getBlockOffset(x, i, z);
+ final int tMeta = aBaseMetaTileEntity.getMetaIDOffset(x, i, z);
+ if (tBlock != GregTech_API.sBlockReinforced || tMeta != 2) {
+ y = i + 1;
+ break;
+ }
+ }
+ if (y > -2) {
+ if (debugCleanroom) {
+ GT_Log.out.println("Cleanroom: Room not tall enough?");
+ }
+ return false;
+ }
+ for (int dX = -x; dX <= x; dX++) {
+ for (int dZ = -z; dZ <= z; dZ++) {
+ for (int dY = 0; dY >= y; dY--) {
+ if (dX == -x || dX == x || dY == 0 || dY == y || dZ == -z || dZ == z) {
+ Block tBlock = aBaseMetaTileEntity.getBlockOffset(dX, dY, dZ);
+ int tMeta = aBaseMetaTileEntity.getMetaIDOffset(dX, dY, dZ);
+ if (dY == 0) { // TOP
+ if (dX == -x || dX == x || dZ == -z || dZ == z) { // Top Border
+ if (tBlock != GregTech_API.sBlockReinforced || tMeta != 2) {
+ if (debugCleanroom) {
+ GT_Log.out.println("Cleanroom: Non reinforced block on top edge? tMeta != 2");
+ }
+ return false;
+ }
+ } else if (dX != 0 || dZ != 0) { // Top Inner exclude center
+ if (tBlock != GregTech_API.sBlockCasings3 || tMeta != 11) {
+ if (debugCleanroom) {
+ GT_Log.out.println(
+ "Cleanroom: Non reinforced block on top face interior? tMeta != 11");
+ }
+ return false;
+ }
+ }
+ } else if (tBlock == GregTech_API.sBlockReinforced && tMeta == 2) {
+ mPlascreteCount++;
+ } else {
+ final IGregTechTileEntity tTileEntity = aBaseMetaTileEntity
+ .getIGregTechTileEntityOffset(dX, dY, dZ);
+ if ((!this.addMaintenanceToMachineList(tTileEntity, 210))
+ && (!this.addEnergyInputToMachineList(tTileEntity, 210))) {
+ if (tBlock instanceof ic2.core.block.BlockIC2Door) {
+ if ((tMeta & 8) == 0) {
+ // let's not fiddle with bits anymore.
+ if (Math.abs(dZ) < z) // on side parallel to z axis
+ doorState = tMeta == 1 || tMeta == 3 || tMeta == 4 || tMeta == 6;
+ else if (Math.abs(dX) < x) // on side parallel to x axis
+ doorState = tMeta == 0 || tMeta == 2 || tMeta == 5 || tMeta == 7;
+ // corners ignored
+ }
+ mDoorCount++;
+ } else {
+ if (tTileEntity != null) {
+ final IMetaTileEntity aMetaTileEntity = tTileEntity.getMetaTileEntity();
+ if (aMetaTileEntity == null) {
+ if (debugCleanroom) {
+ GT_Log.out.println("Cleanroom: Missing block? Not a aMetaTileEntity");
+ }
+ return false;
+ }
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_BasicHull) {
+ mHullCount++;
+ } else {
+ if (debugCleanroom) {
+ GT_Log.out.println(
+ "Cleanroom: Incorrect GT block? " + tBlock.getUnlocalizedName());
+ }
+ return false;
+ }
+ } else {
+ String key = tBlock.getUnlocalizedName() + ":" + tMeta;
+ if (config.containsKey(key)) { // check with meta first
+ otherBlocks.compute(key, (k, v) -> v == null ? 1 : v + 1);
+ } else {
+ key = tBlock.getUnlocalizedName();
+ if (config.containsKey(key)) {
+ otherBlocks.compute(key, (k, v) -> v == null ? 1 : v + 1);
+ } else {
+ if (debugCleanroom) {
+ GT_Log.out.println(
+ "Cleanroom: not allowed block " + tBlock.getUnlocalizedName());
+ }
+ return false;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (this.mMaintenanceHatches.size() != 1 || this.mEnergyHatches.size() != 1
+ || mDoorCount > 4
+ || mHullCount > 10) {
+ if (debugCleanroom) {
+ GT_Log.out.println("Cleanroom: Incorrect number of doors, hulls, or hatches.");
+ }
+ return false;
+ }
+ if (mPlascreteCount < 20) {
+ if (debugCleanroom) {
+ GT_Log.out.println("Cleanroom: Could not find 20 Plascrete.");
+ }
+ return false;
+ }
+ final float ratio = (((float) mPlascreteCount) / 100f);
+ for (Map.Entry<String, Integer> e : otherBlocks.entrySet()) {
+ final ConfigEntry ce = config.get(e.getKey());
+ if (ce.allowedCount > 0) { // count has priority
+ if (e.getValue() > ce.allowedCount) {
+ if (debugCleanroom) {
+ GT_Log.out.println("Cleanroom: Absolute count too high for a block.");
+ }
+ return false;
+ }
+ } else if (e.getValue() > ratio * ce.percentage) {
+ if (debugCleanroom) {
+ GT_Log.out.println("Cleanroom: Relative count too high for a block.");
+ }
+ return false;
+ }
+ }
+
+ setCleanroomReceivers(x, y, z, aBaseMetaTileEntity);
+
+ if (doorState) {
+ this.mEfficiency = Math.max(0, this.mEfficiency - 200);
+ }
+ for (final ForgeDirection tSide : ForgeDirection.VALID_DIRECTIONS) {
+ final byte t = (byte) Math.max(1, (byte) (15 / (10000f / this.mEfficiency)));
+ aBaseMetaTileEntity.setInternalOutputRedstoneSignal(tSide, t);
+ }
+ this.mHeight = -y;
+ if (debugCleanroom) {
+ GT_Log.out.println("Cleanroom: Check successful.");
+ }
+ return true;
+ }
+
+ private void setCleanroomReceivers(int x, int y, int z, IGregTechTileEntity aBaseMetaTileEntity) {
+ for (int dX = -x + 1; dX <= x - 1; dX++) {
+ for (int dZ = -z + 1; dZ <= z - 1; dZ++) for (int dY = -1; dY >= y + 1; dY--) {
+ TileEntity tTileEntity = aBaseMetaTileEntity.getTileEntityOffset(dX, dY, dZ);
+ if (tTileEntity instanceof ICleanroomReceiver receiver) {
+ receiver.setCleanroom(this);
+ cleanroomReceivers.add(receiver);
+ }
+ }
+ }
+ }
+
+ @Override
+ public boolean allowGeneralRedstoneOutput() {
+ return true;
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity baseMetaTileEntity, ForgeDirection sideDirection,
+ ForgeDirection facingDirection, int colorIndex, boolean active, boolean redstoneLevel) {
+ if ((sideDirection.flag & (ForgeDirection.UP.flag | ForgeDirection.DOWN.flag)) != 0) {
+ return new ITexture[] { TextureFactory.of(BLOCK_PLASCRETE), active
+ ? TextureFactory.of(
+ TextureFactory.of(OVERLAY_TOP_CLEANROOM_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_CLEANROOM_ACTIVE_GLOW)
+ .glow()
+ .build())
+ : TextureFactory.of(
+ TextureFactory.of(OVERLAY_TOP_CLEANROOM),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_CLEANROOM_GLOW)
+ .glow()
+ .build()) };
+ }
+ return new ITexture[] { TextureFactory.of(BLOCK_PLASCRETE) };
+ }
+
+ @Override
+ public boolean isCorrectMachinePart(ItemStack aStack) {
+ return true;
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack aStack) {
+ return 10000;
+ }
+
+ @Override
+ public int getDamageToComponent(ItemStack aStack) {
+ return 0;
+ }
+
+ @Override
+ public boolean explodesOnComponentBreak(ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public void construct(ItemStack itemStack, boolean b) {
+ int i = Math.min(itemStack.stackSize, 7);
+ IGregTechTileEntity baseEntity = this.getBaseMetaTileEntity();
+ World world = baseEntity.getWorld();
+ int x = baseEntity.getXCoord();
+ int y = baseEntity.getYCoord();
+ int z = baseEntity.getZCoord();
+ int yoff = Math.max(i * 2, 3);
+ for (int X = x - i; X <= x + i; X++) for (int Y = y; Y >= y - yoff; Y--) for (int Z = z - i; Z <= z + i; Z++) {
+ if (X == x && Y == y && Z == z) continue;
+ if (X == x - i || X == x + i || Z == z - i || Z == z + i || Y == y - yoff) {
+ if (b) StructureLibAPI.hintParticle(world, X, Y, Z, GregTech_API.sBlockReinforced, 2);
+ else world.setBlock(X, Y, Z, GregTech_API.sBlockReinforced, 2, 2);
+ } else if (Y == y) {
+ if (b) StructureLibAPI.hintParticle(world, X, Y, Z, GregTech_API.sBlockCasings3, 11);
+ else world.setBlock(X, Y, Z, GregTech_API.sBlockCasings3, 11, 2);
+ }
+ }
+ }
+
+ private static class ConfigEntry {
+
+ final int percentage;
+ final int allowedCount;
+
+ ConfigEntry(int percentage, int count) {
+ this.percentage = percentage;
+ this.allowedCount = count;
+ }
+ }
+
+ private static final HashMap<String, ConfigEntry> config = new HashMap<>();
+ private static final String category = "cleanroom_allowed_blocks";
+
+ private static void setDefaultConfigValues(Configuration cfg) {
+ cfg.get("cleanroom_allowed_blocks.manaGlass", "Name", "tile.manaGlass");
+ cfg.get("cleanroom_allowed_blocks.manaGlass", "Percentage", 50);
+ cfg.get("cleanroom_allowed_blocks.elfGlass", "Name", "tile.elfGlass");
+ cfg.get("cleanroom_allowed_blocks.elfGlass", "Percentage", 50);
+ cfg.get("cleanroom_allowed_blocks.reinforced_glass", "Name", "blockAlloyGlass");
+ cfg.get("cleanroom_allowed_blocks.reinforced_glass", "Percentage", 5);
+ cfg.get("cleanroom_allowed_blocks.bw_reinforced_glass_0", "Name", "BW_GlasBlocks");
+ cfg.get("cleanroom_allowed_blocks.bw_reinforced_glass_0", "Percentage", 50);
+ cfg.get("cleanroom_allowed_blocks.bw_reinforced_glass_0", "Meta", 0);
+ cfg.get("cleanroom_allowed_blocks.bw_reinforced_glass", "Name", "BW_GlasBlocks");
+ cfg.get("cleanroom_allowed_blocks.bw_reinforced_glass", "Percentage", 100);
+ cfg.get("cleanroom_allowed_blocks.elevator", "Name", "tile.openblocks.elevator");
+ cfg.get("cleanroom_allowed_blocks.elevator", "Count", 1);
+ cfg.get("cleanroom_allowed_blocks.travel_anchor", "Name", "tile.blockTravelAnchor");
+ cfg.get("cleanroom_allowed_blocks.travel_anchor", "Count", 1);
+ cfg.get("cleanroom_allowed_blocks.warded_glass", "Name", "tile.blockCosmeticOpaque");
+ cfg.get("cleanroom_allowed_blocks.warded_glass", "Meta", 2);
+ cfg.get("cleanroom_allowed_blocks.warded_glass", "Percentage", 50);
+ }
+
+ public static void loadConfig(Configuration cfg) {
+ if (!cfg.hasCategory(category)) setDefaultConfigValues(cfg);
+ for (ConfigCategory cc : cfg.getCategory(category)
+ .getChildren()) {
+ final String name = cc.get("Name")
+ .getString();
+ if (cc.containsKey("Count")) {
+ if (cc.containsKey("Meta")) config.put(
+ name + ":"
+ + cc.get("Meta")
+ .getInt(),
+ new ConfigEntry(
+ 0,
+ cc.get("Count")
+ .getInt()));
+ else config.put(
+ name,
+ new ConfigEntry(
+ 0,
+ cc.get("Count")
+ .getInt()));
+ } else if (cc.containsKey("Percentage")) {
+ if (cc.containsKey("Meta")) config.put(
+ name + ":"
+ + cc.get("Meta")
+ .getInt(),
+ new ConfigEntry(
+ cc.get("Percentage")
+ .getInt(),
+ 0));
+ else config.put(
+ name,
+ new ConfigEntry(
+ cc.get("Percentage")
+ .getInt(),
+ 0));
+ }
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ConcreteBackfiller1.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ConcreteBackfiller1.java
new file mode 100644
index 0000000000..e61cfc0feb
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ConcreteBackfiller1.java
@@ -0,0 +1,53 @@
+package gregtech.common.tileentities.machines.multi;
+
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Materials;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+
+public class GT_MetaTileEntity_ConcreteBackfiller1 extends GT_MetaTileEntity_ConcreteBackfillerBase {
+
+ public GT_MetaTileEntity_ConcreteBackfiller1(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_ConcreteBackfiller1(String aName) {
+ super(aName);
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ return createTooltip("Concrete Backfiller");
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_ConcreteBackfiller1(mName);
+ }
+
+ @Override
+ protected ItemList getCasingBlockItem() {
+ return ItemList.Casing_SolidSteel;
+ }
+
+ @Override
+ protected Materials getFrameMaterial() {
+ return Materials.Steel;
+ }
+
+ @Override
+ protected int getCasingTextureIndex() {
+ return 16;
+ }
+
+ @Override
+ protected int getRadius() {
+ return 16;
+ }
+
+ @Override
+ protected int getMinTier() {
+ return 2;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ConcreteBackfiller2.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ConcreteBackfiller2.java
new file mode 100644
index 0000000000..c175d73cb1
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ConcreteBackfiller2.java
@@ -0,0 +1,54 @@
+package gregtech.common.tileentities.machines.multi;
+
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Materials;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+
+public class GT_MetaTileEntity_ConcreteBackfiller2 extends GT_MetaTileEntity_ConcreteBackfillerBase {
+
+ public GT_MetaTileEntity_ConcreteBackfiller2(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_ConcreteBackfiller2(String aName) {
+ super(aName);
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ return createTooltip("Advanced Concrete Backfiller");
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_ConcreteBackfiller2(mName);
+ }
+
+ @Override
+ protected ItemList getCasingBlockItem() {
+ return ItemList.Casing_StableTitanium;
+ }
+
+ @Override
+ protected Materials getFrameMaterial() {
+ return Materials.Titanium;
+ }
+
+ @Override
+ protected int getCasingTextureIndex() {
+ return 50;
+ }
+
+ @Override
+ protected int getRadius() {
+ int tConfig = getTotalConfigValue() * 2;
+ return tConfig >= 128 ? 128 : tConfig <= 0 ? 64 : tConfig;
+ }
+
+ @Override
+ protected int getMinTier() {
+ return 4;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ConcreteBackfillerBase.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ConcreteBackfillerBase.java
new file mode 100644
index 0000000000..e520b87e43
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ConcreteBackfillerBase.java
@@ -0,0 +1,180 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static gregtech.api.enums.GT_HatchElement.Energy;
+import static gregtech.api.enums.GT_HatchElement.InputBus;
+import static gregtech.api.enums.GT_HatchElement.InputHatch;
+import static gregtech.api.enums.GT_HatchElement.Maintenance;
+import static gregtech.api.enums.GT_Values.VN;
+
+import java.util.List;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.StatCollector;
+
+import com.google.common.collect.ImmutableList;
+import com.gtnewhorizons.modularui.api.NumberFormatMUI;
+import com.gtnewhorizons.modularui.api.math.Alignment;
+import com.gtnewhorizons.modularui.common.widget.DynamicPositionedColumn;
+import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget;
+import com.gtnewhorizons.modularui.common.widget.SlotWidget;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.Materials;
+import gregtech.api.interfaces.IHatchElement;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.shutdown.ShutDownReasonRegistry;
+
+public abstract class GT_MetaTileEntity_ConcreteBackfillerBase extends GT_MetaTileEntity_DrillerBase {
+
+ private int mLastXOff = 0, mLastZOff = 0;
+
+ /** Used to drive the readout in the GUI for the backfiller's current y-level. */
+ private int clientYHead;
+
+ public GT_MetaTileEntity_ConcreteBackfillerBase(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ initRecipeResults();
+ }
+
+ public GT_MetaTileEntity_ConcreteBackfillerBase(String aName) {
+ super(aName);
+ initRecipeResults();
+ }
+
+ private void initRecipeResults() {
+ addResultMessage(STATE_UPWARD, true, "backfiller_working");
+ }
+
+ protected GT_Multiblock_Tooltip_Builder createTooltip(String aStructureName) {
+ String casings = getCasingBlockItem().get(0)
+ .getDisplayName();
+
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Concrete Backfiller")
+ .addInfo("Controller Block for the " + aStructureName)
+ .addInfo("Will fill in areas below it with light concrete. This goes through walls")
+ .addInfo("Use it to remove any spawning locations beneath your base to reduce lag")
+ .addInfo("Will pull back the pipes after it finishes that layer")
+ .addInfo("Radius is " + getRadius() + " blocks")
+ .addSeparator()
+ .beginStructureBlock(3, 7, 3, false)
+ .addController("Front bottom")
+ .addOtherStructurePart(casings, "form the 3x1x3 Base")
+ .addOtherStructurePart(casings, "1x3x1 pillar above the center of the base (2 minimum total)")
+ .addOtherStructurePart(getFrameMaterial().mName + " Frame Boxes", "Each pillar's side and 1x3x1 on top")
+ .addEnergyHatch("1x " + VN[getMinTier()] + "+, Any base casing", 1)
+ .addMaintenanceHatch("Any base casing", 1)
+ .addInputBus("Mining Pipes, optional, any base casing", 1)
+ .addInputHatch("GT Concrete, any base casing", 1)
+ .addOutputBus("Mining Pipes, optional, any base casing", 1)
+ .toolTipFinisher("Gregtech");
+ return tt;
+ }
+
+ protected abstract int getRadius();
+
+ @Override
+ protected boolean checkHatches() {
+ return !mMaintenanceHatches.isEmpty() && !mInputHatches.isEmpty() && mEnergyHatches.size() == 1;
+ }
+
+ @Override
+ protected List<IHatchElement<? super GT_MetaTileEntity_DrillerBase>> getAllowedHatches() {
+ return ImmutableList.of(InputHatch, InputBus, Maintenance, Energy);
+ }
+
+ @Override
+ protected void setElectricityStats() {
+ this.mEfficiency = getCurrentEfficiency(null);
+ this.mEfficiencyIncrease = 10000;
+ int tier = Math.max(1, GT_Utility.getTier(getMaxInputVoltage()));
+ this.mEUt = -6 * (1 << (tier << 1));
+ this.mMaxProgresstime = (workState == STATE_UPWARD ? 240 : 80) / (1 << tier);
+ this.mMaxProgresstime = Math.max(1, this.mMaxProgresstime);
+ }
+
+ @Override
+ protected boolean workingUpward(ItemStack aStack, int xDrill, int yDrill, int zDrill, int xPipe, int zPipe,
+ int yHead, int oldYHead) {
+ if (isRefillableBlock(xPipe, yHead - 1, zPipe)) return tryRefillBlock(xPipe, yHead - 1, zPipe);
+ int radius = getRadius();
+ if (mLastXOff == 0 && mLastZOff == 0) {
+ mLastXOff = -radius;
+ mLastZOff = -radius;
+ }
+ if (yHead != yDrill) {
+ for (int i = mLastXOff; i <= radius; i++) {
+ for (int j = (i == mLastXOff ? mLastZOff : -radius); j <= radius; j++) {
+ if (isRefillableBlock(xPipe + i, yHead, zPipe + j)) {
+ mLastXOff = i;
+ mLastZOff = j;
+ return tryRefillBlock(xPipe + i, yHead, zPipe + j);
+ }
+ }
+ }
+ }
+
+ if (tryPickPipe()) {
+ mLastXOff = 0;
+ mLastZOff = 0;
+ return true;
+ } else {
+ workState = STATE_DOWNWARD;
+ stopMachine(ShutDownReasonRegistry.NONE);
+ setShutdownReason(StatCollector.translateToLocal("GT5U.gui.text.backfiller_finished"));
+ return false;
+ }
+ }
+
+ private boolean isRefillableBlock(int aX, int aY, int aZ) {
+ IGregTechTileEntity aBaseTile = getBaseMetaTileEntity();
+ if (!aBaseTile.getBlock(aX, aY, aZ)
+ .isAir(aBaseTile.getWorld(), aX, aY, aZ) || aBaseTile.getBlock(aX, aY, aZ)
+ .getMaterial()
+ .isSolid())
+ return false;
+ return GT_Utility
+ .setBlockByFakePlayer(getFakePlayer(aBaseTile), aX, aY, aZ, GregTech_API.sBlockConcretes, 8, true);
+ }
+
+ private boolean tryRefillBlock(int aX, int aY, int aZ) {
+ if (!tryConsumeFluid()) {
+ setRuntimeFailureReason(CheckRecipeResultRegistry.BACKFILLER_NO_CONCRETE);
+ return false;
+ }
+ getBaseMetaTileEntity().getWorld()
+ .setBlock(aX, aY, aZ, GregTech_API.sBlockConcretes, 8, 3);
+ return true;
+ }
+
+ private boolean tryConsumeFluid() {
+ if (!depleteInput(Materials.Concrete.getMolten(144L))) {
+ mMaxProgresstime = 0;
+ return false;
+ }
+ return true;
+ }
+
+ protected static final NumberFormatMUI numberFormat = new NumberFormatMUI();
+
+ @Override
+ protected void drawTexts(DynamicPositionedColumn screenElements, SlotWidget inventorySlot) {
+ super.drawTexts(screenElements, inventorySlot);
+ screenElements
+ .widget(
+ TextWidget
+ .dynamicString(
+ () -> StatCollector.translateToLocalFormatted(
+ "GT5U.gui.text.backfiller_current_area",
+ numberFormat.format(clientYHead)))
+ .setSynced(false)
+ .setTextAlignment(Alignment.CenterLeft)
+ .setEnabled(widget -> getBaseMetaTileEntity().isActive() && workState == STATE_UPWARD))
+ .widget(new FakeSyncWidget.IntegerSyncer(this::getYHead, newInt -> clientYHead = newInt))
+ .widget(new FakeSyncWidget.IntegerSyncer(() -> workState, newInt -> workState = newInt));
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DieselEngine.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DieselEngine.java
new file mode 100644
index 0000000000..6c77dc7f0d
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DieselEngine.java
@@ -0,0 +1,416 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.lazy;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.transpose;
+import static gregtech.api.enums.GT_HatchElement.Dynamo;
+import static gregtech.api.enums.GT_HatchElement.InputHatch;
+import static gregtech.api.enums.GT_HatchElement.Maintenance;
+import static gregtech.api.enums.GT_HatchElement.Muffler;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_DIESEL_ENGINE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_DIESEL_ENGINE_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_DIESEL_ENGINE_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_DIESEL_ENGINE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.casingTexturePages;
+import static gregtech.api.util.GT_StructureUtility.buildHatchAdder;
+import static gregtech.api.util.GT_Utility.filterValidMTEs;
+
+import java.util.ArrayList;
+
+import net.minecraft.block.Block;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.StatCollector;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidStack;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+
+import gregtech.GT_Mod;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.Materials;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_EnhancedMultiBlockBase;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Dynamo;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Muffler;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.recipe.check.SimpleCheckRecipeResult;
+import gregtech.api.recipe.maps.FuelBackend;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_DieselEngine
+ extends GT_MetaTileEntity_EnhancedMultiBlockBase<GT_MetaTileEntity_DieselEngine> implements ISurvivalConstructable {
+
+ private static final String STRUCTURE_PIECE_MAIN = "main";
+ private static final ClassValue<IStructureDefinition<GT_MetaTileEntity_DieselEngine>> STRUCTURE_DEFINITION = new ClassValue<>() {
+
+ @Override
+ protected IStructureDefinition<GT_MetaTileEntity_DieselEngine> computeValue(Class<?> type) {
+ return StructureDefinition.<GT_MetaTileEntity_DieselEngine>builder()
+ .addShape(
+ STRUCTURE_PIECE_MAIN,
+ transpose(
+ new String[][] { { "---", "iii", "chc", "chc", "ccc", }, { "---", "i~i", "hgh", "hgh", "cdc", },
+ { "---", "iii", "chc", "chc", "ccc", }, }))
+ .addElement('i', lazy(t -> ofBlock(t.getIntakeBlock(), t.getIntakeMeta())))
+ .addElement('c', lazy(t -> ofBlock(t.getCasingBlock(), t.getCasingMeta())))
+ .addElement('g', lazy(t -> ofBlock(t.getGearboxBlock(), t.getGearboxMeta())))
+ .addElement('d', lazy(t -> Dynamo.newAny(t.getCasingTextureIndex(), 2)))
+ .addElement(
+ 'h',
+ lazy(
+ t -> buildHatchAdder(GT_MetaTileEntity_DieselEngine.class)
+ .atLeast(InputHatch, InputHatch, InputHatch, Muffler, Maintenance)
+ .casingIndex(t.getCasingTextureIndex())
+ .dot(1)
+ .buildAndChain(t.getCasingBlock(), t.getCasingMeta())))
+ .build();
+ }
+ };
+ protected int fuelConsumption = 0;
+ protected int fuelValue = 0;
+ protected int fuelRemaining = 0;
+ protected boolean boostEu = false;
+
+ public GT_MetaTileEntity_DieselEngine(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_DieselEngine(String aName) {
+ super(aName);
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Combustion Generator")
+ .addInfo("Controller block for the Large Combustion Engine")
+ .addInfo("Supply Diesel Fuels and 1000L of Lubricant per hour to run")
+ .addInfo("Supply 40L/s of Oxygen to boost output (optional)")
+ .addInfo("Default: Produces 2048EU/t at 100% fuel efficiency")
+ .addInfo("Boosted: Produces 6144EU/t at 150% fuel efficiency")
+ .addInfo("You need to wait for it to reach 300% to output full power")
+ .addPollutionAmount(getPollutionPerSecond(null))
+ .addSeparator()
+ .beginStructureBlock(3, 3, 4, false)
+ .addController("Front center")
+ .addCasingInfoRange("Stable Titanium Machine Casing", 16, 22, false)
+ .addOtherStructurePart("Titanium Gear Box Machine Casing", "Inner 2 blocks")
+ .addOtherStructurePart("Engine Intake Machine Casing", "8x, ring around controller")
+ .addStructureInfo("Engine Intake Casings must not be obstructed in front (only air blocks)")
+ .addDynamoHatch("Back center", 2)
+ .addMaintenanceHatch("One of the casings next to a Gear Box", 1)
+ .addMufflerHatch("Top middle back, above the rear Gear Box", 1)
+ .addInputHatch("Diesel Fuel, next to a Gear Box", 1)
+ .addInputHatch("Lubricant, next to a Gear Box", 1)
+ .addInputHatch("Oxygen, optional, next to a Gear Box", 1)
+ .toolTipFinisher("Gregtech");
+ return tt;
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection aFacing,
+ int colorIndex, boolean aActive, boolean redstoneLevel) {
+ if (side == aFacing) {
+ if (aActive) return new ITexture[] { casingTexturePages[0][50], TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_DIESEL_ENGINE_ACTIVE)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_DIESEL_ENGINE_ACTIVE_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ return new ITexture[] { casingTexturePages[0][50], TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_DIESEL_ENGINE)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_DIESEL_ENGINE_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ }
+ return new ITexture[] { casingTexturePages[0][50] };
+ }
+
+ @Override
+ public boolean isCorrectMachinePart(ItemStack aStack) {
+ return getMaxEfficiency(aStack) > 0;
+ }
+
+ @Override
+ public RecipeMap<FuelBackend> getRecipeMap() {
+ return RecipeMaps.dieselFuels;
+ }
+
+ @Override
+ protected boolean filtersFluid() {
+ return false;
+ }
+
+ /**
+ * The nominal energy output This can be further multiplied by {@link #getMaxEfficiency(ItemStack)} when boosted
+ */
+ protected int getNominalOutput() {
+ return 2048;
+ }
+
+ protected Materials getBooster() {
+ return Materials.Oxygen;
+ }
+
+ /**
+ * x times fuel will be consumed when boosted This will however NOT increase power output Go tweak
+ * {@link #getMaxEfficiency(ItemStack)} and {@link #getNominalOutput()} instead
+ */
+ protected int getBoostFactor() {
+ return 2;
+ }
+
+ /**
+ * x times of additive will be consumed when boosted
+ */
+ protected int getAdditiveFactor() {
+ return 1;
+ }
+
+ /**
+ * Efficiency will increase by this amount every tick
+ */
+ protected int getEfficiencyIncrease() {
+ return 15;
+ }
+
+ @Override
+ @NotNull
+ public CheckRecipeResult checkProcessing() {
+ ArrayList<FluidStack> tFluids = getStoredFluids();
+
+ // fast track lookup
+ if (!tFluids.isEmpty()) {
+ double boostedFuelValue = 0;
+ double boostedOutput = 0;
+ double extraFuelFraction = 0;
+ for (FluidStack tFluid : tFluids) {
+ GT_Recipe tRecipe = getRecipeMap().getBackend()
+ .findFuel(tFluid);
+ if (tRecipe == null) continue;
+ fuelValue = tRecipe.mSpecialValue;
+
+ FluidStack tLiquid = tFluid.copy();
+ if (boostEu) {
+ boostedFuelValue = GT_Utility.safeInt((long) (fuelValue * 1.5));
+ boostedOutput = getNominalOutput() * 3;
+
+ fuelConsumption = tLiquid.amount = getBoostFactor() * getNominalOutput() / fuelValue;
+
+ // HOG consumption rate is normally 1 L/t, when it's supposed to be around 1.64 L/t
+ // This code increases fuel consumption by 1 at random, but with a weighted chance
+ if (boostedFuelValue * 2 > boostedOutput) {
+ extraFuelFraction = boostedOutput / boostedFuelValue;
+ extraFuelFraction = extraFuelFraction - (int) extraFuelFraction;
+ double rand = Math.random();
+ if (rand < extraFuelFraction) {
+ tLiquid.amount += 1;
+ }
+ }
+
+ } else {
+ fuelConsumption = tLiquid.amount = getNominalOutput() / fuelValue;
+ }
+
+ // Deplete that amount
+ if (!depleteInput(tLiquid)) return CheckRecipeResultRegistry.NO_FUEL_FOUND;
+ boostEu = depleteInput(getBooster().getGas(2L * getAdditiveFactor()));
+
+ // Check to prevent burning HOG without consuming it, if not boosted
+ if (!boostEu && fuelValue > getNominalOutput()) {
+ return SimpleCheckRecipeResult.ofFailure("fuel_quality_too_high");
+ }
+
+ // Deplete Lubricant. 1000L should = 1 hour of runtime (if baseEU = 2048)
+ if ((mRuntime % 72 == 0 || mRuntime == 0)
+ && !depleteInput(Materials.Lubricant.getFluid((boostEu ? 2L : 1L) * getAdditiveFactor())))
+ return SimpleCheckRecipeResult.ofFailure("no_lubricant");
+
+ fuelRemaining = tFluid.amount; // Record available fuel
+ this.mEUt = mEfficiency < 2000 ? 0 : getNominalOutput(); // Output 0 if startup is less than 20%
+ this.mProgresstime = 1;
+ this.mMaxProgresstime = 1;
+ this.mEfficiencyIncrease = getEfficiencyIncrease();
+ return CheckRecipeResultRegistry.GENERATING;
+ }
+ }
+ this.mEUt = 0;
+ this.mEfficiency = 0;
+ return CheckRecipeResultRegistry.NO_FUEL_FOUND;
+ }
+
+ @Override
+ public IStructureDefinition<GT_MetaTileEntity_DieselEngine> getStructureDefinition() {
+ return STRUCTURE_DEFINITION.get(getClass());
+ }
+
+ @Override
+ public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+ return checkPiece(STRUCTURE_PIECE_MAIN, 1, 1, 1) && !mMufflerHatches.isEmpty()
+ && mMaintenanceHatches.size() == 1;
+ }
+
+ public Block getCasingBlock() {
+ return GregTech_API.sBlockCasings4;
+ }
+
+ public byte getCasingMeta() {
+ return 2;
+ }
+
+ public Block getIntakeBlock() {
+ return GregTech_API.sBlockCasings4;
+ }
+
+ public byte getIntakeMeta() {
+ return 13;
+ }
+
+ public Block getGearboxBlock() {
+ return GregTech_API.sBlockCasings2;
+ }
+
+ public byte getGearboxMeta() {
+ return 4;
+ }
+
+ public byte getCasingTextureIndex() {
+ return 50;
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_DieselEngine(this.mName);
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ }
+
+ @Override
+ public int getDamageToComponent(ItemStack aStack) {
+ return 1;
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack aStack) {
+ return boostEu ? 30000 : 10000;
+ }
+
+ @Override
+ public int getPollutionPerSecond(ItemStack aStack) {
+ return GT_Mod.gregtechproxy.mPollutionLargeCombustionEnginePerSecond;
+ }
+
+ @Override
+ public boolean explodesOnComponentBreak(ItemStack aStack) {
+ return true;
+ }
+
+ @Override
+ public String[] getInfoData() {
+ int mPollutionReduction = 0;
+ for (GT_MetaTileEntity_Hatch_Muffler tHatch : filterValidMTEs(mMufflerHatches)) {
+ mPollutionReduction = Math.max(tHatch.calculatePollutionReduction(100), mPollutionReduction);
+ }
+
+ long storedEnergy = 0;
+ long maxEnergy = 0;
+ for (GT_MetaTileEntity_Hatch_Dynamo tHatch : filterValidMTEs(mDynamoHatches)) {
+ storedEnergy += tHatch.getBaseMetaTileEntity()
+ .getStoredEU();
+ maxEnergy += tHatch.getBaseMetaTileEntity()
+ .getEUCapacity();
+ }
+
+ return new String[] { EnumChatFormatting.BLUE + "Diesel Engine" + EnumChatFormatting.RESET,
+ StatCollector.translateToLocal("GT5U.multiblock.energy") + ": "
+ + EnumChatFormatting.GREEN
+ + GT_Utility.formatNumbers(storedEnergy)
+ + EnumChatFormatting.RESET
+ + " EU / "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(maxEnergy)
+ + EnumChatFormatting.RESET
+ + " EU",
+ getIdealStatus() == getRepairStatus()
+ ? EnumChatFormatting.GREEN + StatCollector.translateToLocal("GT5U.turbine.maintenance.false")
+ + EnumChatFormatting.RESET
+ : EnumChatFormatting.RED + StatCollector.translateToLocal("GT5U.turbine.maintenance.true")
+ + EnumChatFormatting.RESET,
+ StatCollector.translateToLocal("GT5U.engine.output") + ": "
+ + EnumChatFormatting.RED
+ + GT_Utility.formatNumbers(((long) mEUt * mEfficiency / 10000))
+ + EnumChatFormatting.RESET
+ + " EU/t",
+ StatCollector.translateToLocal("GT5U.engine.consumption") + ": "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(fuelConsumption)
+ + EnumChatFormatting.RESET
+ + " L/t",
+ StatCollector.translateToLocal("GT5U.engine.value") + ": "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(fuelValue)
+ + EnumChatFormatting.RESET
+ + " EU/L",
+ StatCollector.translateToLocal("GT5U.turbine.fuel") + ": "
+ + EnumChatFormatting.GOLD
+ + GT_Utility.formatNumbers(fuelRemaining)
+ + EnumChatFormatting.RESET
+ + " L",
+ StatCollector.translateToLocal("GT5U.engine.efficiency") + ": "
+ + EnumChatFormatting.YELLOW
+ + (mEfficiency / 100F)
+ + EnumChatFormatting.YELLOW
+ + " %",
+ StatCollector.translateToLocal("GT5U.multiblock.pollution") + ": "
+ + EnumChatFormatting.GREEN
+ + mPollutionReduction
+ + EnumChatFormatting.RESET
+ + " %" };
+ }
+
+ @Override
+ public boolean isGivingInformation() {
+ return true;
+ }
+
+ @Override
+ public void construct(ItemStack stackSize, boolean hintsOnly) {
+ buildPiece(STRUCTURE_PIECE_MAIN, stackSize, hintsOnly, 1, 1, 1);
+ }
+
+ @Override
+ public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
+ if (mMachine) return -1;
+ return survivialBuildPiece(STRUCTURE_PIECE_MAIN, stackSize, 1, 1, 1, elementBudget, env, false, true);
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DistillationTower.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DistillationTower.java
new file mode 100644
index 0000000000..dfc3a4928d
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DistillationTower.java
@@ -0,0 +1,367 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.isAir;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofChain;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.onElementPass;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.transpose;
+import static gregtech.api.enums.GT_HatchElement.Energy;
+import static gregtech.api.enums.GT_HatchElement.InputBus;
+import static gregtech.api.enums.GT_HatchElement.InputHatch;
+import static gregtech.api.enums.GT_HatchElement.Maintenance;
+import static gregtech.api.enums.GT_HatchElement.OutputBus;
+import static gregtech.api.enums.GT_HatchElement.OutputHatch;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_DISTILLATION_TOWER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_DISTILLATION_TOWER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_DISTILLATION_TOWER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_DISTILLATION_TOWER_GLOW;
+import static gregtech.api.util.GT_StructureUtility.buildHatchAdder;
+import static gregtech.api.util.GT_StructureUtility.ofHatchAdder;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidStack;
+
+import com.gtnewhorizon.structurelib.alignment.IAlignmentLimits;
+import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.SoundResource;
+import gregtech.api.enums.Textures;
+import gregtech.api.enums.Textures.BlockIcons;
+import gregtech.api.interfaces.IHatchElement;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.fluid.IFluidStore;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.logic.ProcessingLogic;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_EnhancedMultiBlockBase;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Output;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.common.tileentities.machines.GT_MetaTileEntity_Hatch_Output_ME;
+
+public class GT_MetaTileEntity_DistillationTower extends
+ GT_MetaTileEntity_EnhancedMultiBlockBase<GT_MetaTileEntity_DistillationTower> implements ISurvivalConstructable {
+
+ protected static final int CASING_INDEX = 49;
+ protected static final String STRUCTURE_PIECE_BASE = "base";
+ protected static final String STRUCTURE_PIECE_LAYER = "layer";
+ protected static final String STRUCTURE_PIECE_LAYER_HINT = "layerHint";
+ protected static final String STRUCTURE_PIECE_TOP_HINT = "topHint";
+ private static final IStructureDefinition<GT_MetaTileEntity_DistillationTower> STRUCTURE_DEFINITION;
+
+ static {
+ IHatchElement<GT_MetaTileEntity_DistillationTower> layeredOutputHatch = OutputHatch
+ .withCount(GT_MetaTileEntity_DistillationTower::getCurrentLayerOutputHatchCount)
+ .withAdder(GT_MetaTileEntity_DistillationTower::addLayerOutputHatch);
+ STRUCTURE_DEFINITION = StructureDefinition.<GT_MetaTileEntity_DistillationTower>builder()
+ .addShape(STRUCTURE_PIECE_BASE, transpose(new String[][] { { "b~b", "bbb", "bbb" }, }))
+ .addShape(STRUCTURE_PIECE_LAYER, transpose(new String[][] { { "lll", "lcl", "lll" }, }))
+ .addShape(STRUCTURE_PIECE_LAYER_HINT, transpose(new String[][] { { "lll", "l-l", "lll" }, }))
+ .addShape(STRUCTURE_PIECE_TOP_HINT, transpose(new String[][] { { "LLL", "LLL", "LLL" }, }))
+ .addElement(
+ 'b',
+ ofChain(
+ buildHatchAdder(GT_MetaTileEntity_DistillationTower.class)
+ .atLeast(Energy, OutputBus, InputHatch, InputBus, Maintenance)
+ .casingIndex(CASING_INDEX)
+ .dot(1)
+ .build(),
+ onElementPass(
+ GT_MetaTileEntity_DistillationTower::onCasingFound,
+ ofBlock(GregTech_API.sBlockCasings4, 1))))
+ .addElement(
+ 'l',
+ ofChain(
+ buildHatchAdder(GT_MetaTileEntity_DistillationTower.class).atLeast(layeredOutputHatch)
+ .casingIndex(CASING_INDEX)
+ .dot(2)
+ .disallowOnly(ForgeDirection.UP, ForgeDirection.DOWN)
+ .build(),
+ ofHatchAdder(GT_MetaTileEntity_DistillationTower::addEnergyInputToMachineList, CASING_INDEX, 2),
+ ofHatchAdder(GT_MetaTileEntity_DistillationTower::addLayerOutputHatch, CASING_INDEX, 2),
+ ofHatchAdder(GT_MetaTileEntity_DistillationTower::addMaintenanceToMachineList, CASING_INDEX, 2),
+ onElementPass(
+ GT_MetaTileEntity_DistillationTower::onCasingFound,
+ ofBlock(GregTech_API.sBlockCasings4, 1))))
+ // hint element only used in top layer
+ .addElement(
+ 'L',
+ buildHatchAdder(GT_MetaTileEntity_DistillationTower.class).atLeast(layeredOutputHatch)
+ .casingIndex(CASING_INDEX)
+ .dot(2)
+ .disallowOnly(ForgeDirection.UP)
+ .buildAndChain(GregTech_API.sBlockCasings4, 1))
+ .addElement(
+ 'c',
+ ofChain(
+ onElementPass(
+ t -> t.onTopLayerFound(false),
+ ofHatchAdder(GT_MetaTileEntity_DistillationTower::addOutputToMachineList, CASING_INDEX, 3)),
+ onElementPass(
+ t -> t.onTopLayerFound(false),
+ ofHatchAdder(
+ GT_MetaTileEntity_DistillationTower::addMaintenanceToMachineList,
+ CASING_INDEX,
+ 3)),
+ onElementPass(t -> t.onTopLayerFound(true), ofBlock(GregTech_API.sBlockCasings4, 1)),
+ isAir()))
+ .build();
+ }
+
+ protected final List<List<GT_MetaTileEntity_Hatch_Output>> mOutputHatchesByLayer = new ArrayList<>();
+ protected int mHeight;
+ protected int mCasing;
+ protected boolean mTopLayerFound;
+
+ public GT_MetaTileEntity_DistillationTower(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_DistillationTower(String aName) {
+ super(aName);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_DistillationTower(this.mName);
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Distillery")
+ .addInfo("Controller block for the Distillation Tower")
+ .addInfo("Fluids are only put out at the correct height")
+ .addInfo("The correct height equals the slot number in the NEI recipe")
+ .addSeparator()
+ .beginVariableStructureBlock(3, 3, 3, 12, 3, 3, true)
+ .addController("Front bottom")
+ .addOtherStructurePart("Clean Stainless Steel Machine Casing", "7 x h - 5 (minimum)")
+ .addEnergyHatch("Any casing except top centre", 1, 2)
+ .addMaintenanceHatch("Any casing", 1, 2, 3)
+ .addInputHatch("Any bottom layer casing", 1)
+ .addOutputBus("Any bottom layer casing", 1)
+ .addOutputHatch("2-11x Output Hatches (At least one per layer except bottom layer)", 2, 3)
+ .toolTipFinisher("Gregtech");
+ return tt;
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity baseMetaTileEntity, ForgeDirection sideDirection,
+ ForgeDirection facingDirection, int colorIndex, boolean active, boolean redstoneLevel) {
+ if (sideDirection == facingDirection) {
+ if (active) return new ITexture[] { BlockIcons.getCasingTextureForId(CASING_INDEX), TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_DISTILLATION_TOWER_ACTIVE)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_DISTILLATION_TOWER_ACTIVE_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ return new ITexture[] { BlockIcons.getCasingTextureForId(CASING_INDEX), TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_DISTILLATION_TOWER)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_DISTILLATION_TOWER_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ }
+ return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(CASING_INDEX) };
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.distillationTowerRecipes;
+ }
+
+ @Override
+ public boolean isCorrectMachinePart(ItemStack aStack) {
+ return true;
+ }
+
+ @Override
+ protected ProcessingLogic createProcessingLogic() {
+ return new ProcessingLogic();
+ }
+
+ protected void onCasingFound() {
+ mCasing++;
+ }
+
+ protected void onTopLayerFound(boolean aIsCasing) {
+ mTopLayerFound = true;
+ if (aIsCasing) onCasingFound();
+ }
+
+ protected int getCurrentLayerOutputHatchCount() {
+ return mOutputHatchesByLayer.size() < mHeight || mHeight <= 0 ? 0
+ : mOutputHatchesByLayer.get(mHeight - 1)
+ .size();
+ }
+
+ protected boolean addLayerOutputHatch(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
+ if (aTileEntity == null || aTileEntity.isDead()
+ || !(aTileEntity.getMetaTileEntity() instanceof GT_MetaTileEntity_Hatch_Output tHatch)) return false;
+ while (mOutputHatchesByLayer.size() < mHeight) mOutputHatchesByLayer.add(new ArrayList<>());
+ tHatch.updateTexture(aBaseCasingIndex);
+ return mOutputHatchesByLayer.get(mHeight - 1)
+ .add(tHatch);
+ }
+
+ @Override
+ public List<? extends IFluidStore> getFluidOutputSlots(FluidStack[] toOutput) {
+ return getFluidOutputSlotsByLayer(toOutput, mOutputHatchesByLayer);
+ }
+
+ @Override
+ protected IAlignmentLimits getInitialAlignmentLimits() {
+ // don't rotate a freaking tower, it won't work
+ return (d, r, f) -> (d.flag & (ForgeDirection.UP.flag | ForgeDirection.DOWN.flag)) == 0 && r.isNotRotated()
+ && !f.isVerticallyFliped();
+ }
+
+ @Override
+ public boolean isRotationChangeAllowed() {
+ return false;
+ }
+
+ @Override
+ public IStructureDefinition<GT_MetaTileEntity_DistillationTower> getStructureDefinition() {
+ return STRUCTURE_DEFINITION;
+ }
+
+ @Override
+ public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+ // reset
+ mOutputHatchesByLayer.forEach(List::clear);
+ mHeight = 1;
+ mTopLayerFound = false;
+ mCasing = 0;
+
+ // check base
+ if (!checkPiece(STRUCTURE_PIECE_BASE, 1, 0, 0)) return false;
+
+ // check each layer
+ while (mHeight < 12) {
+ if (!checkPiece(STRUCTURE_PIECE_LAYER, 1, mHeight, 0)) {
+ return false;
+ }
+ if (mOutputHatchesByLayer.size() < mHeight || mOutputHatchesByLayer.get(mHeight - 1)
+ .isEmpty())
+ // layer without output hatch
+ return false;
+ if (mTopLayerFound) {
+ break;
+ }
+ // not top
+ mHeight++;
+ }
+
+ // validate final invariants... (actual height is mHeight+1)
+ return mCasing >= 7 * (mHeight + 1) - 5 && mHeight + 1 >= 3
+ && mTopLayerFound
+ && mMaintenanceHatches.size() == 1;
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack aStack) {
+ return 10000;
+ }
+
+ @Override
+ public int getDamageToComponent(ItemStack aStack) {
+ return 0;
+ }
+
+ @Override
+ public boolean explodesOnComponentBreak(ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ protected void addFluidOutputs(FluidStack[] mOutputFluids2) {
+ for (int i = 0; i < mOutputFluids2.length && i < mOutputHatchesByLayer.size(); i++) {
+ final FluidStack fluidStack = mOutputFluids2[i];
+ if (fluidStack == null) continue;
+ FluidStack tStack = fluidStack.copy();
+ if (!dumpFluid(mOutputHatchesByLayer.get(i), tStack, true))
+ dumpFluid(mOutputHatchesByLayer.get(i), tStack, false);
+ }
+ }
+
+ @Override
+ public boolean canDumpFluidToME() {
+ // All fluids can be dumped to ME only if each layer contains a ME Output Hatch.
+ return this.mOutputHatchesByLayer.stream()
+ .allMatch(
+ tLayerOutputHatches -> tLayerOutputHatches.stream()
+ .anyMatch(tHatch -> tHatch instanceof GT_MetaTileEntity_Hatch_Output_ME));
+ }
+
+ @Override
+ public void construct(ItemStack stackSize, boolean hintsOnly) {
+ buildPiece(STRUCTURE_PIECE_BASE, stackSize, hintsOnly, 1, 0, 0);
+ int tTotalHeight = Math.min(12, stackSize.stackSize + 2); // min 2 output layer, so at least 1 + 2 height
+ for (int i = 1; i < tTotalHeight - 1; i++) {
+ buildPiece(STRUCTURE_PIECE_LAYER_HINT, stackSize, hintsOnly, 1, i, 0);
+ }
+ buildPiece(STRUCTURE_PIECE_TOP_HINT, stackSize, hintsOnly, 1, tTotalHeight - 1, 0);
+ }
+
+ @Override
+ public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
+ if (mMachine) return -1;
+ mHeight = 0;
+ int built = survivialBuildPiece(STRUCTURE_PIECE_BASE, stackSize, 1, 0, 0, elementBudget, env, false, true);
+ if (built >= 0) return built;
+ int tTotalHeight = Math.min(12, stackSize.stackSize + 2); // min 2 output layer, so at least 1 + 2 height
+ for (int i = 1; i < tTotalHeight - 1; i++) {
+ mHeight = i;
+ built = survivialBuildPiece(
+ STRUCTURE_PIECE_LAYER_HINT,
+ stackSize,
+ 1,
+ i,
+ 0,
+ elementBudget,
+ env,
+ false,
+ true);
+ if (built >= 0) return built;
+ }
+ mHeight = tTotalHeight - 1;
+ return survivialBuildPiece(
+ STRUCTURE_PIECE_TOP_HINT,
+ stackSize,
+ 1,
+ tTotalHeight - 1,
+ 0,
+ elementBudget,
+ env,
+ false,
+ true);
+ }
+
+ @Override
+ protected SoundResource getProcessStartSound() {
+ return SoundResource.GT_MACHINES_DISTILLERY_LOOP;
+ }
+
+ @Override
+ public boolean supportsVoidProtection() {
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DrillerBase.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DrillerBase.java
new file mode 100644
index 0000000000..db58a1152e
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DrillerBase.java
@@ -0,0 +1,985 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.lazy;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.transpose;
+import static gregtech.api.enums.GT_HatchElement.Energy;
+import static gregtech.api.enums.GT_HatchElement.InputBus;
+import static gregtech.api.enums.GT_HatchElement.InputHatch;
+import static gregtech.api.enums.GT_HatchElement.Maintenance;
+import static gregtech.api.enums.GT_HatchElement.Muffler;
+import static gregtech.api.enums.GT_HatchElement.OutputBus;
+import static gregtech.api.enums.GT_HatchElement.OutputHatch;
+import static gregtech.api.enums.GT_Values.W;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ORE_DRILL;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ORE_DRILL_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ORE_DRILL_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ORE_DRILL_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.getCasingTextureForId;
+import static gregtech.api.metatileentity.BaseTileEntity.TOOLTIP_DELAY;
+import static gregtech.api.util.GT_StructureUtility.buildHatchAdder;
+import static gregtech.api.util.GT_StructureUtility.ofFrame;
+import static gregtech.api.util.GT_Utility.filterValidMTEs;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.player.EntityPlayer;
+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.ChunkCoordIntPair;
+import net.minecraftforge.common.util.FakePlayer;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.google.common.collect.ImmutableList;
+import com.gtnewhorizon.structurelib.alignment.IAlignmentLimits;
+import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+import com.gtnewhorizons.modularui.api.drawable.IDrawable;
+import com.gtnewhorizons.modularui.api.math.Alignment;
+import com.gtnewhorizons.modularui.api.math.Pos2d;
+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.DynamicPositionedColumn;
+import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget;
+import com.gtnewhorizons.modularui.common.widget.SlotWidget;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Materials;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.gui.widgets.GT_LockedWhileActiveButton;
+import gregtech.api.interfaces.IChunkLoader;
+import gregtech.api.interfaces.IHatchElement;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_EnhancedMultiBlockBase;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_DataAccess;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Energy;
+import gregtech.api.objects.GT_ChunkManager;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.recipe.check.SimpleCheckRecipeResult;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.IGT_HatchAdder;
+import gregtech.api.util.shutdown.ShutDownReasonRegistry;
+
+public abstract class GT_MetaTileEntity_DrillerBase
+ extends GT_MetaTileEntity_EnhancedMultiBlockBase<GT_MetaTileEntity_DrillerBase>
+ implements IChunkLoader, ISurvivalConstructable {
+
+ private static final ItemStack miningPipe = GT_ModHandler.getIC2Item("miningPipe", 0);
+ private static final ItemStack miningPipeTip = GT_ModHandler.getIC2Item("miningPipeTip", 0);
+ private static final Block miningPipeBlock = GT_Utility.getBlockFromStack(miningPipe);
+ private static final Block miningPipeTipBlock = GT_Utility.getBlockFromStack(miningPipeTip);
+ protected static final String STRUCTURE_PIECE_MAIN = "main";
+ protected static final ClassValue<IStructureDefinition<GT_MetaTileEntity_DrillerBase>> STRUCTURE_DEFINITION = new ClassValue<>() {
+
+ @Override
+ protected IStructureDefinition<GT_MetaTileEntity_DrillerBase> computeValue(Class<?> type) {
+ return StructureDefinition.<GT_MetaTileEntity_DrillerBase>builder()
+ .addShape(
+ STRUCTURE_PIECE_MAIN,
+ transpose(
+ new String[][] { { " ", " f ", " " }, { " ", " f ", " " }, { " ", " f ", " " },
+ { " f ", "fcf", " f " }, { " f ", "fcf", " f " }, { " f ", "fcf", " f " },
+ { "b~b", "bbb", "bbb" }, }))
+ .addElement('f', lazy(t -> ofFrame(t.getFrameMaterial())))
+ .addElement(
+ 'c',
+ lazy(
+ t -> ofBlock(
+ t.getCasingBlockItem()
+ .getBlock(),
+ t.getCasingBlockItem()
+ .get(0)
+ .getItemDamage())))
+ .addElement(
+ 'b',
+ lazy(
+ t -> buildHatchAdder(GT_MetaTileEntity_DrillerBase.class).atLeastList(t.getAllowedHatches())
+ .adder(GT_MetaTileEntity_DrillerBase::addToMachineList)
+ .casingIndex(t.casingTextureIndex)
+ .dot(1)
+ .buildAndChain(
+ t.getCasingBlockItem()
+ .getBlock(),
+ t.getCasingBlockItem()
+ .get(0)
+ .getItemDamage())))
+ .build();
+ }
+ };
+
+ private Block casingBlock;
+ private int casingMeta;
+ private int frameMeta;
+ protected int casingTextureIndex;
+ protected boolean isPickingPipes;
+
+ private ForgeDirection back;
+
+ private int xDrill, yDrill, zDrill, xPipe, zPipe, yHead;
+
+ protected int getXDrill() {
+ return xDrill;
+ }
+
+ protected int getZDrill() {
+ return zDrill;
+ }
+
+ protected int getYHead() {
+ return yHead;
+ }
+
+ protected int workState;
+ protected static final int STATE_DOWNWARD = 0, STATE_AT_BOTTOM = 1, STATE_UPWARD = 2, STATE_ABORT = 3;
+
+ protected boolean mChunkLoadingEnabled = true;
+ protected ChunkCoordIntPair mCurrentChunk = null;
+ protected boolean mWorkChunkNeedsReload = true;
+
+ /** Stores default result messages for success/failures of each work state. */
+ private final Map<ResultRegistryKey, CheckRecipeResult> resultRegistry = new HashMap<>();
+
+ /** Allows inheritors to supply custom runtime failure messages. */
+ private CheckRecipeResult runtimeFailure = null;
+ private CheckRecipeResult lastRuntimeFailure = null;
+
+ /** Allows inheritors to supply custom shutdown failure messages. */
+ private @NotNull String shutdownReason = "";
+
+ /** Allows inheritors to suppress wiping the last error if the machine is forcibly turned off. */
+ protected boolean suppressErrorWipe = false;
+
+ public GT_MetaTileEntity_DrillerBase(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ initFields();
+ }
+
+ public GT_MetaTileEntity_DrillerBase(String aName) {
+ super(aName);
+ initFields();
+ }
+
+ private void initFields() {
+ casingBlock = getCasingBlockItem().getBlock();
+ casingMeta = getCasingBlockItem().get(0)
+ .getItemDamage();
+ int frameId = 4096 + getFrameMaterial().mMetaItemSubID;
+ frameMeta = GregTech_API.METATILEENTITIES[frameId] != null
+ ? GregTech_API.METATILEENTITIES[frameId].getTileEntityBaseType()
+ : W;
+ casingTextureIndex = getCasingTextureIndex();
+ workState = STATE_DOWNWARD;
+
+ // Inheritors can overwrite these to add custom operating messages.
+ addResultMessage(STATE_DOWNWARD, true, "deploying_pipe");
+ addResultMessage(STATE_DOWNWARD, false, "extracting_pipe");
+ addResultMessage(STATE_AT_BOTTOM, true, "drilling");
+ addResultMessage(STATE_AT_BOTTOM, false, "no_mining_pipe");
+ addResultMessage(STATE_UPWARD, true, "retracting_pipe");
+ addResultMessage(STATE_UPWARD, false, "drill_generic_finished");
+ addResultMessage(STATE_ABORT, true, "retracting_pipe");
+ addResultMessage(STATE_ABORT, false, "drill_retract_pipes_finished");
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity baseMetaTileEntity, ForgeDirection sideDirection,
+ ForgeDirection facingDirection, int colorIndex, boolean active, boolean redstoneLevel) {
+ if (sideDirection == facingDirection) {
+ if (active) return new ITexture[] { getCasingTextureForId(casingTextureIndex), TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_ORE_DRILL_ACTIVE)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_ORE_DRILL_ACTIVE_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ return new ITexture[] { getCasingTextureForId(casingTextureIndex), TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_ORE_DRILL)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_ORE_DRILL_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ }
+ return new ITexture[] { getCasingTextureForId(casingTextureIndex) };
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ aNBT.setInteger("workState", workState);
+ aNBT.setBoolean("chunkLoadingEnabled", mChunkLoadingEnabled);
+ aNBT.setBoolean("isChunkloading", mCurrentChunk != null);
+ if (mCurrentChunk != null) {
+ aNBT.setInteger("loadedChunkXPos", mCurrentChunk.chunkXPos);
+ aNBT.setInteger("loadedChunkZPos", mCurrentChunk.chunkZPos);
+ }
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ workState = aNBT.getInteger("workState");
+ if (aNBT.hasKey("isPickingPipes"))
+ workState = aNBT.getBoolean("isPickingPipes") ? STATE_UPWARD : STATE_DOWNWARD;
+ if (aNBT.hasKey("chunkLoadingEnabled")) mChunkLoadingEnabled = aNBT.getBoolean("chunkLoadingEnabled");
+ if (aNBT.getBoolean("isChunkloading")) {
+ mCurrentChunk = new ChunkCoordIntPair(
+ aNBT.getInteger("loadedChunkXPos"),
+ aNBT.getInteger("loadedChunkZPos"));
+ }
+ }
+
+ @Override
+ public boolean onSolderingToolRightClick(ForgeDirection side, ForgeDirection wrenchingSide,
+ EntityPlayer entityPlayer, float aX, float aY, float aZ) {
+ if (side == getBaseMetaTileEntity().getFrontFacing()) {
+ mChunkLoadingEnabled = !mChunkLoadingEnabled;
+ GT_Utility.sendChatToPlayer(
+ entityPlayer,
+ mChunkLoadingEnabled ? GT_Utility.trans("502", "Mining chunk loading enabled")
+ : GT_Utility.trans("503", "Mining chunk loading disabled"));
+ return true;
+ }
+ return super.onSolderingToolRightClick(side, wrenchingSide, entityPlayer, aX, aY, aZ);
+ }
+
+ @Override
+ public void onRemoval() {
+ if (mChunkLoadingEnabled) GT_ChunkManager.releaseTicket((TileEntity) getBaseMetaTileEntity());
+ super.onRemoval();
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ super.onPostTick(aBaseMetaTileEntity, aTick);
+ if (aBaseMetaTileEntity.isServerSide() && mCurrentChunk != null
+ && !mWorkChunkNeedsReload
+ && !aBaseMetaTileEntity.isAllowedToWork()) {
+ // if machine has stopped, stop chunkloading
+ GT_ChunkManager.releaseTicket((TileEntity) aBaseMetaTileEntity);
+ mWorkChunkNeedsReload = true;
+ }
+ }
+
+ protected boolean tryPickPipe() {
+ if (yHead == yDrill) return isPickingPipes = false;
+ if (tryOutputPipe()) {
+ if (checkBlockAndMeta(xPipe, yHead + 1, zPipe, miningPipeBlock, W)) getBaseMetaTileEntity().getWorld()
+ .setBlock(xPipe, yHead + 1, zPipe, miningPipeTipBlock);
+ getBaseMetaTileEntity().getWorld()
+ .setBlockToAir(xPipe, yHead, zPipe);
+ return isPickingPipes = true;
+ }
+ return isPickingPipes = false;
+ }
+
+ /**
+ * Added for compability reasons
+ *
+ * @return true if the state is 0 false otherwise.
+ * @deprecated compatibility reason
+ */
+ @Deprecated
+ protected boolean tryLowerPipe() {
+ return tryLowerPipeState(false) == 0;
+ }
+
+ /**
+ * @return 0 for succeeded, 1 for invalid block, 2 for not having mining pipes, 3 for event canceled.
+ */
+ protected int tryLowerPipeState() {
+ return tryLowerPipeState(false);
+ }
+
+ /**
+ * @return 0 for succeeded, 1 for invalid block, 2 for not having mining pipes, 3 for event canceled.
+ */
+ protected int tryLowerPipeState(boolean isSimulating) {
+ if (!isHasMiningPipes()) return 2;
+ switch (canLowerPipe()) {
+ case 1 -> {
+ return 1;
+ }
+ case 2 -> {
+ return 3;
+ }
+ }
+
+ Block b = getBaseMetaTileEntity().getBlock(xPipe, yHead - 1, zPipe);
+ if (b != miningPipeTipBlock && !GT_Utility.setBlockByFakePlayer(
+ getFakePlayer(getBaseMetaTileEntity()),
+ xPipe,
+ yHead - 1,
+ zPipe,
+ miningPipeTipBlock,
+ 0,
+ isSimulating)) return 3;
+ if (!isSimulating) {
+ if (yHead != yDrill) getBaseMetaTileEntity().getWorld()
+ .setBlock(xPipe, yHead, zPipe, miningPipeBlock);
+ if (b != miningPipeBlock && b != miningPipeTipBlock) getBaseMetaTileEntity().decrStackSize(1, 1);
+ }
+
+ return 0;
+ }
+
+ private void putMiningPipesFromInputsInController() {
+ int maxPipes = miningPipe.getMaxStackSize();
+ if (isHasMiningPipes(maxPipes)) return;
+
+ ItemStack pipes = getStackInSlot(1);
+ if (pipes != null && !pipes.isItemEqual(miningPipe)) return;
+ for (ItemStack storedItem : getStoredInputs()) {
+ if (!storedItem.isItemEqual(miningPipe)) continue;
+
+ if (pipes == null) {
+ setInventorySlotContents(1, GT_Utility.copyOrNull(miningPipe));
+ pipes = getStackInSlot(1);
+ }
+
+ if (pipes.stackSize == maxPipes) break;
+
+ int needPipes = maxPipes - pipes.stackSize;
+ int transferPipes = Math.min(storedItem.stackSize, needPipes);
+
+ pipes.stackSize += transferPipes;
+ storedItem.stackSize -= transferPipes;
+ }
+ updateSlots();
+ }
+
+ private boolean tryOutputPipe() {
+ if (!getBaseMetaTileEntity().addStackToSlot(1, GT_Utility.copyAmount(1, miningPipe)))
+ mOutputItems = new ItemStack[] { GT_Utility.copyAmount(1, miningPipe) };
+ return true;
+ }
+
+ /**
+ * @return 0 for available, 1 for invalid block, 2 for event canceled.
+ */
+ protected int canLowerPipe() {
+ IGregTechTileEntity aBaseTile = getBaseMetaTileEntity();
+ if (yHead > 0 && GT_Utility.getBlockHardnessAt(aBaseTile.getWorld(), xPipe, yHead - 1, zPipe) >= 0) {
+ return GT_Utility.eraseBlockByFakePlayer(getFakePlayer(aBaseTile), xPipe, yHead - 1, zPipe, true) ? 0 : 2;
+ }
+ return 1;
+ }
+
+ protected boolean reachingVoidOrBedrock() {
+ return yHead <= 0 || checkBlockAndMeta(xPipe, yHead - 1, zPipe, Blocks.bedrock, W);
+ }
+
+ private boolean isHasMiningPipes() {
+ return isHasMiningPipes(1);
+ }
+
+ private boolean isHasMiningPipes(int minCount) {
+ ItemStack pipe = getStackInSlot(1);
+ return pipe != null && pipe.stackSize > minCount - 1 && pipe.isItemEqual(miningPipe);
+ }
+
+ /**
+ * @deprecated Readded for compability
+ * @return if no pipes are present
+ */
+ @Deprecated
+ protected boolean waitForPipes() {
+ return !isHasMiningPipes();
+ }
+
+ private boolean isEnergyEnough() {
+ long requiredEnergy = 512 + getMaxInputVoltage() * 4;
+ for (GT_MetaTileEntity_Hatch_Energy energyHatch : mEnergyHatches) {
+ requiredEnergy -= energyHatch.getEUVar();
+ if (requiredEnergy <= 0) return true;
+ }
+ return false;
+ }
+
+ protected boolean workingDownward(ItemStack aStack, int xDrill, int yDrill, int zDrill, int xPipe, int zPipe,
+ int yHead, int oldYHead) {
+ switch (tryLowerPipeState()) {
+ case 2 -> {
+ mMaxProgresstime = 0;
+ setRuntimeFailureReason(CheckRecipeResultRegistry.MISSING_MINING_PIPE);
+ return false;
+ }
+ case 3 -> {
+ workState = STATE_UPWARD;
+ return true;
+ }
+ case 1 -> {
+ workState = STATE_AT_BOTTOM;
+ return true;
+ }
+ default -> {
+ return true;
+ }
+ }
+ }
+
+ protected boolean workingAtBottom(ItemStack aStack, int xDrill, int yDrill, int zDrill, int xPipe, int zPipe,
+ int yHead, int oldYHead) {
+ if (tryLowerPipeState(true) == 0) {
+ workState = STATE_DOWNWARD;
+ return true;
+ }
+ workState = STATE_UPWARD;
+ return true;
+ }
+
+ protected boolean workingUpward(ItemStack aStack, int xDrill, int yDrill, int zDrill, int xPipe, int zPipe,
+ int yHead, int oldYHead) {
+ if (tryPickPipe()) {
+ return true;
+ } else {
+ workState = STATE_DOWNWARD;
+ stopMachine(ShutDownReasonRegistry.NONE);
+ return false;
+ }
+ }
+
+ /** Called once when the abort button is clicked. Use to perform any needed cleanup (e.g. unloading chunks.) */
+ protected void onAbort() {}
+
+ protected void abortDrilling() {
+ if (workState != STATE_ABORT) {
+ workState = STATE_ABORT;
+ onAbort();
+ setShutdownReason("");
+
+ if (!isAllowedToWork()) {
+ enableWorking();
+ }
+ }
+ }
+
+ // This is a distinct state from workingUpward, because some inheritors (like concrete backfiller) operate
+ // exclusively on the workingUpward phase. It also allows for more distinct status messages.
+ protected boolean workingToAbortOperation(@NotNull ItemStack aStack, int xDrill, int yDrill, int zDrill, int xPipe,
+ int zPipe, int yHead, int oldYHead) {
+ if (tryPickPipe()) {
+ return true;
+ } else {
+ workState = STATE_DOWNWARD;
+ stopMachine(ShutDownReasonRegistry.NONE);
+ return false;
+ }
+ }
+
+ @Override
+ public void enableWorking() {
+ super.enableWorking();
+ shutdownReason = "";
+ }
+
+ @Override
+ public void onDisableWorking() {
+ if (suppressErrorWipe) {
+ suppressErrorWipe = false;
+ } else {
+ super.onDisableWorking();
+ }
+ }
+
+ @Override
+ @NotNull
+ public CheckRecipeResult checkProcessing() {
+ ItemStack controllerStack = getControllerSlot();
+ // Public pipe actions
+ setElectricityStats();
+ int oldYHead = yHead;
+ if (!checkPipesAndSetYHead()) {
+ stopMachine(ShutDownReasonRegistry.NONE);
+ return SimpleCheckRecipeResult.ofFailure("no_mining_pipe");
+ } else if (!isEnergyEnough()) {
+ stopMachine(ShutDownReasonRegistry.NONE);
+ return SimpleCheckRecipeResult.ofFailure("not_enough_energy");
+ }
+ putMiningPipesFromInputsInController();
+
+ final boolean wasSuccessful;
+ switch (workState) {
+ case STATE_DOWNWARD -> wasSuccessful = workingDownward(
+ controllerStack,
+ xDrill,
+ yDrill,
+ zDrill,
+ xPipe,
+ zPipe,
+ yHead,
+ oldYHead);
+ case STATE_AT_BOTTOM -> wasSuccessful = workingAtBottom(
+ controllerStack,
+ xDrill,
+ yDrill,
+ zDrill,
+ xPipe,
+ zPipe,
+ yHead,
+ oldYHead);
+ case STATE_UPWARD -> wasSuccessful = workingUpward(
+ controllerStack,
+ xDrill,
+ yDrill,
+ zDrill,
+ xPipe,
+ zPipe,
+ yHead,
+ oldYHead);
+ case STATE_ABORT -> wasSuccessful = workingToAbortOperation(
+ controllerStack,
+ xDrill,
+ yDrill,
+ zDrill,
+ xPipe,
+ zPipe,
+ yHead,
+ oldYHead);
+ default -> wasSuccessful = false;
+ }
+
+ if (runtimeFailure == null) {
+ if (wasSuccessful) {
+ lastRuntimeFailure = null;
+ }
+
+ return resultRegistry.getOrDefault(
+ new ResultRegistryKey(workState, wasSuccessful),
+ SimpleCheckRecipeResult.ofFailure("no_mining_pipe"));
+ } else {
+ final CheckRecipeResult result;
+ result = lastRuntimeFailure = runtimeFailure;
+ runtimeFailure = null;
+ return result;
+ }
+ }
+
+ /**
+ * Allow drills to set a specific failure reason specific to their situation. E.g.: out of drilling fluid.
+ * Should be used when the machine doesn't turn off due to the failure.
+ *
+ * @param newFailureReason A new failure reason
+ */
+ protected void setRuntimeFailureReason(@NotNull CheckRecipeResult newFailureReason) {
+ runtimeFailure = newFailureReason;
+ }
+
+ /**
+ * Gets a reason for why the drill turned off, for use in UIs and such.
+ *
+ * @return A reason, or empty if the machine is active or there is no message set yet.
+ */
+ @NotNull
+ protected Optional<String> getFailureReason() {
+ if (getBaseMetaTileEntity().isActive()) {
+ return Optional.empty();
+ }
+
+ if (!shutdownReason.isEmpty()) {
+ return Optional.of(shutdownReason);
+ }
+
+ return Optional.ofNullable(lastRuntimeFailure)
+ .map(CheckRecipeResult::getDisplayString);
+ }
+
+ /**
+ * Sets a line in the UI to explain why the drill shut down. E.g.: operation finished.
+ * Should be used when the machine has been turned off due to an operating issue or completion.
+ *
+ * @param newReason The reason for the machine shutdown
+ */
+ protected void setShutdownReason(@NotNull String newReason) {
+ shutdownReason = newReason;
+ }
+
+ @Override
+ protected IAlignmentLimits getInitialAlignmentLimits() {
+ return (d, r, f) -> (d.flag & (ForgeDirection.UP.flag | ForgeDirection.DOWN.flag)) == 0 && r.isNotRotated()
+ && !f.isVerticallyFliped();
+ }
+
+ @Override
+ public boolean isRotationChangeAllowed() {
+ return false;
+ }
+
+ @Override
+ public final IStructureDefinition<GT_MetaTileEntity_DrillerBase> getStructureDefinition() {
+ return STRUCTURE_DEFINITION.get(getClass());
+ }
+
+ @Override
+ public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+ updateCoordinates();
+ return checkPiece(STRUCTURE_PIECE_MAIN, 1, 6, 0) && checkHatches()
+ && GT_Utility.getTier(getMaxInputVoltage()) >= getMinTier()
+ && mMaintenanceHatches.size() == 1;
+ }
+
+ private void updateCoordinates() {
+ xDrill = getBaseMetaTileEntity().getXCoord();
+ yDrill = getBaseMetaTileEntity().getYCoord();
+ zDrill = getBaseMetaTileEntity().getZCoord();
+ back = getBaseMetaTileEntity().getBackFacing();
+ xPipe = xDrill + back.offsetX;
+ zPipe = zDrill + back.offsetZ;
+ }
+
+ private boolean checkPipesAndSetYHead() {
+ yHead = yDrill - 1;
+ while (checkBlockAndMeta(xPipe, yHead, zPipe, miningPipeBlock, W)) yHead--; // skip pipes
+ // is pipe tip OR is controller layer
+ if (checkBlockAndMeta(xPipe, yHead, zPipe, miningPipeTipBlock, W) || ++yHead == yDrill) return true;
+ // pipe column is broken - try fix
+ getBaseMetaTileEntity().getWorld()
+ .setBlock(xPipe, yHead, zPipe, miningPipeTipBlock);
+ return true;
+ }
+
+ @Deprecated
+ protected boolean checkCasingBlock(int xOff, int yOff, int zOff) {
+ return checkBlockAndMetaOffset(xOff, yOff, zOff, casingBlock, casingMeta);
+ }
+
+ // meta of frame is getTileEntityBaseType; frame should be checked using its drops (possible a high weight
+ // operation)
+ @Deprecated
+ protected boolean checkFrameBlock(int xOff, int yOff, int zOff) {
+ return checkBlockAndMetaOffset(xOff, yOff, zOff, GregTech_API.sBlockMachines, frameMeta);
+ }
+
+ @Deprecated
+ protected boolean checkBlockAndMetaOffset(int xOff, int yOff, int zOff, Block block, int meta) {
+ return checkBlockAndMeta(xDrill + xOff, yDrill + yOff, zDrill + zOff, block, meta);
+ }
+
+ private boolean checkBlockAndMeta(int x, int y, int z, Block block, int meta) {
+ return (meta == W || getBaseMetaTileEntity().getMetaID(x, y, z) == meta)
+ && getBaseMetaTileEntity().getBlock(x, y, z) == block;
+ }
+
+ private FakePlayer mFakePlayer = null;
+
+ protected FakePlayer getFakePlayer(IGregTechTileEntity aBaseTile) {
+ if (mFakePlayer == null) mFakePlayer = GT_Utility.getFakePlayer(aBaseTile);
+ mFakePlayer.setWorld(aBaseTile.getWorld());
+ mFakePlayer.setPosition(aBaseTile.getXCoord(), aBaseTile.getYCoord(), aBaseTile.getZCoord());
+ return mFakePlayer;
+ }
+
+ @Override
+ public boolean isCorrectMachinePart(ItemStack aStack) {
+ return true;
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack aStack) {
+ return 10000;
+ }
+
+ @Override
+ public int getDamageToComponent(ItemStack aStack) {
+ return 0;
+ }
+
+ @Override
+ public boolean explodesOnComponentBreak(ItemStack aStack) {
+ return false;
+ }
+
+ protected abstract ItemList getCasingBlockItem();
+
+ @Deprecated
+ protected String getCasingName() {
+ return null;
+ }
+
+ protected abstract Materials getFrameMaterial();
+
+ protected abstract int getCasingTextureIndex();
+
+ protected abstract int getMinTier();
+
+ protected abstract boolean checkHatches();
+
+ protected abstract void setElectricityStats();
+
+ public int getTotalConfigValue() {
+ int config = 0;
+ ArrayList<ItemStack> tCircuitList = getDataItems(1);
+ for (ItemStack tCircuit : tCircuitList) config += tCircuit.getItemDamage();
+ return config;
+ }
+
+ public ArrayList<GT_MetaTileEntity_Hatch_DataAccess> mDataAccessHatches = new ArrayList<>();
+
+ /**
+ * @param state using bitmask, 1 for IntegratedCircuit, 2 for DataStick, 4 for DataOrb
+ */
+ private boolean isCorrectDataItem(ItemStack aStack, int state) {
+ if ((state & 1) != 0 && ItemList.Circuit_Integrated.isStackEqual(aStack, true, true)) return true;
+ if ((state & 2) != 0 && ItemList.Tool_DataStick.isStackEqual(aStack, false, true)) return true;
+ return (state & 4) != 0 && ItemList.Tool_DataOrb.isStackEqual(aStack, false, true);
+ }
+
+ /**
+ * @param state using bitmask, 1 for IntegratedCircuit, 2 for DataStick, 4 for DataOrb
+ */
+ public ArrayList<ItemStack> getDataItems(int state) {
+ ArrayList<ItemStack> rList = new ArrayList<>();
+ if (GT_Utility.isStackValid(mInventory[1]) && isCorrectDataItem(mInventory[1], state)) {
+ rList.add(mInventory[1]);
+ }
+ for (GT_MetaTileEntity_Hatch_DataAccess tHatch : filterValidMTEs(mDataAccessHatches)) {
+ for (int i = 0; i < tHatch.getBaseMetaTileEntity()
+ .getSizeInventory(); i++) {
+ if (tHatch.getBaseMetaTileEntity()
+ .getStackInSlot(i) != null && isCorrectDataItem(
+ tHatch.getBaseMetaTileEntity()
+ .getStackInSlot(i),
+ state))
+ rList.add(
+ tHatch.getBaseMetaTileEntity()
+ .getStackInSlot(i));
+ }
+ }
+ return rList;
+ }
+
+ @Override
+ public boolean addToMachineList(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
+ return super.addToMachineList(aTileEntity, aBaseCasingIndex)
+ || addDataAccessToMachineList(aTileEntity, aBaseCasingIndex);
+ }
+
+ public boolean addDataAccessToMachineList(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
+ if (aTileEntity == null) return false;
+ IMetaTileEntity aMetaTileEntity = aTileEntity.getMetaTileEntity();
+ if (aMetaTileEntity == null) return false;
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_DataAccess) {
+ ((GT_MetaTileEntity_Hatch) aMetaTileEntity).updateTexture((byte) aBaseCasingIndex);
+ return mDataAccessHatches.add((GT_MetaTileEntity_Hatch_DataAccess) aMetaTileEntity);
+ }
+ return false;
+ }
+
+ @Override
+ public ChunkCoordIntPair getActiveChunk() {
+ return mCurrentChunk;
+ }
+
+ @Override
+ public void construct(ItemStack stackSize, boolean hintsOnly) {
+ buildPiece(STRUCTURE_PIECE_MAIN, stackSize, hintsOnly, 1, 6, 0);
+ }
+
+ @Override
+ public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
+ if (mMachine) return -1;
+ return survivialBuildPiece(STRUCTURE_PIECE_MAIN, stackSize, 1, 6, 0, elementBudget, env, false, true);
+ }
+
+ @Override
+ protected void drawTexts(DynamicPositionedColumn screenElements, SlotWidget inventorySlot) {
+ super.drawTexts(screenElements, inventorySlot);
+ screenElements.widget(
+ TextWidget.dynamicString(() -> shutdownReason)
+ .setSynced(false)
+ .setTextAlignment(Alignment.CenterLeft)
+ .setEnabled(widget -> !(getBaseMetaTileEntity().isActive() || shutdownReason.isEmpty())))
+ .widget(new FakeSyncWidget.StringSyncer(() -> shutdownReason, newString -> shutdownReason = newString));
+ }
+
+ @Override
+ protected boolean showRecipeTextInGUI() {
+ return false;
+ }
+
+ /**
+ * Adds additional buttons to the main button row. You do not need to set the position.
+ *
+ * @param builder Only use to attach SyncWidgets.
+ * @param buildContext Context for things like the player.
+ */
+ protected List<ButtonWidget> getAdditionalButtons(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ return ImmutableList.of();
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ super.addUIWidgets(builder, buildContext);
+ final int BUTTON_Y_LEVEL = 91;
+
+ builder.widget(
+ new GT_LockedWhileActiveButton(this.getBaseMetaTileEntity(), builder)
+ .setOnClick((clickData, widget) -> mChunkLoadingEnabled = !mChunkLoadingEnabled)
+ .setPlayClickSound(true)
+ .setBackground(() -> {
+ if (mChunkLoadingEnabled) {
+ return new IDrawable[] { GT_UITextures.BUTTON_STANDARD_PRESSED,
+ GT_UITextures.OVERLAY_BUTTON_CHUNK_LOADING };
+ }
+ return new IDrawable[] { GT_UITextures.BUTTON_STANDARD,
+ GT_UITextures.OVERLAY_BUTTON_CHUNK_LOADING_OFF };
+ })
+ .attachSyncer(
+ new FakeSyncWidget.BooleanSyncer(
+ () -> mChunkLoadingEnabled,
+ newBoolean -> mChunkLoadingEnabled = newBoolean),
+ builder,
+ (widget, val) -> widget.notifyTooltipChange())
+ .dynamicTooltip(
+ () -> ImmutableList.of(
+ StatCollector.translateToLocal(
+ mChunkLoadingEnabled ? "GT5U.gui.button.chunk_loading_on"
+ : "GT5U.gui.button.chunk_loading_off")))
+ .setTooltipShowUpDelay(TOOLTIP_DELAY)
+ .setPos(new Pos2d(80, BUTTON_Y_LEVEL))
+ .setSize(16, 16))
+ .widget(
+ new ButtonWidget().setOnClick((clickData, widget) -> abortDrilling())
+ .setPlayClickSound(true)
+ .setBackground(() -> {
+ if (workState == STATE_ABORT) {
+ return new IDrawable[] { GT_UITextures.BUTTON_STANDARD_PRESSED,
+ GT_UITextures.OVERLAY_BUTTON_RETRACT_PIPE, GT_UITextures.OVERLAY_BUTTON_LOCKED };
+ }
+ return new IDrawable[] { GT_UITextures.BUTTON_STANDARD,
+ GT_UITextures.OVERLAY_BUTTON_RETRACT_PIPE };
+ })
+ .attachSyncer(
+ new FakeSyncWidget.IntegerSyncer(() -> workState, (newInt) -> workState = newInt),
+ builder,
+ (widget, integer) -> widget.notifyTooltipChange())
+ .dynamicTooltip(
+ () -> ImmutableList.of(
+ StatCollector.translateToLocalFormatted(
+ workState == STATE_ABORT ? "GT5U.gui.button.drill_retract_pipes_active"
+ : "GT5U.gui.button.drill_retract_pipes")))
+ .setTooltipShowUpDelay(TOOLTIP_DELAY)
+ .setPos(new Pos2d(174, 130))
+ .setSize(16, 16));
+
+ int left = 98;
+ for (ButtonWidget button : getAdditionalButtons(builder, buildContext)) {
+ button.setPos(new Pos2d(left, BUTTON_Y_LEVEL))
+ .setSize(16, 16);
+ builder.widget(button);
+ left += 18;
+ }
+ }
+
+ protected List<IHatchElement<? super GT_MetaTileEntity_DrillerBase>> getAllowedHatches() {
+ return ImmutableList.of(
+ InputHatch,
+ OutputHatch,
+ InputBus,
+ OutputBus,
+ Muffler,
+ Maintenance,
+ Energy,
+ DataHatchElement.DataAccess);
+ }
+
+ protected enum DataHatchElement implements IHatchElement<GT_MetaTileEntity_DrillerBase> {
+
+ DataAccess;
+
+ @Override
+ public List<? extends Class<? extends IMetaTileEntity>> mteClasses() {
+ return Collections.singletonList(GT_MetaTileEntity_Hatch_DataAccess.class);
+ }
+
+ @Override
+ public IGT_HatchAdder<GT_MetaTileEntity_DrillerBase> adder() {
+ return GT_MetaTileEntity_DrillerBase::addDataAccessToMachineList;
+ }
+
+ @Override
+ public long count(GT_MetaTileEntity_DrillerBase t) {
+ return t.mDataAccessHatches.size();
+ }
+ }
+
+ /**
+ * Sets or overrides the {@link CheckRecipeResult} for a given work state
+ *
+ * @param state A work state like {@link #STATE_DOWNWARD}.
+ * @param result A previously registered recipe result.
+ */
+ protected void addResultMessage(final int state, @NotNull final CheckRecipeResult result) {
+ resultRegistry.put(new ResultRegistryKey(state, result.wasSuccessful()), result);
+ }
+
+ /**
+ * Sets or overrides the {@link CheckRecipeResult} for a given work state and operation success type.
+ *
+ * @param state A work state like {@link #STATE_DOWNWARD}.
+ * @param wasSuccessful Whether the operation was successful.
+ * @param resultKey An I18N key for the message.
+ */
+ protected void addResultMessage(final int state, final boolean wasSuccessful, @NotNull final String resultKey) {
+ addResultMessage(
+ state,
+ wasSuccessful ? SimpleCheckRecipeResult.ofSuccess(resultKey)
+ : SimpleCheckRecipeResult.ofFailure(resultKey));
+ }
+
+ @SuppressWarnings("ClassCanBeRecord")
+ private final static class ResultRegistryKey {
+
+ private final int state;
+ private final boolean successful;
+
+ public ResultRegistryKey(final int state, final boolean successful) {
+ this.state = state;
+ this.successful = successful;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof ResultRegistryKey other)) {
+ return false;
+ }
+
+ return (state == other.state && successful == other.successful);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(state, successful);
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ElectricBlastFurnace.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ElectricBlastFurnace.java
new file mode 100644
index 0000000000..8913e8fedd
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ElectricBlastFurnace.java
@@ -0,0 +1,401 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.transpose;
+import static gregtech.api.enums.GT_HatchElement.Energy;
+import static gregtech.api.enums.GT_HatchElement.InputBus;
+import static gregtech.api.enums.GT_HatchElement.InputHatch;
+import static gregtech.api.enums.GT_HatchElement.Maintenance;
+import static gregtech.api.enums.GT_HatchElement.Muffler;
+import static gregtech.api.enums.GT_HatchElement.OutputBus;
+import static gregtech.api.enums.GT_HatchElement.OutputHatch;
+import static gregtech.api.enums.GT_Values.VN;
+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.enums.Textures.BlockIcons.casingTexturePages;
+import static gregtech.api.util.GT_StructureUtility.buildHatchAdder;
+import static gregtech.api.util.GT_StructureUtility.ofCoil;
+import static gregtech.api.util.GT_Utility.filterValidMTEs;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.StatCollector;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidStack;
+
+import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+
+import gregtech.GT_Mod;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.HeatingCoilLevel;
+import gregtech.api.enums.Materials;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.fluid.IFluidStore;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.logic.ProcessingLogic;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Energy;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Muffler;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Output;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_OverclockCalculator;
+import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_ElectricBlastFurnace extends
+ GT_MetaTileEntity_AbstractMultiFurnace<GT_MetaTileEntity_ElectricBlastFurnace> implements ISurvivalConstructable {
+
+ private int mHeatingCapacity = 0;
+ protected final ArrayList<GT_MetaTileEntity_Hatch_Output> mPollutionOutputHatches = new ArrayList<>();
+ protected final FluidStack[] pollutionFluidStacks = { Materials.CarbonDioxide.getGas(1000),
+ Materials.CarbonMonoxide.getGas(1000), Materials.SulfurDioxide.getGas(1000) };
+
+ protected static final int CASING_INDEX = 11;
+ protected static final String STRUCTURE_PIECE_MAIN = "main";
+ private static final IStructureDefinition<GT_MetaTileEntity_ElectricBlastFurnace> STRUCTURE_DEFINITION = StructureDefinition
+ .<GT_MetaTileEntity_ElectricBlastFurnace>builder()
+ .addShape(
+ STRUCTURE_PIECE_MAIN,
+ transpose(
+ new String[][] { { "ttt", "tmt", "ttt" }, { "CCC", "C-C", "CCC" }, { "CCC", "C-C", "CCC" },
+ { "b~b", "bbb", "bbb" } }))
+ .addElement(
+ 't',
+ buildHatchAdder(GT_MetaTileEntity_ElectricBlastFurnace.class)
+ .atLeast(
+ OutputHatch.withAdder(GT_MetaTileEntity_ElectricBlastFurnace::addOutputHatchToTopList)
+ .withCount(t -> t.mPollutionOutputHatches.size()))
+ .casingIndex(CASING_INDEX)
+ .dot(1)
+ .buildAndChain(GregTech_API.sBlockCasings1, CASING_INDEX))
+ .addElement('m', Muffler.newAny(CASING_INDEX, 2))
+ .addElement(
+ 'C',
+ ofCoil(
+ GT_MetaTileEntity_ElectricBlastFurnace::setCoilLevel,
+ GT_MetaTileEntity_ElectricBlastFurnace::getCoilLevel))
+ .addElement(
+ 'b',
+ buildHatchAdder(GT_MetaTileEntity_ElectricBlastFurnace.class)
+ .atLeast(InputHatch, OutputHatch, InputBus, OutputBus, Maintenance, Energy)
+ .casingIndex(CASING_INDEX)
+ .dot(1)
+ .buildAndChain(GregTech_API.sBlockCasings1, CASING_INDEX))
+ .build();
+
+ public GT_MetaTileEntity_ElectricBlastFurnace(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_ElectricBlastFurnace(String aName) {
+ super(aName);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_ElectricBlastFurnace(this.mName);
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Blast Furnace")
+ .addInfo("Controller block for the Electric Blast Furnace")
+ .addInfo("You can use some fluids to reduce recipe time. Place the circuit in the Input Bus")
+ .addInfo("Each 900K over the min. Heat required reduces power consumption by 5% (multiplicatively)")
+ .addInfo("Each 1800K over the min. Heat allows for an overclock to be upgraded to a perfect overclock.")
+ .addInfo("That means the EBF will reduce recipe time by a factor 4 instead of 2 (giving 100% efficiency).")
+ .addInfo("Additionally gives +100K for every tier past MV")
+ .addPollutionAmount(getPollutionPerSecond(null))
+ .addSeparator()
+ .beginStructureBlock(3, 4, 3, true)
+ .addController("Front bottom")
+ .addCasingInfoRange("Heat Proof Machine Casing", 0, 15, false)
+ .addOtherStructurePart("Heating Coils", "Two middle Layers")
+ .addEnergyHatch("Any bottom layer casing", 3)
+ .addMaintenanceHatch("Any bottom layer casing", 3)
+ .addMufflerHatch("Top middle", 2)
+ .addInputBus("Any bottom layer casing", 3)
+ .addInputHatch("Any bottom layer casing", 3)
+ .addOutputBus("Any bottom layer casing", 3)
+ .addOutputHatch("Fluid outputs, Any bottom layer casing")
+ .addOutputHatch("Pollution gases (CO2/CO/SO2), Any top layer casing", 1)
+ .addStructureInfo("Pollution gas output amount scales with Muffler Hatch tier")
+ .toolTipFinisher("Gregtech");
+ return tt;
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection aFacing,
+ int colorIndex, boolean aActive, boolean redstoneLevel) {
+ if (side == aFacing) {
+ if (aActive) return new ITexture[] { casingTexturePages[0][CASING_INDEX], TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_ELECTRIC_BLAST_FURNACE_ACTIVE)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_ELECTRIC_BLAST_FURNACE_ACTIVE_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ return new ITexture[] { casingTexturePages[0][CASING_INDEX], TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_ELECTRIC_BLAST_FURNACE)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_ELECTRIC_BLAST_FURNACE_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ }
+ return new ITexture[] { casingTexturePages[0][CASING_INDEX] };
+ }
+
+ @Override
+ public int getPollutionPerSecond(ItemStack aStack) {
+ return GT_Mod.gregtechproxy.mPollutionEBFPerSecond;
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.blastFurnaceRecipes;
+ }
+
+ @Override
+ public boolean isCorrectMachinePart(ItemStack aStack) {
+ return true;
+ }
+
+ @Override
+ public IStructureDefinition<GT_MetaTileEntity_ElectricBlastFurnace> getStructureDefinition() {
+ return STRUCTURE_DEFINITION;
+ }
+
+ @Override
+ protected ProcessingLogic createProcessingLogic() {
+ return new ProcessingLogic() {
+
+ @Nonnull
+ @Override
+ protected GT_OverclockCalculator createOverclockCalculator(@Nonnull GT_Recipe recipe) {
+ return super.createOverclockCalculator(recipe).setRecipeHeat(recipe.mSpecialValue)
+ .setMachineHeat(mHeatingCapacity)
+ .setHeatOC(true)
+ .setHeatDiscount(true);
+ }
+
+ @Override
+ protected @Nonnull CheckRecipeResult validateRecipe(@Nonnull GT_Recipe recipe) {
+ return recipe.mSpecialValue <= mHeatingCapacity ? CheckRecipeResultRegistry.SUCCESSFUL
+ : CheckRecipeResultRegistry.insufficientHeat(recipe.mSpecialValue);
+ }
+ };
+ }
+
+ public boolean addOutputHatchToTopList(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
+ if (aTileEntity == null) return false;
+ IMetaTileEntity aMetaTileEntity = aTileEntity.getMetaTileEntity();
+ if (aMetaTileEntity == null) return false;
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Output) {
+ ((GT_MetaTileEntity_Hatch) aMetaTileEntity).updateTexture(aBaseCasingIndex);
+ return mPollutionOutputHatches.add((GT_MetaTileEntity_Hatch_Output) aMetaTileEntity);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+ this.mHeatingCapacity = 0;
+
+ setCoilLevel(HeatingCoilLevel.None);
+
+ mPollutionOutputHatches.clear();
+
+ if (!checkPiece(STRUCTURE_PIECE_MAIN, 1, 3, 0)) return false;
+
+ if (getCoilLevel() == HeatingCoilLevel.None) return false;
+
+ if (mMaintenanceHatches.size() != 1) return false;
+
+ this.mHeatingCapacity = (int) getCoilLevel().getHeat() + 100 * (GT_Utility.getTier(getMaxInputVoltage()) - 2);
+ return true;
+ }
+
+ @Override
+ public boolean addOutput(FluidStack aLiquid) {
+ if (aLiquid == null) return false;
+ FluidStack tLiquid = aLiquid.copy();
+ ArrayList<GT_MetaTileEntity_Hatch_Output> tOutputHatches;
+ if (isPollutionFluid(tLiquid)) {
+ tOutputHatches = this.mPollutionOutputHatches;
+ multiplyPollutionFluidAmount(tLiquid);
+ } else {
+ tOutputHatches = this.mOutputHatches;
+ }
+ return dumpFluid(tOutputHatches, tLiquid, true) || dumpFluid(tOutputHatches, tLiquid, false);
+ }
+
+ protected boolean isPollutionFluid(@Nullable FluidStack fluidStack) {
+ if (fluidStack == null) return false;
+ for (FluidStack pollutionFluidStack : pollutionFluidStacks) {
+ if (!fluidStack.isFluidEqual(pollutionFluidStack)) continue;
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public List<? extends IFluidStore> getFluidOutputSlots(FluidStack[] toOutput) {
+ if (Arrays.stream(toOutput)
+ .anyMatch(this::isPollutionFluid)) {
+ return filterValidMTEs(mPollutionOutputHatches);
+ }
+ return filterValidMTEs(mOutputHatches);
+ }
+
+ /**
+ * @return 100 -> all released to air, 0 -> all dumped to hatch
+ */
+ public int getPollutionReduction() {
+ int reduction = 100;
+ for (GT_MetaTileEntity_Hatch_Muffler tHatch : filterValidMTEs(mMufflerHatches)) {
+ reduction = Math.min(tHatch.calculatePollutionReduction(100), reduction);
+ }
+ return reduction;
+ }
+
+ protected void multiplyPollutionFluidAmount(@Nonnull FluidStack fluid) {
+ fluid.amount = fluid.amount * Math.min(100 - getPollutionReduction(), 100) / 100;
+ }
+
+ @Override
+ public String[] getInfoData() {
+ int mPollutionReduction = getPollutionReduction();
+ long storedEnergy = 0;
+ long maxEnergy = 0;
+ for (GT_MetaTileEntity_Hatch_Energy tHatch : filterValidMTEs(mEnergyHatches)) {
+ storedEnergy += tHatch.getBaseMetaTileEntity()
+ .getStoredEU();
+ maxEnergy += tHatch.getBaseMetaTileEntity()
+ .getEUCapacity();
+ }
+
+ return new String[] {
+ StatCollector.translateToLocal("GT5U.multiblock.Progress") + ": "
+ + EnumChatFormatting.GREEN
+ + GT_Utility.formatNumbers(mProgresstime / 20)
+ + EnumChatFormatting.RESET
+ + " s / "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(mMaxProgresstime / 20)
+ + EnumChatFormatting.RESET
+ + " s",
+ StatCollector.translateToLocal("GT5U.multiblock.energy") + ": "
+ + EnumChatFormatting.GREEN
+ + GT_Utility.formatNumbers(storedEnergy)
+ + EnumChatFormatting.RESET
+ + " EU / "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(maxEnergy)
+ + EnumChatFormatting.RESET
+ + " EU",
+ StatCollector.translateToLocal("GT5U.multiblock.usage") + ": "
+ + EnumChatFormatting.RED
+ + GT_Utility.formatNumbers(-mEUt)
+ + EnumChatFormatting.RESET
+ + " EU/t",
+ StatCollector.translateToLocal("GT5U.multiblock.mei") + ": "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(getMaxInputVoltage())
+ + EnumChatFormatting.RESET
+ + " EU/t(*2A) "
+ + StatCollector.translateToLocal("GT5U.machines.tier")
+ + ": "
+ + EnumChatFormatting.YELLOW
+ + VN[GT_Utility.getTier(getMaxInputVoltage())]
+ + EnumChatFormatting.RESET,
+ StatCollector.translateToLocal("GT5U.multiblock.problems") + ": "
+ + EnumChatFormatting.RED
+ + (getIdealStatus() - getRepairStatus())
+ + EnumChatFormatting.RESET
+ + " "
+ + StatCollector.translateToLocal("GT5U.multiblock.efficiency")
+ + ": "
+ + EnumChatFormatting.YELLOW
+ + mEfficiency / 100.0F
+ + EnumChatFormatting.RESET
+ + " %",
+ StatCollector.translateToLocal("GT5U.EBF.heat") + ": "
+ + EnumChatFormatting.GREEN
+ + GT_Utility.formatNumbers(mHeatingCapacity)
+ + EnumChatFormatting.RESET
+ + " K",
+ StatCollector.translateToLocal("GT5U.multiblock.pollution") + ": "
+ + EnumChatFormatting.GREEN
+ + mPollutionReduction
+ + EnumChatFormatting.RESET
+ + " %" };
+ }
+
+ @Override
+ public void construct(ItemStack stackSize, boolean hintsOnly) {
+ buildPiece(STRUCTURE_PIECE_MAIN, stackSize, hintsOnly, 1, 3, 0);
+ }
+
+ @Override
+ public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
+ if (mMachine) return -1;
+ return survivialBuildPiece(STRUCTURE_PIECE_MAIN, stackSize, 1, 3, 0, elementBudget, env, false, true);
+ }
+
+ @Override
+ public void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ inputSeparation = !inputSeparation;
+ GT_Utility.sendChatToPlayer(
+ aPlayer,
+ StatCollector.translateToLocal("GT5U.machines.separatebus") + " " + inputSeparation);
+ }
+
+ @Override
+ public void loadNBTData(final NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ if (aNBT.hasKey("isBussesSeparate")) {
+ // backward compatibility
+ inputSeparation = aNBT.getBoolean("isBussesSeparate");
+ }
+ }
+
+ @Override
+ public boolean supportsVoidProtection() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsInputSeparation() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsBatchMode() {
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ExtremeDieselEngine.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ExtremeDieselEngine.java
new file mode 100644
index 0000000000..dace58a492
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ExtremeDieselEngine.java
@@ -0,0 +1,237 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_EXTREME_DIESEL_ENGINE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_EXTREME_DIESEL_ENGINE_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_EXTREME_DIESEL_ENGINE_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_EXTREME_DIESEL_ENGINE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.casingTexturePages;
+import static gregtech.api.util.GT_Utility.filterValidMTEs;
+
+import net.minecraft.block.Block;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.StatCollector;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.GT_Mod;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.Materials;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Dynamo;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Muffler;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.recipe.maps.FuelBackend;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_ExtremeDieselEngine extends GT_MetaTileEntity_DieselEngine {
+
+ public GT_MetaTileEntity_ExtremeDieselEngine(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_ExtremeDieselEngine(String aName) {
+ super(aName);
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Combustion Generator")
+ .addInfo("Controller block for the Extreme Combustion Engine")
+ .addInfo("Supply high rating fuel and 8000L of Lubricant per hour to run")
+ .addInfo("Supply 40L/s of Liquid Oxygen to boost output (optional)")
+ .addInfo("Default: Produces 10900EU/t at 100% fuel efficiency")
+ .addInfo("Boosted: Produces 32700EU/t at 150% fuel efficiency")
+ .addInfo("You need to wait for it to reach 300% to output full power")
+ .addPollutionAmount(getPollutionPerSecond(null))
+ .addSeparator()
+ .beginStructureBlock(3, 3, 4, false)
+ .addController("Front center")
+ .addCasingInfoRange("Robust Tungstensteel Machine Casing", 16, 22, false)
+ .addOtherStructurePart("Titanium Gear Box Machine Casing", "Inner 2 blocks")
+ .addOtherStructurePart("Extreme Engine Intake Machine Casing", "8x, ring around controller")
+ .addStructureInfo("Extreme Engine Intake Casings must not be obstructed in front (only air blocks)")
+ .addDynamoHatch("Back center", 2)
+ .addMaintenanceHatch("One of the casings next to a Gear Box", 1)
+ .addMufflerHatch("Top middle back, above the rear Gear Box", 1)
+ .addInputHatch("HOG, next to a Gear Box", 1)
+ .addInputHatch("Lubricant, next to a Gear Box", 1)
+ .addInputHatch("Liquid Oxygen, optional, next to a Gear Box", 1)
+ .toolTipFinisher("Gregtech");
+ return tt;
+ }
+
+ @Override
+ public RecipeMap<FuelBackend> getRecipeMap() {
+ return RecipeMaps.extremeDieselFuels;
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection aFacing,
+ int colorIndex, boolean aActive, boolean redstoneLevel) {
+ if (side == aFacing) {
+ if (aActive) return new ITexture[] { casingTexturePages[0][60], TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_EXTREME_DIESEL_ENGINE_ACTIVE)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_EXTREME_DIESEL_ENGINE_ACTIVE_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ return new ITexture[] { casingTexturePages[0][60], TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_EXTREME_DIESEL_ENGINE)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_EXTREME_DIESEL_ENGINE_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ }
+ return new ITexture[] { casingTexturePages[0][60] };
+ }
+
+ @Override
+ public Block getCasingBlock() {
+ return GregTech_API.sBlockCasings4;
+ }
+
+ @Override
+ public byte getCasingMeta() {
+ return 0;
+ }
+
+ @Override
+ public Block getIntakeBlock() {
+ return GregTech_API.sBlockCasings8;
+ }
+
+ @Override
+ public byte getIntakeMeta() {
+ return 4;
+ }
+
+ @Override
+ public Block getGearboxBlock() {
+ return GregTech_API.sBlockCasings2;
+ }
+
+ @Override
+ public byte getGearboxMeta() {
+ return 4;
+ }
+
+ @Override
+ public byte getCasingTextureIndex() {
+ return 60;
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_ExtremeDieselEngine(this.mName);
+ }
+
+ @Override
+ protected int getNominalOutput() {
+ return 10900;
+ }
+
+ @Override
+ protected int getBoostFactor() {
+ return 2;
+ }
+
+ @Override
+ protected Materials getBooster() {
+ return Materials.LiquidOxygen;
+ }
+
+ @Override
+ protected int getAdditiveFactor() {
+ return 1;
+ }
+
+ @Override
+ protected int getEfficiencyIncrease() {
+ return 20;
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack aStack) {
+ return boostEu ? 30000 : 10000;
+ }
+
+ @Override
+ public int getPollutionPerSecond(ItemStack aStack) {
+ return GT_Mod.gregtechproxy.mPollutionExtremeCombustionEnginePerSecond;
+ }
+
+ @Override
+ public String[] getInfoData() {
+ int mPollutionReduction = 0;
+ for (GT_MetaTileEntity_Hatch_Muffler tHatch : filterValidMTEs(mMufflerHatches)) {
+ mPollutionReduction = Math.max(tHatch.calculatePollutionReduction(100), mPollutionReduction);
+ }
+
+ long storedEnergy = 0;
+ long maxEnergy = 0;
+ for (GT_MetaTileEntity_Hatch_Dynamo tHatch : filterValidMTEs(mDynamoHatches)) {
+ storedEnergy += tHatch.getBaseMetaTileEntity()
+ .getStoredEU();
+ maxEnergy += tHatch.getBaseMetaTileEntity()
+ .getEUCapacity();
+ }
+
+ return new String[] { EnumChatFormatting.BLUE + "Extreme Diesel Engine" + EnumChatFormatting.RESET,
+ StatCollector.translateToLocal("GT5U.multiblock.energy") + ": "
+ + EnumChatFormatting.GREEN
+ + GT_Utility.formatNumbers(storedEnergy)
+ + EnumChatFormatting.RESET
+ + " EU / "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(maxEnergy)
+ + EnumChatFormatting.RESET
+ + " EU",
+ getIdealStatus() == getRepairStatus()
+ ? EnumChatFormatting.GREEN + StatCollector.translateToLocal("GT5U.turbine.maintenance.false")
+ + EnumChatFormatting.RESET
+ : EnumChatFormatting.RED + StatCollector.translateToLocal("GT5U.turbine.maintenance.true")
+ + EnumChatFormatting.RESET,
+ StatCollector.translateToLocal("GT5U.engine.output") + ": "
+ + EnumChatFormatting.RED
+ + GT_Utility.formatNumbers((long) -mEUt * mEfficiency / 10000)
+ + EnumChatFormatting.RESET
+ + " EU/t",
+ StatCollector.translateToLocal("GT5U.engine.consumption") + ": "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(fuelConsumption)
+ + EnumChatFormatting.RESET
+ + " L/t",
+ StatCollector.translateToLocal("GT5U.engine.value") + ": "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(fuelValue)
+ + EnumChatFormatting.RESET
+ + " EU/L",
+ StatCollector.translateToLocal("GT5U.turbine.fuel") + ": "
+ + EnumChatFormatting.GOLD
+ + GT_Utility.formatNumbers(fuelRemaining)
+ + EnumChatFormatting.RESET
+ + " L",
+ StatCollector.translateToLocal("GT5U.engine.efficiency") + ": "
+ + EnumChatFormatting.YELLOW
+ + (mEfficiency / 100F)
+ + EnumChatFormatting.YELLOW
+ + " %",
+ StatCollector.translateToLocal("GT5U.multiblock.pollution") + ": "
+ + EnumChatFormatting.GREEN
+ + mPollutionReduction
+ + EnumChatFormatting.RESET
+ + " %" };
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_FusionComputer.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_FusionComputer.java
new file mode 100644
index 0000000000..493546211c
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_FusionComputer.java
@@ -0,0 +1,656 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.lazy;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.transpose;
+import static gregtech.api.enums.GT_HatchElement.Energy;
+import static gregtech.api.enums.GT_HatchElement.InputHatch;
+import static gregtech.api.enums.GT_HatchElement.OutputHatch;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASING_FUSION_GLASS;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASING_FUSION_GLASS_YELLOW;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASING_FUSION_GLASS_YELLOW_GLOW;
+import static gregtech.api.util.GT_StructureUtility.buildHatchAdder;
+import static gregtech.api.util.GT_StructureUtility.filterByMTETier;
+import static gregtech.api.util.GT_Utility.filterValidMTEs;
+
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.block.Block;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.StatCollector;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidStack;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.google.common.collect.ImmutableMap;
+import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+import com.gtnewhorizons.modularui.api.NumberFormatMUI;
+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.DrawableWidget;
+import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget;
+import com.gtnewhorizons.modularui.common.widget.ProgressBar;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.GT_Mod;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.enums.SoundResource;
+import gregtech.api.enums.Textures;
+import gregtech.api.enums.VoidingMode;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.gui.modularui.GUITextureSet;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.modularui.IAddUIWidgets;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.interfaces.tileentity.IOverclockDescriptionProvider;
+import gregtech.api.logic.ProcessingLogic;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_EnhancedMultiBlockBase;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Energy;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Input;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Output;
+import gregtech.api.objects.GT_ItemStack;
+import gregtech.api.objects.overclockdescriber.FusionOverclockDescriber;
+import gregtech.api.objects.overclockdescriber.OverclockDescriber;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_OverclockCalculator;
+import gregtech.api.util.GT_ParallelHelper;
+import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.shutdown.ShutDownReason;
+import gregtech.api.util.shutdown.ShutDownReasonRegistry;
+
+public abstract class GT_MetaTileEntity_FusionComputer
+ extends GT_MetaTileEntity_EnhancedMultiBlockBase<GT_MetaTileEntity_FusionComputer>
+ implements ISurvivalConstructable, IAddUIWidgets, IOverclockDescriptionProvider {
+
+ private final OverclockDescriber overclockDescriber;
+
+ public static final String STRUCTURE_PIECE_MAIN = "main";
+ private static final ClassValue<IStructureDefinition<GT_MetaTileEntity_FusionComputer>> STRUCTURE_DEFINITION = new ClassValue<>() {
+
+ @Override
+ protected IStructureDefinition<GT_MetaTileEntity_FusionComputer> computeValue(Class<?> type) {
+ return StructureDefinition.<GT_MetaTileEntity_FusionComputer>builder()
+ .addShape(
+ STRUCTURE_PIECE_MAIN,
+ transpose(
+ new String[][] {
+ { " ", " ihi ", " hh hh ", " h h ",
+ " h h ", " h h ", " i i ", " h h ",
+ " i i ", " h h ", " h h ", " h h ",
+ " hh hh ", " ihi ", " ", },
+ { " xhx ", " hhccchh ", " eccxhxcce ", " eceh hece ",
+ " hce ech ", " hch hch ", "xcx xcx", "hch hch",
+ "xcx xcx", " hch hch ", " hce ech ", " eceh hece ",
+ " eccx~xcce ", " hhccchh ", " xhx ", },
+ { " ", " ihi ", " hh hh ", " h h ",
+ " h h ", " h h ", " i i ", " h h ",
+ " i i ", " h h ", " h h ", " h h ",
+ " hh hh ", " ihi ", " ", } }))
+ .addElement('c', lazy(t -> ofBlock(t.getFusionCoil(), t.getFusionCoilMeta())))
+ .addElement('h', lazy(t -> ofBlock(t.getCasing(), t.getCasingMeta())))
+ .addElement(
+ 'i',
+ lazy(
+ t -> buildHatchAdder(GT_MetaTileEntity_FusionComputer.class)
+ .atLeast(
+ ImmutableMap.of(InputHatch.withAdder(GT_MetaTileEntity_FusionComputer::addInjector), 2))
+ .hatchItemFilterAnd(t2 -> filterByMTETier(t2.tier(), Integer.MAX_VALUE))
+ .casingIndex(53)
+ .dot(1)
+ .buildAndChain(t.getCasing(), t.getCasingMeta())))
+ .addElement(
+ 'e',
+ lazy(
+ t -> buildHatchAdder(GT_MetaTileEntity_FusionComputer.class).atLeast(
+ ImmutableMap.of(Energy.withAdder(GT_MetaTileEntity_FusionComputer::addEnergyInjector), 16))
+ .hatchItemFilterAnd(t2 -> filterByMTETier(t2.tier(), Integer.MAX_VALUE))
+ .casingIndex(53)
+ .dot(2)
+ .buildAndChain(t.getCasing(), t.getCasingMeta())))
+ .addElement(
+ 'x',
+ lazy(
+ t -> buildHatchAdder(GT_MetaTileEntity_FusionComputer.class)
+ .atLeast(OutputHatch.withAdder(GT_MetaTileEntity_FusionComputer::addExtractor))
+ .hatchItemFilterAnd(t2 -> filterByMTETier(t2.tier(), Integer.MAX_VALUE))
+ .casingIndex(53)
+ .dot(3)
+ .buildAndChain(t.getCasing(), t.getCasingMeta())))
+ .build();
+ }
+ };
+ public GT_Recipe mLastRecipe;
+ public long mEUStore;
+
+ static {
+ Textures.BlockIcons.setCasingTextureForId(
+ 52,
+ TextureFactory.of(
+ TextureFactory.builder()
+ .addIcon(MACHINE_CASING_FUSION_GLASS_YELLOW)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(MACHINE_CASING_FUSION_GLASS_YELLOW_GLOW)
+ .extFacing()
+ .glow()
+ .build()));
+ }
+
+ public GT_MetaTileEntity_FusionComputer(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ this.overclockDescriber = createOverclockDescriber();
+ }
+
+ public GT_MetaTileEntity_FusionComputer(String aName) {
+ super(aName);
+ this.overclockDescriber = createOverclockDescriber();
+ }
+
+ protected OverclockDescriber createOverclockDescriber() {
+ return new FusionOverclockDescriber((byte) tier(), capableStartupCanonical());
+ }
+
+ @Nonnull
+ @Override
+ public OverclockDescriber getOverclockDescriber() {
+ return overclockDescriber;
+ }
+
+ public abstract int tier();
+
+ @Override
+ public abstract long maxEUStore();
+
+ /**
+ * Unlike {@link #maxEUStore()}, this provides theoretical limit of startup EU, without considering the amount of
+ * hatches nor the room for extra energy. Intended for simulation.
+ */
+ public abstract long capableStartupCanonical();
+
+ @Override
+ public abstract MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity);
+
+ @Override
+ public boolean allowCoverOnSide(ForgeDirection side, GT_ItemStack aStack) {
+
+ return side != getBaseMetaTileEntity().getFrontFacing();
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ if (mEUt > 0) {
+ mEUt = -mEUt;
+ }
+ }
+
+ @Override
+ public IStructureDefinition<GT_MetaTileEntity_FusionComputer> getStructureDefinition() {
+ return STRUCTURE_DEFINITION.get(getClass());
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addController("Fusion Reactor")
+ .addInfo("Some kind of fusion reactor, maybe")
+ .addSeparator()
+ .addInfo("Some kind of fusion reactor, maybe")
+ .addStructureInfo("Should probably be built similar to other fusions")
+ .addStructureInfo("See controller tooltip for details")
+ .toolTipFinisher("Gregtech");
+ return tt;
+ }
+
+ @Override
+ public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+ if (checkPiece(STRUCTURE_PIECE_MAIN, 7, 1, 12) && mInputHatches.size() > 1
+ && !mOutputHatches.isEmpty()
+ && !mEnergyHatches.isEmpty()) {
+ mWrench = true;
+ mScrewdriver = true;
+ mSoftHammer = true;
+ mHardHammer = true;
+ mSolderingTool = true;
+ mCrowbar = true;
+ return true;
+ }
+ return false;
+ }
+
+ private boolean addEnergyInjector(IGregTechTileEntity aBaseMetaTileEntity, int aBaseCasingIndex) {
+ IMetaTileEntity aMetaTileEntity = aBaseMetaTileEntity.getMetaTileEntity();
+ if (aMetaTileEntity == null) return false;
+ if (!(aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Energy tHatch)) return false;
+ if (tHatch.mTier < tier()) return false;
+ tHatch.updateTexture(aBaseCasingIndex);
+ return mEnergyHatches.add(tHatch);
+ }
+
+ private boolean addInjector(IGregTechTileEntity aBaseMetaTileEntity, int aBaseCasingIndex) {
+ IMetaTileEntity aMetaTileEntity = aBaseMetaTileEntity.getMetaTileEntity();
+ if (aMetaTileEntity == null) return false;
+ if (!(aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Input tHatch)) return false;
+ if (tHatch.getTierForStructure() < tier()) return false;
+ tHatch.updateTexture(aBaseCasingIndex);
+ tHatch.mRecipeMap = getRecipeMap();
+ return mInputHatches.add(tHatch);
+ }
+
+ private boolean addExtractor(IGregTechTileEntity aBaseMetaTileEntity, int aBaseCasingIndex) {
+ if (aBaseMetaTileEntity == null) return false;
+ IMetaTileEntity aMetaTileEntity = aBaseMetaTileEntity.getMetaTileEntity();
+ if (aMetaTileEntity == null) return false;
+ if (!(aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Output tHatch)) return false;
+ if (tHatch.getTierForStructure() < tier()) return false;
+ tHatch.updateTexture(aBaseCasingIndex);
+ return mOutputHatches.add(tHatch);
+ }
+
+ public abstract Block getCasing();
+
+ public abstract int getCasingMeta();
+
+ public abstract Block getFusionCoil();
+
+ public abstract int getFusionCoilMeta();
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection aFacing,
+ int colorIndex, boolean aActive, boolean redstoneLevel) {
+ if (side == aFacing) return new ITexture[] { TextureFactory.builder()
+ .addIcon(MACHINE_CASING_FUSION_GLASS)
+ .extFacing()
+ .build(), getTextureOverlay() };
+ if (aActive) return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(52) };
+ return new ITexture[] { TextureFactory.builder()
+ .addIcon(MACHINE_CASING_FUSION_GLASS)
+ .extFacing()
+ .build() };
+ }
+
+ /**
+ * @return The list of textures overlay
+ */
+ public abstract ITexture getTextureOverlay();
+
+ @Override
+ public boolean isCorrectMachinePart(ItemStack aStack) {
+ return true;
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.fusionRecipes;
+ }
+
+ @Override
+ protected ProcessingLogic createProcessingLogic() {
+ return new ProcessingLogic() {
+
+ @NotNull
+ @Override
+ protected GT_ParallelHelper createParallelHelper(@NotNull GT_Recipe recipe) {
+ // When the fusion first loads and is still processing, it does the recipe check without consuming.
+ return super.createParallelHelper(recipe).setConsumption(!mRunningOnLoad);
+ }
+
+ @NotNull
+ @Override
+ protected GT_OverclockCalculator createOverclockCalculator(@NotNull GT_Recipe recipe) {
+ return overclockDescriber.createCalculator(super.createOverclockCalculator(recipe), recipe);
+ }
+
+ @NotNull
+ @Override
+ protected CheckRecipeResult validateRecipe(@NotNull GT_Recipe recipe) {
+ if (!mRunningOnLoad && recipe.mSpecialValue > maxEUStore()) {
+ return CheckRecipeResultRegistry.insufficientStartupPower(recipe.mSpecialValue);
+ }
+ return CheckRecipeResultRegistry.SUCCESSFUL;
+ }
+
+ @NotNull
+ @Override
+ public CheckRecipeResult process() {
+ CheckRecipeResult result = super.process();
+ if (mRunningOnLoad) mRunningOnLoad = false;
+ turnCasingActive(result.wasSuccessful());
+ if (result.wasSuccessful()) {
+ mLastRecipe = lastRecipe;
+ } else {
+ mLastRecipe = null;
+ }
+ return result;
+ }
+ };
+ }
+
+ @Override
+ protected void setProcessingLogicPower(ProcessingLogic logic) {
+ logic.setAvailableVoltage(GT_Values.V[tier()]);
+ logic.setAvailableAmperage(1);
+ logic.setAmperageOC(false);
+ }
+
+ public boolean turnCasingActive(boolean status) {
+ if (this.mEnergyHatches != null) {
+ for (GT_MetaTileEntity_Hatch_Energy hatch : this.mEnergyHatches) {
+ hatch.updateTexture(status ? 52 : 53);
+ }
+ }
+ if (this.mOutputHatches != null) {
+ for (GT_MetaTileEntity_Hatch_Output hatch : this.mOutputHatches) {
+ hatch.updateTexture(status ? 52 : 53);
+ }
+ }
+ if (this.mInputHatches != null) {
+ for (GT_MetaTileEntity_Hatch_Input hatch : this.mInputHatches) {
+ hatch.updateTexture(status ? 52 : 53);
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ if (aBaseMetaTileEntity.isServerSide()) {
+ if (mEfficiency < 0) mEfficiency = 0;
+ if (mRunningOnLoad && checkMachine(aBaseMetaTileEntity, mInventory[1])) {
+ this.mEUStore = aBaseMetaTileEntity.getStoredEU();
+ checkRecipe();
+ }
+ if (mUpdated) {
+ mUpdate = 50;
+ mUpdated = false;
+ }
+ if (--mUpdate == 0 || --mStartUpCheck == 0) {
+ checkStructure(true, aBaseMetaTileEntity);
+ }
+ if (mStartUpCheck < 0) {
+ if (mMachine) {
+ this.mEUStore = aBaseMetaTileEntity.getStoredEU();
+ if (this.mEnergyHatches != null) {
+ for (GT_MetaTileEntity_Hatch_Energy tHatch : filterValidMTEs(mEnergyHatches)) {
+ long energyToMove = GT_Values.V[tier()] / 16;
+ if (aBaseMetaTileEntity.getStoredEU() + energyToMove < maxEUStore()
+ && tHatch.getBaseMetaTileEntity()
+ .decreaseStoredEnergyUnits(energyToMove, false)) {
+ aBaseMetaTileEntity.increaseStoredEnergyUnits(energyToMove, true);
+ }
+ }
+ }
+ if (this.mEUStore <= 0 && mMaxProgresstime > 0) {
+ stopMachine(ShutDownReasonRegistry.POWER_LOSS);
+ }
+ if (mMaxProgresstime > 0) {
+ this.getBaseMetaTileEntity()
+ .decreaseStoredEnergyUnits(-mEUt, true);
+ if (mMaxProgresstime > 0 && ++mProgresstime >= mMaxProgresstime) {
+ if (mOutputItems != null)
+ for (ItemStack tStack : mOutputItems) if (tStack != null) addOutput(tStack);
+ if (mOutputFluids != null)
+ for (FluidStack tStack : mOutputFluids) if (tStack != null) addOutput(tStack);
+ mEfficiency = Math
+ .max(0, Math.min(mEfficiency + mEfficiencyIncrease, getMaxEfficiency(mInventory[1])));
+ mOutputItems = null;
+ mProgresstime = 0;
+ mMaxProgresstime = 0;
+ mEfficiencyIncrease = 0;
+ if (mOutputFluids != null && mOutputFluids.length > 0) {
+ try {
+ GT_Mod.achievements.issueAchivementHatchFluid(
+ aBaseMetaTileEntity.getWorld()
+ .getPlayerEntityByName(aBaseMetaTileEntity.getOwnerName()),
+ mOutputFluids[0]);
+ } catch (Exception ignored) {}
+ }
+ this.mEUStore = aBaseMetaTileEntity.getStoredEU();
+ if (aBaseMetaTileEntity.isAllowedToWork()) checkRecipe();
+ }
+ } else {
+ if (aTick % 100 == 0 || aBaseMetaTileEntity.hasWorkJustBeenEnabled()
+ || aBaseMetaTileEntity.hasInventoryBeenModified()) {
+ turnCasingActive(mMaxProgresstime > 0);
+ if (aBaseMetaTileEntity.isAllowedToWork()) {
+ this.mEUStore = aBaseMetaTileEntity.getStoredEU();
+ if (checkRecipe()) {
+ if (this.mEUStore < this.mLastRecipe.mSpecialValue + this.mEUt) {
+ stopMachine(ShutDownReasonRegistry.POWER_LOSS);
+ }
+ aBaseMetaTileEntity
+ .decreaseStoredEnergyUnits(this.mLastRecipe.mSpecialValue + this.mEUt, true);
+ }
+ }
+ if (mMaxProgresstime <= 0) mEfficiency = Math.max(0, mEfficiency - 1000);
+ }
+ }
+ } else if (aBaseMetaTileEntity.isAllowedToWork()) {
+ this.mLastRecipe = null;
+ stopMachine(ShutDownReasonRegistry.STRUCTURE_INCOMPLETE);
+ }
+ }
+ aBaseMetaTileEntity
+ .setErrorDisplayID((aBaseMetaTileEntity.getErrorDisplayID() & ~127) | (mMachine ? 0 : 64));
+ aBaseMetaTileEntity.setActive(mMaxProgresstime > 0);
+ }
+ }
+
+ @Override
+ public boolean drainEnergyInput(long aEU) {
+ return false;
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack aStack) {
+ return 10000;
+ }
+
+ @Override
+ public int getDamageToComponent(ItemStack aStack) {
+ return 0;
+ }
+
+ @Override
+ public boolean explodesOnComponentBreak(ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public void stopMachine(@NotNull ShutDownReason reason) {
+ super.stopMachine(reason);
+ turnCasingActive(false);
+ }
+
+ @Override
+ public String[] getInfoData() {
+ String tier = tier() == 6 ? EnumChatFormatting.RED + "I" + EnumChatFormatting.RESET
+ : tier() == 7 ? EnumChatFormatting.YELLOW + "II" + EnumChatFormatting.RESET
+ : tier() == 8 ? EnumChatFormatting.GRAY + "III" + EnumChatFormatting.RESET : "IV";
+ float plasmaOut = 0;
+ int powerRequired = 0;
+ if (this.mLastRecipe != null) {
+ powerRequired = this.mLastRecipe.mEUt;
+ if (this.mLastRecipe.getFluidOutput(0) != null) {
+ plasmaOut = (float) this.mLastRecipe.getFluidOutput(0).amount / (float) this.mLastRecipe.mDuration;
+ }
+ }
+
+ return new String[] { EnumChatFormatting.BLUE + "Fusion Reactor MK " + EnumChatFormatting.RESET + tier,
+ StatCollector.translateToLocal("GT5U.fusion.req") + ": "
+ + EnumChatFormatting.RED
+ + GT_Utility.formatNumbers(powerRequired)
+ + EnumChatFormatting.RESET
+ + "EU/t",
+ StatCollector.translateToLocal("GT5U.multiblock.energy") + ": "
+ + EnumChatFormatting.GREEN
+ + GT_Utility.formatNumbers(mEUStore)
+ + EnumChatFormatting.RESET
+ + " EU / "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(maxEUStore())
+ + EnumChatFormatting.RESET
+ + " EU",
+ StatCollector.translateToLocal("GT5U.fusion.plasma") + ": "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(plasmaOut)
+ + EnumChatFormatting.RESET
+ + "L/t" };
+ }
+
+ @Override
+ public boolean isGivingInformation() {
+ return true;
+ }
+
+ @Override
+ public void construct(ItemStack stackSize, boolean hintsOnly) {
+ buildPiece(STRUCTURE_PIECE_MAIN, stackSize, hintsOnly, 7, 1, 12);
+ }
+
+ @Override
+ public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
+ if (mMachine) return -1;
+ return survivialBuildPiece(STRUCTURE_PIECE_MAIN, stackSize, 7, 1, 12, elementBudget, env, false, true);
+ }
+
+ @Override
+ protected SoundResource getProcessStartSound() {
+ return SoundResource.GT_MACHINES_FUSION_LOOP;
+ }
+
+ @Override
+ public boolean doesBindPlayerInventory() {
+ return false;
+ }
+
+ @Override
+ public void addGregTechLogo(ModularWindow.Builder builder) {
+ builder.widget(
+ new DrawableWidget().setDrawable(getGUITextureSet().getGregTechLogo())
+ .setSize(17, 17)
+ .setPos(155, 145));
+ }
+
+ @Override
+ public GUITextureSet getGUITextureSet() {
+ return new GUITextureSet().setMainBackground(GT_UITextures.BACKGROUND_FUSION_COMPUTER);
+ }
+
+ @Override
+ public int getGUIWidth() {
+ return 176;
+ }
+
+ @Override
+ public int getGUIHeight() {
+ return 166;
+ }
+
+ protected static final NumberFormatMUI numberFormat = new NumberFormatMUI();
+ protected long clientEU;
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ builder
+ .widget(
+ new TextWidget(GT_Utility.trans("138", "Incomplete Structure.")).setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setEnabled(widget -> !mMachine)
+ .setPos(10, 8))
+ .widget(new FakeSyncWidget.BooleanSyncer(() -> mMachine, val -> mMachine = val))
+ .widget(
+ new TextWidget("Hit with Soft Mallet to (re-)start the Machine if it doesn't start.")
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setTextAlignment(Alignment.Center)
+ .setEnabled(
+ widget -> getBaseMetaTileEntity().getErrorDisplayID() == 0
+ && !getBaseMetaTileEntity().isActive())
+ .setPos(-getGUIWidth() / 2, 170)
+ .setSize(getGUIWidth() * 2, 9))
+ .widget(
+ new FakeSyncWidget.IntegerSyncer(
+ () -> getBaseMetaTileEntity().getErrorDisplayID(),
+ val -> getBaseMetaTileEntity().setErrorDisplayID(val)))
+ .widget(
+ new FakeSyncWidget.BooleanSyncer(
+ () -> getBaseMetaTileEntity().isActive(),
+ val -> getBaseMetaTileEntity().setActive(val)))
+ .widget(
+ new TextWidget("Running perfectly.").setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setTextAlignment(Alignment.Center)
+ .setEnabled(
+ widget -> getBaseMetaTileEntity().getErrorDisplayID() == 0
+ && getBaseMetaTileEntity().isActive())
+ .setPos(0, 170)
+ .setSize(getGUIWidth(), 9))
+ .widget(
+ new FakeSyncWidget.IntegerSyncer(
+ () -> getBaseMetaTileEntity().getErrorDisplayID(),
+ val -> getBaseMetaTileEntity().setErrorDisplayID(val)))
+ .widget(
+ new ProgressBar()
+ .setProgress(
+ () -> (float) getBaseMetaTileEntity().getStoredEU() / getBaseMetaTileEntity().getEUCapacity())
+ .setDirection(ProgressBar.Direction.RIGHT)
+ .setTexture(GT_UITextures.PROGRESSBAR_STORED_EU, 147)
+ .setPos(5, 156)
+ .setSize(147, 5))
+ .widget(new TextWidget().setStringSupplier(() -> {
+ if (clientEU > 160_000_000L && clientEU < 160_010_000L) {
+ clientEU = 160_000_000L;
+ }
+ if (clientEU > 320_000_000L && clientEU < 320_010_000L) {
+ clientEU = 320_000_000L;
+ }
+ if (clientEU > 640_000_000L && clientEU < 640_010_000L) {
+ clientEU = 640_000_000L;
+ }
+ if (clientEU > 5_120_000_000L && clientEU < 5_120_080_000L) {
+ clientEU = 5_120_000_000L;
+ }
+ return numberFormat.format(clientEU) + " EU";
+ })
+ .setDefaultColor(COLOR_TEXT_RED.get())
+ .setTextAlignment(Alignment.Center)
+ .setScale(0.5f)
+ .setPos(5, 157)
+ .setSize(147, 5))
+ .widget(new FakeSyncWidget.LongSyncer(() -> getBaseMetaTileEntity().getStoredEU(), val -> clientEU = val))
+ .widget(
+ new ButtonWidget().setNEITransferRect(
+ RecipeMaps.fusionRecipes.getFrontend()
+ .getUIProperties().neiTransferRectId)
+ .setBackground(GT_UITextures.BUTTON_STANDARD, GT_UITextures.OVERLAY_BUTTON_NEI)
+ .setPos(154, 4)
+ .setSize(18, 18));
+ }
+
+ @Override
+ public boolean supportsVoidProtection() {
+ return true;
+ }
+
+ @Override
+ public Set<VoidingMode> getAllowedVoidingModes() {
+ return VoidingMode.FLUID_ONLY_MODES;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_FusionComputer1.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_FusionComputer1.java
new file mode 100644
index 0000000000..e3a2432bf9
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_FusionComputer1.java
@@ -0,0 +1,103 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FUSION1;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FUSION1_GLOW;
+
+import net.minecraft.block.Block;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+
+public class GT_MetaTileEntity_FusionComputer1 extends GT_MetaTileEntity_FusionComputer {
+
+ private static final ITexture textureOverlay = TextureFactory.of(
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FUSION1)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FUSION1_GLOW)
+ .extFacing()
+ .glow()
+ .build());
+
+ public GT_MetaTileEntity_FusionComputer1(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_FusionComputer1(String aName) {
+ super(aName);
+ }
+
+ @Override
+ public int tier() {
+ return 6;
+ }
+
+ @Override
+ public long maxEUStore() {
+ return 160003000L * (Math.min(16, this.mEnergyHatches.size())) / 16L;
+ }
+
+ @Override
+ public long capableStartupCanonical() {
+ return 160_000_000;
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_FusionComputer1(mName);
+ }
+
+ @Override
+ public Block getCasing() {
+ return GregTech_API.sBlockCasings1;
+ }
+
+ @Override
+ public int getCasingMeta() {
+ return 6;
+ }
+
+ @Override
+ public Block getFusionCoil() {
+ return GregTech_API.sBlockCasings1;
+ }
+
+ @Override
+ public int getFusionCoilMeta() {
+ return 15;
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Fusion Reactor")
+ .addInfo("It's over 9000!!!")
+ .addInfo("Controller block for the Fusion Reactor Mk I")
+ .addInfo("2048EU/t and 10M EU capacity per Energy Hatch")
+ .addInfo("If the recipe has a startup cost greater than the")
+ .addInfo("number of energy hatches * cap, you can't do it")
+ .addSeparator()
+ .beginStructureBlock(15, 3, 15, false)
+ .addController("See diagram when placed")
+ .addCasingInfoRange("LuV Machine Casing", 79, 123, false)
+ .addStructureInfo("Cover the coils with casing")
+ .addOtherStructurePart("Superconducting Coil Block", "Center part of the ring")
+ .addEnergyHatch("1-16, Specified casings", 2)
+ .addInputHatch("2-16, Specified casings", 1)
+ .addOutputHatch("1-16, Specified casings", 3)
+ .addStructureInfo("ALL Hatches must be LuV or better")
+ .toolTipFinisher("Gregtech");
+ return tt;
+ }
+
+ @Override
+ public ITexture getTextureOverlay() {
+ return textureOverlay;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_FusionComputer2.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_FusionComputer2.java
new file mode 100644
index 0000000000..0b1f10158b
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_FusionComputer2.java
@@ -0,0 +1,103 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FUSION2;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FUSION2_GLOW;
+
+import net.minecraft.block.Block;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+
+public class GT_MetaTileEntity_FusionComputer2 extends GT_MetaTileEntity_FusionComputer {
+
+ private static final ITexture textureOverlay = TextureFactory.of(
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FUSION2)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FUSION2_GLOW)
+ .extFacing()
+ .glow()
+ .build());
+
+ public GT_MetaTileEntity_FusionComputer2(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_FusionComputer2(String aName) {
+ super(aName);
+ }
+
+ @Override
+ public int tier() {
+ return 7;
+ }
+
+ @Override
+ public long maxEUStore() {
+ return 320006000L * (Math.min(16, this.mEnergyHatches.size())) / 16L;
+ }
+
+ @Override
+ public long capableStartupCanonical() {
+ return 320_000_000;
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_FusionComputer2(mName);
+ }
+
+ @Override
+ public Block getCasing() {
+ return GregTech_API.sBlockCasings4;
+ }
+
+ @Override
+ public int getCasingMeta() {
+ return 6;
+ }
+
+ @Override
+ public Block getFusionCoil() {
+ return GregTech_API.sBlockCasings4;
+ }
+
+ @Override
+ public int getFusionCoilMeta() {
+ return 7;
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Fusion Reactor")
+ .addInfo("It's over 9000!!!")
+ .addInfo("Controller block for the Fusion Reactor Mk II")
+ .addInfo("8192EU/t and 20M EU capacity per Energy Hatch")
+ .addInfo("If the recipe has a startup cost greater than the")
+ .addInfo("number of energy hatches * cap, you can't do it")
+ .addSeparator()
+ .beginStructureBlock(15, 3, 15, false)
+ .addController("See diagram when placed")
+ .addCasingInfoRange("Fusion Machine Casing", 79, 123, false)
+ .addStructureInfo("Cover the coils with casing")
+ .addOtherStructurePart("Fusion Coil Block", "Center part of the ring")
+ .addEnergyHatch("1-16, Specified casings", 2)
+ .addInputHatch("2-16, Specified casings", 1)
+ .addOutputHatch("1-16, Specified casings", 3)
+ .addStructureInfo("ALL Hatches must be ZPM or better")
+ .toolTipFinisher("Gregtech");
+ return tt;
+ }
+
+ @Override
+ public ITexture getTextureOverlay() {
+ return textureOverlay;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_FusionComputer3.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_FusionComputer3.java
new file mode 100644
index 0000000000..64d92ccc99
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_FusionComputer3.java
@@ -0,0 +1,103 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FUSION3;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FUSION3_GLOW;
+
+import net.minecraft.block.Block;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+
+public class GT_MetaTileEntity_FusionComputer3 extends GT_MetaTileEntity_FusionComputer {
+
+ private static final ITexture textureOverlay = TextureFactory.of(
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FUSION3)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FUSION3_GLOW)
+ .extFacing()
+ .glow()
+ .build());
+
+ public GT_MetaTileEntity_FusionComputer3(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_FusionComputer3(String aName) {
+ super(aName);
+ }
+
+ @Override
+ public int tier() {
+ return 8;
+ }
+
+ @Override
+ public long maxEUStore() {
+ return 640010000L * (Math.min(16, this.mEnergyHatches.size())) / 16L;
+ }
+
+ @Override
+ public long capableStartupCanonical() {
+ return 640_000_000;
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_FusionComputer3(mName);
+ }
+
+ @Override
+ public Block getCasing() {
+ return GregTech_API.sBlockCasings4;
+ }
+
+ @Override
+ public int getCasingMeta() {
+ return 8;
+ }
+
+ @Override
+ public Block getFusionCoil() {
+ return GregTech_API.sBlockCasings4;
+ }
+
+ @Override
+ public int getFusionCoilMeta() {
+ return 7;
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Fusion Reactor")
+ .addInfo("A SUN DOWN ON EARTH")
+ .addInfo("Controller block for the Fusion Reactor Mk III")
+ .addInfo("32768EU/t and 40M EU capacity per Energy Hatch")
+ .addInfo("If the recipe has a startup cost greater than the")
+ .addInfo("number of energy hatches * cap, you can't do it")
+ .addSeparator()
+ .beginStructureBlock(15, 3, 15, false)
+ .addController("See diagram when placed")
+ .addCasingInfoRange("Fusion Machine Casing Mk II", 79, 123, false)
+ .addStructureInfo("Cover the coils with casing")
+ .addOtherStructurePart("Fusion Coil Block", "Center part of the ring")
+ .addEnergyHatch("1-16, Specified casings", 2)
+ .addInputHatch("2-16, Specified casings", 1)
+ .addOutputHatch("1-16, Specified casings", 3)
+ .addStructureInfo("ALL Hatches must be UV or better")
+ .toolTipFinisher("Gregtech");
+ return tt;
+ }
+
+ @Override
+ public ITexture getTextureOverlay() {
+ return textureOverlay;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_HeatExchanger.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_HeatExchanger.java
new file mode 100644
index 0000000000..70e8079b5b
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_HeatExchanger.java
@@ -0,0 +1,416 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.onElementPass;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.transpose;
+import static gregtech.api.enums.GT_HatchElement.InputBus;
+import static gregtech.api.enums.GT_HatchElement.InputHatch;
+import static gregtech.api.enums.GT_HatchElement.Maintenance;
+import static gregtech.api.enums.GT_HatchElement.OutputBus;
+import static gregtech.api.enums.GT_HatchElement.OutputHatch;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_HEAT_EXCHANGER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_HEAT_EXCHANGER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_HEAT_EXCHANGER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_HEAT_EXCHANGER_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.casingTexturePages;
+import static gregtech.api.util.GT_StructureUtility.buildHatchAdder;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.StatCollector;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidRegistry;
+import net.minecraftforge.fluids.FluidStack;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.gtnewhorizon.structurelib.alignment.IAlignmentLimits;
+import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_EnhancedMultiBlockBase;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Input;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Output;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Log;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_HeatExchanger extends
+ GT_MetaTileEntity_EnhancedMultiBlockBase<GT_MetaTileEntity_HeatExchanger> implements ISurvivalConstructable {
+
+ private int dryHeatCounter = 0; // Counts up to dryHeatMaximum to check for explosion conditions
+ private static final int dryHeatMaximum = 2000; // 2000 ticks = 100 seconds
+ private static final int CASING_INDEX = 50;
+ private static final String STRUCTURE_PIECE_MAIN = "main";
+ private static final IStructureDefinition<GT_MetaTileEntity_HeatExchanger> STRUCTURE_DEFINITION = StructureDefinition
+ .<GT_MetaTileEntity_HeatExchanger>builder()
+ .addShape(
+ STRUCTURE_PIECE_MAIN,
+ transpose(
+ new String[][] { { "ccc", "cCc", "ccc" }, { "ccc", "cPc", "ccc" }, { "ccc", "cPc", "ccc" },
+ { "c~c", "cHc", "ccc" }, }))
+ .addElement('P', ofBlock(GregTech_API.sBlockCasings2, 14))
+ .addElement(
+ 'C',
+ OutputHatch.withAdder(GT_MetaTileEntity_HeatExchanger::addColdFluidOutputToMachineList)
+ .withCount(t -> t.mOutputColdFluidHatch.isValid() ? 1 : 0)
+ .newAny(CASING_INDEX, 3))
+ .addElement(
+ 'H',
+ InputHatch.withAdder(GT_MetaTileEntity_HeatExchanger::addHotFluidInputToMachineList)
+ .withCount(t -> t.mInputHotFluidHatch.isValid() ? 1 : 0)
+ .newAny(CASING_INDEX, 3))
+ .addElement(
+ 'c',
+ buildHatchAdder(GT_MetaTileEntity_HeatExchanger.class)
+ .atLeast(InputBus, InputHatch, OutputBus, OutputHatch, Maintenance)
+ .casingIndex(CASING_INDEX)
+ .dot(1)
+ .buildAndChain(
+ onElementPass(
+ GT_MetaTileEntity_HeatExchanger::onCasingAdded,
+ ofBlock(GregTech_API.sBlockCasings4, (byte) 2))))
+ .build();
+ public static float penalty_per_config = 0.015f; // penalize 1.5% efficiency per circuitry level (1-25)
+
+ private GT_MetaTileEntity_Hatch_Input mInputHotFluidHatch;
+ private GT_MetaTileEntity_Hatch_Output mOutputColdFluidHatch;
+ private boolean superheated = false;
+ private int superheated_threshold = 0;
+ /**
+ * How much more steam we can make without draining real water. Unit is (1L/GT_Values.STEAM_PER_WATER)
+ */
+ private int steamBudget;
+
+ private int mCasingAmount;
+
+ public GT_MetaTileEntity_HeatExchanger(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_HeatExchanger(String aName) {
+ super(aName);
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Heat Exchanger")
+ .addInfo("Controller Block for the Large Heat Exchanger")
+ .addInfo("More complicated than a Fusion Reactor. Seriously")
+ .addInfo("Inputs are Hot Coolant or Lava")
+ .addInfo("Outputs Coolant or Pahoehoe Lava and SH Steam/Steam")
+ .addInfo("Read the wiki article to understand how it works")
+ .addInfo("Then go to the Discord to understand the wiki")
+ .addSeparator()
+ .beginStructureBlock(3, 4, 3, false)
+ .addController("Front bottom")
+ .addCasingInfoRange("Stable Titanium Machine Casing", 20, 32, false)
+ .addOtherStructurePart("Titanium Pipe Casing", "Center 2 blocks")
+ .addMaintenanceHatch("Any casing", 1)
+ .addInputHatch("Hot fluid, bottom center", 2)
+ .addInputHatch("Distilled water, any casing", 1)
+ .addOutputHatch("Cold fluid, top center", 3)
+ .addOutputHatch("Steam/SH Steam, any casing", 1)
+ .toolTipFinisher("Gregtech");
+ return tt;
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ superheated = aNBT.getBoolean("superheated");
+ steamBudget = aNBT.getInteger("steamBudget");
+ super.loadNBTData(aNBT);
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ aNBT.setBoolean("superheated", superheated);
+ aNBT.setInteger("steamBudget", steamBudget);
+ super.saveNBTData(aNBT);
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection aFacing,
+ int colorIndex, boolean aActive, boolean redstoneLevel) {
+ if (side == aFacing) {
+ if (aActive) return new ITexture[] { casingTexturePages[0][CASING_INDEX], TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_HEAT_EXCHANGER_ACTIVE)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_HEAT_EXCHANGER_ACTIVE_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ return new ITexture[] { casingTexturePages[0][CASING_INDEX], TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_HEAT_EXCHANGER)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_HEAT_EXCHANGER_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ }
+ return new ITexture[] { casingTexturePages[0][CASING_INDEX] };
+ }
+
+ @Override
+ public boolean isCorrectMachinePart(ItemStack aStack) {
+ return true;
+ }
+
+ @Override
+ protected IAlignmentLimits getInitialAlignmentLimits() {
+ return (d, r, f) -> !r.isUpsideDown() && !f.isVerticallyFliped();
+ }
+
+ @Override
+ @NotNull
+ public CheckRecipeResult checkProcessing() {
+ if (mInputHotFluidHatch.getFluid() == null) return CheckRecipeResultRegistry.NO_RECIPE;
+
+ int fluidAmountToConsume = mInputHotFluidHatch.getFluidAmount(); // how much fluid is in hatch
+
+ superheated_threshold = 4000; // default: must have 4000L per second to generate superheated steam
+ float efficiency = 1f; // default: operate at 100% efficiency with no integrated circuitry
+ int shs_reduction_per_config = 150; // reduce threshold 150L/s per circuitry level (1-25)
+ float steam_output_multiplier = 20f; // default: multiply output by 4 * 10 (boosted x5)
+ float penalty = 0.0f; // penalty to apply to output based on circuitry level (1-25).
+ boolean do_lava = false;
+ boolean do_coolant = false;
+ boolean do_solarSalt = false;
+
+ // Do we have an integrated circuit with a valid configuration?
+ if (mInventory[1] != null && mInventory[1].getUnlocalizedName()
+ .startsWith("gt.integrated_circuit")) {
+ int circuit_config = mInventory[1].getItemDamage();
+ if (circuit_config >= 1 && circuit_config <= 25) {
+ // If so, apply the penalty and reduce the threshold.
+ penalty = (circuit_config - 1) * penalty_per_config;
+ superheated_threshold -= (shs_reduction_per_config * (circuit_config - 1));
+ }
+ }
+ efficiency -= penalty;
+
+ // If we're working with lava, adjust the threshold and multipliers accordingly.
+ if (GT_ModHandler.isLava(mInputHotFluidHatch.getFluid())) {
+ steam_output_multiplier /= 5f; // lava is not boosted
+ superheated_threshold /= 4f; // unchanged
+ do_lava = true;
+ } else if (mInputHotFluidHatch.getFluid()
+ .isFluidEqual(FluidRegistry.getFluidStack("ic2hotcoolant", 1))) {
+ steam_output_multiplier /= 2f; // was boosted x2 on top of x5 -> total x10 ->
+ // nerf with this code back to 5x
+ superheated_threshold /= 5f; // 10x smaller since the Hot Things production in
+ // reactor is the same.
+ do_coolant = true;
+ } else if (mInputHotFluidHatch.getFluid()
+ .isFluidEqual(FluidRegistry.getFluidStack("molten.solarsalthot", 1))) {
+ steam_output_multiplier *= 2.5f; // Solar Salt:Steam value is 5x higher than Hot
+ // Coolant's value
+ superheated_threshold /= 25f; // Given that, multiplier is 5x higher and
+ // threshold is 5x lower
+ do_solarSalt = true;
+ } else {
+ // If we're working with neither, fail out
+ superheated_threshold = 0;
+ return CheckRecipeResultRegistry.NO_RECIPE;
+ }
+
+ superheated = fluidAmountToConsume >= superheated_threshold; // set the internal superheated flag if we have
+ // enough hot fluid. Used in the
+ // onRunningTick method.
+ fluidAmountToConsume = Math.min(fluidAmountToConsume, superheated_threshold * 2); // Don't consume too much hot
+ // fluid per second
+ mInputHotFluidHatch.drain(fluidAmountToConsume, true);
+ this.mMaxProgresstime = 20;
+ this.mEUt = (int) (fluidAmountToConsume * steam_output_multiplier * efficiency);
+ if (do_lava) {
+ mOutputColdFluidHatch.fill(FluidRegistry.getFluidStack("ic2pahoehoelava", fluidAmountToConsume), true);
+ } else if (do_coolant) {
+ mOutputColdFluidHatch.fill(FluidRegistry.getFluidStack("ic2coolant", fluidAmountToConsume), true);
+ } else {
+ mOutputColdFluidHatch.fill(FluidRegistry.getFluidStack("molten.solarsaltcold", fluidAmountToConsume), true);
+ }
+ this.mEfficiencyIncrease = 80;
+ return CheckRecipeResultRegistry.SUCCESSFUL;
+ }
+
+ private int useWater(int steam) {
+ steamBudget -= steam;
+ int usage = -Math.min(0, Math.floorDiv(steamBudget, GT_Values.STEAM_PER_WATER));
+ // still subtract, because usage will be a negative number
+ steamBudget += usage * GT_Values.STEAM_PER_WATER;
+ return usage;
+ }
+
+ @Override
+ public boolean onRunningTick(ItemStack aStack) {
+ if (this.mEUt > 0) {
+ int tGeneratedEU = (int) (this.mEUt * 2L * this.mEfficiency / 10000L); // APPROXIMATELY how much steam to
+ // generate.
+ if (tGeneratedEU > 0) {
+
+ if (superheated) tGeneratedEU /= 2; // We produce half as much superheated steam if necessary
+
+ int distilledConsumed = useWater(tGeneratedEU); // how much distilled water to consume
+ // tGeneratedEU = distilledConsumed * 160; // EXACTLY how much steam to generate, producing a perfect
+ // 1:160 ratio with distilled water consumption
+
+ FluidStack distilledStack = GT_ModHandler.getDistilledWater(distilledConsumed);
+ startRecipeProcessing();
+ if (depleteInput(distilledStack)) // Consume the distilled water
+ {
+ if (superheated) {
+ addOutput(FluidRegistry.getFluidStack("ic2superheatedsteam", tGeneratedEU)); // Generate
+ // superheated
+ // steam
+ } else {
+ addOutput(GT_ModHandler.getSteam(tGeneratedEU)); // Generate regular steam
+ }
+ dryHeatCounter = 0;
+ } else {
+ if (dryHeatCounter < dryHeatMaximum) {
+ dryHeatCounter += 1;
+ } else {
+ GT_Log.exp.println(this.mName + " was too hot and had no more Distilled Water!");
+ explodeMultiblock(); // Generate crater
+ }
+ }
+ endRecipeProcessing();
+ }
+ return true;
+ }
+ return true;
+ }
+
+ @Override
+ public IStructureDefinition<GT_MetaTileEntity_HeatExchanger> getStructureDefinition() {
+ return STRUCTURE_DEFINITION;
+ }
+
+ private void onCasingAdded() {
+ mCasingAmount++;
+ }
+
+ @Override
+ public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+ mOutputColdFluidHatch = null;
+ mInputHotFluidHatch = null;
+ mCasingAmount = 0;
+ return checkPiece(STRUCTURE_PIECE_MAIN, 1, 3, 0) && mCasingAmount >= 20 && mMaintenanceHatches.size() == 1;
+ }
+
+ public boolean addColdFluidOutputToMachineList(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
+ if (aTileEntity == null) return false;
+ IMetaTileEntity aMetaTileEntity = aTileEntity.getMetaTileEntity();
+ if (aMetaTileEntity == null) return false;
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Output) {
+ ((GT_MetaTileEntity_Hatch) aMetaTileEntity).updateTexture(aBaseCasingIndex);
+ mOutputColdFluidHatch = (GT_MetaTileEntity_Hatch_Output) aMetaTileEntity;
+ return true;
+ }
+ return false;
+ }
+
+ public boolean addHotFluidInputToMachineList(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
+ if (aTileEntity == null) return false;
+ IMetaTileEntity aMetaTileEntity = aTileEntity.getMetaTileEntity();
+ if (aMetaTileEntity == null) return false;
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Input) {
+ ((GT_MetaTileEntity_Hatch) aMetaTileEntity).updateTexture(aBaseCasingIndex);
+ ((GT_MetaTileEntity_Hatch_Input) aMetaTileEntity).mRecipeMap = getRecipeMap();
+ mInputHotFluidHatch = (GT_MetaTileEntity_Hatch_Input) aMetaTileEntity;
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack aStack) {
+ return 10000;
+ }
+
+ @Override
+ public int getDamageToComponent(ItemStack aStack) {
+ return 0;
+ }
+
+ @Override
+ public boolean explodesOnComponentBreak(ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_HeatExchanger(this.mName);
+ }
+
+ @Override
+ public String[] getInfoData() {
+ return new String[] {
+ StatCollector.translateToLocal("GT5U.multiblock.Progress") + ": "
+ + EnumChatFormatting.GREEN
+ + GT_Utility.formatNumbers(mProgresstime / 20)
+ + EnumChatFormatting.RESET
+ + " s / "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(mMaxProgresstime / 20)
+ + EnumChatFormatting.RESET
+ + " s",
+ StatCollector.translateToLocal("GT5U.multiblock.usage") + " "
+ + StatCollector.translateToLocal("GT5U.LHE.steam")
+ + ": "
+ + (superheated ? EnumChatFormatting.RED : EnumChatFormatting.YELLOW)
+ + GT_Utility.formatNumbers(superheated ? -2L * mEUt : -mEUt)
+ + EnumChatFormatting.RESET
+ + " EU/t",
+ StatCollector.translateToLocal("GT5U.multiblock.problems") + ": "
+ + EnumChatFormatting.RED
+ + (getIdealStatus() - getRepairStatus())
+ + EnumChatFormatting.RESET
+ + " "
+ + StatCollector.translateToLocal("GT5U.multiblock.efficiency")
+ + ": "
+ + EnumChatFormatting.YELLOW
+ + mEfficiency / 100.0F
+ + EnumChatFormatting.RESET
+ + " %",
+ StatCollector.translateToLocal("GT5U.LHE.superheated") + ": "
+ + (superheated ? EnumChatFormatting.RED : EnumChatFormatting.BLUE)
+ + superheated
+ + EnumChatFormatting.RESET,
+ StatCollector.translateToLocal("GT5U.LHE.superheated") + " "
+ + StatCollector.translateToLocal("GT5U.LHE.threshold")
+ + ": "
+ + EnumChatFormatting.GREEN
+ + GT_Utility.formatNumbers(superheated_threshold)
+ + EnumChatFormatting.RESET };
+ }
+
+ @Override
+ public void construct(ItemStack stackSize, boolean hintsOnly) {
+ buildPiece(STRUCTURE_PIECE_MAIN, stackSize, hintsOnly, 1, 3, 0);
+ }
+
+ @Override
+ public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
+ if (mMachine) return -1;
+ return survivialBuildPiece(STRUCTURE_PIECE_MAIN, stackSize, 1, 3, 0, elementBudget, env, false, true);
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ImplosionCompressor.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ImplosionCompressor.java
new file mode 100644
index 0000000000..a1968b05d4
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ImplosionCompressor.java
@@ -0,0 +1,163 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofChain;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_IMPLOSION_COMPRESSOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_IMPLOSION_COMPRESSOR_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_IMPLOSION_COMPRESSOR_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_IMPLOSION_COMPRESSOR_GLOW;
+
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.gtnewhorizon.structurelib.structure.IStructureElement;
+
+import gregtech.GT_Mod;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.SoundResource;
+import gregtech.api.enums.Textures;
+import gregtech.api.enums.Textures.BlockIcons;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.logic.ProcessingLogic;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_CubicMultiBlockBase;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+
+public class GT_MetaTileEntity_ImplosionCompressor
+ extends GT_MetaTileEntity_CubicMultiBlockBase<GT_MetaTileEntity_ImplosionCompressor> {
+
+ public GT_MetaTileEntity_ImplosionCompressor(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_ImplosionCompressor(String aName) {
+ super(aName);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_ImplosionCompressor(this.mName);
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Implosion Compressor")
+ .addInfo("Explosions are fun")
+ .addInfo("Controller block for the Implosion Compressor")
+ .addPollutionAmount(getPollutionPerSecond(null))
+ .addSeparator()
+ .beginStructureBlock(3, 3, 3, true)
+ .addController("Front center")
+ .addCasingInfoRange("Solid Steel Machine Casing", 16, 24, false)
+ .addStructureInfo("Casings can be replaced with Explosion Warning Signs")
+ .addEnergyHatch("Any casing", 1)
+ .addMaintenanceHatch("Any casing", 1)
+ .addMufflerHatch("Any casing", 1)
+ .addInputBus("Any casing", 1)
+ .addOutputBus("Any casing", 1)
+ .toolTipFinisher("Gregtech");
+ return tt;
+ }
+
+ @Override
+ public boolean addToMachineList(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
+ return super.addToMachineList(aTileEntity, aBaseCasingIndex)
+ || addMufflerToMachineList(aTileEntity, aBaseCasingIndex);
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection aFacing,
+ int colorIndex, boolean aActive, boolean redstoneLevel) {
+ if (side == aFacing) {
+ if (aActive) return new ITexture[] { BlockIcons.casingTexturePages[0][16], TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_IMPLOSION_COMPRESSOR_ACTIVE)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_IMPLOSION_COMPRESSOR_ACTIVE_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ return new ITexture[] { BlockIcons.casingTexturePages[0][16], TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_IMPLOSION_COMPRESSOR)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_IMPLOSION_COMPRESSOR_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ }
+ return new ITexture[] { Textures.BlockIcons.casingTexturePages[0][16] };
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.implosionRecipes;
+ }
+
+ @Override
+ public boolean isCorrectMachinePart(ItemStack aStack) {
+ return true;
+ }
+
+ @Override
+ protected ProcessingLogic createProcessingLogic() {
+ return new ProcessingLogic();
+ }
+
+ @Override
+ protected int getTimeBetweenProcessSounds() {
+ return 10;
+ }
+
+ @Override
+ protected SoundResource getProcessStartSound() {
+ return SoundResource.RANDOM_EXPLODE;
+ }
+
+ @Override
+ protected IStructureElement<GT_MetaTileEntity_CubicMultiBlockBase<?>> getCasingElement() {
+ return ofChain(ofBlock(GregTech_API.sBlockCasings2, 0), ofBlock(GregTech_API.sBlockCasings3, 4));
+ }
+
+ @Override
+ protected int getHatchTextureIndex() {
+ return 16;
+ }
+
+ @Override
+ protected int getRequiredCasingCount() {
+ return 16;
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack aStack) {
+ return 10000;
+ }
+
+ @Override
+ public int getPollutionPerSecond(ItemStack aStack) {
+ return GT_Mod.gregtechproxy.mPollutionImplosionCompressorPerSecond;
+ }
+
+ @Override
+ public int getDamageToComponent(ItemStack aStack) {
+ return 0;
+ }
+
+ @Override
+ public boolean explodesOnComponentBreak(ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public boolean supportsVoidProtection() {
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_IntegratedOreFactory.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_IntegratedOreFactory.java
new file mode 100644
index 0000000000..48ab5a10f5
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_IntegratedOreFactory.java
@@ -0,0 +1,831 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.transpose;
+import static gregtech.api.enums.GT_HatchElement.Energy;
+import static gregtech.api.enums.GT_HatchElement.InputBus;
+import static gregtech.api.enums.GT_HatchElement.InputHatch;
+import static gregtech.api.enums.GT_HatchElement.Maintenance;
+import static gregtech.api.enums.GT_HatchElement.Muffler;
+import static gregtech.api.enums.GT_HatchElement.OutputBus;
+import static gregtech.api.enums.GT_HatchElement.OutputHatch;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_PROCESSING_ARRAY;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_PROCESSING_ARRAY_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_PROCESSING_ARRAY_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_PROCESSING_ARRAY_GLOW;
+import static gregtech.api.enums.TickTime.SECOND;
+import static gregtech.api.util.GT_StructureUtility.buildHatchAdder;
+import static gregtech.api.util.GT_StructureUtility.ofFrame;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Random;
+import java.util.stream.Collectors;
+
+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.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidStack;
+import net.minecraftforge.oredict.OreDictionary;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.gtnewhorizon.structurelib.alignment.IAlignmentLimits;
+import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_ExtendedPowerMultiBlockBase;
+import gregtech.api.multitileentity.multiblock.casing.Glasses;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_OverclockCalculator;
+import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.GT_Utility;
+import mcp.mobius.waila.api.IWailaConfigHandler;
+import mcp.mobius.waila.api.IWailaDataAccessor;
+
+public class GT_MetaTileEntity_IntegratedOreFactory
+ extends GT_MetaTileEntity_ExtendedPowerMultiBlockBase<GT_MetaTileEntity_IntegratedOreFactory>
+ implements ISurvivalConstructable {
+
+ private static final int CASING_INDEX1 = 183;
+ private static final int CASING_INDEX2 = 49;
+ private static final int MAX_PARA = 1024;
+ private static final long RECIPE_EUT = 30;
+ private static final String STRUCTURE_PIECE_MAIN = "main";
+ private static final IStructureDefinition<GT_MetaTileEntity_IntegratedOreFactory> STRUCTURE_DEFINITION = StructureDefinition
+ .<GT_MetaTileEntity_IntegratedOreFactory>builder()
+ .addShape(
+ STRUCTURE_PIECE_MAIN,
+ transpose(
+ new String[][] {
+ { " ", " ", " WWW ", " WWW ", " ", " " },
+ { " ", " sss ", " sppps", " sppps", " sss ", " " },
+ { " ", " sss ", " s s", " s s", " sss ", " " },
+ { " ", " sss ", " sppps", " sppps", " sss ", " " },
+ { " ", " sss ", " s s", " s s", " sss ", " " },
+ { " ", " sss ", " sppps", " sppps", " sss ", " " },
+ { "iiiiii ", "iIIIIiisssi", "iIIIIis s", "iIIIIis s", "iIIIIiisssi", "iiiiii " },
+ { "iggggi ", "gt t isssi", "g xx sppps", "g xx sppps", "gt t isssi", "iggggi " },
+ { "iggggi ", "gt t isssi", "g xx s s", "g xx s s", "gt t isssi", "iggggi " },
+ { "iggggi ", "gt t is~si", "g xx spppO", "g xx spppO", "gt t isssi", "iggggi " },
+ { "iggggi ", "gt t isssi", "g xx s O", "g xx s O", "gt t isssi", "iggggi " },
+ { "EEEEEE ", "EEEEEEEEEEE", "EEEEEEEEEEE", "EEEEEEEEEEE", "EEEEEEEEEEE", "EEEEEE " } }))
+ .addElement('i', ofBlock(GregTech_API.sBlockCasings8, 7))
+ .addElement('s', ofBlock(GregTech_API.sBlockCasings4, 1))
+ .addElement('g', Glasses.chainAllGlasses())
+ .addElement('x', ofBlock(GregTech_API.sBlockCasings2, 3))
+ .addElement('p', ofBlock(GregTech_API.sBlockCasings2, 15))
+ .addElement('t', ofFrame(Materials.TungstenSteel))
+ .addElement(
+ 'E',
+ buildHatchAdder(GT_MetaTileEntity_IntegratedOreFactory.class).atLeast(Energy, Maintenance)
+ .casingIndex(CASING_INDEX1)
+ .dot(1)
+ .buildAndChain(GregTech_API.sBlockCasings8, 7))
+ .addElement(
+ 'I',
+ buildHatchAdder(GT_MetaTileEntity_IntegratedOreFactory.class).atLeast(InputBus)
+ .casingIndex(CASING_INDEX1)
+ .dot(2)
+ .buildAndChain(GregTech_API.sBlockCasings8, 7))
+ .addElement(
+ 'W',
+ buildHatchAdder(GT_MetaTileEntity_IntegratedOreFactory.class).atLeast(InputHatch, Muffler)
+ .casingIndex(CASING_INDEX2)
+ .dot(3)
+ .buildAndChain(GregTech_API.sBlockCasings4, 1))
+ .addElement(
+ 'O',
+ buildHatchAdder(GT_MetaTileEntity_IntegratedOreFactory.class).atLeast(OutputBus, OutputHatch)
+ .casingIndex(CASING_INDEX2)
+ .dot(4)
+ .buildAndChain(GregTech_API.sBlockCasings4, 1))
+ .build();
+
+ private static final HashSet<Integer> isCrushedOre = new HashSet<>();
+ private static final HashSet<Integer> isCrushedPureOre = new HashSet<>();
+ private static final HashSet<Integer> isPureDust = new HashSet<>();
+ private static final HashSet<Integer> isImpureDust = new HashSet<>();
+ private static final HashSet<Integer> isThermal = new HashSet<>();
+ private static final HashSet<Integer> isOre = new HashSet<>();
+ private static boolean isInit = false;
+ private ItemStack[] sMidProduct;
+ private int sMode = 0;
+ private boolean sVoidStone = false;
+ private int currentParallelism = 0;
+
+ private static void initHash() {
+ for (String name : OreDictionary.getOreNames()) {
+ if (name == null || name.isEmpty()) continue;
+ if (name.startsWith("crushedPurified")) {
+ for (ItemStack stack : OreDictionary.getOres(name)) {
+ isCrushedPureOre.add(GT_Utility.stackToInt(stack));
+ }
+ } else if (name.startsWith("crushedCentrifuged")) {
+ for (ItemStack stack : OreDictionary.getOres(name)) {
+ isThermal.add(GT_Utility.stackToInt(stack));
+ }
+ } else if (name.startsWith("crushed")) {
+ for (ItemStack stack : OreDictionary.getOres(name)) {
+ isCrushedOre.add(GT_Utility.stackToInt(stack));
+ }
+ } else if (name.startsWith("dustImpure")) {
+ for (ItemStack stack : OreDictionary.getOres(name)) {
+ isImpureDust.add(GT_Utility.stackToInt(stack));
+ }
+ } else if (name.startsWith("dustPure")) {
+ for (ItemStack stack : OreDictionary.getOres(name)) {
+ isPureDust.add(GT_Utility.stackToInt(stack));
+ }
+ } else if (name.startsWith("ore")) {
+ for (ItemStack stack : OreDictionary.getOres(name)) {
+ isOre.add(GT_Utility.stackToInt(stack));
+ }
+ } else if (name.startsWith("rawOre")) {
+ for (ItemStack stack : OreDictionary.getOres(name)) {
+ isOre.add(GT_Utility.stackToInt(stack));
+ }
+ }
+ }
+ }
+
+ public GT_MetaTileEntity_IntegratedOreFactory(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_IntegratedOreFactory(String aName) {
+ super(aName);
+ }
+
+ @Override
+ public IStructureDefinition<GT_MetaTileEntity_IntegratedOreFactory> getStructureDefinition() {
+ return STRUCTURE_DEFINITION;
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Ore Processor")
+ .addInfo("Controller Block for the Integrated Ore Factory")
+ .addInfo("It is OP. I mean ore processor.")
+ .addInfo("Do all ore processing in one step.")
+ .addInfo("Can process up to 1024 ores at a time.")
+ .addInfo("Every ore costs 30EU/t, 2L lubricant, 200L distilled water.")
+ .addInfo("Processing time is dependent on mode.")
+ .addInfo("Use a screwdriver to switch mode.")
+ .addInfo("Sneak click with screwdriver to void the stone dust.")
+ .addSeparator()
+ .beginStructureBlock(6, 12, 11, false)
+ .addController("The third layer")
+ .addStructureInfo("128 Advanced Iridium Plated Machine Casing")
+ .addStructureInfo("105 Clean Stainless Steel Machine Casing")
+ .addStructureInfo("48 Reinforced Glass")
+ .addStructureInfo("30 Tungstensteel Pipe Casing")
+ .addStructureInfo("16 Tungstensteel Frame Box")
+ .addStructureInfo("16 Steel Gear Box Casing")
+ .addEnergyHatch("Any bottom Casing", 1)
+ .addMaintenanceHatch("Any bottom Casing", 1)
+ .addInputBus("Input ore/crushed ore", 2)
+ .addInputHatch("Input lubricant/distilled water/washing chemicals", 3)
+ .addMufflerHatch("Output Pollution", 3)
+ .addOutputBus("Output products", 4)
+ .toolTipFinisher("Gregtech");
+ return tt;
+ }
+
+ @Override
+ protected IAlignmentLimits getInitialAlignmentLimits() {
+ return (d, r, f) -> !r.isUpsideDown() && !f.isVerticallyFliped();
+ }
+
+ @Override
+ public void construct(ItemStack itemStack, boolean b) {
+ buildPiece(STRUCTURE_PIECE_MAIN, itemStack, b, 8, 9, 1);
+ }
+
+ @Override
+ public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
+ if (mMachine) return -1;
+ return survivialBuildPiece(STRUCTURE_PIECE_MAIN, stackSize, 8, 9, 1, elementBudget, env, false, true);
+ }
+
+ @Override
+ public boolean isCorrectMachinePart(ItemStack aStack) {
+ return true;
+ }
+
+ private static int getTime(int mode) {
+ return switch (mode) {
+ case 0 -> 30 * SECOND;
+ case 1 -> 15 * SECOND;
+ case 2 -> 10 * SECOND;
+ case 3 -> 20 * SECOND;
+ case 4 -> 17 * SECOND;
+ default ->
+ // go to hell
+ 1000000000;
+ };
+ }
+
+ @Override
+ @NotNull
+ public CheckRecipeResult checkProcessing() {
+ if (!isInit) {
+ initHash();
+ isInit = true;
+ }
+
+ List<ItemStack> tInput = getStoredInputs();
+ List<FluidStack> tInputFluid = getStoredFluids();
+ long availableEUt = getMaxInputVoltage();
+ if (availableEUt < RECIPE_EUT) {
+ return CheckRecipeResultRegistry.insufficientPower(RECIPE_EUT);
+ }
+ if (tInput.isEmpty() || tInputFluid.isEmpty()) {
+ return CheckRecipeResultRegistry.NO_RECIPE;
+ }
+
+ int maxParallel = MAX_PARA;
+ int originalMaxParallel = maxParallel;
+
+ GT_OverclockCalculator calculator = new GT_OverclockCalculator().setEUt(availableEUt)
+ .setRecipeEUt(RECIPE_EUT)
+ .setDuration(getTime(sMode));
+
+ double tickTimeAfterOC = calculator.setParallel(originalMaxParallel)
+ .calculateDurationUnderOneTick();
+
+ if (tickTimeAfterOC < 1) {
+ maxParallel = GT_Utility.safeInt((long) (maxParallel / tickTimeAfterOC), 0);
+ }
+
+ int maxParallelBeforeBatchMode = maxParallel;
+ if (isBatchModeEnabled()) {
+ maxParallel = GT_Utility.safeInt((long) maxParallel * getMaxBatchSize(), 0);
+ }
+
+ int currentParallel = (int) Math.min(maxParallel, availableEUt / RECIPE_EUT);
+ // Calculate parallel by fluids
+ int tLube = 0;
+ int tWater = 0;
+ for (FluidStack fluid : tInputFluid) {
+ if (fluid != null && fluid.equals(GT_ModHandler.getDistilledWater(1L))) {
+ tWater += fluid.amount;
+ } else if (fluid != null && fluid.equals(Materials.Lubricant.getFluid(1L))) {
+ tLube += fluid.amount;
+ }
+ }
+ currentParallel = Math.min(currentParallel, tLube / 2);
+ currentParallel = Math.min(currentParallel, tWater / 200);
+ if (currentParallel <= 0) {
+ return CheckRecipeResultRegistry.NO_RECIPE;
+ }
+
+ // Calculate parallel by items
+ int itemParallel = 0;
+ for (ItemStack ore : tInput) {
+ int tID = GT_Utility.stackToInt(ore);
+ if (tID == 0) continue;
+ if (isPureDust.contains(tID) || isImpureDust.contains(tID)
+ || isCrushedPureOre.contains(tID)
+ || isThermal.contains(tID)
+ || isCrushedOre.contains(tID)
+ || isOre.contains(tID)) {
+ if (itemParallel + ore.stackSize <= currentParallel) {
+ itemParallel += ore.stackSize;
+ } else {
+ itemParallel = currentParallel;
+ break;
+ }
+ }
+ }
+ currentParallel = itemParallel;
+ int currentParallelBeforeBatchMode = Math.min(currentParallel, maxParallelBeforeBatchMode);
+
+ long eutUseAfterOC = calculator
+ .calculateEUtConsumptionUnderOneTick(originalMaxParallel, currentParallelBeforeBatchMode);
+ calculator.setParallel(Math.min(currentParallelBeforeBatchMode, originalMaxParallel))
+ .calculate();
+
+ double batchMultiplierMax = 1;
+ // In case batch mode enabled
+ if (currentParallel > maxParallelBeforeBatchMode && calculator.getDuration() < getMaxBatchSize()) {
+ batchMultiplierMax = (double) getMaxBatchSize() / calculator.getDuration();
+ batchMultiplierMax = Math.min(batchMultiplierMax, (double) currentParallel / maxParallelBeforeBatchMode);
+ }
+
+ int finalParallel = (int) (batchMultiplierMax * maxParallelBeforeBatchMode);
+
+ // for scanner
+ setCurrentParallelism(finalParallel);
+
+ // Consume fluids
+ depleteInput(GT_ModHandler.getDistilledWater(finalParallel * 200L));
+ depleteInput(Materials.Lubricant.getFluid(finalParallel * 2L));
+
+ // Consume items and generate outputs
+ List<ItemStack> tOres = new ArrayList<>();
+ int remainingCost = finalParallel;
+ for (ItemStack ore : tInput) {
+ int tID = GT_Utility.stackToInt(ore);
+ if (tID == 0) continue;
+ if (isPureDust.contains(tID) || isImpureDust.contains(tID)
+ || isCrushedPureOre.contains(tID)
+ || isThermal.contains(tID)
+ || isCrushedOre.contains(tID)
+ || isOre.contains(tID)) {
+ if (remainingCost >= ore.stackSize) {
+ tOres.add(GT_Utility.copy(ore));
+ remainingCost -= ore.stackSize;
+ ore.stackSize = 0;
+ } else {
+ tOres.add(GT_Utility.copyAmountUnsafe(remainingCost, ore));
+ ore.stackSize -= remainingCost;
+ break;
+ }
+ }
+ }
+ sMidProduct = tOres.toArray(new ItemStack[0]);
+ switch (sMode) {
+ case 0 -> {
+ doMac(isOre);
+ doWash(isCrushedOre);
+ doThermal(isCrushedPureOre, isCrushedOre);
+ doMac(isThermal, isOre, isCrushedOre, isCrushedPureOre);
+ }
+ case 1 -> {
+ doMac(isOre);
+ doWash(isCrushedOre);
+ doMac(isOre, isCrushedOre, isCrushedPureOre);
+ doCentrifuge(isImpureDust, isPureDust);
+ }
+ case 2 -> {
+ doMac(isOre);
+ doMac(isThermal, isOre, isCrushedOre, isCrushedPureOre);
+ doCentrifuge(isImpureDust, isPureDust);
+ }
+ case 3 -> {
+ doMac(isOre);
+ doWash(isCrushedOre);
+ doSift(isCrushedPureOre);
+ }
+ case 4 -> {
+ doMac(isOre);
+ doChemWash(isCrushedOre, isCrushedPureOre);
+ doMac(isCrushedOre, isCrushedPureOre);
+ doCentrifuge(isImpureDust, isPureDust);
+ }
+ default -> {
+ return CheckRecipeResultRegistry.NO_RECIPE;
+ }
+ }
+
+ this.mEfficiency = 10000 - (getIdealStatus() - getRepairStatus()) * 1000;
+ this.mEfficiencyIncrease = 10000;
+ this.mOutputItems = sMidProduct;
+ this.mMaxProgresstime = (int) (calculator.getDuration() * batchMultiplierMax);
+ this.lEUt = eutUseAfterOC;
+ if (this.lEUt > 0) {
+ this.lEUt = -this.lEUt;
+ }
+ this.updateSlots();
+
+ return CheckRecipeResultRegistry.SUCCESSFUL;
+ }
+
+ @SafeVarargs
+ private boolean checkTypes(int aID, HashSet<Integer>... aTables) {
+ for (HashSet<Integer> set : aTables) {
+ if (set.contains(aID)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public final void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ if (aPlayer.isSneaking()) {
+ sVoidStone = !sVoidStone;
+ GT_Utility.sendChatToPlayer(
+ aPlayer,
+ StatCollector.translateToLocalFormatted("GT5U.machines.oreprocessor.void", sVoidStone));
+ return;
+ }
+ sMode = (sMode + 1) % 5;
+ List<String> des = getDisplayMode(sMode);
+ GT_Utility.sendChatToPlayer(aPlayer, String.join("", des));
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ sMode = aNBT.getInteger("ssMode");
+ sVoidStone = aNBT.getBoolean("ssStone");
+ currentParallelism = aNBT.getInteger("currentParallelism");
+ super.loadNBTData(aNBT);
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ aNBT.setInteger("ssMode", sMode);
+ aNBT.setBoolean("ssStone", sVoidStone);
+ aNBT.setInteger("currentParallelism", currentParallelism);
+ super.saveNBTData(aNBT);
+ }
+
+ @SafeVarargs
+ private void doMac(HashSet<Integer>... aTables) {
+ List<ItemStack> tProduct = new ArrayList<>();
+ if (sMidProduct != null) {
+ for (ItemStack aStack : sMidProduct) {
+ int tID = GT_Utility.stackToInt(aStack);
+ if (checkTypes(tID, aTables)) {
+ GT_Recipe tRecipe = RecipeMaps.maceratorRecipes
+ .findRecipe(getBaseMetaTileEntity(), false, GT_Values.V[15], null, aStack);
+ if (tRecipe != null) {
+ tProduct.addAll(getOutputStack(tRecipe, aStack.stackSize));
+ } else {
+ tProduct.add(aStack);
+ }
+ } else {
+ tProduct.add(aStack);
+ }
+ }
+ }
+ doCompress(tProduct);
+ }
+
+ @SafeVarargs
+ private void doWash(HashSet<Integer>... aTables) {
+ List<ItemStack> tProduct = new ArrayList<>();
+ if (sMidProduct != null) {
+ for (ItemStack aStack : sMidProduct) {
+ int tID = GT_Utility.stackToInt(aStack);
+ if (checkTypes(tID, aTables)) {
+ GT_Recipe tRecipe = RecipeMaps.oreWasherRecipes.findRecipe(
+ getBaseMetaTileEntity(),
+ false,
+ GT_Values.V[15],
+ new FluidStack[] { GT_ModHandler.getDistilledWater(Integer.MAX_VALUE) },
+ aStack);
+ if (tRecipe != null) {
+ tProduct.addAll(getOutputStack(tRecipe, aStack.stackSize));
+ } else {
+ tProduct.add(aStack);
+ }
+ } else {
+ tProduct.add(aStack);
+ }
+ }
+ }
+ doCompress(tProduct);
+ }
+
+ @SafeVarargs
+ private void doThermal(HashSet<Integer>... aTables) {
+ List<ItemStack> tProduct = new ArrayList<>();
+ if (sMidProduct != null) {
+ for (ItemStack aStack : sMidProduct) {
+ int tID = GT_Utility.stackToInt(aStack);
+ if (checkTypes(tID, aTables)) {
+ GT_Recipe tRecipe = RecipeMaps.thermalCentrifugeRecipes
+ .findRecipe(getBaseMetaTileEntity(), false, GT_Values.V[15], null, aStack);
+ if (tRecipe != null) {
+ tProduct.addAll(getOutputStack(tRecipe, aStack.stackSize));
+ } else {
+ tProduct.add(aStack);
+ }
+ } else {
+ tProduct.add(aStack);
+ }
+ }
+ }
+ doCompress(tProduct);
+ }
+
+ @SafeVarargs
+ private void doCentrifuge(HashSet<Integer>... aTables) {
+ List<ItemStack> tProduct = new ArrayList<>();
+ if (sMidProduct != null) {
+ for (ItemStack aStack : sMidProduct) {
+ int tID = GT_Utility.stackToInt(aStack);
+ if (checkTypes(tID, aTables)) {
+ GT_Recipe tRecipe = RecipeMaps.centrifugeRecipes
+ .findRecipe(getBaseMetaTileEntity(), false, GT_Values.V[15], null, aStack);
+ if (tRecipe != null) {
+ tProduct.addAll(getOutputStack(tRecipe, aStack.stackSize));
+ } else {
+ tProduct.add(aStack);
+ }
+ } else {
+ tProduct.add(aStack);
+ }
+ }
+ }
+ doCompress(tProduct);
+ }
+
+ @SafeVarargs
+ private void doSift(HashSet<Integer>... aTables) {
+ List<ItemStack> tProduct = new ArrayList<>();
+ if (sMidProduct != null) {
+ for (ItemStack aStack : sMidProduct) {
+ int tID = GT_Utility.stackToInt(aStack);
+ if (checkTypes(tID, aTables)) {
+ GT_Recipe tRecipe = RecipeMaps.sifterRecipes
+ .findRecipe(getBaseMetaTileEntity(), false, GT_Values.V[15], null, aStack);
+ if (tRecipe != null) {
+ tProduct.addAll(getOutputStack(tRecipe, aStack.stackSize));
+ } else {
+ tProduct.add(aStack);
+ }
+ } else {
+ tProduct.add(aStack);
+ }
+ }
+ }
+ doCompress(tProduct);
+ }
+
+ @SafeVarargs
+ private void doChemWash(HashSet<Integer>... aTables) {
+ List<ItemStack> tProduct = new ArrayList<>();
+ if (sMidProduct != null) {
+ for (ItemStack aStack : sMidProduct) {
+ int tID = GT_Utility.stackToInt(aStack);
+ if (checkTypes(tID, aTables)) {
+ GT_Recipe tRecipe = RecipeMaps.chemicalBathRecipes.findRecipe(
+ getBaseMetaTileEntity(),
+ false,
+ GT_Values.V[15],
+ getStoredFluids().toArray(new FluidStack[0]),
+ aStack);
+ if (tRecipe != null && tRecipe.getRepresentativeFluidInput(0) != null) {
+ FluidStack tInputFluid = tRecipe.getRepresentativeFluidInput(0)
+ .copy();
+ int tStored = getFluidAmount(tInputFluid);
+ int tWashed = Math.min(tStored / tInputFluid.amount, aStack.stackSize);
+ depleteInput(new FluidStack(tInputFluid.getFluid(), tWashed * tInputFluid.amount));
+ tProduct.addAll(getOutputStack(tRecipe, tWashed));
+ if (tWashed < aStack.stackSize) {
+ tProduct.add(GT_Utility.copyAmountUnsafe(aStack.stackSize - tWashed, aStack));
+ }
+ } else {
+ tProduct.add(aStack);
+ }
+ } else {
+ tProduct.add(aStack);
+ }
+ }
+ }
+ doCompress(tProduct);
+ }
+
+ private int getFluidAmount(FluidStack aFluid) {
+ int tAmt = 0;
+ if (aFluid == null) return 0;
+ for (FluidStack fluid : getStoredFluids()) {
+ if (aFluid.isFluidEqual(fluid)) {
+ tAmt += fluid.amount;
+ }
+ }
+ return tAmt;
+ }
+
+ private List<ItemStack> getOutputStack(GT_Recipe aRecipe, int aTime) {
+ List<ItemStack> tOutput = new ArrayList<>();
+ for (int i = 0; i < aRecipe.mOutputs.length; i++) {
+ if (aRecipe.getOutput(i) == null) {
+ continue;
+ }
+ int tChance = aRecipe.getOutputChance(i);
+ if (tChance == 10000) {
+ tOutput.add(GT_Utility.copyAmountUnsafe(aTime * aRecipe.getOutput(i).stackSize, aRecipe.getOutput(i)));
+ } else {
+ // Use Normal Distribution
+ double u = aTime * (tChance / 10000D);
+ double e = aTime * (tChance / 10000D) * (1 - (tChance / 10000D));
+ Random random = new Random();
+ int tAmount = (int) Math.ceil(Math.sqrt(e) * random.nextGaussian() + u);
+ tOutput
+ .add(GT_Utility.copyAmountUnsafe(tAmount * aRecipe.getOutput(i).stackSize, aRecipe.getOutput(i)));
+ }
+ }
+ return tOutput.stream()
+ .filter(i -> (i != null && i.stackSize > 0))
+ .collect(Collectors.toList());
+ }
+
+ private void doCompress(List<ItemStack> aList) {
+ HashMap<Integer, Integer> rProduct = new HashMap<>();
+ for (ItemStack stack : aList) {
+ int tID = GT_Utility.stackToInt(stack);
+ if (sVoidStone) {
+ if (GT_Utility.areStacksEqual(Materials.Stone.getDust(1), stack)) {
+ continue;
+ }
+ }
+ if (tID != 0) {
+ if (rProduct.containsKey(tID)) {
+ rProduct.put(tID, rProduct.get(tID) + stack.stackSize);
+ } else {
+ rProduct.put(tID, stack.stackSize);
+ }
+ }
+ }
+ sMidProduct = new ItemStack[rProduct.size()];
+ int cnt = 0;
+ for (Integer id : rProduct.keySet()) {
+ ItemStack stack = GT_Utility.intToStack(id);
+ sMidProduct[cnt] = GT_Utility.copyAmountUnsafe(rProduct.get(id), stack);
+ cnt++;
+ }
+ }
+
+ @Override
+ public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+ return checkPiece(STRUCTURE_PIECE_MAIN, 8, 9, 1) && mMaintenanceHatches.size() <= 1
+ && !mMufflerHatches.isEmpty();
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack aStack) {
+ return 10000;
+ }
+
+ @Override
+ public int getDamageToComponent(ItemStack aStack) {
+ return 0;
+ }
+
+ @Override
+ public int getPollutionPerSecond(ItemStack aStack) {
+ return 200;
+ }
+
+ @Override
+ public boolean explodesOnComponentBreak(ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_IntegratedOreFactory(mName);
+ }
+
+ private void setCurrentParallelism(int parallelism) {
+ this.currentParallelism = parallelism;
+ }
+
+ private int getCurrentParallelism() {
+ return this.currentParallelism;
+ }
+
+ @Override
+ public String[] getInfoData() {
+ List<String> informationData = new ArrayList<>(Arrays.asList(super.getInfoData()));
+ String parallelism = StatCollector.translateToLocal("GT5U.multiblock.parallelism") + ": "
+ + EnumChatFormatting.BLUE
+ + getCurrentParallelism()
+ + EnumChatFormatting.RESET;
+ informationData.add(parallelism);
+ informationData.add(StatCollector.translateToLocalFormatted("GT5U.machines.oreprocessor.void", sVoidStone));
+ informationData.addAll(getDisplayMode(sMode));
+ return informationData.toArray(new String[0]);
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection aFacing,
+ int colorIndex, boolean aActive, boolean redstoneLevel) {
+ if (side == aFacing) {
+ if (aActive) return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(CASING_INDEX2),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_PROCESSING_ARRAY_ACTIVE)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_PROCESSING_ARRAY_ACTIVE_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(CASING_INDEX2), TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_PROCESSING_ARRAY)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_PROCESSING_ARRAY_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ }
+ return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(CASING_INDEX2) };
+ }
+
+ private static List<String> getDisplayMode(int mode) {
+ final EnumChatFormatting AQUA = EnumChatFormatting.AQUA;
+ final String CRUSH = StatCollector.translateToLocalFormatted("GT5U.machines.oreprocessor.Macerate");
+ final String WASH = StatCollector.translateToLocalFormatted("GT5U.machines.oreprocessor.Ore_Washer")
+ .replace(" ", " " + AQUA);
+ final String THERMAL = StatCollector.translateToLocalFormatted("GT5U.machines.oreprocessor.Thermal_Centrifuge")
+ .replace(" ", " " + AQUA);
+ final String CENTRIFUGE = StatCollector.translateToLocalFormatted("GT5U.machines.oreprocessor.Centrifuge");
+ final String SIFTER = StatCollector.translateToLocalFormatted("GT5U.machines.oreprocessor.Sifter");
+ final String CHEM_WASH = StatCollector.translateToLocalFormatted("GT5U.machines.oreprocessor.Chemical_Bathing")
+ .replace(" ", " " + AQUA);
+ final String ARROW = " " + AQUA + "-> ";
+
+ List<String> des = new ArrayList<>();
+ des.add(StatCollector.translateToLocalFormatted("GT5U.machines.oreprocessor1") + " ");
+
+ switch (mode) {
+ case 0 -> {
+ des.add(AQUA + CRUSH + ARROW);
+ des.add(AQUA + WASH + ARROW);
+ des.add(AQUA + THERMAL + ARROW);
+ des.add(AQUA + CRUSH + ' ');
+ }
+ case 1 -> {
+ des.add(AQUA + CRUSH + ARROW);
+ des.add(AQUA + WASH + ARROW);
+ des.add(AQUA + CRUSH + ARROW);
+ des.add(AQUA + CENTRIFUGE + ' ');
+ }
+ case 2 -> {
+ des.add(AQUA + CRUSH + ARROW);
+ des.add(AQUA + CRUSH + ARROW);
+ des.add(AQUA + CENTRIFUGE + ' ');
+ }
+ case 3 -> {
+ des.add(AQUA + CRUSH + ARROW);
+ des.add(AQUA + WASH + ARROW);
+ des.add(AQUA + SIFTER + ' ');
+ }
+ case 4 -> {
+ des.add(AQUA + CRUSH + ARROW);
+ des.add(AQUA + CHEM_WASH + ARROW);
+ des.add(AQUA + CRUSH + ARROW);
+ des.add(AQUA + CENTRIFUGE + ' ');
+ }
+ default -> des.add(StatCollector.translateToLocalFormatted("GT5U.machines.oreprocessor.WRONG_MODE"));
+ }
+
+ des.add(StatCollector.translateToLocalFormatted("GT5U.machines.oreprocessor2", getTime(mode) / 20));
+
+ return des;
+
+ }
+
+ @Override
+ public void getWailaBody(ItemStack itemStack, List<String> currenttip, IWailaDataAccessor accessor,
+ IWailaConfigHandler config) {
+ super.getWailaBody(itemStack, currenttip, accessor, config);
+ NBTTagCompound tag = accessor.getNBTData();
+
+ currenttip.add(
+ StatCollector.translateToLocal("GT5U.multiblock.parallelism") + ": "
+ + EnumChatFormatting.BLUE
+ + tag.getInteger("currentParallelism")
+ + EnumChatFormatting.RESET);
+ currenttip.addAll(getDisplayMode(tag.getInteger("ssMode")));
+ currenttip
+ .add(StatCollector.translateToLocalFormatted("GT5U.machines.oreprocessor.void", tag.getBoolean("ssStone")));
+
+ }
+
+ @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("ssMode", sMode);
+ tag.setBoolean("ssStone", sVoidStone);
+ tag.setInteger("currentParallelism", currentParallelism);
+ }
+
+ @Override
+ public boolean supportsBatchMode() {
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeBoiler.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeBoiler.java
new file mode 100644
index 0000000000..ae740447c8
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeBoiler.java
@@ -0,0 +1,504 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.lazy;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.onElementPass;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.transpose;
+import static gregtech.api.enums.GT_HatchElement.InputBus;
+import static gregtech.api.enums.GT_HatchElement.InputHatch;
+import static gregtech.api.enums.GT_HatchElement.Maintenance;
+import static gregtech.api.enums.GT_HatchElement.Muffler;
+import static gregtech.api.enums.GT_HatchElement.OutputHatch;
+import static gregtech.api.enums.GT_Values.STEAM_PER_WATER;
+import static gregtech.api.enums.ItemList.Circuit_Integrated;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_LARGE_BOILER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_LARGE_BOILER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_LARGE_BOILER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_LARGE_BOILER_GLOW;
+import static gregtech.api.util.GT_StructureUtility.buildHatchAdder;
+import static gregtech.api.util.GT_Utility.formatNumbers;
+
+import java.util.ArrayList;
+
+import net.minecraft.block.Block;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidRegistry;
+import net.minecraftforge.fluids.FluidStack;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+
+import gregtech.GT_Mod;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.enums.Textures;
+import gregtech.api.enums.Textures.BlockIcons;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_EnhancedMultiBlockBase;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.recipe.maps.LargeBoilerFuelBackend;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Log;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_OreDictUnificator;
+import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.GT_Utility;
+
+public abstract class GT_MetaTileEntity_LargeBoiler
+ extends GT_MetaTileEntity_EnhancedMultiBlockBase<GT_MetaTileEntity_LargeBoiler> implements ISurvivalConstructable {
+
+ private static final String STRUCTURE_PIECE_MAIN = "main";
+ private static final ClassValue<IStructureDefinition<GT_MetaTileEntity_LargeBoiler>> STRUCTURE_DEFINITION = new ClassValue<>() {
+
+ @Override
+ protected IStructureDefinition<GT_MetaTileEntity_LargeBoiler> computeValue(Class<?> type) {
+ return StructureDefinition.<GT_MetaTileEntity_LargeBoiler>builder()
+ .addShape(
+ STRUCTURE_PIECE_MAIN,
+ transpose(
+ new String[][] { { "ccc", "ccc", "ccc" }, { "ccc", "cPc", "ccc" }, { "ccc", "cPc", "ccc" },
+ { "ccc", "cPc", "ccc" }, { "f~f", "fff", "fff" }, }))
+ .addElement('P', lazy(t -> ofBlock(t.getPipeBlock(), t.getPipeMeta())))
+ .addElement(
+ 'c',
+ lazy(
+ t -> buildHatchAdder(GT_MetaTileEntity_LargeBoiler.class).atLeast(OutputHatch)
+ .casingIndex(t.getCasingTextureIndex())
+ .dot(2)
+ .buildAndChain(
+ onElementPass(
+ GT_MetaTileEntity_LargeBoiler::onCasingAdded,
+ ofBlock(t.getCasingBlock(), t.getCasingMeta())))))
+ .addElement(
+ 'f',
+ lazy(
+ t -> buildHatchAdder(GT_MetaTileEntity_LargeBoiler.class)
+ .atLeast(Maintenance, InputHatch, InputBus, Muffler)
+ .casingIndex(t.getFireboxTextureIndex())
+ .dot(1)
+ .buildAndChain(
+ onElementPass(
+ GT_MetaTileEntity_LargeBoiler::onFireboxAdded,
+ ofBlock(t.getFireboxBlock(), t.getFireboxMeta())))))
+ .build();
+ }
+ };
+ private boolean firstRun = true;
+ private int mSuperEfficencyIncrease = 0;
+ private int integratedCircuitConfig = 0; // Steam output is reduced by 1000L per config
+ private int excessWater = 0; // Eliminate rounding errors for water
+ private int excessFuel = 0; // Eliminate rounding errors for fuels that burn half items
+ private int excessProjectedEU = 0; // Eliminate rounding errors from throttling the boiler
+ private int mCasingAmount;
+ private int mFireboxAmount;
+ protected int pollutionPerSecond = 1; // placeholder for the child classes
+
+ public GT_MetaTileEntity_LargeBoiler(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_LargeBoiler(String aName) {
+ super(aName);
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+
+ tt.addMachineType("Boiler")
+ .addInfo("Controller block for the Large " + getCasingMaterial() + " Boiler");
+ // Tooltip differs between the boilers that output Superheated Steam (Titanium and Tungstensteel) and the ones
+ // that do not (Bronze and Steel)
+ if (isSuperheated()) {
+ tt.addInfo(
+ "Produces " + formatNumbers((getEUt() * 40) * ((runtimeBoost(20) / (20f)) / superToNormalSteam))
+ + "L of Superheated Steam with 1 Coal at "
+ + formatNumbers((getEUt() * 40L) / superToNormalSteam)
+ + "L/s") // ?
+ .addInfo("A programmed circuit in the main block throttles the boiler (-1000L/s per config)")
+ .addInfo("Only some solid fuels are allowed (check the NEI Large Boiler tab for details)")
+ .addInfo("If there are any disallowed fuels in the input bus, the boiler won't run!");
+ } else {
+ tt.addInfo(
+ "Produces " + formatNumbers((getEUt() * 40) * (runtimeBoost(20) / 20f))
+ + "L of Steam with 1 Coal at "
+ + formatNumbers(getEUt() * 40L)
+ + "L/s") // ?
+ .addInfo("A programmed circuit in the main block throttles the boiler (-1000L/s per config)")
+ .addInfo("Solid Fuels with a burn value that is too high or too low will not work");
+ }
+ tt.addInfo(
+ String.format(
+ "Diesel fuels have 1/4 efficiency - Takes %s seconds to heat up",
+ formatNumbers(500.0 / getEfficiencyIncrease()))) // ? check semifluid again
+ .addPollutionAmount(getPollutionPerSecond(null))
+ .addSeparator()
+ .beginStructureBlock(3, 5, 3, false)
+ .addController("Front bottom")
+ .addCasingInfoRange(getCasingMaterial() + " " + getCasingBlockType() + " Casing", 24, 31, false) // ?
+ .addOtherStructurePart(getCasingMaterial() + " Fire Boxes", "Bottom layer, 3 minimum")
+ .addOtherStructurePart(getCasingMaterial() + " Pipe Casing Blocks", "Inner 3 blocks")
+ .addMaintenanceHatch("Any firebox", 1)
+ .addMufflerHatch("Any firebox", 1)
+ .addInputBus("Solid fuel, Any firebox", 1)
+ .addInputHatch("Liquid fuel, Any firebox", 1)
+ .addStructureInfo("You can use either, or both")
+ .addInputHatch("Water, Any firebox", 1)
+ .addOutputHatch("Steam, any casing", 2)
+ .toolTipFinisher("Gregtech");
+
+ return tt;
+ }
+
+ public abstract String getCasingMaterial();
+
+ public abstract Block getCasingBlock();
+
+ public abstract String getCasingBlockType();
+
+ public abstract byte getCasingMeta();
+
+ public abstract byte getCasingTextureIndex();
+
+ public abstract Block getPipeBlock();
+
+ public abstract byte getPipeMeta();
+
+ public abstract Block getFireboxBlock();
+
+ public abstract byte getFireboxMeta();
+
+ public abstract byte getFireboxTextureIndex();
+
+ public abstract int getEUt();
+
+ public abstract int getEfficiencyIncrease();
+
+ public int getIntegratedCircuitConfig() {
+ return integratedCircuitConfig;
+ }
+
+ @Override
+ public int getPollutionPerSecond(ItemStack aStack) {
+ // allows for 0 pollution if circuit throttle is too high
+ return Math.max(
+ 0,
+ (int) (pollutionPerSecond
+ * (1 - GT_Mod.gregtechproxy.mPollutionReleasedByThrottle * getIntegratedCircuitConfig())));
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection aFacing,
+ int colorIndex, boolean aActive, boolean redstoneLevel) {
+ if (side == aFacing) {
+ if (aActive) return new ITexture[] { BlockIcons.getCasingTextureForId(getCasingTextureIndex()),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_LARGE_BOILER_ACTIVE)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_LARGE_BOILER_ACTIVE_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ return new ITexture[] { BlockIcons.getCasingTextureForId(getCasingTextureIndex()), TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_LARGE_BOILER)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_LARGE_BOILER_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ }
+ return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(getCasingTextureIndex()) };
+ }
+
+ @Override
+ public boolean isCorrectMachinePart(ItemStack aStack) {
+ return true;
+ }
+
+ boolean isFuelValid() {
+ if (!isSuperheated()) return true;
+ for (ItemStack input : getStoredInputs()) {
+ if (!LargeBoilerFuelBackend.isAllowedSolidFuel(input)
+ && !Circuit_Integrated.isStackEqual(input, true, true)) {
+ // if any item is not in ALLOWED_SOLID_FUELS, operation cannot be allowed because it might still be
+ // consumed
+ this.mMaxProgresstime = 0;
+ this.mEUt = 0;
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ // Only for visual
+ return RecipeMaps.largeBoilerFakeFuels;
+ }
+
+ @Override
+ protected boolean filtersFluid() {
+ return false;
+ }
+
+ @Override
+ @NotNull
+ public CheckRecipeResult checkProcessing() {
+ if (!isFuelValid()) return CheckRecipeResultRegistry.NO_FUEL_FOUND;
+ // Do we have an integrated circuit with a valid configuration?
+ if (Circuit_Integrated.isStackEqual(mInventory[1], true, true)) {
+ int circuit_config = mInventory[1].getItemDamage();
+ if (circuit_config >= 1 && circuit_config <= 25) {
+ // If so, overwrite the current config
+ this.integratedCircuitConfig = circuit_config;
+ }
+ } else {
+ // If not, set the config to zero
+ this.integratedCircuitConfig = 0;
+ }
+
+ this.mSuperEfficencyIncrease = 0;
+ if (!isSuperheated()) {
+ for (GT_Recipe tRecipe : RecipeMaps.dieselFuels.getAllRecipes()) {
+ FluidStack tFluid = GT_Utility.getFluidForFilledItem(tRecipe.getRepresentativeInput(0), true);
+ if (tFluid != null && tRecipe.mSpecialValue > 1) {
+ tFluid.amount = 1000;
+ if (depleteInput(tFluid)) {
+ this.mMaxProgresstime = adjustBurnTimeForConfig(runtimeBoost(tRecipe.mSpecialValue / 2));
+ this.mEUt = adjustEUtForConfig(getEUt());
+ this.mEfficiencyIncrease = this.mMaxProgresstime * getEfficiencyIncrease() * 4;
+ return CheckRecipeResultRegistry.SUCCESSFUL;
+ }
+ }
+ }
+ for (GT_Recipe tRecipe : RecipeMaps.denseLiquidFuels.getAllRecipes()) {
+ FluidStack tFluid = GT_Utility.getFluidForFilledItem(tRecipe.getRepresentativeInput(0), true);
+ if (tFluid != null) {
+ tFluid.amount = 1000;
+ if (depleteInput(tFluid)) {
+ this.mMaxProgresstime = adjustBurnTimeForConfig(
+ Math.max(1, runtimeBoost(tRecipe.mSpecialValue * 2)));
+ this.mEUt = adjustEUtForConfig(getEUt());
+ this.mEfficiencyIncrease = this.mMaxProgresstime * getEfficiencyIncrease();
+ return CheckRecipeResultRegistry.SUCCESSFUL;
+ }
+ }
+ }
+ }
+
+ ArrayList<ItemStack> tInputList = getStoredInputs();
+ if (!tInputList.isEmpty()) {
+ if (isSuperheated()) {
+ for (ItemStack tInput : tInputList) {
+ if (tInput != GT_OreDictUnificator.get(OrePrefixes.bucket, Materials.Lava, 1)) {
+ if (GT_Utility.getFluidForFilledItem(tInput, true) == null
+ && (this.mMaxProgresstime = GT_ModHandler.getFuelValue(tInput) / 80) > 0) {
+ this.excessFuel += GT_ModHandler.getFuelValue(tInput) % 80;
+ this.mMaxProgresstime += this.excessFuel / 80;
+ this.excessFuel %= 80;
+ this.mMaxProgresstime = adjustBurnTimeForConfig(runtimeBoost(this.mMaxProgresstime));
+ this.mEUt = adjustEUtForConfig(getEUt());
+ this.mEfficiencyIncrease = this.mMaxProgresstime * getEfficiencyIncrease();
+ this.mOutputItems = new ItemStack[] { GT_Utility.getContainerItem(tInput, true) };
+ tInput.stackSize -= 1;
+ updateSlots();
+ if (this.mEfficiencyIncrease > 5000) {
+ this.mEfficiencyIncrease = 0;
+ this.mSuperEfficencyIncrease = 20;
+ }
+ return CheckRecipeResultRegistry.SUCCESSFUL;
+ }
+ }
+ }
+ } else {
+ for (ItemStack tInput : tInputList) {
+ if (tInput != GT_OreDictUnificator.get(OrePrefixes.bucket, Materials.Lava, 1)) {
+ // Solid fuels with burn values below getEUt are ignored (mostly items like sticks), and also
+ // those with very high fuel values that would cause an overflow error.
+ if (GT_Utility.getFluidForFilledItem(tInput, true) == null
+ && (this.mMaxProgresstime = GT_ModHandler.getFuelValue(tInput) / 80) > 0
+ && (GT_ModHandler.getFuelValue(tInput) * 2 / this.getEUt()) > 1
+ && GT_ModHandler.getFuelValue(tInput) < 100000000) {
+ this.excessFuel += GT_ModHandler.getFuelValue(tInput) % 80;
+ this.mMaxProgresstime += this.excessFuel / 80;
+ this.excessFuel %= 80;
+ this.mMaxProgresstime = adjustBurnTimeForConfig(runtimeBoost(this.mMaxProgresstime));
+ this.mEUt = adjustEUtForConfig(getEUt());
+ this.mEfficiencyIncrease = this.mMaxProgresstime * getEfficiencyIncrease();
+ this.mOutputItems = new ItemStack[] { GT_Utility.getContainerItem(tInput, true) };
+ tInput.stackSize -= 1;
+ updateSlots();
+ if (this.mEfficiencyIncrease > 5000) {
+ this.mEfficiencyIncrease = 0;
+ this.mSuperEfficencyIncrease = 20;
+ }
+ return CheckRecipeResultRegistry.SUCCESSFUL;
+ }
+ }
+ }
+ }
+ }
+ this.mMaxProgresstime = 0;
+ this.mEUt = 0;
+ return CheckRecipeResultRegistry.NO_FUEL_FOUND;
+ }
+
+ abstract int runtimeBoost(int mTime);
+
+ abstract boolean isSuperheated();
+
+ private final int superToNormalSteam = 3;
+
+ @Override
+ public boolean onRunningTick(ItemStack aStack) {
+ if (this.mEUt > 0) {
+ if (this.mSuperEfficencyIncrease > 0) mEfficiency = Math.max(
+ 0,
+ Math.min(
+ mEfficiency + mSuperEfficencyIncrease,
+ getMaxEfficiency(mInventory[1]) - ((getIdealStatus() - getRepairStatus()) * 1000)));
+ int tGeneratedEU = (int) (this.mEUt * 2L * this.mEfficiency / 10000L);
+ if (tGeneratedEU > 0) {
+ long amount = (tGeneratedEU + STEAM_PER_WATER) / STEAM_PER_WATER;
+ excessWater += amount * STEAM_PER_WATER - tGeneratedEU;
+ amount -= excessWater / STEAM_PER_WATER;
+ excessWater %= STEAM_PER_WATER;
+ startRecipeProcessing();
+ if (isSuperheated()) {
+ // Consumes only one third of the water if producing Superheated Steam, to maintain water in the
+ // chain.
+ if (depleteInput(Materials.Water.getFluid(amount / superToNormalSteam))
+ || depleteInput(GT_ModHandler.getDistilledWater(amount / superToNormalSteam))) {
+ // Outputs Superheated Steam instead of Steam, at one third of the amount (equivalent in power
+ // output to the normal Steam amount).
+ addOutput(
+ FluidRegistry.getFluidStack("ic2superheatedsteam", tGeneratedEU / superToNormalSteam));
+ } else {
+ GT_Log.exp.println("Boiler " + this.mName + " had no Water!");
+ explodeMultiblock();
+ }
+ } else {
+ if (depleteInput(Materials.Water.getFluid(amount))
+ || depleteInput(GT_ModHandler.getDistilledWater(amount))) {
+ addOutput(GT_ModHandler.getSteam(tGeneratedEU));
+ } else {
+ GT_Log.exp.println("Boiler " + this.mName + " had no Water!");
+ explodeMultiblock();
+ }
+ }
+ endRecipeProcessing();
+ }
+ return true;
+ }
+ return true;
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ aNBT.setInteger("excessFuel", excessFuel);
+ aNBT.setInteger("excessWater", excessWater);
+ aNBT.setInteger("excessProjectedEU", excessProjectedEU);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ excessFuel = aNBT.getInteger("excessFuel");
+ excessWater = aNBT.getInteger("excessWater");
+ excessProjectedEU = aNBT.getInteger("excessProjectedEU");
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ if (mProgresstime > 0 && firstRun) {
+ firstRun = false;
+ GT_Mod.achievements.issueAchievement(
+ aBaseMetaTileEntity.getWorld()
+ .getPlayerEntityByName(aBaseMetaTileEntity.getOwnerName()),
+ "extremepressure");
+ }
+ super.onPostTick(aBaseMetaTileEntity, aTick);
+ }
+
+ @Override
+ public IStructureDefinition<GT_MetaTileEntity_LargeBoiler> getStructureDefinition() {
+ return STRUCTURE_DEFINITION.get(getClass());
+ }
+
+ private void onCasingAdded() {
+ mCasingAmount++;
+ }
+
+ private void onFireboxAdded() {
+ mFireboxAmount++;
+ }
+
+ @Override
+ public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+ mCasingAmount = 0;
+ mFireboxAmount = 0;
+ return checkPiece(STRUCTURE_PIECE_MAIN, 1, 4, 0) && mCasingAmount >= 24
+ && mFireboxAmount >= 3
+ && mMaintenanceHatches.size() == 1
+ && !mMufflerHatches.isEmpty();
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack aStack) {
+ return 10000;
+ }
+
+ @Override
+ public int getDamageToComponent(ItemStack aStack) {
+ return 0;
+ }
+
+ @Override
+ public boolean explodesOnComponentBreak(ItemStack aStack) {
+ return false;
+ }
+
+ private int adjustEUtForConfig(int rawEUt) {
+ int adjustedSteamOutput = rawEUt - (isSuperheated() ? 75 : 25) * integratedCircuitConfig;
+ return Math.max(adjustedSteamOutput, 25);
+ }
+
+ private int adjustBurnTimeForConfig(int rawBurnTime) {
+ if (mEfficiency < getMaxEfficiency(mInventory[1]) - ((getIdealStatus() - getRepairStatus()) * 1000)) {
+ return rawBurnTime;
+ }
+ int adjustedEUt = Math.max(25, getEUt() - (isSuperheated() ? 75 : 25) * integratedCircuitConfig);
+ int adjustedBurnTime = rawBurnTime * getEUt() / adjustedEUt;
+ this.excessProjectedEU += getEUt() * rawBurnTime - adjustedEUt * adjustedBurnTime;
+ adjustedBurnTime += this.excessProjectedEU / adjustedEUt;
+ this.excessProjectedEU %= adjustedEUt;
+ return adjustedBurnTime;
+ }
+
+ @Override
+ public void construct(ItemStack stackSize, boolean hintsOnly) {
+ buildPiece(STRUCTURE_PIECE_MAIN, stackSize, hintsOnly, 1, 4, 0);
+ }
+
+ @Override
+ public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
+ if (mMachine) return -1;
+ return survivialBuildPiece(STRUCTURE_PIECE_MAIN, stackSize, 1, 4, 0, elementBudget, env, false, true);
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeBoiler_Bronze.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeBoiler_Bronze.java
new file mode 100644
index 0000000000..2effcf7966
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeBoiler_Bronze.java
@@ -0,0 +1,96 @@
+package gregtech.common.tileentities.machines.multi;
+
+import net.minecraft.block.Block;
+
+import gregtech.GT_Mod;
+import gregtech.api.GregTech_API;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+
+public class GT_MetaTileEntity_LargeBoiler_Bronze extends GT_MetaTileEntity_LargeBoiler {
+
+ public GT_MetaTileEntity_LargeBoiler_Bronze(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ pollutionPerSecond = GT_Mod.gregtechproxy.mPollutionLargeBronzeBoilerPerSecond;
+ }
+
+ public GT_MetaTileEntity_LargeBoiler_Bronze(String aName) {
+ super(aName);
+ pollutionPerSecond = GT_Mod.gregtechproxy.mPollutionLargeBronzeBoilerPerSecond;
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_LargeBoiler_Bronze(this.mName);
+ }
+
+ @Override
+ public String getCasingMaterial() {
+ return "Bronze";
+ }
+
+ @Override
+ public String getCasingBlockType() {
+ return "Plated Bricks";
+ }
+
+ @Override
+ public Block getCasingBlock() {
+ return GregTech_API.sBlockCasings1;
+ }
+
+ @Override
+ public byte getCasingMeta() {
+ return 10;
+ }
+
+ @Override
+ public byte getCasingTextureIndex() {
+ return 10;
+ }
+
+ @Override
+ public Block getPipeBlock() {
+ return GregTech_API.sBlockCasings2;
+ }
+
+ @Override
+ public byte getPipeMeta() {
+ return 12;
+ }
+
+ @Override
+ public Block getFireboxBlock() {
+ return GregTech_API.sBlockCasings3;
+ }
+
+ @Override
+ public byte getFireboxMeta() {
+ return 13;
+ }
+
+ @Override
+ public byte getFireboxTextureIndex() {
+ return 45;
+ }
+
+ @Override
+ public int getEUt() {
+ return 400;
+ }
+
+ @Override
+ public int getEfficiencyIncrease() {
+ return 16;
+ }
+
+ @Override
+ int runtimeBoost(int mTime) {
+ return mTime * 2;
+ }
+
+ @Override
+ boolean isSuperheated() {
+ return false;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeBoiler_Steel.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeBoiler_Steel.java
new file mode 100644
index 0000000000..c7bd766945
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeBoiler_Steel.java
@@ -0,0 +1,96 @@
+package gregtech.common.tileentities.machines.multi;
+
+import net.minecraft.block.Block;
+
+import gregtech.GT_Mod;
+import gregtech.api.GregTech_API;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+
+public class GT_MetaTileEntity_LargeBoiler_Steel extends GT_MetaTileEntity_LargeBoiler {
+
+ public GT_MetaTileEntity_LargeBoiler_Steel(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ pollutionPerSecond = GT_Mod.gregtechproxy.mPollutionLargeSteelBoilerPerSecond;
+ }
+
+ public GT_MetaTileEntity_LargeBoiler_Steel(String aName) {
+ super(aName);
+ pollutionPerSecond = GT_Mod.gregtechproxy.mPollutionLargeSteelBoilerPerSecond;
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_LargeBoiler_Steel(this.mName);
+ }
+
+ @Override
+ public String getCasingMaterial() {
+ return "Steel";
+ }
+
+ @Override
+ public String getCasingBlockType() {
+ return "Machine Casings";
+ }
+
+ @Override
+ public Block getCasingBlock() {
+ return GregTech_API.sBlockCasings2;
+ }
+
+ @Override
+ public byte getCasingMeta() {
+ return 0;
+ }
+
+ @Override
+ public byte getCasingTextureIndex() {
+ return 16;
+ }
+
+ @Override
+ public Block getPipeBlock() {
+ return GregTech_API.sBlockCasings2;
+ }
+
+ @Override
+ public byte getPipeMeta() {
+ return 13;
+ }
+
+ @Override
+ public Block getFireboxBlock() {
+ return GregTech_API.sBlockCasings3;
+ }
+
+ @Override
+ public byte getFireboxMeta() {
+ return 14;
+ }
+
+ @Override
+ public byte getFireboxTextureIndex() {
+ return 46;
+ }
+
+ @Override
+ public int getEUt() {
+ return 1000;
+ }
+
+ @Override
+ public int getEfficiencyIncrease() {
+ return 12;
+ }
+
+ @Override
+ int runtimeBoost(int mTime) {
+ return mTime;
+ }
+
+ @Override
+ boolean isSuperheated() {
+ return false;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeBoiler_Titanium.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeBoiler_Titanium.java
new file mode 100644
index 0000000000..61f2756622
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeBoiler_Titanium.java
@@ -0,0 +1,96 @@
+package gregtech.common.tileentities.machines.multi;
+
+import net.minecraft.block.Block;
+
+import gregtech.GT_Mod;
+import gregtech.api.GregTech_API;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+
+public class GT_MetaTileEntity_LargeBoiler_Titanium extends GT_MetaTileEntity_LargeBoiler {
+
+ public GT_MetaTileEntity_LargeBoiler_Titanium(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ pollutionPerSecond = GT_Mod.gregtechproxy.mPollutionLargeTitaniumBoilerPerSecond;
+ }
+
+ public GT_MetaTileEntity_LargeBoiler_Titanium(String aName) {
+ super(aName);
+ pollutionPerSecond = GT_Mod.gregtechproxy.mPollutionLargeTitaniumBoilerPerSecond;
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_LargeBoiler_Titanium(this.mName);
+ }
+
+ @Override
+ public String getCasingMaterial() {
+ return "Titanium";
+ }
+
+ @Override
+ public String getCasingBlockType() {
+ return "Machine Casings";
+ }
+
+ @Override
+ public Block getCasingBlock() {
+ return GregTech_API.sBlockCasings4;
+ }
+
+ @Override
+ public byte getCasingMeta() {
+ return 2;
+ }
+
+ @Override
+ public byte getCasingTextureIndex() {
+ return 50;
+ }
+
+ @Override
+ public Block getPipeBlock() {
+ return GregTech_API.sBlockCasings2;
+ }
+
+ @Override
+ public byte getPipeMeta() {
+ return 14;
+ }
+
+ @Override
+ public Block getFireboxBlock() {
+ return GregTech_API.sBlockCasings4;
+ }
+
+ @Override
+ public byte getFireboxMeta() {
+ return 3;
+ }
+
+ @Override
+ public byte getFireboxTextureIndex() {
+ return 51;
+ }
+
+ @Override
+ public int getEUt() {
+ return 4000;
+ }
+
+ @Override
+ public int getEfficiencyIncrease() {
+ return 8;
+ }
+
+ @Override
+ int runtimeBoost(int mTime) {
+ return mTime * 130 / 400;
+ }
+
+ @Override
+ boolean isSuperheated() {
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeBoiler_TungstenSteel.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeBoiler_TungstenSteel.java
new file mode 100644
index 0000000000..f00ea287b2
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeBoiler_TungstenSteel.java
@@ -0,0 +1,96 @@
+package gregtech.common.tileentities.machines.multi;
+
+import net.minecraft.block.Block;
+
+import gregtech.GT_Mod;
+import gregtech.api.GregTech_API;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+
+public class GT_MetaTileEntity_LargeBoiler_TungstenSteel extends GT_MetaTileEntity_LargeBoiler {
+
+ public GT_MetaTileEntity_LargeBoiler_TungstenSteel(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ pollutionPerSecond = GT_Mod.gregtechproxy.mPollutionLargeTungstenSteelBoilerPerSecond;
+ }
+
+ public GT_MetaTileEntity_LargeBoiler_TungstenSteel(String aName) {
+ super(aName);
+ pollutionPerSecond = GT_Mod.gregtechproxy.mPollutionLargeTungstenSteelBoilerPerSecond;
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_LargeBoiler_TungstenSteel(this.mName);
+ }
+
+ @Override
+ public String getCasingMaterial() {
+ return "TungstenSteel";
+ }
+
+ @Override
+ public String getCasingBlockType() {
+ return "Machine Casings";
+ }
+
+ @Override
+ public Block getCasingBlock() {
+ return GregTech_API.sBlockCasings4;
+ }
+
+ @Override
+ public byte getCasingMeta() {
+ return 0;
+ }
+
+ @Override
+ public byte getCasingTextureIndex() {
+ return 48;
+ }
+
+ @Override
+ public Block getPipeBlock() {
+ return GregTech_API.sBlockCasings2;
+ }
+
+ @Override
+ public byte getPipeMeta() {
+ return 15;
+ }
+
+ @Override
+ public Block getFireboxBlock() {
+ return GregTech_API.sBlockCasings3;
+ }
+
+ @Override
+ public byte getFireboxMeta() {
+ return 15;
+ }
+
+ @Override
+ public byte getFireboxTextureIndex() {
+ return 47;
+ }
+
+ @Override
+ public int getEUt() {
+ return 16000;
+ }
+
+ @Override
+ public int getEfficiencyIncrease() {
+ return 4;
+ }
+
+ @Override
+ int runtimeBoost(int mTime) {
+ return mTime * 120 / 750;
+ }
+
+ @Override
+ boolean isSuperheated() {
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeChemicalReactor.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeChemicalReactor.java
new file mode 100644
index 0000000000..8e4b5ec650
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeChemicalReactor.java
@@ -0,0 +1,298 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.onElementPass;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.transpose;
+import static gregtech.api.enums.GT_HatchElement.Energy;
+import static gregtech.api.enums.GT_HatchElement.InputBus;
+import static gregtech.api.enums.GT_HatchElement.InputHatch;
+import static gregtech.api.enums.GT_HatchElement.Maintenance;
+import static gregtech.api.enums.GT_HatchElement.OutputBus;
+import static gregtech.api.enums.GT_HatchElement.OutputHatch;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_LARGE_CHEMICAL_REACTOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_LARGE_CHEMICAL_REACTOR_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_LARGE_CHEMICAL_REACTOR_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_LARGE_CHEMICAL_REACTOR_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.casingTexturePages;
+import static gregtech.api.util.GT_StructureUtility.buildHatchAdder;
+
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.IChatComponent;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.gtnewhorizon.structurelib.StructureLibAPI;
+import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
+import com.gtnewhorizon.structurelib.structure.AutoPlaceEnvironment;
+import com.gtnewhorizon.structurelib.structure.IItemSource;
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.IStructureElement;
+import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+import com.gtnewhorizon.structurelib.structure.StructureUtility;
+import com.gtnewhorizon.structurelib.util.ItemStackPredicate;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.HeatingCoilLevel;
+import gregtech.api.interfaces.IHeatingCoil;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.logic.ProcessingLogic;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_EnhancedMultiBlockBase;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+
+public class GT_MetaTileEntity_LargeChemicalReactor extends
+ GT_MetaTileEntity_EnhancedMultiBlockBase<GT_MetaTileEntity_LargeChemicalReactor> implements ISurvivalConstructable {
+
+ private static final int CASING_INDEX = 176;
+ private static final String STRUCTURE_PIECE_MAIN = "main";
+ private static final IStructureDefinition<GT_MetaTileEntity_LargeChemicalReactor> STRUCTURE_DEFINITION = StructureDefinition
+ .<GT_MetaTileEntity_LargeChemicalReactor>builder()
+ .addShape(
+ STRUCTURE_PIECE_MAIN,
+ transpose(new String[][] { { "ccc", "cxc", "ccc" }, { "c~c", "xPx", "cxc" }, { "ccc", "cxc", "ccc" }, }))
+ .addElement('P', ofBlock(GregTech_API.sBlockCasings8, 1))
+ .addElement(
+ 'c',
+ buildHatchAdder(GT_MetaTileEntity_LargeChemicalReactor.class)
+ .atLeast(InputHatch, OutputHatch, InputBus, OutputBus, Maintenance, Energy)
+ .casingIndex(CASING_INDEX)
+ .dot(1)
+ .buildAndChain(
+ onElementPass(
+ GT_MetaTileEntity_LargeChemicalReactor::onCasingAdded,
+ ofBlock(GregTech_API.sBlockCasings8, 0))))
+ .addElement(
+ 'x',
+ buildHatchAdder(GT_MetaTileEntity_LargeChemicalReactor.class)
+ .atLeast(InputHatch, OutputHatch, InputBus, OutputBus, Maintenance, Energy)
+ .casingIndex(CASING_INDEX)
+ .dot(1)
+ .buildAndChain(
+ CoilStructureElement.INSTANCE,
+ onElementPass(
+ GT_MetaTileEntity_LargeChemicalReactor::onCasingAdded,
+ ofBlock(GregTech_API.sBlockCasings8, 0))))
+ .build();
+
+ private int mCasingAmount;
+ private int mCoilAmount;
+
+ public GT_MetaTileEntity_LargeChemicalReactor(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_LargeChemicalReactor(String aName) {
+ super(aName);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_LargeChemicalReactor(this.mName);
+ }
+
+ @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 Large Chemical Reactor")
+ .addInfo("Does not lose efficiency when overclocked")
+ .addInfo("Accepts fluids instead of fluid cells")
+ .addSeparator()
+ .beginStructureBlock(3, 3, 3, false)
+ .addController("Front center")
+ .addCasingInfoRange("Chemically Inert Machine Casing", 8, 22, false)
+ .addOtherStructurePart("PTFE Pipe Machine Casing", "Center")
+ .addOtherStructurePart("Heating Coil", "Adjacent to the PTFE Pipe Machine Casing", 1)
+ .addEnergyHatch("Any casing", 1, 2)
+ .addMaintenanceHatch("Any casing", 1, 2)
+ .addInputBus("Any casing", 1, 2)
+ .addInputHatch("Any casing", 1, 2)
+ .addOutputBus("Any casing", 1, 2)
+ .addOutputHatch("Any casing", 1, 2)
+ .addStructureInfo("You can have multiple hatches/busses")
+ .toolTipFinisher("Gregtech");
+ return tt;
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection aFacing,
+ int colorIndex, boolean aActive, boolean redstoneLevel) {
+ if (side == aFacing) {
+ if (aActive) return new ITexture[] { casingTexturePages[1][48], TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_LARGE_CHEMICAL_REACTOR_ACTIVE)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_LARGE_CHEMICAL_REACTOR_ACTIVE_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ return new ITexture[] { casingTexturePages[1][48], TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_LARGE_CHEMICAL_REACTOR)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_LARGE_CHEMICAL_REACTOR_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ }
+ return new ITexture[] { casingTexturePages[1][48] };
+ }
+
+ @Override
+ public boolean isCorrectMachinePart(ItemStack aStack) {
+ return true;
+ }
+
+ @Override
+ public boolean supportsSingleRecipeLocking() {
+ return true;
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.multiblockChemicalReactorRecipes;
+ }
+
+ @Override
+ protected ProcessingLogic createProcessingLogic() {
+ return new ProcessingLogic().enablePerfectOverclock();
+ }
+
+ @Override
+ public IStructureDefinition<GT_MetaTileEntity_LargeChemicalReactor> getStructureDefinition() {
+ return STRUCTURE_DEFINITION;
+ }
+
+ private void onCasingAdded() {
+ mCasingAmount++;
+ }
+
+ @Override
+ public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+ mCasingAmount = 0;
+ mCoilAmount = 0;
+ return checkPiece(STRUCTURE_PIECE_MAIN, 1, 1, 0) && mCasingAmount >= 8
+ && mCoilAmount == 1
+ && !mEnergyHatches.isEmpty()
+ && mMaintenanceHatches.size() == 1;
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack aStack) {
+ return 10000;
+ }
+
+ @Override
+ public int getDamageToComponent(ItemStack aStack) {
+ return 0;
+ }
+
+ @Override
+ public boolean explodesOnComponentBreak(ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public void construct(ItemStack stackSize, boolean hintsOnly) {
+ mCoilAmount = 0;
+ buildPiece(STRUCTURE_PIECE_MAIN, stackSize, hintsOnly, 1, 1, 0);
+ }
+
+ @Override
+ public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
+ if (mMachine) return -1;
+ mCoilAmount = 0;
+ return survivialBuildPiece(STRUCTURE_PIECE_MAIN, stackSize, 1, 1, 0, elementBudget, env, false, true);
+ }
+
+ @Override
+ public boolean supportsVoidProtection() {
+ return true;
+ }
+
+ private enum CoilStructureElement implements IStructureElement<GT_MetaTileEntity_LargeChemicalReactor> {
+
+ INSTANCE;
+
+ @Override
+ public boolean check(GT_MetaTileEntity_LargeChemicalReactor t, World world, int x, int y, int z) {
+ Block block = world.getBlock(x, y, z);
+ if (block instanceof IHeatingCoil
+ && ((IHeatingCoil) block).getCoilHeat(world.getBlockMetadata(x, y, z)) != HeatingCoilLevel.None) {
+ return t.mCoilAmount++ == 0;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public boolean spawnHint(GT_MetaTileEntity_LargeChemicalReactor t, World world, int x, int y, int z,
+ ItemStack trigger) {
+ StructureLibAPI.hintParticle(world, x, y, z, GregTech_API.sBlockCasings5, 0);
+ return true;
+ }
+
+ @Override
+ public boolean placeBlock(GT_MetaTileEntity_LargeChemicalReactor t, World world, int x, int y, int z,
+ ItemStack trigger) {
+ if (t.mCoilAmount > 0) return false;
+ boolean b = world.setBlock(x, y, z, GregTech_API.sBlockCasings5, 0, 3);
+ if (b) t.mCoilAmount++;
+ return b;
+ }
+
+ @Override
+ public PlaceResult survivalPlaceBlock(GT_MetaTileEntity_LargeChemicalReactor t, World world, int x, int y,
+ int z, ItemStack trigger, IItemSource s, EntityPlayerMP actor, Consumer<IChatComponent> chatter) {
+ return survivalPlaceBlock(t, world, x, y, z, trigger, AutoPlaceEnvironment.fromLegacy(s, actor, chatter));
+ }
+
+ @Override
+ public BlocksToPlace getBlocksToPlace(
+ GT_MetaTileEntity_LargeChemicalReactor gt_metaTileEntity_largeChemicalReactor, World world, int x, int y,
+ int z, ItemStack trigger, AutoPlaceEnvironment env) {
+ return BlocksToPlace.create(
+ IntStream.range(0, 8)
+ .mapToObj(i -> new ItemStack(GregTech_API.sBlockCasings5, 1, i))
+ .collect(Collectors.toList()));
+ }
+
+ @Override
+ public PlaceResult survivalPlaceBlock(GT_MetaTileEntity_LargeChemicalReactor t, World world, int x, int y,
+ int z, ItemStack trigger, AutoPlaceEnvironment env) {
+ if (t.mCoilAmount > 0) return PlaceResult.SKIP;
+ if (check(t, world, x, y, z)) return PlaceResult.SKIP;
+ if (!StructureLibAPI.isBlockTriviallyReplaceable(world, x, y, z, env.getActor())) return PlaceResult.REJECT;
+ ItemStack result = env.getSource()
+ .takeOne(ItemStackPredicate.from(GregTech_API.sBlockCasings5), true);
+ if (result == null) return PlaceResult.REJECT;
+ PlaceResult ret = StructureUtility.survivalPlaceBlock(
+ result,
+ ItemStackPredicate.NBTMode.EXACT,
+ null,
+ true,
+ world,
+ x,
+ y,
+ z,
+ env.getSource(),
+ env.getActor(),
+ env.getChatter());
+ if (ret == PlaceResult.ACCEPT) t.mCoilAmount++;
+ return ret;
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeTurbine.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeTurbine.java
new file mode 100644
index 0000000000..54ad5939f8
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeTurbine.java
@@ -0,0 +1,492 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.lazy;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.transpose;
+import static gregtech.api.enums.GT_HatchElement.Dynamo;
+import static gregtech.api.enums.GT_HatchElement.InputBus;
+import static gregtech.api.enums.GT_HatchElement.InputHatch;
+import static gregtech.api.enums.GT_HatchElement.Maintenance;
+import static gregtech.api.enums.GT_HatchElement.Muffler;
+import static gregtech.api.enums.GT_HatchElement.OutputBus;
+import static gregtech.api.enums.GT_HatchElement.OutputHatch;
+import static gregtech.api.enums.Textures.BlockIcons.TURBINE_NEW;
+import static gregtech.api.enums.Textures.BlockIcons.TURBINE_NEW_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.TURBINE_NEW_EMPTY;
+import static gregtech.api.util.GT_StructureUtility.buildHatchAdder;
+import static gregtech.api.util.GT_Utility.filterValidMTEs;
+
+import java.util.ArrayList;
+
+import net.minecraft.block.Block;
+import net.minecraft.client.renderer.RenderBlocks;
+import net.minecraft.client.renderer.Tessellator;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.StatCollector;
+import net.minecraft.world.IBlockAccess;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidStack;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.gtnewhorizon.structurelib.alignment.IAlignmentLimits;
+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.ISurvivalBuildEnvironment;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+
+import gregtech.api.enums.Dyes;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_EnhancedMultiBlockBase;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Dynamo;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Muffler;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.LightingHelper;
+import gregtech.api.util.shutdown.ShutDownReasonRegistry;
+import gregtech.common.items.GT_MetaGenerated_Tool_01;
+import gregtech.common.render.GT_RenderUtil;
+
+public abstract class GT_MetaTileEntity_LargeTurbine
+ extends GT_MetaTileEntity_EnhancedMultiBlockBase<GT_MetaTileEntity_LargeTurbine> implements ISurvivalConstructable {
+
+ private static final String STRUCTURE_PIECE_MAIN = "main";
+ private static final ClassValue<IStructureDefinition<GT_MetaTileEntity_LargeTurbine>> STRUCTURE_DEFINITION = new ClassValue<>() {
+
+ @Override
+ protected IStructureDefinition<GT_MetaTileEntity_LargeTurbine> computeValue(Class<?> type) {
+ return StructureDefinition.<GT_MetaTileEntity_LargeTurbine>builder()
+ .addShape(
+ STRUCTURE_PIECE_MAIN,
+ transpose(
+ new String[][] { { " ", " ", " ", " ", " ", },
+ { " --- ", " ccc ", " hhh ", " hhh ", " hhh ", },
+ { " --- ", " c~c ", " h-h ", " h-h ", " hdh ", },
+ { " --- ", " ccc ", " hhh ", " hhh ", " hhh ", },
+ { " ", " ", " ", " ", " ", }, }))
+ .addElement('c', lazy(t -> ofBlock(t.getCasingBlock(), t.getCasingMeta())))
+ .addElement('d', lazy(t -> Dynamo.newAny(t.getCasingTextureIndex(), 1)))
+ .addElement(
+ 'h',
+ lazy(
+ t -> buildHatchAdder(GT_MetaTileEntity_LargeTurbine.class)
+ .atLeast(Maintenance, InputHatch, OutputHatch, OutputBus, InputBus, Muffler)
+ .casingIndex(t.getCasingTextureIndex())
+ .dot(2)
+ .buildAndChain(t.getCasingBlock(), t.getCasingMeta())))
+ .build();
+ }
+ };
+
+ protected int baseEff = 0;
+ protected int optFlow = 0;
+ protected double realOptFlow = 0;
+ protected int storedFluid = 0;
+ protected int counter = 0;
+ protected boolean looseFit = false;
+ protected int overflowMultiplier = 0;
+ protected final float[] flowMultipliers = new float[] { 1, 1, 1 };
+
+ // client side stuff
+ protected boolean mHasTurbine;
+ // mMachine got overwritten by StructureLib extended facing query response
+ // so we use a separate field for this
+ protected boolean mFormed;
+
+ public GT_MetaTileEntity_LargeTurbine(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_LargeTurbine(String aName) {
+ super(aName);
+ }
+
+ @Override
+ public boolean isCorrectMachinePart(ItemStack aStack) {
+ return getMaxEfficiency(aStack) > 0;
+ }
+
+ @Override
+ public IStructureDefinition<GT_MetaTileEntity_LargeTurbine> getStructureDefinition() {
+ return STRUCTURE_DEFINITION.get(getClass());
+ }
+
+ @Override
+ protected IAlignmentLimits getInitialAlignmentLimits() {
+ return (d, r, f) -> r.isNotRotated() && f.isNotFlipped();
+ }
+
+ @Override
+ protected ExtendedFacing getCorrectedAlignment(ExtendedFacing aOldFacing) {
+ return aOldFacing.with(Flip.NONE)
+ .with(Rotation.NORMAL);
+ }
+
+ @Override
+ public boolean isFlipChangeAllowed() {
+ return false;
+ }
+
+ @Override
+ public boolean isRotationChangeAllowed() {
+ return false;
+ }
+
+ @Override
+ public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+ return checkPiece(STRUCTURE_PIECE_MAIN, 2, 2, 1) && mMaintenanceHatches.size() == 1
+ && mMufflerHatches.isEmpty() == (getPollutionPerTick(null) == 0);
+ }
+
+ public abstract Block getCasingBlock();
+
+ public abstract byte getCasingMeta();
+
+ public abstract int getCasingTextureIndex();
+
+ public boolean isNewStyleRendering() {
+ return false;
+ }
+
+ public IIconContainer[] getTurbineTextureActive() {
+ return TURBINE_NEW_ACTIVE;
+ }
+
+ public IIconContainer[] getTurbineTextureFull() {
+ return TURBINE_NEW;
+ }
+
+ public IIconContainer[] getTurbineTextureEmpty() {
+ return TURBINE_NEW_EMPTY;
+ }
+
+ @Override
+ public boolean renderInWorld(IBlockAccess aWorld, int aX, int aY, int aZ, Block aBlock, RenderBlocks aRenderer) {
+ if (!isNewStyleRendering() || !mFormed) return false;
+ int[] tABCCoord = new int[] { -1, -1, 0 };
+ int[] tXYZOffset = new int[3];
+ final ForgeDirection tFacing = getBaseMetaTileEntity().getFrontFacing();
+ final ExtendedFacing tExtendedFacing = getExtendedFacing();
+ final ForgeDirection tDirection = tExtendedFacing.getDirection();
+ final LightingHelper tLighting = new LightingHelper(aRenderer);
+
+ // for some reason +x and -z need this field set to true, but not any other sides
+ if (tFacing == ForgeDirection.NORTH || tFacing == ForgeDirection.EAST) aRenderer.field_152631_f = true;
+ final Block tBlock = getCasingBlock();
+
+ IIconContainer[] tTextures;
+ if (getBaseMetaTileEntity().isActive()) tTextures = getTurbineTextureActive();
+ else if (hasTurbine()) tTextures = getTurbineTextureFull();
+ else tTextures = getTurbineTextureEmpty();
+
+ assert tTextures != null && tTextures.length == tABCCoord.length;
+
+ for (int i = 0; i < 9; i++) {
+ if (i != 4) { // do not draw ourselves again.
+ tExtendedFacing.getWorldOffset(tABCCoord, tXYZOffset);
+ // since structure check passed, we can assume it is turbine casing
+ int tX = tXYZOffset[0] + aX;
+ int tY = tXYZOffset[1] + aY;
+ int tZ = tXYZOffset[2] + aZ;
+ // we skip the occlusion test, as we always require a working turbine to have a block of air before it
+ // so the front face cannot be occluded whatsoever in the most cases.
+ Tessellator.instance.setBrightness(
+ tBlock.getMixedBrightnessForBlock(
+ aWorld,
+ aX + tDirection.offsetX,
+ tY + tDirection.offsetY,
+ aZ + tDirection.offsetZ));
+ tLighting.setupLighting(tBlock, tX, tY, tZ, tFacing)
+ .setupColor(tFacing, Dyes._NULL.mRGBa);
+ GT_RenderUtil.renderBlockIcon(
+ aRenderer,
+ tBlock,
+ tX + tDirection.offsetX * 0.01,
+ tY + tDirection.offsetY * 0.01,
+ tZ + tDirection.offsetZ * 0.01,
+ tTextures[i].getIcon(),
+ tFacing);
+ }
+ if (++tABCCoord[0] == 2) {
+ tABCCoord[0] = -1;
+ tABCCoord[1]++;
+ }
+ }
+
+ aRenderer.field_152631_f = false;
+ return false;
+ }
+
+ @Override
+ public void onValueUpdate(byte aValue) {
+ mHasTurbine = (aValue & 0x1) != 0;
+ mFormed = (aValue & 0x2) != 0;
+ super.onValueUpdate(aValue);
+ }
+
+ @Override
+ public byte getUpdateData() {
+ return (byte) ((hasTurbine() ? 1 : 0) | (mMachine ? 2 : 0));
+ }
+
+ @Override
+ public boolean addToMachineList(IGregTechTileEntity tTileEntity, int aBaseCasingIndex) {
+ return addMaintenanceToMachineList(tTileEntity, getCasingTextureIndex())
+ || addInputToMachineList(tTileEntity, getCasingTextureIndex())
+ || addOutputToMachineList(tTileEntity, getCasingTextureIndex())
+ || addMufflerToMachineList(tTileEntity, getCasingTextureIndex());
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ }
+
+ @Override
+ @NotNull
+ public CheckRecipeResult checkProcessing() {
+ ItemStack controllerSlot = getControllerSlot();
+ if ((counter & 7) == 0
+ && (controllerSlot == null || !(controllerSlot.getItem() instanceof GT_MetaGenerated_Tool)
+ || controllerSlot.getItemDamage() < 170
+ || controllerSlot.getItemDamage() > 179)) {
+ stopMachine(ShutDownReasonRegistry.NO_TURBINE);
+ return CheckRecipeResultRegistry.NO_TURBINE_FOUND;
+ }
+ ArrayList<FluidStack> tFluids = getStoredFluids();
+ if (!tFluids.isEmpty()) {
+
+ if (baseEff == 0 || optFlow == 0
+ || counter >= 512
+ || this.getBaseMetaTileEntity()
+ .hasWorkJustBeenEnabled()
+ || this.getBaseMetaTileEntity()
+ .hasInventoryBeenModified()) {
+ counter = 0;
+ baseEff = GT_Utility.safeInt(
+ (long) ((5F
+ + ((GT_MetaGenerated_Tool) controllerSlot.getItem()).getToolCombatDamage(controllerSlot))
+ * 1000F));
+ optFlow = GT_Utility.safeInt(
+ (long) Math.max(
+ Float.MIN_NORMAL,
+ ((GT_MetaGenerated_Tool) controllerSlot.getItem()).getToolStats(controllerSlot)
+ .getSpeedMultiplier() * GT_MetaGenerated_Tool.getPrimaryMaterial(controllerSlot).mToolSpeed
+ * 50));
+
+ overflowMultiplier = getOverflowMultiplier(controllerSlot);
+
+ flowMultipliers[0] = GT_MetaGenerated_Tool.getPrimaryMaterial(controllerSlot).mSteamMultiplier;
+ flowMultipliers[1] = GT_MetaGenerated_Tool.getPrimaryMaterial(controllerSlot).mGasMultiplier;
+ flowMultipliers[2] = GT_MetaGenerated_Tool.getPrimaryMaterial(controllerSlot).mPlasmaMultiplier;
+
+ if (optFlow <= 0 || baseEff <= 0) {
+ stopMachine(ShutDownReasonRegistry.NONE); // in case the turbine got removed
+ return CheckRecipeResultRegistry.NO_FUEL_FOUND;
+ }
+ } else {
+ counter++;
+ }
+ }
+
+ int newPower = fluidIntoPower(tFluids, optFlow, baseEff, overflowMultiplier, flowMultipliers); // How much the
+ // turbine should
+ // be producing
+ // with this flow
+ int difference = newPower - this.mEUt; // difference between current output and new output
+
+ // Magic numbers: can always change by at least 10 eu/t, but otherwise by at most 1 percent of the difference in
+ // power level (per tick)
+ // This is how much the turbine can actually change during this tick
+ int maxChangeAllowed = Math.max(10, GT_Utility.safeInt((long) Math.abs(difference) / 100));
+
+ if (Math.abs(difference) > maxChangeAllowed) { // If this difference is too big, use the maximum allowed change
+ int change = maxChangeAllowed * (difference > 0 ? 1 : -1); // Make the change positive or negative.
+ this.mEUt += change; // Apply the change
+ } else this.mEUt = newPower;
+
+ if (this.mEUt <= 0) {
+ // stopMachine();
+ this.mEUt = 0;
+ this.mEfficiency = 0;
+ return CheckRecipeResultRegistry.NO_FUEL_FOUND;
+ } else {
+ this.mMaxProgresstime = 1;
+ this.mEfficiencyIncrease = 10;
+ // Overvoltage is handled inside the MultiBlockBase when pushing out to dynamos. no need to do it here.
+ return CheckRecipeResultRegistry.GENERATING;
+ }
+ }
+
+ abstract int fluidIntoPower(ArrayList<FluidStack> aFluids, int aOptFlow, int aBaseEff, int overflowMultiplier,
+ float[] flowMultipliers);
+
+ abstract float getOverflowEfficiency(int totalFlow, int actualOptimalFlow, int overflowMultiplier);
+
+ // Gets the maximum output that the turbine currently can handle. Going above this will cause the turbine to explode
+ public long getMaximumOutput() {
+ long aTotal = 0;
+ for (GT_MetaTileEntity_Hatch_Dynamo aDynamo : filterValidMTEs(mDynamoHatches)) {
+ long aVoltage = aDynamo.maxEUOutput();
+ aTotal = aDynamo.maxAmperesOut() * aVoltage;
+ }
+ return aTotal;
+ }
+
+ public int getOverflowMultiplier(ItemStack aStack) {
+ int aOverflowMultiplier = 0;
+ int toolQualityLevel = GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mToolQuality;
+ if (toolQualityLevel >= 6) {
+ aOverflowMultiplier = 3;
+ } else if (toolQualityLevel >= 3) {
+ aOverflowMultiplier = 2;
+ } else {
+ aOverflowMultiplier = 1;
+ }
+ return aOverflowMultiplier;
+ }
+
+ @Override
+ public int getDamageToComponent(ItemStack aStack) {
+ return 1;
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack aStack) {
+ if (GT_Utility.isStackInvalid(aStack)) {
+ return 0;
+ }
+ if (aStack.getItem() instanceof GT_MetaGenerated_Tool_01) {
+ return 10000;
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean explodesOnComponentBreak(ItemStack aStack) {
+ return true;
+ }
+
+ @Override
+ public String[] getInfoData() {
+ int mPollutionReduction = 0;
+ for (GT_MetaTileEntity_Hatch_Muffler tHatch : filterValidMTEs(mMufflerHatches)) {
+ mPollutionReduction = Math.max(tHatch.calculatePollutionReduction(100), mPollutionReduction);
+ }
+
+ String tRunning = mMaxProgresstime > 0
+ ? EnumChatFormatting.GREEN + StatCollector.translateToLocal("GT5U.turbine.running.true")
+ + EnumChatFormatting.RESET
+ : EnumChatFormatting.RED + StatCollector.translateToLocal("GT5U.turbine.running.false")
+ + EnumChatFormatting.RESET;
+ String tMaintainance = getIdealStatus() == getRepairStatus()
+ ? EnumChatFormatting.GREEN + StatCollector.translateToLocal("GT5U.turbine.maintenance.false")
+ + EnumChatFormatting.RESET
+ : EnumChatFormatting.RED + StatCollector.translateToLocal("GT5U.turbine.maintenance.true")
+ + EnumChatFormatting.RESET;
+ int tDura = 0;
+
+ if (mInventory[1] != null && mInventory[1].getItem() instanceof GT_MetaGenerated_Tool_01) {
+ tDura = GT_Utility.safeInt(
+ (long) (100.0f / GT_MetaGenerated_Tool.getToolMaxDamage(mInventory[1])
+ * (GT_MetaGenerated_Tool.getToolDamage(mInventory[1])) + 1));
+ }
+
+ long storedEnergy = 0;
+ long maxEnergy = 0;
+ for (GT_MetaTileEntity_Hatch_Dynamo tHatch : filterValidMTEs(mDynamoHatches)) {
+ storedEnergy += tHatch.getBaseMetaTileEntity()
+ .getStoredEU();
+ maxEnergy += tHatch.getBaseMetaTileEntity()
+ .getEUCapacity();
+ }
+ String[] ret = new String[] {
+ // 8 Lines available for information panels
+ tRunning + ": "
+ + EnumChatFormatting.RED
+ + GT_Utility.formatNumbers(((long) mEUt * mEfficiency) / 10000)
+ + EnumChatFormatting.RESET
+ + " EU/t", /* 1 */
+ tMaintainance, /* 2 */
+ StatCollector.translateToLocal("GT5U.turbine.efficiency") + ": "
+ + EnumChatFormatting.YELLOW
+ + (mEfficiency / 100F)
+ + EnumChatFormatting.RESET
+ + "%", /* 2 */
+ StatCollector.translateToLocal("GT5U.multiblock.energy") + ": "
+ + EnumChatFormatting.GREEN
+ + GT_Utility.formatNumbers(storedEnergy)
+ + EnumChatFormatting.RESET
+ + " EU / "
+ + /* 3 */ EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(maxEnergy)
+ + EnumChatFormatting.RESET
+ + " EU",
+ StatCollector.translateToLocal("GT5U.turbine.flow") + ": "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(GT_Utility.safeInt((long) realOptFlow))
+ + EnumChatFormatting.RESET
+ + " L/t"
+ + /* 4 */ EnumChatFormatting.YELLOW
+ + " ("
+ + (looseFit ? StatCollector.translateToLocal("GT5U.turbine.loose")
+ : StatCollector.translateToLocal("GT5U.turbine.tight"))
+ + ")", /* 5 */
+ StatCollector.translateToLocal("GT5U.turbine.fuel") + ": "
+ + EnumChatFormatting.GOLD
+ + GT_Utility.formatNumbers(storedFluid)
+ + EnumChatFormatting.RESET
+ + "L", /* 6 */
+ StatCollector.translateToLocal(
+ "GT5U.turbine.dmg") + ": " + EnumChatFormatting.RED + tDura + EnumChatFormatting.RESET + "%", /* 7 */
+ StatCollector.translateToLocal("GT5U.multiblock.pollution") + ": "
+ + EnumChatFormatting.GREEN
+ + mPollutionReduction
+ + EnumChatFormatting.RESET
+ + " %" /* 8 */
+ };
+ if (!this.getClass()
+ .getName()
+ .contains("Steam"))
+ ret[4] = StatCollector.translateToLocal("GT5U.turbine.flow") + ": "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.safeInt((long) realOptFlow)
+ + EnumChatFormatting.RESET
+ + " L/t";
+ return ret;
+ }
+
+ public boolean hasTurbine() {
+ return getBaseMetaTileEntity() != null && getBaseMetaTileEntity().isClientSide() ? mHasTurbine
+ : this.getMaxEfficiency(mInventory[1]) > 0;
+ }
+
+ @Override
+ public boolean isGivingInformation() {
+ return true;
+ }
+
+ @Override
+ public void construct(ItemStack stackSize, boolean hintsOnly) {
+ buildPiece(STRUCTURE_PIECE_MAIN, stackSize, hintsOnly, 2, 2, 1);
+ }
+
+ @Override
+ public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
+ if (mMachine) return -1;
+ return survivialBuildPiece(STRUCTURE_PIECE_MAIN, stackSize, 2, 2, 1, elementBudget, env, false, true);
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeTurbine_Gas.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeTurbine_Gas.java
new file mode 100644
index 0000000000..e84c695d68
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeTurbine_Gas.java
@@ -0,0 +1,222 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static gregtech.api.enums.Textures.BlockIcons.LARGETURBINE_NEW5;
+import static gregtech.api.enums.Textures.BlockIcons.LARGETURBINE_NEW_ACTIVE5;
+import static gregtech.api.enums.Textures.BlockIcons.LARGETURBINE_NEW_EMPTY5;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASINGS;
+import static gregtech.api.enums.Textures.BlockIcons.casingTexturePages;
+
+import java.util.ArrayList;
+
+import net.minecraft.block.Block;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidStack;
+
+import gregtech.GT_Mod;
+import gregtech.api.GregTech_API;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_LargeTurbine_Gas extends GT_MetaTileEntity_LargeTurbine {
+
+ public GT_MetaTileEntity_LargeTurbine_Gas(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_LargeTurbine_Gas(String aName) {
+ super(aName);
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection aFacing,
+ int colorIndex, boolean aActive, boolean redstoneLevel) {
+ return new ITexture[] { MACHINE_CASINGS[1][colorIndex + 1],
+ aFacing == side ? (aActive ? TextureFactory.builder()
+ .addIcon(LARGETURBINE_NEW_ACTIVE5)
+ .build()
+ : hasTurbine() ? TextureFactory.builder()
+ .addIcon(LARGETURBINE_NEW5)
+ .build()
+ : TextureFactory.builder()
+ .addIcon(LARGETURBINE_NEW_EMPTY5)
+ .build())
+ : casingTexturePages[0][58] };
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Gas Turbine")
+ .addInfo("Controller block for the Large Gas Turbine")
+ .addInfo("Needs a Turbine, place inside controller")
+ .addInfo("Warning: Will be capped at 8192 EU/t in a future update")
+ .addInfo("See the Advanced Large Gas Turbine as the next, uncapped, option")
+ // .addInfo("The excess fuel that gets consumed will be voided!")
+ .addPollutionAmount(getPollutionPerSecond(null))
+ .addSeparator()
+ .beginStructureBlock(3, 3, 4, true)
+ .addController("Front center")
+ .addCasingInfoRange("Stainless Steel Turbine Casing", 8, 30, false)
+ .addDynamoHatch("Back center", 1)
+ .addMaintenanceHatch("Side centered", 2)
+ .addMufflerHatch("Side centered", 2)
+ .addInputHatch("Gas Fuel, Side centered", 2)
+ .addOtherStructurePart("Air", "3x3 area in front of controller")
+ .toolTipFinisher("Gregtech");
+ return tt;
+ }
+
+ public int getFuelValue(FluidStack aLiquid) {
+ if (aLiquid == null) return 0;
+ GT_Recipe tFuel = RecipeMaps.gasTurbineFuels.getBackend()
+ .findFuel(aLiquid);
+ if (tFuel != null) return tFuel.mSpecialValue;
+ return 0;
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_LargeTurbine_Gas(mName);
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.gasTurbineFuels;
+ }
+
+ @Override
+ public int getRecipeCatalystPriority() {
+ return -1;
+ }
+
+ @Override
+ protected boolean filtersFluid() {
+ return false;
+ }
+
+ @Override
+ public Block getCasingBlock() {
+ return GregTech_API.sBlockCasings4;
+ }
+
+ @Override
+ public byte getCasingMeta() {
+ return 10;
+ }
+
+ @Override
+ public int getCasingTextureIndex() {
+ return 58;
+ }
+
+ @Override
+ public boolean isNewStyleRendering() {
+ return true;
+ }
+
+ @Override
+ public int getPollutionPerSecond(ItemStack aStack) {
+ return GT_Mod.gregtechproxy.mPollutionLargeGasTurbinePerSecond;
+ }
+
+ @Override
+ int fluidIntoPower(ArrayList<FluidStack> aFluids, int aOptFlow, int aBaseEff, int overflowMultiplier,
+ float[] flowMultipliers) {
+ if (aFluids.size() >= 1) {
+ int tEU = 0;
+ int actualOptimalFlow = 0;
+
+ FluidStack firstFuelType = new FluidStack(aFluids.get(0), 0); // Identify a SINGLE type of fluid to process.
+ // Doesn't matter which one. Ignore the rest!
+ int fuelValue = getFuelValue(firstFuelType);
+
+ if (aOptFlow < fuelValue) {
+ // turbine too weak and/or fuel too powerful
+ // at least consume 1L
+ this.realOptFlow = 1;
+ // wastes the extra fuel and generate aOptFlow directly
+ depleteInput(new FluidStack(firstFuelType, 1));
+ this.storedFluid += 1;
+ return GT_Utility.safeInt((long) aOptFlow * (long) aBaseEff / 10000L);
+ }
+
+ actualOptimalFlow = GT_Utility.safeInt((long) (aOptFlow * flowMultipliers[1] / fuelValue));
+ this.realOptFlow = actualOptimalFlow;
+
+ // Allowed to use up to 450% optimal flow rate, depending on the value of overflowMultiplier.
+ // This value is chosen because the highest EU/t possible depends on the overflowMultiplier, and the formula
+ // used
+ // makes it so the flow rate for that max, per value of overflowMultiplier, is (percentage of optimal flow
+ // rate):
+ // - 150% if it is 1
+ // - 300% if it is 2
+ // - 450% if it is 3
+ // Variable required outside of loop for multi-hatch scenarios.
+ int remainingFlow = GT_Utility.safeInt((long) (actualOptimalFlow * (1.5f * overflowMultiplier)));
+ int flow = 0;
+ int totalFlow = 0;
+
+ storedFluid = 0;
+ for (FluidStack aFluid : aFluids) {
+ if (aFluid.isFluidEqual(firstFuelType)) {
+ flow = Math.min(aFluid.amount, remainingFlow); // try to use up to the max flow defined just above
+ depleteInput(new FluidStack(aFluid, flow)); // deplete that amount
+ this.storedFluid += aFluid.amount;
+ remainingFlow -= flow; // track amount we're allowed to continue depleting from hatches
+ totalFlow += flow; // track total input used
+ }
+ }
+ if (totalFlow <= 0) return 0;
+ tEU = GT_Utility.safeInt((long) totalFlow * fuelValue);
+
+ if (totalFlow != actualOptimalFlow) {
+ float efficiency = getOverflowEfficiency(totalFlow, actualOptimalFlow, overflowMultiplier);
+ tEU *= efficiency;
+ }
+ tEU = GT_Utility.safeInt((long) tEU * (long) aBaseEff / 10000L);
+
+ // EU/t output cap to properly tier the LGT against the Advanced LGT, will be implemented in a future dev
+ // update
+ /*
+ * if (tEU > 8192) { tEU = 8192; }
+ */
+
+ // If next output is above the maximum the dynamo can handle, set it to the maximum instead of exploding the
+ // turbine
+ // Raising the maximum allowed flow rate to account for the efficiency changes beyond the optimal flow
+ // When the max fuel consumption rate was increased, turbines could explode on world load
+ if (tEU > getMaximumOutput()) {
+ tEU = GT_Utility.safeInt(getMaximumOutput());
+ }
+ return tEU;
+ }
+ return 0;
+ }
+
+ @Override
+ float getOverflowEfficiency(int totalFlow, int actualOptimalFlow, int overflowMultiplier) {
+ // overflowMultiplier changes how quickly the turbine loses efficiency after flow goes beyond the optimal value
+ // At the default value of 1, any flow will generate less EU/t than optimal flow, regardless of the amount of
+ // fuel used
+ // The bigger this number is, the slower efficiency loss happens as flow moves beyond the optimal value
+ // Gases are the second most efficient in this regard, with plasma being the most efficient
+ float efficiency = 0;
+
+ if (totalFlow > actualOptimalFlow) {
+ efficiency = 1.0f - Math.abs((totalFlow - actualOptimalFlow))
+ / ((float) actualOptimalFlow * ((overflowMultiplier * 3) - 1));
+ } else {
+ efficiency = 1.0f - Math.abs((totalFlow - actualOptimalFlow) / (float) actualOptimalFlow);
+ }
+
+ return efficiency;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeTurbine_GasAdvanced.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeTurbine_GasAdvanced.java
new file mode 100644
index 0000000000..4926655476
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeTurbine_GasAdvanced.java
@@ -0,0 +1,219 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static gregtech.api.enums.Textures.BlockIcons.LARGETURBINE_NEW5;
+import static gregtech.api.enums.Textures.BlockIcons.LARGETURBINE_NEW_ACTIVE5;
+import static gregtech.api.enums.Textures.BlockIcons.LARGETURBINE_NEW_EMPTY5;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASINGS;
+import static gregtech.api.enums.Textures.BlockIcons.casingTexturePages;
+
+import java.util.ArrayList;
+
+import net.minecraft.block.Block;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidStack;
+
+import gregtech.GT_Mod;
+import gregtech.api.GregTech_API;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_LargeTurbine_GasAdvanced extends GT_MetaTileEntity_LargeTurbine {
+
+ public GT_MetaTileEntity_LargeTurbine_GasAdvanced(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_LargeTurbine_GasAdvanced(String aName) {
+ super(aName);
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection aFacing,
+ int colorIndex, boolean aActive, boolean redstoneLevel) {
+ return new ITexture[] { MACHINE_CASINGS[1][colorIndex + 1],
+ aFacing == side ? (aActive ? TextureFactory.builder()
+ .addIcon(LARGETURBINE_NEW_ACTIVE5)
+ .build()
+ : hasTurbine() ? TextureFactory.builder()
+ .addIcon(LARGETURBINE_NEW5)
+ .build()
+ : TextureFactory.builder()
+ .addIcon(LARGETURBINE_NEW_EMPTY5)
+ .build())
+ : casingTexturePages[1][57] };
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Gas Turbine")
+ .addInfo("Warning: This is an experimental multiblock, subject to changes ")
+ .addInfo("Controller block for the Large Advanced Gas Turbine")
+ .addInfo("Needs a Turbine, place inside controller")
+ .addInfo("Only accepts gases above 800k EU/bucket")
+ .addInfo("Has no maximum EU/t output, only depends on the Dynamo Hatch")
+ .addPollutionAmount(getPollutionPerSecond(null))
+ .addSeparator()
+ .beginStructureBlock(3, 3, 4, true)
+ .addController("Front center")
+ .addCasingInfoRange("Advanced Gas Turbine Casing", 8, 30, false)
+ .addDynamoHatch("Back center", 1)
+ .addMaintenanceHatch("Side centered", 2)
+ .addMufflerHatch("Side centered", 2)
+ .addInputHatch("Gas Fuel, Side centered", 2)
+ .toolTipFinisher("Gregtech");
+ return tt;
+ }
+
+ public int getFuelValue(FluidStack aLiquid) {
+ if (aLiquid == null) return 0;
+ GT_Recipe tFuel = RecipeMaps.gasTurbineFuels.getBackend()
+ .findFuel(aLiquid);
+ if (tFuel != null) return tFuel.mSpecialValue;
+ return 0;
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_LargeTurbine_GasAdvanced(mName);
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.gasTurbineFuels;
+ }
+
+ @Override
+ public int getRecipeCatalystPriority() {
+ return -2;
+ }
+
+ @Override
+ protected boolean filtersFluid() {
+ return false;
+ }
+
+ @Override
+ public Block getCasingBlock() {
+ return GregTech_API.sBlockCasings8;
+ }
+
+ @Override
+ public byte getCasingMeta() {
+ return 9;
+ }
+
+ @Override
+ public int getCasingTextureIndex() {
+ return 185;
+ }
+
+ @Override
+ public boolean isNewStyleRendering() {
+ return true;
+ }
+
+ @Override
+ public int getPollutionPerSecond(ItemStack aStack) {
+ return GT_Mod.gregtechproxy.mPollutionLargeGasTurbinePerSecond;
+ }
+
+ @Override
+ int fluidIntoPower(ArrayList<FluidStack> aFluids, int aOptFlow, int aBaseEff, int overflowMultiplier,
+ float[] flowMultipliers) {
+ if (aFluids.size() >= 1) {
+ int tEU = 0;
+ int actualOptimalFlow = 0;
+
+ FluidStack firstFuelType = new FluidStack(aFluids.get(0), 0); // Identify a SINGLE type of fluid to process.
+ // Doesn't matter which one. Ignore the rest!
+ int fuelValue = getFuelValue(firstFuelType);
+
+ if (fuelValue < 100) {
+ return 0;
+ }
+
+ if (aOptFlow < fuelValue) {
+ // turbine too weak and/or fuel too powerful
+ // at least consume 1L
+ this.realOptFlow = 1;
+ // wastes the extra fuel and generate aOptFlow directly
+ depleteInput(new FluidStack(firstFuelType, 1));
+ this.storedFluid += 1;
+ return GT_Utility.safeInt((long) aOptFlow * (long) aBaseEff / 10000L);
+ }
+
+ actualOptimalFlow = GT_Utility.safeInt((long) (aOptFlow * flowMultipliers[1] / fuelValue));
+ this.realOptFlow = actualOptimalFlow;
+
+ // Allowed to use up to 450% optimal flow rate, depending on the value of overflowMultiplier.
+ // This value is chosen because the highest EU/t possible depends on the overflowMultiplier, and the formula
+ // used
+ // makes it so the flow rate for that max, per value of overflowMultiplier, is (percentage of optimal flow
+ // rate):
+ // - 150% if it is 1
+ // - 300% if it is 2
+ // - 450% if it is 3
+ // Variable required outside of loop for multi-hatch scenarios.
+ int remainingFlow = GT_Utility.safeInt((long) (actualOptimalFlow * (1.5f * overflowMultiplier)));
+ int flow = 0;
+ int totalFlow = 0;
+
+ storedFluid = 0;
+ for (FluidStack aFluid : aFluids) {
+ if (aFluid.isFluidEqual(firstFuelType)) {
+ flow = Math.min(aFluid.amount, remainingFlow); // try to use up to the max flow defined just above
+ depleteInput(new FluidStack(aFluid, flow)); // deplete that amount
+ this.storedFluid += aFluid.amount;
+ remainingFlow -= flow; // track amount we're allowed to continue depleting from hatches
+ totalFlow += flow; // track total input used
+ }
+ }
+ if (totalFlow <= 0) return 0;
+ tEU = GT_Utility.safeInt((long) totalFlow * fuelValue);
+
+ if (totalFlow != actualOptimalFlow) {
+ float efficiency = getOverflowEfficiency(totalFlow, actualOptimalFlow, overflowMultiplier);
+ tEU *= efficiency;
+ }
+ tEU = GT_Utility.safeInt((long) tEU * (long) aBaseEff / 10000L);
+
+ // If next output is above the maximum the dynamo can handle, set it to the maximum instead of exploding the
+ // turbine
+ // Raising the maximum allowed flow rate to account for the efficiency changes beyond the optimal flow
+ // When the max fuel consumption rate was increased, turbines could explode on world load
+ if (tEU > getMaximumOutput()) {
+ tEU = GT_Utility.safeInt(getMaximumOutput());
+ }
+ return tEU;
+ }
+ return 0;
+ }
+
+ @Override
+ float getOverflowEfficiency(int totalFlow, int actualOptimalFlow, int overflowMultiplier) {
+ // overflowMultiplier changes how quickly the turbine loses efficiency after flow goes beyond the optimal value
+ // At the default value of 1, any flow will generate less EU/t than optimal flow, regardless of the amount of
+ // fuel used
+ // The bigger this number is, the slower efficiency loss happens as flow moves beyond the optimal value
+ // Gases are the second most efficient in this regard, with plasma being the most efficient
+ float efficiency = 0;
+
+ if (totalFlow > actualOptimalFlow) {
+ efficiency = 1.0f - Math.abs((totalFlow - actualOptimalFlow))
+ / ((float) actualOptimalFlow * ((overflowMultiplier * 3) - 1));
+ } else {
+ efficiency = 1.0f - Math.abs((totalFlow - actualOptimalFlow) / (float) actualOptimalFlow);
+ }
+
+ return efficiency;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeTurbine_HPSteam.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeTurbine_HPSteam.java
new file mode 100644
index 0000000000..d61e75eac3
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeTurbine_HPSteam.java
@@ -0,0 +1,232 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static gregtech.api.enums.Textures.BlockIcons.LARGETURBINE_NEW5;
+import static gregtech.api.enums.Textures.BlockIcons.LARGETURBINE_NEW_ACTIVE5;
+import static gregtech.api.enums.Textures.BlockIcons.LARGETURBINE_NEW_EMPTY5;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASINGS;
+import static gregtech.api.enums.Textures.BlockIcons.casingTexturePages;
+import static gregtech.api.objects.XSTR.XSTR_INSTANCE;
+import static gregtech.common.tileentities.machines.multi.GT_MetaTileEntity_LargeTurbine_Steam.calculateLooseFlow;
+
+import java.util.ArrayList;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidStack;
+
+import gregtech.GT_Mod;
+import gregtech.api.GregTech_API;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_LargeTurbine_HPSteam extends GT_MetaTileEntity_LargeTurbine {
+
+ public boolean achievement = false;
+ private boolean looseFit = false;
+
+ public GT_MetaTileEntity_LargeTurbine_HPSteam(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_LargeTurbine_HPSteam(String aName) {
+ super(aName);
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection aFacing,
+ int colorIndex, boolean aActive, boolean redstoneLevel) {
+ return new ITexture[] { MACHINE_CASINGS[1][colorIndex + 1],
+ aFacing == side ? (aActive ? TextureFactory.builder()
+ .addIcon(LARGETURBINE_NEW_ACTIVE5)
+ .build()
+ : hasTurbine() ? TextureFactory.builder()
+ .addIcon(LARGETURBINE_NEW5)
+ .build()
+ : TextureFactory.builder()
+ .addIcon(LARGETURBINE_NEW_EMPTY5)
+ .build())
+ : casingTexturePages[0][59] };
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Steam Turbine")
+ .addInfo("Controller block for the Large High Pressure Steam Turbine")
+ .addInfo("Needs a Turbine, place inside controller")
+ .addInfo("Outputs Steam as well as producing power")
+ .addInfo("Power output depends on turbine and fitting")
+ .addInfo("Use screwdriver to adjust fitting of turbine")
+ .addSeparator()
+ .beginStructureBlock(3, 3, 4, true)
+ .addController("Front center")
+ .addCasingInfoRange("Titanium Turbine Casing", 8, 31, false)
+ .addDynamoHatch("Back center", 1)
+ .addMaintenanceHatch("Side centered", 2)
+ .addInputHatch("Superheated Steam, Side centered", 2)
+ .addOutputHatch("Steam, Side centered", 2)
+ .toolTipFinisher("Gregtech");
+ return tt;
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_LargeTurbine_HPSteam(mName);
+ }
+
+ @Override
+ public Block getCasingBlock() {
+ return GregTech_API.sBlockCasings4;
+ }
+
+ @Override
+ public byte getCasingMeta() {
+ return 11;
+ }
+
+ @Override
+ public int getCasingTextureIndex() {
+ return 59;
+ }
+
+ @Override
+ public boolean isNewStyleRendering() {
+ return true;
+ }
+
+ @Override
+ int fluidIntoPower(ArrayList<FluidStack> aFluids, int aOptFlow, int aBaseEff, int overflowEfficiency,
+ float[] flowMultipliers) {
+ if (looseFit) {
+ float[] calculatedFlow = calculateLooseFlow(aOptFlow, aBaseEff);
+ aOptFlow = GT_Utility.safeInt((long) calculatedFlow[0]);
+ aBaseEff = GT_Utility.safeInt((long) calculatedFlow[1]);
+ }
+ int tEU = 0;
+ int totalFlow = 0; // Byproducts are based on actual flow
+ int flow = 0;
+
+ // Allowed to use up to 300% optimal flow rate, depending on the value of overflowMultiplier.
+ // This value is chosen because the highest EU/t possible depends on the overflowMultiplier, and the formula
+ // used
+ // makes it so the flow rate for that max, per value of overflowMultiplier, is (percentage of optimal flow
+ // rate):
+ // - 200% if it is 1
+ // - 250% if it is 2
+ // - 300% if it is 3
+ // Variable required outside of loop for multi-hatch scenarios.
+ this.realOptFlow = aOptFlow * flowMultipliers[0];
+ int remainingFlow = GT_Utility.safeInt((long) (realOptFlow * (0.5f * overflowMultiplier + 1.5)));
+
+ storedFluid = 0;
+ for (int i = 0; i < aFluids.size() && remainingFlow > 0; i++) {
+ final FluidStack aFluidStack = aFluids.get(i);
+ if (GT_ModHandler.isSuperHeatedSteam(aFluidStack)) {
+ flow = Math.min(aFluidStack.amount, remainingFlow); // try to use up to the max flow defined just above
+ depleteInput(new FluidStack(aFluidStack, flow)); // deplete that amount
+ this.storedFluid += aFluidStack.amount;
+ remainingFlow -= flow; // track amount we're allowed to continue depleting from hatches
+ totalFlow += flow; // track total input used
+ if (!achievement) {
+ try {
+ GT_Mod.achievements.issueAchievement(
+ this.getBaseMetaTileEntity()
+ .getWorld()
+ .getPlayerEntityByName(
+ this.getBaseMetaTileEntity()
+ .getOwnerName()),
+ "efficientsteam");
+ } catch (Exception ignored) {}
+ achievement = true;
+ }
+ } else if (GT_ModHandler.isAnySteam(aFluidStack)) {
+ depleteInput(new FluidStack(aFluidStack, aFluidStack.amount));
+ }
+ }
+ if (totalFlow <= 0) return 0;
+ tEU = totalFlow;
+ addOutput(GT_ModHandler.getSteam(totalFlow));
+ if (totalFlow == (GT_Utility.safeInt((long) realOptFlow))) {
+ tEU = GT_Utility.safeInt((long) tEU * (long) aBaseEff / 10000L);
+ } else {
+ float efficiency = getOverflowEfficiency(
+ totalFlow,
+ (GT_Utility.safeInt((long) realOptFlow)),
+ overflowMultiplier);
+ tEU *= efficiency;
+ tEU = Math.max(1, GT_Utility.safeInt((long) tEU * (long) aBaseEff / 10000L));
+ }
+
+ // If next output is above the maximum the dynamo can handle, set it to the maximum instead of exploding the
+ // turbine
+ // Raising the maximum allowed flow rate to account for the efficiency changes beyond the optimal flow rate can
+ // explode turbines on world load
+ if (tEU > getMaximumOutput()) {
+ tEU = GT_Utility.safeInt(getMaximumOutput());
+ }
+
+ return tEU;
+ }
+
+ @Override
+ float getOverflowEfficiency(int totalFlow, int actualOptimalFlow, int overflowMultiplier) {
+ // overflowMultiplier changes how quickly the turbine loses efficiency after flow goes beyond the optimal value
+ // At the default value of 1, any flow will generate less EU/t than optimal flow, regardless of the amount of
+ // fuel used
+ // The bigger this number is, the slower efficiency loss happens as flow moves beyond the optimal value
+ // Superheated steam is the second least efficient out of all turbine fuels in this regard, with steam being the
+ // least efficient
+ float efficiency = 0;
+
+ if (totalFlow > actualOptimalFlow) {
+ efficiency = 1.0f
+ - Math.abs((totalFlow - actualOptimalFlow)) / ((float) actualOptimalFlow * (overflowMultiplier + 2));
+ } else {
+ efficiency = 1.0f - Math.abs((totalFlow - actualOptimalFlow) / (float) actualOptimalFlow);
+ }
+
+ return efficiency;
+ }
+
+ @Override
+ public void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ if (side == getBaseMetaTileEntity().getFrontFacing()) {
+ looseFit ^= true;
+ GT_Utility.sendChatToPlayer(
+ aPlayer,
+ looseFit ? GT_Utility.trans("500", "Fitting: Loose - More Flow")
+ : GT_Utility.trans("501", "Fitting: Tight - More Efficiency"));
+ }
+ }
+
+ @Override
+ public int getDamageToComponent(ItemStack aStack) {
+ return (looseFit && XSTR_INSTANCE.nextInt(4) == 0) ? 0 : 1;
+ }
+
+ @Override
+ public String[] getInfoData() {
+ super.looseFit = looseFit;
+ return super.getInfoData();
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ aNBT.setBoolean("turbineFitting", looseFit);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ looseFit = aNBT.getBoolean("turbineFitting");
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeTurbine_Plasma.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeTurbine_Plasma.java
new file mode 100644
index 0000000000..2ecc79cd3b
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeTurbine_Plasma.java
@@ -0,0 +1,391 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static gregtech.api.enums.Textures.BlockIcons.LARGETURBINE_NEW5;
+import static gregtech.api.enums.Textures.BlockIcons.LARGETURBINE_NEW_ACTIVE5;
+import static gregtech.api.enums.Textures.BlockIcons.LARGETURBINE_NEW_EMPTY5;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASINGS;
+import static gregtech.api.enums.Textures.BlockIcons.casingTexturePages;
+import static gregtech.api.util.GT_Utility.filterValidMTEs;
+
+import java.util.ArrayList;
+
+import net.minecraft.block.Block;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.StatCollector;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidRegistry;
+import net.minecraftforge.fluids.FluidStack;
+
+import org.jetbrains.annotations.NotNull;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Dynamo;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Muffler;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.shutdown.ShutDownReasonRegistry;
+import gregtech.common.items.GT_MetaGenerated_Tool_01;
+
+public class GT_MetaTileEntity_LargeTurbine_Plasma extends GT_MetaTileEntity_LargeTurbine {
+
+ public GT_MetaTileEntity_LargeTurbine_Plasma(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_LargeTurbine_Plasma(String aName) {
+ super(aName);
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection aFacing,
+ int colorIndex, boolean aActive, boolean redstoneLevel) {
+ return new ITexture[] { MACHINE_CASINGS[1][colorIndex + 1],
+ aFacing == side ? (aActive ? TextureFactory.builder()
+ .addIcon(LARGETURBINE_NEW_ACTIVE5)
+ .build()
+ : hasTurbine() ? TextureFactory.builder()
+ .addIcon(LARGETURBINE_NEW5)
+ .build()
+ : TextureFactory.builder()
+ .addIcon(LARGETURBINE_NEW_EMPTY5)
+ .build())
+ : casingTexturePages[0][60] };
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Plasma Turbine")
+ .addInfo("Controller block for the Large Plasma Generator")
+ .addInfo("Needs a Turbine, place inside controller")
+ .addInfo("Use your Fusion Reactor to produce the Plasma")
+ .addSeparator()
+ .beginStructureBlock(3, 3, 4, true)
+ .addController("Front center")
+ .addCasingInfoRange("Tungstensteel Turbine Casing", 8, 31, false)
+ .addDynamoHatch("Back center", 1)
+ .addMaintenanceHatch("Side centered", 2)
+ .addInputHatch("Plasma Fluid, Side centered", 2)
+ .addOutputHatch("Molten Fluid, optional, Side centered", 2)
+ .toolTipFinisher("Gregtech");
+ return tt;
+ }
+
+ public int getFuelValue(FluidStack aLiquid) {
+ if (aLiquid == null) return 0;
+ GT_Recipe tFuel = RecipeMaps.plasmaFuels.getBackend()
+ .findFuel(aLiquid);
+ if (tFuel != null) return tFuel.mSpecialValue;
+ return 0;
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_LargeTurbine_Plasma(mName);
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.plasmaFuels;
+ }
+
+ @Override
+ public int getRecipeCatalystPriority() {
+ return -1;
+ }
+
+ @Override
+ protected boolean filtersFluid() {
+ return false;
+ }
+
+ @Override
+ public Block getCasingBlock() {
+ return GregTech_API.sBlockCasings4;
+ }
+
+ @Override
+ public byte getCasingMeta() {
+ return 12;
+ }
+
+ @Override
+ public int getCasingTextureIndex() {
+ return 60;
+ }
+
+ @Override
+ public boolean isNewStyleRendering() {
+ return true;
+ }
+
+ @Override
+ int fluidIntoPower(ArrayList<FluidStack> aFluids, int aOptFlow, int aBaseEff, int overflowMultiplier,
+ float[] flowMultipliers) {
+ if (aFluids.size() >= 1) {
+ aOptFlow *= 800; // CHANGED THINGS HERE, check recipe runs once per 20 ticks
+ int tEU = 0;
+
+ int actualOptimalFlow = 0;
+
+ FluidStack firstFuelType = new FluidStack(aFluids.get(0), 0); // Identify a SINGLE type of fluid to process.
+ // Doesn't matter which one. Ignore the rest!
+ int fuelValue = getFuelValue(firstFuelType);
+ actualOptimalFlow = GT_Utility
+ .safeInt((long) Math.ceil((double) aOptFlow * flowMultipliers[2] / (double) fuelValue));
+ this.realOptFlow = actualOptimalFlow; // For scanner info
+
+ // Allowed to use up to 550% optimal flow rate, depending on the value of overflowMultiplier.
+ // This value is chosen because the highest EU/t possible depends on the overflowMultiplier, and the formula
+ // used
+ // makes it so the flow rate for that max, per value of overflowMultiplier, is (percentage of optimal flow
+ // rate):
+ // - 250% if it is 1
+ // - 400% if it is 2
+ // - 550% if it is 3
+ // Variable required outside of loop for multi-hatch scenarios.
+ int remainingFlow = GT_Utility.safeInt((long) (actualOptimalFlow * (1.5f * overflowMultiplier + 1)));
+ int flow = 0;
+ int totalFlow = 0;
+
+ storedFluid = 0;
+ for (FluidStack aFluid : aFluids) {
+ if (aFluid.isFluidEqual(firstFuelType)) {
+ flow = Math.min(aFluid.amount, remainingFlow); // try to use up to the max flow defined just above
+ depleteInput(new FluidStack(aFluid, flow)); // deplete that amount
+ this.storedFluid += aFluid.amount;
+ remainingFlow -= flow; // track amount we're allowed to continue depleting from hatches
+ totalFlow += flow; // track total input used
+ }
+ }
+ String fn = FluidRegistry.getFluidName(firstFuelType);
+ String[] nameSegments = fn.split("\\.", 2);
+ if (nameSegments.length == 2) {
+ String outputName = nameSegments[1];
+ FluidStack output = FluidRegistry.getFluidStack(outputName, totalFlow);
+ if (output == null) {
+ output = FluidRegistry.getFluidStack("molten." + outputName, totalFlow);
+ }
+ if (output != null) {
+ addOutput(output);
+ }
+ }
+ if (totalFlow <= 0) return 0;
+ tEU = GT_Utility.safeInt((long) ((fuelValue / 20D) * (double) totalFlow));
+
+ // GT_FML_LOGGER.info(totalFlow+" : "+fuelValue+" : "+aOptFlow+" : "+actualOptimalFlow+" : "+tEU);
+
+ if (totalFlow != actualOptimalFlow) {
+ float efficiency = getOverflowEfficiency(totalFlow, actualOptimalFlow, overflowMultiplier);
+ tEU = (int) (tEU * efficiency);
+ }
+ tEU = GT_Utility.safeInt((long) (aBaseEff / 10000D * tEU));
+
+ // If next output is above the maximum the dynamo can handle, set it to the maximum instead of exploding the
+ // turbine
+ // Raising the maximum allowed flow rate to account for the efficiency changes beyond the optimal flow rate
+ // can explode turbines on world load
+ if (tEU > getMaximumOutput()) {
+ tEU = GT_Utility.safeInt(getMaximumOutput());
+ }
+
+ return tEU;
+ }
+ return 0;
+ }
+
+ @Override
+ float getOverflowEfficiency(int totalFlow, int actualOptimalFlow, int overflowMultiplier) {
+ // overflowMultiplier changes how quickly the turbine loses efficiency after flow goes beyond the optimal value
+ // At the default value of 1, any flow will generate less EU/t than optimal flow, regardless of the amount of
+ // fuel used
+ // The bigger this number is, the slower efficiency loss happens as flow moves beyond the optimal value
+ // Plasmas are the most efficient out of all turbine fuels in this regard
+ float efficiency = 0;
+
+ if (totalFlow > actualOptimalFlow) {
+ efficiency = 1.0f - Math.abs((totalFlow - actualOptimalFlow))
+ / ((float) actualOptimalFlow * ((overflowMultiplier * 3) + 1));
+ } else {
+ efficiency = 1.0f - Math.abs((totalFlow - actualOptimalFlow) / (float) actualOptimalFlow);
+ }
+
+ return efficiency;
+ }
+
+ @Override
+ @NotNull
+ public CheckRecipeResult checkProcessing() {
+ ItemStack controllerSlot = getControllerSlot();
+ if ((counter & 7) == 0
+ && (controllerSlot == null || !(controllerSlot.getItem() instanceof GT_MetaGenerated_Tool)
+ || controllerSlot.getItemDamage() < 170
+ || controllerSlot.getItemDamage() > 179)) {
+ stopMachine(ShutDownReasonRegistry.NO_TURBINE);
+ return CheckRecipeResultRegistry.NO_TURBINE_FOUND;
+ }
+ ArrayList<FluidStack> tFluids = getStoredFluids();
+ if (!tFluids.isEmpty()) {
+ if (baseEff == 0 || optFlow == 0
+ || counter >= 512
+ || this.getBaseMetaTileEntity()
+ .hasWorkJustBeenEnabled()
+ || this.getBaseMetaTileEntity()
+ .hasInventoryBeenModified()) {
+ counter = 0;
+ baseEff = GT_Utility.safeInt(
+ (long) ((5F
+ + ((GT_MetaGenerated_Tool) controllerSlot.getItem()).getToolCombatDamage(controllerSlot))
+ * 1000F));
+ optFlow = GT_Utility.safeInt(
+ (long) Math.max(
+ Float.MIN_NORMAL,
+ ((GT_MetaGenerated_Tool) controllerSlot.getItem()).getToolStats(controllerSlot)
+ .getSpeedMultiplier() * GT_MetaGenerated_Tool.getPrimaryMaterial(controllerSlot).mToolSpeed
+ * 50));
+ overflowMultiplier = getOverflowMultiplier(controllerSlot);
+
+ flowMultipliers[0] = GT_MetaGenerated_Tool.getPrimaryMaterial(controllerSlot).mSteamMultiplier;
+ flowMultipliers[1] = GT_MetaGenerated_Tool.getPrimaryMaterial(controllerSlot).mGasMultiplier;
+ flowMultipliers[2] = GT_MetaGenerated_Tool.getPrimaryMaterial(controllerSlot).mPlasmaMultiplier;
+
+ if (optFlow <= 0 || baseEff <= 0) {
+ stopMachine(ShutDownReasonRegistry.NONE); // in case the turbine got removed
+ return CheckRecipeResultRegistry.NO_FUEL_FOUND;
+ }
+ } else {
+ counter++;
+ }
+ }
+
+ int newPower = fluidIntoPower(tFluids, optFlow, baseEff, overflowMultiplier, flowMultipliers); // How much the
+ // turbine should
+ // be producing
+ // with this flow
+
+ int difference = newPower - this.mEUt; // difference between current output and new output
+
+ // Magic numbers: can always change by at least 10 eu/t, but otherwise by at most 1 percent of the difference in
+ // power level (per tick)
+ // This is how much the turbine can actually change during this tick
+ int maxChangeAllowed = Math.max(200, GT_Utility.safeInt((long) Math.abs(difference) / 5));
+
+ if (Math.abs(difference) > maxChangeAllowed) { // If this difference is too big, use the maximum allowed change
+ int change = maxChangeAllowed * (difference > 0 ? 1 : -1); // Make the change positive or negative.
+ this.mEUt += change; // Apply the change
+ } else this.mEUt = newPower;
+
+ if (this.mEUt <= 0) {
+ // stopMachine();
+ this.mEUt = 0;
+ this.mEfficiency = 0;
+ return CheckRecipeResultRegistry.NO_FUEL_FOUND;
+ } else {
+ this.mMaxProgresstime = 20;
+ this.mEfficiencyIncrease = 200;
+ // Overvoltage is handled inside the MultiBlockBase when pushing out to dynamos. no need to do it here.
+
+ return CheckRecipeResultRegistry.GENERATING;
+ }
+ }
+
+ @Override
+ public String[] getInfoData() {
+ int mPollutionReduction = 0;
+ for (GT_MetaTileEntity_Hatch_Muffler tHatch : filterValidMTEs(mMufflerHatches)) {
+ mPollutionReduction = Math.max(tHatch.calculatePollutionReduction(100), mPollutionReduction);
+ }
+
+ String tRunning = mMaxProgresstime > 0
+ ? EnumChatFormatting.GREEN + StatCollector.translateToLocal("GT5U.turbine.running.true")
+ + EnumChatFormatting.RESET
+ : EnumChatFormatting.RED + StatCollector.translateToLocal("GT5U.turbine.running.false")
+ + EnumChatFormatting.RESET;
+ String tMaintainance = getIdealStatus() == getRepairStatus()
+ ? EnumChatFormatting.GREEN + StatCollector.translateToLocal("GT5U.turbine.maintenance.false")
+ + EnumChatFormatting.RESET
+ : EnumChatFormatting.RED + StatCollector.translateToLocal("GT5U.turbine.maintenance.true")
+ + EnumChatFormatting.RESET;
+ int tDura = 0;
+
+ if (mInventory[1] != null && mInventory[1].getItem() instanceof GT_MetaGenerated_Tool_01) {
+ tDura = GT_Utility.safeInt(
+ (long) (100.0f / GT_MetaGenerated_Tool.getToolMaxDamage(mInventory[1])
+ * (GT_MetaGenerated_Tool.getToolDamage(mInventory[1])) + 1));
+ }
+
+ long storedEnergy = 0;
+ long maxEnergy = 0;
+ for (GT_MetaTileEntity_Hatch_Dynamo tHatch : filterValidMTEs(mDynamoHatches)) {
+ storedEnergy += tHatch.getBaseMetaTileEntity()
+ .getStoredEU();
+ maxEnergy += tHatch.getBaseMetaTileEntity()
+ .getEUCapacity();
+ }
+ String[] ret = new String[] {
+ // 8 Lines available for information panels
+ tRunning + ": "
+ + EnumChatFormatting.RED
+ + GT_Utility.formatNumbers(((long) mEUt * mEfficiency) / 10000)
+ + EnumChatFormatting.RESET
+ + " EU/t", /* 1 */
+ tMaintainance, /* 2 */
+ StatCollector.translateToLocal("GT5U.turbine.efficiency") + ": "
+ + EnumChatFormatting.YELLOW
+ + (mEfficiency / 100F)
+ + EnumChatFormatting.RESET
+ + "%", /* 2 */
+ StatCollector.translateToLocal("GT5U.multiblock.energy") + ": "
+ + EnumChatFormatting.GREEN
+ + GT_Utility.formatNumbers(storedEnergy)
+ + EnumChatFormatting.RESET
+ + " EU / "
+ + /* 3 */ EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(maxEnergy)
+ + EnumChatFormatting.RESET
+ + " EU",
+ StatCollector.translateToLocal("GT5U.turbine.flow") + ": "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(GT_Utility.safeInt((long) realOptFlow))
+ + EnumChatFormatting.RESET
+ + " L/s"
+ + /* 4 */ EnumChatFormatting.YELLOW
+ + " ("
+ + (looseFit ? StatCollector.translateToLocal("GT5U.turbine.loose")
+ : StatCollector.translateToLocal("GT5U.turbine.tight"))
+ + ")", /* 5 */
+ StatCollector.translateToLocal("GT5U.turbine.fuel") + ": "
+ + EnumChatFormatting.GOLD
+ + GT_Utility.formatNumbers(storedFluid)
+ + EnumChatFormatting.RESET
+ + "L", /* 6 */
+ StatCollector.translateToLocal(
+ "GT5U.turbine.dmg") + ": " + EnumChatFormatting.RED + tDura + EnumChatFormatting.RESET + "%", /* 7 */
+ StatCollector.translateToLocal("GT5U.multiblock.pollution") + ": "
+ + EnumChatFormatting.GREEN
+ + mPollutionReduction
+ + EnumChatFormatting.RESET
+ + " %" /* 8 */
+ };
+ if (!this.getClass()
+ .getName()
+ .contains("Steam"))
+ ret[4] = StatCollector.translateToLocal("GT5U.turbine.flow") + ": "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.safeInt((long) realOptFlow)
+ + EnumChatFormatting.RESET
+ + " L/s";
+ return ret;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeTurbine_Steam.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeTurbine_Steam.java
new file mode 100644
index 0000000000..849d0af462
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeTurbine_Steam.java
@@ -0,0 +1,273 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static gregtech.api.enums.GT_Values.STEAM_PER_WATER;
+import static gregtech.api.enums.Textures.BlockIcons.LARGETURBINE_NEW5;
+import static gregtech.api.enums.Textures.BlockIcons.LARGETURBINE_NEW_ACTIVE5;
+import static gregtech.api.enums.Textures.BlockIcons.LARGETURBINE_NEW_EMPTY5;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASINGS;
+import static gregtech.api.enums.Textures.BlockIcons.casingTexturePages;
+import static gregtech.api.objects.XSTR.XSTR_INSTANCE;
+
+import java.util.ArrayList;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidStack;
+
+import gregtech.GT_Mod;
+import gregtech.api.GregTech_API;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_LargeTurbine_Steam extends GT_MetaTileEntity_LargeTurbine {
+
+ private int excessWater;
+ private boolean achievement = false;
+ private boolean looseFit = false;
+
+ public GT_MetaTileEntity_LargeTurbine_Steam(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_LargeTurbine_Steam(String aName) {
+ super(aName);
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection aFacing,
+ int colorIndex, boolean aActive, boolean redstoneLevel) {
+ return new ITexture[] { MACHINE_CASINGS[1][colorIndex + 1],
+ aFacing == side ? (aActive ? TextureFactory.builder()
+ .addIcon(LARGETURBINE_NEW_ACTIVE5)
+ .build()
+ : hasTurbine() ? TextureFactory.builder()
+ .addIcon(LARGETURBINE_NEW5)
+ .build()
+ : TextureFactory.builder()
+ .addIcon(LARGETURBINE_NEW_EMPTY5)
+ .build())
+ : casingTexturePages[0][57] };
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Steam Turbine")
+ .addInfo("Controller block for the Large Steam Turbine")
+ .addInfo("Needs a Turbine, place inside controller")
+ .addInfo("Outputs Distilled Water as well as producing power")
+ .addInfo("Power output depends on turbine and fitting")
+ .addInfo("Use screwdriver to adjust fitting of turbine")
+ .addSeparator()
+ .beginStructureBlock(3, 3, 4, true)
+ .addController("Front center")
+ .addCasingInfoRange("Turbine Casing", 8, 31, false)
+ .addDynamoHatch("Back center", 1)
+ .addMaintenanceHatch("Side centered", 2)
+ .addInputHatch("Steam, Side centered", 2)
+ .addOutputHatch("Distilled Water, Side centered", 2)
+ .toolTipFinisher("Gregtech");
+ return tt;
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_LargeTurbine_Steam(mName);
+ }
+
+ @Override
+ public Block getCasingBlock() {
+ return GregTech_API.sBlockCasings4;
+ }
+
+ @Override
+ public byte getCasingMeta() {
+ return 9;
+ }
+
+ @Override
+ public int getCasingTextureIndex() {
+ return 16;
+ }
+
+ @Override
+ public boolean isNewStyleRendering() {
+ return true;
+ }
+
+ private int condenseSteam(int steam) {
+ excessWater += steam;
+ int water = excessWater / STEAM_PER_WATER;
+ excessWater %= STEAM_PER_WATER;
+ return water;
+ }
+
+ @Override
+ int fluidIntoPower(ArrayList<FluidStack> aFluids, int aOptFlow, int aBaseEff, int overflowEfficiency,
+ float[] flowMultipliers) {
+ if (looseFit) {
+ float[] calculatedFlow = calculateLooseFlow(aOptFlow, aBaseEff);
+ aOptFlow = GT_Utility.safeInt((long) calculatedFlow[0]);
+ aBaseEff = GT_Utility.safeInt((long) calculatedFlow[1]);
+ }
+ int tEU = 0;
+ int totalFlow = 0; // Byproducts are based on actual flow
+ int flow = 0;
+
+ // Allowed to use up to 250% optimal flow rate, depending on the value of overflowMultiplier.
+ // This value is chosen because the highest EU/t possible depends on the overflowMultiplier, and the formula
+ // used
+ // makes it so the flow rate for that max, per value of overflowMultiplier, is (percentage of optimal flow
+ // rate):
+ // - 150% if it is 1
+ // - 200% if it is 2
+ // - 250% if it is 3
+ // Variable required outside of loop for multi-hatch scenarios.
+ this.realOptFlow = aOptFlow * flowMultipliers[0];
+ int remainingFlow = GT_Utility.safeInt((long) (realOptFlow * (0.5f * overflowMultiplier + 1)));
+
+ storedFluid = 0;
+ for (int i = 0; i < aFluids.size() && remainingFlow > 0; i++) { // loop through each hatch; extract inputs and
+ // track totals.
+ final FluidStack aFluidStack = aFluids.get(i);
+ if (GT_ModHandler.isAnySteam(aFluidStack)) {
+ flow = Math.min(aFluidStack.amount, remainingFlow); // try to use up to the max flow defined just above
+ depleteInput(new FluidStack(aFluidStack, flow)); // deplete that amount
+ this.storedFluid += aFluidStack.amount;
+ remainingFlow -= flow; // track amount we're allowed to continue depleting from hatches
+ totalFlow += flow; // track total input used
+ if (!achievement) {
+ GT_Mod.achievements.issueAchievement(
+ this.getBaseMetaTileEntity()
+ .getWorld()
+ .getPlayerEntityByName(
+ this.getBaseMetaTileEntity()
+ .getOwnerName()),
+ "muchsteam");
+ achievement = true;
+ }
+ } else if (GT_ModHandler.isSuperHeatedSteam(aFluidStack)) {
+ depleteInput(new FluidStack(aFluidStack, aFluidStack.amount));
+ }
+ }
+ if (totalFlow <= 0) return 0;
+ tEU = totalFlow;
+ int waterToOutput = condenseSteam(totalFlow);
+ addOutput(GT_ModHandler.getDistilledWater(waterToOutput));
+ if (totalFlow == (GT_Utility.safeInt((long) realOptFlow))) {
+ tEU = GT_Utility.safeInt((long) tEU * (long) aBaseEff / 20000L);
+ } else {
+ float efficiency = getOverflowEfficiency(
+ totalFlow,
+ (GT_Utility.safeInt((long) realOptFlow)),
+ overflowMultiplier);
+ tEU *= efficiency;
+ tEU = Math.max(1, GT_Utility.safeInt((long) tEU * (long) aBaseEff / 20000L));
+ }
+
+ // If next output is above the maximum the dynamo can handle, set it to the maximum instead of exploding the
+ // turbine
+ // Raising the maximum allowed flow rate to account for the efficiency changes beyond the optimal flow rate can
+ // explode turbines on world load
+ if (tEU > getMaximumOutput()) {
+ tEU = GT_Utility.safeInt(getMaximumOutput());
+ }
+
+ return tEU;
+ }
+
+ @Override
+ float getOverflowEfficiency(int totalFlow, int actualOptimalFlow, int overflowMultiplier) {
+ // overflowMultiplier changes how quickly the turbine loses efficiency after flow goes beyond the optimal value
+ // At the default value of 1, any flow will generate less EU/t than optimal flow, regardless of the amount of
+ // fuel used
+ // The bigger this number is, the slower efficiency loss happens as flow moves beyond the optimal value
+ // Steam is the least efficient out of all turbine fuels in this regard
+ float efficiency = 0;
+
+ if (totalFlow > actualOptimalFlow) {
+ efficiency = 1.0f
+ - Math.abs((totalFlow - actualOptimalFlow)) / ((float) actualOptimalFlow * (overflowMultiplier + 1));
+ } else {
+ efficiency = 1.0f - Math.abs((totalFlow - actualOptimalFlow) / (float) actualOptimalFlow);
+ }
+
+ return efficiency;
+ }
+
+ public static float[] calculateLooseFlow(float aOptFlow, float aBaseEff) {
+ aOptFlow *= 4f;
+ if (aBaseEff >= 26000f) {
+ aOptFlow = aOptFlow * (float) Math.pow(1.1f, ((aBaseEff - 8000f) / 10000f) * 20f);
+ aBaseEff = aBaseEff * 0.6f;
+ } else if (aBaseEff > 22000f) {
+ aOptFlow = aOptFlow * (float) Math.pow(1.1f, ((aBaseEff - 7000f) / 10000f) * 20f);
+ aBaseEff = aBaseEff * 0.65f;
+ } else if (aBaseEff > 18000f) {
+ aOptFlow = aOptFlow * (float) Math.pow(1.1f, ((aBaseEff - 6000f) / 10000f) * 20f);
+ aBaseEff = aBaseEff * 0.70f;
+ } else if (aBaseEff > 14000f) {
+ aOptFlow = aOptFlow * (float) Math.pow(1.1f, ((aBaseEff - 5000f) / 10000f) * 20f);
+ aBaseEff = aBaseEff * 0.75f;
+ } else if (aBaseEff > 10000f) {
+ aOptFlow = aOptFlow * (float) Math.pow(1.1f, ((aBaseEff - 4000f) / 10000f) * 20f);
+ aBaseEff = aBaseEff * 0.8f;
+ } else if (aBaseEff > 6000f) {
+ aOptFlow = aOptFlow * (float) Math.pow(1.1f, ((aBaseEff - 3000f) / 10000f) * 20f);
+ aBaseEff = aBaseEff * 0.85f;
+ } else {
+ aBaseEff = aBaseEff * 0.9f;
+ }
+
+ if (aBaseEff % 100 != 0) {
+ aBaseEff -= aBaseEff % 100;
+ }
+
+ float[] looseFlow = new float[2];
+ looseFlow[0] = aOptFlow;
+ looseFlow[1] = aBaseEff;
+ return looseFlow;
+ }
+
+ @Override
+ public void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ if (side == getBaseMetaTileEntity().getFrontFacing()) {
+ looseFit ^= true;
+ GT_Utility.sendChatToPlayer(
+ aPlayer,
+ looseFit ? GT_Utility.trans("500", "Fitting: Loose - More Flow")
+ : GT_Utility.trans("501", "Fitting: Tight - More Efficiency"));
+ }
+ }
+
+ @Override
+ public int getDamageToComponent(ItemStack aStack) {
+ return (looseFit && XSTR_INSTANCE.nextInt(4) == 0) ? 0 : 1;
+ }
+
+ @Override
+ public String[] getInfoData() {
+ super.looseFit = looseFit;
+ return super.getInfoData();
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ aNBT.setBoolean("turbineFitting", looseFit);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ looseFit = aNBT.getBoolean("turbineFitting");
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_MultiFurnace.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_MultiFurnace.java
new file mode 100644
index 0000000000..0dba58092e
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_MultiFurnace.java
@@ -0,0 +1,377 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofChain;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.transpose;
+import static gregtech.api.enums.GT_HatchElement.Energy;
+import static gregtech.api.enums.GT_HatchElement.InputBus;
+import static gregtech.api.enums.GT_HatchElement.Maintenance;
+import static gregtech.api.enums.GT_HatchElement.Muffler;
+import static gregtech.api.enums.GT_HatchElement.OutputBus;
+import static gregtech.api.enums.GT_Values.VN;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_MULTI_SMELTER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_MULTI_SMELTER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_MULTI_SMELTER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_MULTI_SMELTER_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.casingTexturePages;
+import static gregtech.api.util.GT_Utility.filterValidMTEs;
+
+import java.util.ArrayList;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.StatCollector;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+
+import gregtech.GT_Mod;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.HeatingCoilLevel;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Energy;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Muffler;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_OverclockCalculator;
+import gregtech.api.util.GT_StructureUtility;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_MultiFurnace
+ extends GT_MetaTileEntity_AbstractMultiFurnace<GT_MetaTileEntity_MultiFurnace> implements ISurvivalConstructable {
+
+ private int mLevel = 0;
+ private int mCostDiscount = 1;
+
+ private static final long RECIPE_EUT = 4;
+ private static final int RECIPE_DURATION = 512;
+ private static final int CASING_INDEX = 11;
+ private static final String STRUCTURE_PIECE_MAIN = "main";
+ private static final IStructureDefinition<GT_MetaTileEntity_MultiFurnace> STRUCTURE_DEFINITION = StructureDefinition
+ .<GT_MetaTileEntity_MultiFurnace>builder()
+ .addShape(
+ STRUCTURE_PIECE_MAIN,
+ transpose(new String[][] { { "ccc", "cmc", "ccc" }, { "CCC", "C-C", "CCC" }, { "b~b", "bbb", "bbb" } }))
+ .addElement('c', ofBlock(GregTech_API.sBlockCasings1, CASING_INDEX))
+ .addElement('m', Muffler.newAny(CASING_INDEX, 2))
+ .addElement(
+ 'C',
+ GT_StructureUtility
+ .ofCoil(GT_MetaTileEntity_MultiFurnace::setCoilLevel, GT_MetaTileEntity_MultiFurnace::getCoilLevel))
+ .addElement(
+ 'b',
+ ofChain(
+ GT_StructureUtility.<GT_MetaTileEntity_MultiFurnace>buildHatchAdder()
+ .atLeast(Maintenance, InputBus, OutputBus, Energy)
+ .casingIndex(CASING_INDEX)
+ .dot(1)
+ .build(),
+ ofBlock(GregTech_API.sBlockCasings1, CASING_INDEX)))
+ .build();
+
+ public GT_MetaTileEntity_MultiFurnace(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_MultiFurnace(String aName) {
+ super(aName);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_MultiFurnace(this.mName);
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Furnace")
+ .addInfo("Controller Block for the Multi Smelter")
+ .addInfo("Smelts up to 8-8192 items at once")
+ .addInfo("Items smelted increases with coil tier")
+ .addPollutionAmount(getPollutionPerSecond(null))
+ .addSeparator()
+ .beginStructureBlock(3, 3, 3, true)
+ .addController("Front bottom")
+ .addCasingInfoRange("Heat Proof Machine Casing", 8, 14, false)
+ .addOtherStructurePart("Heating Coils", "Middle layer")
+ .addEnergyHatch("Any bottom casing", 1)
+ .addMaintenanceHatch("Any bottom casing", 1)
+ .addMufflerHatch("Top Middle", 2)
+ .addInputBus("Any bottom casing", 1)
+ .addOutputBus("Any bottom casing", 1)
+ .toolTipFinisher("Gregtech");
+ return tt;
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity baseMetaTileEntity, ForgeDirection sideDirection,
+ ForgeDirection facingDirection, int colorIndex, boolean active, boolean redstoneLevel) {
+ if (sideDirection != facingDirection) return new ITexture[] { casingTexturePages[0][CASING_INDEX] };
+ if (active) return new ITexture[] { casingTexturePages[0][CASING_INDEX], TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_MULTI_SMELTER_ACTIVE)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_MULTI_SMELTER_ACTIVE_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ return new ITexture[] { casingTexturePages[0][CASING_INDEX], TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_MULTI_SMELTER)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_MULTI_SMELTER_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.furnaceRecipes;
+ }
+
+ @Override
+ public int getPollutionPerSecond(ItemStack aStack) {
+ return GT_Mod.gregtechproxy.mPollutionMultiSmelterPerSecond;
+ }
+
+ @Override
+ @NotNull
+ public CheckRecipeResult checkProcessing() {
+ ArrayList<ItemStack> tInputList = getAllStoredInputs();
+ if (tInputList.isEmpty()) return CheckRecipeResultRegistry.NO_RECIPE;
+
+ int mVoltage = GT_Utility.safeInt(getMaxInputVoltage());
+
+ GT_OverclockCalculator calculator = new GT_OverclockCalculator().setEUt(mVoltage)
+ .setRecipeEUt(RECIPE_EUT)
+ .setDuration(RECIPE_DURATION);
+ int maxParallel = this.mLevel;
+ int originalMaxParallel = maxParallel;
+ double tickTimeAfterOC = calculator.calculateDurationUnderOneTick();
+ if (tickTimeAfterOC < 1) {
+ maxParallel = GT_Utility.safeInt((long) (maxParallel / tickTimeAfterOC), 0);
+ }
+
+ int maxParallelBeforeBatchMode = maxParallel;
+ if (isBatchModeEnabled()) {
+ maxParallel = GT_Utility.safeInt((long) maxParallel * getMaxBatchSize(), 0);
+ }
+
+ // Calculate parallel
+ int tCurrentParallel = 0;
+ for (ItemStack item : tInputList) {
+ ItemStack smeltedOutput = GT_ModHandler.getSmeltingOutput(item, false, null);
+ if (smeltedOutput != null) {
+ if (item.stackSize <= (maxParallel - tCurrentParallel)) {
+ tCurrentParallel += item.stackSize;
+ } else {
+ tCurrentParallel = maxParallel;
+ break;
+ }
+ }
+ }
+ if (tCurrentParallel <= 0) {
+ return CheckRecipeResultRegistry.NO_RECIPE;
+ }
+ int currentParallelBeforeBatchMode = Math.min(tCurrentParallel, maxParallelBeforeBatchMode);
+
+ long eutUseAfterOC = calculator.calculateEUtConsumptionUnderOneTick(
+ 1,
+ (int) Math.ceil((double) currentParallelBeforeBatchMode / originalMaxParallel));
+ calculator
+ .setParallel(Math.min((int) Math.ceil((double) currentParallelBeforeBatchMode / originalMaxParallel), 1))
+ .calculate();
+
+ double batchMultiplierMax = 1;
+ // In case batch mode enabled
+ if (tCurrentParallel > maxParallelBeforeBatchMode && calculator.getDuration() < getMaxBatchSize()) {
+ batchMultiplierMax = (double) getMaxBatchSize() / calculator.getDuration();
+ batchMultiplierMax = Math.min(batchMultiplierMax, (double) tCurrentParallel / maxParallelBeforeBatchMode);
+ }
+ int finalParallel = (int) (batchMultiplierMax * maxParallelBeforeBatchMode);
+
+ // Consume inputs and generate outputs
+ ArrayList<ItemStack> smeltedOutputs = new ArrayList<>();
+ int remainingCost = finalParallel;
+ for (ItemStack item : tInputList) {
+ ItemStack smeltedOutput = GT_ModHandler.getSmeltingOutput(item, false, null);
+ if (smeltedOutput != null) {
+ if (remainingCost >= item.stackSize) {
+ remainingCost -= item.stackSize;
+ smeltedOutput.stackSize *= item.stackSize;
+ item.stackSize = 0;
+ smeltedOutputs.add(smeltedOutput);
+ } else {
+ smeltedOutput.stackSize *= remainingCost;
+ item.stackSize -= remainingCost;
+ smeltedOutputs.add(smeltedOutput);
+ break;
+ }
+ }
+ }
+ this.mOutputItems = smeltedOutputs.toArray(new ItemStack[0]);
+
+ this.mEfficiency = 10000 - (getIdealStatus() - getRepairStatus()) * 1000;
+ this.mEfficiencyIncrease = 10000;
+ this.mMaxProgresstime = (int) (calculator.getDuration() * batchMultiplierMax);
+ this.lEUt = eutUseAfterOC;
+
+ if (this.lEUt > 0) this.lEUt = -this.lEUt;
+
+ updateSlots();
+ return CheckRecipeResultRegistry.SUCCESSFUL;
+ }
+
+ @Override
+ public IStructureDefinition<GT_MetaTileEntity_MultiFurnace> getStructureDefinition() {
+ return STRUCTURE_DEFINITION;
+ }
+
+ @Override
+ public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+ this.mLevel = 0;
+ this.mCostDiscount = 1;
+
+ replaceDeprecatedCoils(aBaseMetaTileEntity);
+
+ setCoilLevel(HeatingCoilLevel.None);
+
+ if (!checkPiece(STRUCTURE_PIECE_MAIN, 1, 2, 0)) return false;
+
+ if (getCoilLevel() == HeatingCoilLevel.None) return false;
+
+ if (mMaintenanceHatches.size() != 1) return false;
+
+ if (getCoilLevel().getHeat() < 9000) {
+ this.mLevel = 8 * getCoilLevel().getLevel();
+ } else {
+ this.mLevel = 1 << (getCoilLevel().getTier());
+ }
+ this.mCostDiscount = getCoilLevel().getCostDiscount();
+ return true;
+ }
+
+ private void replaceDeprecatedCoils(IGregTechTileEntity aBaseMetaTileEntity) {
+ final int xDir = aBaseMetaTileEntity.getBackFacing().offsetX;
+ final int zDir = aBaseMetaTileEntity.getBackFacing().offsetZ;
+ final int tX = aBaseMetaTileEntity.getXCoord() + xDir;
+ final int tY = aBaseMetaTileEntity.getYCoord();
+ final int tZ = aBaseMetaTileEntity.getZCoord() + zDir;
+ int tUsedMeta;
+ for (int xPos = tX - 1; xPos <= tX + 1; xPos++) for (int zPos = tZ - 1; zPos <= tZ + 1; zPos++) {
+ if ((xPos == tX) && (zPos == tZ)) continue;
+ tUsedMeta = aBaseMetaTileEntity.getMetaID(xPos, tY + 1, zPos);
+ if (tUsedMeta >= 12 && tUsedMeta <= 14
+ && aBaseMetaTileEntity.getBlock(xPos, tY + 1, zPos) == GregTech_API.sBlockCasings1)
+ aBaseMetaTileEntity.getWorld()
+ .setBlock(xPos, tY + 1, zPos, GregTech_API.sBlockCasings5, tUsedMeta - 12, 3);
+ }
+ }
+
+ @Override
+ public String[] getInfoData() {
+ int mPollutionReduction = 0;
+ for (final GT_MetaTileEntity_Hatch_Muffler tHatch : filterValidMTEs(mMufflerHatches))
+ mPollutionReduction = Math.max(tHatch.calculatePollutionReduction(100), mPollutionReduction);
+
+ long storedEnergy = 0;
+ long maxEnergy = 0;
+ for (final GT_MetaTileEntity_Hatch_Energy tHatch : filterValidMTEs(mEnergyHatches)) {
+ storedEnergy += tHatch.getBaseMetaTileEntity()
+ .getStoredEU();
+ maxEnergy += tHatch.getBaseMetaTileEntity()
+ .getEUCapacity();
+ }
+
+ return new String[] {
+ StatCollector.translateToLocal("GT5U.multiblock.Progress") + ": "
+ + EnumChatFormatting.GREEN
+ + GT_Utility.formatNumbers(mProgresstime / 20)
+ + EnumChatFormatting.RESET
+ + " s / "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(mMaxProgresstime / 20)
+ + EnumChatFormatting.RESET
+ + " s",
+ StatCollector.translateToLocal("GT5U.multiblock.energy") + ": "
+ + EnumChatFormatting.GREEN
+ + GT_Utility.formatNumbers(storedEnergy)
+ + EnumChatFormatting.RESET
+ + " EU / "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(maxEnergy)
+ + EnumChatFormatting.RESET
+ + " EU",
+ StatCollector.translateToLocal("GT5U.multiblock.usage") + ": "
+ + EnumChatFormatting.RED
+ + GT_Utility.formatNumbers(-mEUt)
+ + EnumChatFormatting.RESET
+ + " EU/t",
+ StatCollector.translateToLocal("GT5U.multiblock.mei") + ": "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(getMaxInputVoltage())
+ + EnumChatFormatting.RESET
+ + " EU/t(*2A) "
+ + StatCollector.translateToLocal("GT5U.machines.tier")
+ + ": "
+ + EnumChatFormatting.YELLOW
+ + VN[GT_Utility.getTier(getMaxInputVoltage())]
+ + EnumChatFormatting.RESET,
+ StatCollector.translateToLocal("GT5U.multiblock.problems") + ": "
+ + EnumChatFormatting.RED
+ + (getIdealStatus() - getRepairStatus())
+ + EnumChatFormatting.RESET
+ + " "
+ + StatCollector.translateToLocal("GT5U.multiblock.efficiency")
+ + ": "
+ + EnumChatFormatting.YELLOW
+ + mEfficiency / 100.0F
+ + EnumChatFormatting.RESET
+ + " %",
+ StatCollector.translateToLocal("GT5U.MS.multismelting") + ": "
+ + EnumChatFormatting.GREEN
+ + mLevel
+ + EnumChatFormatting.RESET
+ + " Discount: (EU/t) / "
+ + EnumChatFormatting.GREEN
+ + GT_Utility.formatNumbers(mCostDiscount)
+ + EnumChatFormatting.RESET,
+ StatCollector.translateToLocal("GT5U.multiblock.pollution") + ": "
+ + EnumChatFormatting.GREEN
+ + mPollutionReduction
+ + EnumChatFormatting.RESET
+ + " %" };
+ }
+
+ @Override
+ public void construct(ItemStack stackSize, boolean hintsOnly) {
+ buildPiece(STRUCTURE_PIECE_MAIN, stackSize, hintsOnly, 1, 2, 0);
+ }
+
+ @Override
+ public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
+ if (mMachine) return -1;
+ return survivialBuildPiece(STRUCTURE_PIECE_MAIN, stackSize, 1, 2, 0, elementBudget, env, false, true);
+ }
+
+ @Override
+ public boolean supportsBatchMode() {
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_NanoForge.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_NanoForge.java
new file mode 100644
index 0000000000..4b0dc16943
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_NanoForge.java
@@ -0,0 +1,467 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.transpose;
+import static gregtech.api.enums.GT_HatchElement.Energy;
+import static gregtech.api.enums.GT_HatchElement.ExoticEnergy;
+import static gregtech.api.enums.GT_HatchElement.InputBus;
+import static gregtech.api.enums.GT_HatchElement.InputHatch;
+import static gregtech.api.enums.GT_HatchElement.Maintenance;
+import static gregtech.api.enums.GT_HatchElement.OutputBus;
+import static gregtech.api.enums.GT_Values.AuthorBlueWeabo;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ASSEMBLY_LINE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ASSEMBLY_LINE_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ASSEMBLY_LINE_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ASSEMBLY_LINE_GLOW;
+import static gregtech.api.util.GT_StructureUtility.buildHatchAdder;
+import static gregtech.api.util.GT_StructureUtility.ofFrame;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.StatCollector;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+import com.gtnewhorizons.modularui.common.widget.DynamicPositionedColumn;
+import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget;
+import com.gtnewhorizons.modularui.common.widget.SlotWidget;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.MaterialsUEVplus;
+import gregtech.api.enums.Textures.BlockIcons;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.logic.ProcessingLogic;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_ExtendedPowerMultiBlockBase;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_OverclockCalculator;
+import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.blocks.GT_Block_Casings8;
+
+public class GT_MetaTileEntity_NanoForge extends
+ GT_MetaTileEntity_ExtendedPowerMultiBlockBase<GT_MetaTileEntity_NanoForge> implements ISurvivalConstructable {
+
+ private static final String STRUCTURE_PIECE_MAIN = "main";
+ private static final String STRUCTURE_PIECE_TIER2 = "tier2";
+ private static final String STRUCTURE_PIECE_TIER3 = "tier3";
+ private static final IStructureDefinition<GT_MetaTileEntity_NanoForge> STRUCTURE_DEFINITION = StructureDefinition
+ .<GT_MetaTileEntity_NanoForge>builder()
+ // spotless:off
+ .addShape(STRUCTURE_PIECE_MAIN, transpose(new String[][] {
+ {" "," "," F "," C "," C "," C "," C "," F "," "," "},
+ {" "," "," F "," C "," C "," C "," C "," F "," "," "},
+ {" "," "," F "," C "," C "," C "," C "," F "," "," "},
+ {" "," "," F "," C "," C "," C "," C "," F "," "," "},
+ {" "," "," F "," C "," C "," C "," C "," F "," "," "},
+ {" "," "," FCF "," C C "," C C "," C C "," C C "," FCF "," "," "},
+ {" "," "," FCF "," C C "," C C "," C C "," C C "," FCF "," "," "},
+ {" "," "," FCF "," C C "," C C "," C C "," C C "," FCF "," "," "},
+ {" "," "," FCF "," C C "," C C "," C C "," C C "," FCF "," "," "},
+ {" "," "," FCF "," C C "," C C "," C C "," C C "," FCF "," "," "},
+ {" "," "," FCF "," C C "," C C "," C C "," C C "," FCF "," "," "},
+ {" "," "," FCF "," C C "," C C "," C C "," C C "," FCF "," "," "},
+ {" "," "," FCF "," C C "," C C "," C C "," C C "," FCF "," "," "},
+ {" "," "," FCF "," C C "," C C "," C C "," C C "," FCF "," "," "},
+ {" "," FCF "," FC CF "," C C "," C C "," C C "," C C "," FC CF "," FCF "," "},
+ {" "," FCF "," FC CF "," C C "," C C "," C C "," C C "," FC CF "," FCF "," "},
+ {" "," FCF "," FC CF "," C C "," C C "," C C "," C C "," FC CF "," FCF "," "},
+ {" "," FCF "," FC CF "," C C "," C C "," C C "," C C "," FC CF "," FCF "," "},
+ {" C "," FCF "," CC CC "," C C "," C C "," C C "," C C "," CC CC "," FCF "," C "},
+ {" C "," FCF "," CC CC "," C C "," C C "," C C "," C C "," CC CC "," FCF "," C "},
+ {" C "," FCF "," CC CC "," C C "," C C "," C C "," C C "," CC CC "," FCF "," C "},
+ {" C "," FCF "," CC CC "," CC CC "," CC CC "," CC CC "," CC CC "," CC CC "," FCF "," C "},
+ {" C "," FCF "," CC CC "," CC CC "," CC CC "," CC CC "," CC CC "," CC CC "," FCF "," C "},
+ {" C "," FCF "," CC CC "," C C "," C C "," C C "," C C "," CC CC "," FCF "," C "},
+ {" C "," FCF "," CC CC "," C C "," C C "," C C "," C C "," CC CC "," FCF "," C "},
+ {" C "," FCF "," CC CC "," C C "," C C "," C C "," C C "," CC CC "," FCF "," C "},
+ {" "," FCF "," FC CF "," C C "," C C "," C C "," C C "," FC CF "," FCF "," "},
+ {" "," FCF "," FC CF "," C C "," C C "," C C "," C C "," FC CF "," FCF "," "},
+ {" "," FCF "," FC CF "," C C "," C C "," C C "," C C "," FC CF "," FCF "," "},
+ {" "," FCF "," FC CF "," C C "," C C "," C C "," C C "," FC CF "," FCF "," "},
+ {" "," "," FCF "," C C "," C C "," C C "," C C "," FCF "," "," "},
+ {" "," "," FCF "," C C "," C C "," C C "," C C "," FCF "," "," "},
+ {" "," "," FCF "," C C "," C C "," C C "," C C "," FCF "," "," "},
+ {" "," "," FCF "," C C "," C C "," C C "," C C "," FCF "," "," "},
+ {" "," "," FCF "," C C "," C C "," C C "," C C "," FCF "," "," "},
+ {" "," "," FCF "," C C "," C C "," C C "," C C "," FCF "," "," "},
+ {" "," "," FCF "," C C "," C C "," C C "," C C "," FCF "," "," "},
+ {" "," BB~BB "," BBBBBBB ","BBBBBBBBB","BBBBBBBBB","BBBBBBBBB","BBBBBBBBB"," BBBBBBB "," BBBBB "," "}
+ }))
+ .addShape(STRUCTURE_PIECE_TIER2, transpose(new String[][] {
+ {" ", " ", " CC ", " CCCC ", " CCCC ", " CC ", " ", " "},
+ {" ", " ", " AA ", " ACCA ", " ACCA ", " AA ", " ", " "},
+ {" ", " ", " CC ", " CCCC ", " CCCC ", " CC ", " ", " "},
+ {" ", " ", " ", " CC ", " CC ", " ", " ", " "},
+ {" ", " ", " ", " CC ", " CC ", " ", " ", " "},
+ {" ", " ", " ", " CC ", " CC ", " ", " ", " "},
+ {" ", " ", " ", " CC ", " CC ", " ", " ", " "},
+ {" ", " ", " CC ", " CCCC ", " CCCC ", " CC ", " ", " "},
+ {" ", " ", " AA ", " ACCA ", " ACCA ", " AA ", " ", " "},
+ {" ", " ", " CC ", " CCCC ", " CCCC ", " CC ", " ", " "},
+ {" ", " ", " ", " CC ", " CC ", " ", " ", " "},
+ {" ", " ", " ", " CC ", " CC ", " ", " ", " "},
+ {" ", " ", " ", " CC ", " CC ", " ", " ", " "},
+ {" ", " ", " ", " CC ", " CC ", " ", " ", " "},
+ {" CCCCCC ", "CCCCCCCC", "CCCCCCCC", "CCCCCCCC", "CCCCCCCC", "CCCCCCCC", "CCCCCCCC", " CCCCCC "}
+ }))
+ .addShape(STRUCTURE_PIECE_TIER3, transpose(new String[][] {
+ {" ", " ", " CC ", " CCCC ", " CCCC ", " CC ", " ", " "},
+ {" ", " ", " FFAA ", " ACCA ", " ACCA ", " AAFF ", " ", " "},
+ {" ", " ", "F CC ", "F CCCC ", " CCCC F", " CC F", " ", " "},
+ {" ", " ", " F", " CC F", "F CC ", "F ", " ", " "},
+ {" ", " F ", " ", " CC ", " CC ", " ", " F ", " "},
+ {" FF ", " ", " ", " CC ", " CC ", " ", " ", " FF "},
+ {" FF ", " ", " ", " CC ", " CC ", " ", " ", " FF "},
+ {" ", " F ", " ", " CC ", " CC ", " ", " F ", " "},
+ {" ", " ", "F ", "F CC ", " CC F", " F", " ", " "},
+ {" ", " ", " CC F", " CCCC F", "F CCCC ", "F CC ", " ", " "},
+ {" ", " F ", " CC ", " CCCC ", " CCCC ", " CC ", " F ", " "},
+ {" FF ", " ", " CC ", " CCCC ", " CCCC ", " CC ", " ", " FF "},
+ {" FF ", " ", " CC ", " CCCC ", " CCCC ", " CC ", " ", " FF "},
+ {" ", " F ", " ", " CC ", " CC ", " ", " F ", " "},
+ {" ", " ", "F ", "F CC ", " CC F", " F", " ", " "},
+ {" ", " ", " F", " CC F", "F CC ", "F ", " ", " "},
+ {" ", " F ", " ", " CC ", " CC ", " ", " F ", " "},
+ {" FF ", " ", " ", " CC ", " CC ", " ", " ", " FF "},
+ {" FF ", " ", " ", " CC ", " CC ", " ", " ", " FF "},
+ {" ", " F ", " ", " CC ", " CC ", " ", " F ", " "},
+ {" ", " ", "F CC ", "F CCCC ", " CCCC F", " CC F", " ", " "},
+ {" ", " ", " AA F", " ACCA F", "F ACCA ", "F AA ", " ", " "},
+ {" ", " F ", " CC ", " CCCC ", " CCCC ", " CC ", " F ", " "},
+ {" FF ", " ", " ", " CC ", " CC ", " ", " ", " FF "},
+ {" FF ", " ", " ", " CC ", " CC ", " ", " ", " FF "},
+ {" ", " F ", " ", " CC ", " CC ", " ", " F ", " "},
+ {" CCCCCC ", "CCCCCCCC", "CCCCCCCC", "CCCCCCCC", "CCCCCCCC", "CCCCCCCC", "CCCCCCCC", " CCCCCC "}
+ }))
+ //spotless:on
+ .addElement('F', ofFrame(Materials.StellarAlloy))
+ .addElement('C', ofBlock(GregTech_API.sBlockCasings8, 10))
+ .addElement('A', ofBlock(GregTech_API.sBlockCasings2, 5))
+ .addElement(
+ 'B',
+ buildHatchAdder(GT_MetaTileEntity_NanoForge.class)
+ .atLeast(InputHatch, OutputBus, InputBus, Maintenance, Energy.or(ExoticEnergy))
+ .dot(1)
+ .casingIndex(((GT_Block_Casings8) GregTech_API.sBlockCasings8).getTextureIndex(10))
+ .buildAndChain(GregTech_API.sBlockCasings8, 10))
+ .build();
+ private byte mSpecialTier = 0;
+
+ public GT_MetaTileEntity_NanoForge(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_NanoForge(String aName) {
+ super(aName);
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.nanoForgeRecipes;
+ }
+
+ @Override
+ public void construct(ItemStack stackSize, boolean hintsOnly) {
+ buildPiece(STRUCTURE_PIECE_MAIN, stackSize, hintsOnly, 4, 37, 1);
+ if (stackSize.stackSize > 1) {
+ buildPiece(STRUCTURE_PIECE_TIER2, stackSize, hintsOnly, -7, 14, 4);
+ }
+ if (stackSize.stackSize > 2) {
+ buildPiece(STRUCTURE_PIECE_TIER3, stackSize, hintsOnly, 14, 26, 4);
+ }
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_NanoForge(this.mName);
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity baseMetaTileEntity, ForgeDirection sideDirection,
+ ForgeDirection facingDirection, int colorIndex, boolean active, boolean redstoneLevel) {
+ if (sideDirection == facingDirection) {
+ if (active) return new ITexture[] {
+ BlockIcons.getCasingTextureForId(GT_Utility.getCasingTextureIndex(GregTech_API.sBlockCasings8, 10)),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_ASSEMBLY_LINE_ACTIVE)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_ASSEMBLY_LINE_ACTIVE_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ return new ITexture[] {
+ BlockIcons.getCasingTextureForId(GT_Utility.getCasingTextureIndex(GregTech_API.sBlockCasings8, 10)),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_ASSEMBLY_LINE)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_ASSEMBLY_LINE_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ }
+ return new ITexture[] {
+ BlockIcons.getCasingTextureForId(GT_Utility.getCasingTextureIndex(GregTech_API.sBlockCasings8, 10)) };
+ }
+
+ @Override
+ public IStructureDefinition<GT_MetaTileEntity_NanoForge> getStructureDefinition() {
+ return STRUCTURE_DEFINITION;
+ }
+
+ @Override
+ public boolean isCorrectMachinePart(ItemStack aStack) {
+ return true;
+ }
+
+ @Override
+ protected ProcessingLogic createProcessingLogic() {
+ return new ProcessingLogic() {
+
+ @Override
+ protected @Nonnull CheckRecipeResult validateRecipe(@Nonnull GT_Recipe recipe) {
+ return recipe.mSpecialValue <= mSpecialTier ? CheckRecipeResultRegistry.SUCCESSFUL
+ : CheckRecipeResultRegistry.NO_RECIPE;
+ }
+
+ @Nonnull
+ @Override
+ protected GT_OverclockCalculator createOverclockCalculator(@Nonnull GT_Recipe recipe) {
+ return super.createOverclockCalculator(recipe)
+ .setDurationDecreasePerOC(mSpecialTier > recipe.mSpecialValue ? 2 : 1);
+ }
+ };
+ }
+
+ @Override
+ protected void setProcessingLogicPower(ProcessingLogic logic) {
+ logic.setAvailableVoltage(getMaxInputEu());
+ logic.setAvailableAmperage(1);
+ logic.setAmperageOC(false);
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ super.onPostTick(aBaseMetaTileEntity, aTick);
+ if (aBaseMetaTileEntity.isServerSide()) {
+ // TODO: Look for proper fix
+ // Updates every 10 sec
+ if (mUpdate <= -150) mUpdate = 50;
+ }
+ }
+
+ @Override
+ public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+ mSpecialTier = 0;
+ if (checkPiece(STRUCTURE_PIECE_MAIN, 4, 37, 1) && aStack != null) {
+ if (aStack.isItemEqual(Materials.Carbon.getNanite(1))) {
+ mSpecialTier = 1;
+ }
+
+ if (aStack.isItemEqual(Materials.Neutronium.getNanite(1)) && checkPiece(STRUCTURE_PIECE_TIER2, -7, 14, 4)) {
+ mSpecialTier = 2;
+ }
+
+ if (aStack.isItemEqual(MaterialsUEVplus.TranscendentMetal.getNanite(1))
+ && checkPiece(STRUCTURE_PIECE_TIER2, -7, 14, 4)
+ && checkPiece(STRUCTURE_PIECE_TIER3, 14, 26, 4)) {
+ mSpecialTier = 3;
+ }
+ }
+
+ if (mMaintenanceHatches.size() != 1) {
+ return false;
+ }
+
+ if (!checkExoticAndNormalEnergyHatches()) {
+ return false;
+ }
+
+ return mSpecialTier > 0;
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack aStack) {
+ return 10000;
+ }
+
+ @Override
+ public int getDamageToComponent(ItemStack aStack) {
+ return 0;
+ }
+
+ @Override
+ public boolean explodesOnComponentBreak(ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
+ if (mMachine) return -1;
+ int built = survivialBuildPiece(STRUCTURE_PIECE_MAIN, stackSize, 4, 37, 1, elementBudget, env, false, true);
+ if (built >= 0) return built;
+ if (stackSize.stackSize > 1) {
+ built += survivialBuildPiece(STRUCTURE_PIECE_TIER2, stackSize, -7, 14, 4, elementBudget, env, false, true);
+ }
+ if (stackSize.stackSize > 2) {
+ built += survivialBuildPiece(STRUCTURE_PIECE_TIER3, stackSize, 14, 26, 4, elementBudget, env, false, true);
+ }
+ return built;
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ aNBT.setByte("mSpecialTier", mSpecialTier);
+ }
+
+ @Override
+ public void loadNBTData(final NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ if (aNBT.hasKey("mSeparate")) {
+ // backward compatibility
+ inputSeparation = aNBT.getBoolean("mSeparate");
+ }
+ mSpecialTier = aNBT.getByte("mSpecialTier");
+ }
+
+ @Override
+ protected void drawTexts(DynamicPositionedColumn screenElements, SlotWidget inventorySlot) {
+ super.drawTexts(screenElements, inventorySlot);
+ screenElements
+ .widget(
+ new TextWidget(StatCollector.translateToLocal("GT5U.gui.button.tier") + " " + mSpecialTier)
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setEnabled(widget -> getBaseMetaTileEntity().getErrorDisplayID() == 0))
+ .widget(
+ new FakeSyncWidget.IntegerSyncer(
+ () -> (int) mSpecialTier,
+ val -> mSpecialTier = (byte) (val % Byte.MAX_VALUE)));
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Nanite Fabricator")
+ .addInfo("Controller block for the Nano Forge")
+ .addInfo("Requires insane amounts of power to create nanites. Each tier")
+ .addInfo("the multi gains a new building next to it. The nanite in the")
+ .addInfo("controller slot controls the tier.")
+ .addInfo("--------------------------------------------")
+ .addInfo("Requires a Carbon Nanite to use tier " + EnumChatFormatting.DARK_PURPLE + 1)
+ .addInfo("Requires a Neutronium Nanite to use tier " + EnumChatFormatting.DARK_PURPLE + 2)
+ .addInfo("Requires a Transcendent Metal Nanite to use tier " + EnumChatFormatting.DARK_PURPLE + 3)
+ .addInfo("--------------------------------------------")
+ .addInfo("If a recipe's tier is lower than the tier of the Nano Forge")
+ .addInfo("it gains " + EnumChatFormatting.RED + "perfect overclock" + EnumChatFormatting.GRAY + ".")
+ .addInfo(AuthorBlueWeabo)
+ .addSeparator()
+ .beginStructureBlock(30, 38, 13, false)
+ .addStructureInfo("Nano Forge Structure is too complex! See schematic for details.")
+ .addStructureInfo("--------------------------------------------")
+ .addStructureInfo("Tier " + EnumChatFormatting.DARK_PURPLE + 1 + EnumChatFormatting.GRAY)
+ .addStructureInfo(
+ EnumChatFormatting.GOLD + "527" + EnumChatFormatting.GRAY + " Radiant Naquadah Alloy Casing")
+ .addStructureInfo(EnumChatFormatting.GOLD + "171" + EnumChatFormatting.GRAY + " Stellar Alloy Frame Box")
+ .addStructureInfo("--------------------------------------------")
+ .addStructureInfo("Tier " + EnumChatFormatting.DARK_PURPLE + 2 + EnumChatFormatting.GRAY)
+ .addStructureInfo(
+ EnumChatFormatting.GOLD + "148" + EnumChatFormatting.GRAY + " Radiant Naquadah Alloy Casing")
+ .addStructureInfo(EnumChatFormatting.GOLD + "16" + EnumChatFormatting.GRAY + " Assembling Line Casing")
+ .addStructureInfo("--------------------------------------------")
+ .addStructureInfo("Tier " + EnumChatFormatting.DARK_PURPLE + 3 + EnumChatFormatting.GRAY)
+ .addStructureInfo(
+ EnumChatFormatting.GOLD + "228" + EnumChatFormatting.GRAY + " Radiant Naquadah Alloy Casing")
+ .addStructureInfo(EnumChatFormatting.GOLD + "84" + EnumChatFormatting.GRAY + " Stellar Alloy Frame Box")
+ .addStructureInfo(EnumChatFormatting.GOLD + "16" + EnumChatFormatting.GRAY + " Assembling Line Casing")
+ .addStructureInfo("--------------------------------------------")
+ .addStructureInfo(
+ "Requires " + EnumChatFormatting.GOLD
+ + "1"
+ + EnumChatFormatting.GRAY
+ + "-"
+ + EnumChatFormatting.GOLD
+ + "2"
+ + EnumChatFormatting.GRAY
+ + " energy hatches or "
+ + EnumChatFormatting.GOLD
+ + "1"
+ + EnumChatFormatting.GRAY
+ + " TT energy hatch.")
+ .addStructureInfo(
+ "Requires " + EnumChatFormatting.GOLD + "1" + EnumChatFormatting.GRAY + " maintenance hatch.")
+ .addStructureInfo(
+ "Requires " + EnumChatFormatting.GOLD
+ + 1
+ + EnumChatFormatting.GRAY
+ + "+"
+ + EnumChatFormatting.GRAY
+ + " input hatches.")
+ .addStructureInfo(
+ "Requires " + EnumChatFormatting.GOLD
+ + 0
+ + EnumChatFormatting.GRAY
+ + "+"
+ + EnumChatFormatting.GRAY
+ + " output hatches.")
+ .addStructureInfo(
+ "Requires " + EnumChatFormatting.GOLD
+ + 1
+ + EnumChatFormatting.GRAY
+ + "+"
+ + EnumChatFormatting.GRAY
+ + " input busses.")
+ .addStructureInfo(
+ "Requires " + EnumChatFormatting.GOLD
+ + 1
+ + EnumChatFormatting.GRAY
+ + "+"
+ + EnumChatFormatting.GRAY
+ + " output busses.")
+ .addStructureInfo("--------------------------------------------")
+ .toolTipFinisher("GregTech");
+ return tt;
+ }
+
+ @Override
+ public final void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ inputSeparation = !inputSeparation;
+ GT_Utility.sendChatToPlayer(
+ aPlayer,
+ StatCollector.translateToLocal("GT5U.machines.separatebus") + " " + inputSeparation);
+ }
+
+ @Override
+ public boolean supportsVoidProtection() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsInputSeparation() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsBatchMode() {
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilCracker.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilCracker.java
new file mode 100644
index 0000000000..9ca671aa49
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilCracker.java
@@ -0,0 +1,423 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.onElementPass;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.transpose;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_OIL_CRACKER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_OIL_CRACKER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_OIL_CRACKER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_OIL_CRACKER_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.casingTexturePages;
+import static gregtech.api.util.GT_StructureUtility.buildHatchAdder;
+import static gregtech.api.util.GT_StructureUtility.ofCoil;
+import static gregtech.api.util.GT_Utility.filterValidMTEs;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidStack;
+
+import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.GT_HatchElement;
+import gregtech.api.enums.HeatingCoilLevel;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.logic.ProcessingLogic;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_EnhancedMultiBlockBase;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Input;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_MultiInput;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Output;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.maps.OilCrackerBackend;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.common.tileentities.machines.GT_MetaTileEntity_Hatch_Input_ME;
+import gregtech.common.tileentities.machines.IRecipeProcessingAwareHatch;
+
+public class GT_MetaTileEntity_OilCracker extends GT_MetaTileEntity_EnhancedMultiBlockBase<GT_MetaTileEntity_OilCracker>
+ implements ISurvivalConstructable {
+
+ private static final byte CASING_INDEX = 49;
+ private static final String STRUCTURE_PIECE_MAIN = "main";
+ private static final IStructureDefinition<GT_MetaTileEntity_OilCracker> STRUCTURE_DEFINITION = StructureDefinition
+ .<GT_MetaTileEntity_OilCracker>builder()
+ .addShape(
+ STRUCTURE_PIECE_MAIN,
+ transpose(
+ new String[][] { { "lcmcr", "lcmcr", "lcmcr" }, { "lc~cr", "l---r", "lcmcr" },
+ { "lcmcr", "lcmcr", "lcmcr" }, }))
+ .addElement('c', ofCoil(GT_MetaTileEntity_OilCracker::setCoilLevel, GT_MetaTileEntity_OilCracker::getCoilLevel))
+ .addElement(
+ 'l',
+ buildHatchAdder(GT_MetaTileEntity_OilCracker.class)
+ .atLeast(
+ GT_HatchElement.InputHatch.withAdder(GT_MetaTileEntity_OilCracker::addLeftHatchToMachineList),
+ GT_HatchElement.Energy,
+ GT_HatchElement.Maintenance)
+ .dot(2)
+ .casingIndex(CASING_INDEX)
+ .buildAndChain(
+ onElementPass(
+ GT_MetaTileEntity_OilCracker::onCasingAdded,
+ ofBlock(GregTech_API.sBlockCasings4, 1))))
+ .addElement(
+ 'r',
+ buildHatchAdder(GT_MetaTileEntity_OilCracker.class)
+ .atLeast(
+ GT_HatchElement.OutputHatch.withAdder(GT_MetaTileEntity_OilCracker::addRightHatchToMachineList),
+ GT_HatchElement.Energy,
+ GT_HatchElement.Maintenance)
+ .dot(3)
+ .casingIndex(CASING_INDEX)
+ .buildAndChain(
+ onElementPass(
+ GT_MetaTileEntity_OilCracker::onCasingAdded,
+ ofBlock(GregTech_API.sBlockCasings4, 1))))
+ .addElement(
+ 'm',
+ buildHatchAdder(GT_MetaTileEntity_OilCracker.class)
+ .atLeast(
+ GT_HatchElement.InputHatch.withAdder(GT_MetaTileEntity_OilCracker::addMiddleInputToMachineList)
+ .withCount(t -> t.mMiddleInputHatches.size()),
+ GT_HatchElement.InputBus,
+ GT_HatchElement.Energy,
+ GT_HatchElement.Maintenance)
+ .dot(1)
+ .casingIndex(CASING_INDEX)
+ .buildAndChain(
+ onElementPass(
+ GT_MetaTileEntity_OilCracker::onCasingAdded,
+ ofBlock(GregTech_API.sBlockCasings4, 1))))
+ .build();
+ private HeatingCoilLevel heatLevel;
+ protected final List<GT_MetaTileEntity_Hatch_Input> mMiddleInputHatches = new ArrayList<>();
+ // 0 -> left, 1 -> right, any other -> not found
+ protected int mInputOnSide;
+ protected int mOutputOnSide;
+ protected int mCasingAmount;
+
+ public GT_MetaTileEntity_OilCracker(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_OilCracker(String aName) {
+ super(aName);
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Cracker")
+ .addInfo("Controller block for the Oil Cracking Unit")
+ .addInfo("Thermally cracks heavy hydrocarbons into lighter fractions")
+ .addInfo("More efficient than the Chemical Reactor")
+ .addInfo("Gives different benefits whether it hydro or steam-cracks:")
+ .addInfo("Hydro - Consumes 20% less Hydrogen and outputs 25% more cracked fluid")
+ .addInfo("Steam - Outputs 50% more cracked fluid")
+ .addInfo("(Values compared to cracking in the Chemical Reactor)")
+ .addInfo("Place the appropriate circuit in the controller or an input bus")
+ .addSeparator()
+ .beginStructureBlock(5, 3, 3, true)
+ .addController("Front center")
+ .addCasingInfoRange("Clean Stainless Steel Machine Casing", 18, 21, false)
+ .addOtherStructurePart("2 Rings of 8 Coils", "Each side of the controller")
+ .addInfo("Gets 10% EU/t reduction per coil tier, up to a maximum of 50%")
+ .addEnergyHatch("Any casing", 1, 2, 3)
+ .addMaintenanceHatch("Any casing", 1, 2, 3)
+ .addInputHatch("For cracking fluid (Steam/Hydrogen/etc.) ONLY, Any middle ring casing", 1)
+ .addInputHatch("Any left/right side casing", 2, 3)
+ .addOutputHatch("Any right/left side casing", 2, 3)
+ .addStructureInfo("Input/Output Hatches must be on opposite sides!")
+ .addInputBus("Any middle ring casing, optional for programmed circuit automation")
+ .addStructureHint("GT5U.cracker.io_side")
+ .toolTipFinisher("Gregtech");
+ return tt;
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity baseMetaTileEntity, ForgeDirection sideDirection,
+ ForgeDirection facingDirection, int colorIndex, boolean active, boolean redstoneLevel) {
+ if (sideDirection == facingDirection) {
+ if (active) return new ITexture[] { casingTexturePages[0][CASING_INDEX], TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_OIL_CRACKER_ACTIVE)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_OIL_CRACKER_ACTIVE_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ return new ITexture[] { casingTexturePages[0][CASING_INDEX], TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_OIL_CRACKER)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_OIL_CRACKER_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ }
+ return new ITexture[] { casingTexturePages[0][CASING_INDEX] };
+ }
+
+ @Override
+ public RecipeMap<OilCrackerBackend> getRecipeMap() {
+ return RecipeMaps.crackingRecipes;
+ }
+
+ @Override
+ protected ProcessingLogic createProcessingLogic() {
+ return new ProcessingLogic() {
+
+ @Nonnull
+ @Override
+ public CheckRecipeResult process() {
+ setEuModifier(1.0F - Math.min(0.1F * (heatLevel.getTier() + 1), 0.5F));
+ return super.process();
+ }
+ };
+ }
+
+ @Override
+ public IStructureDefinition<GT_MetaTileEntity_OilCracker> getStructureDefinition() {
+ return STRUCTURE_DEFINITION;
+ }
+
+ public HeatingCoilLevel getCoilLevel() {
+ return heatLevel;
+ }
+
+ public void setCoilLevel(HeatingCoilLevel aCoilLevel) {
+ heatLevel = aCoilLevel;
+ }
+
+ private boolean addMiddleInputToMachineList(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
+ if (aTileEntity == null) return false;
+ IMetaTileEntity aMetaTileEntity = aTileEntity.getMetaTileEntity();
+ if (aMetaTileEntity == null) return false;
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Input tHatch) {
+ tHatch.updateTexture(aBaseCasingIndex);
+ tHatch.mRecipeMap = getRecipeMap();
+ return mMiddleInputHatches.add(tHatch);
+ }
+ return false;
+ }
+
+ private boolean addLeftHatchToMachineList(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
+ if (aTileEntity == null) return false;
+ IMetaTileEntity aMetaTileEntity = aTileEntity.getMetaTileEntity();
+ if (aMetaTileEntity == null) return false;
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Input tHatch) {
+ if (mInputOnSide == 1) return false;
+ mInputOnSide = 0;
+ mOutputOnSide = 1;
+ tHatch.updateTexture(aBaseCasingIndex);
+ tHatch.mRecipeMap = getRecipeMap();
+ return mInputHatches.add(tHatch);
+ }
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Output tHatch) {
+ if (mOutputOnSide == 1) return false;
+ mInputOnSide = 1;
+ mOutputOnSide = 0;
+ tHatch.updateTexture(aBaseCasingIndex);
+ return mOutputHatches.add(tHatch);
+ }
+ return false;
+ }
+
+ private boolean addRightHatchToMachineList(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
+ if (aTileEntity == null) return false;
+ IMetaTileEntity aMetaTileEntity = aTileEntity.getMetaTileEntity();
+ if (aMetaTileEntity == null) return false;
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Input tHatch) {
+ if (mInputOnSide == 0) return false;
+ mInputOnSide = 1;
+ mOutputOnSide = 0;
+ tHatch.updateTexture(aBaseCasingIndex);
+ tHatch.mRecipeMap = getRecipeMap();
+ return mInputHatches.add(tHatch);
+ }
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Output tHatch) {
+ if (mOutputOnSide == 0) return false;
+ mInputOnSide = 0;
+ mOutputOnSide = 1;
+ tHatch.updateTexture(aBaseCasingIndex);
+ return mOutputHatches.add(tHatch);
+ }
+ return false;
+ }
+
+ private void onCasingAdded() {
+ mCasingAmount++;
+ }
+
+ @Override
+ public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+ setCoilLevel(HeatingCoilLevel.None);
+ mCasingAmount = 0;
+ mMiddleInputHatches.clear();
+ mInputOnSide = -1;
+ mOutputOnSide = -1;
+ replaceDeprecatedCoils(aBaseMetaTileEntity);
+ return checkPiece(STRUCTURE_PIECE_MAIN, 2, 1, 0) && mInputOnSide != -1
+ && mOutputOnSide != -1
+ && mCasingAmount >= 18
+ && mMaintenanceHatches.size() == 1
+ && !mMiddleInputHatches.isEmpty();
+ }
+
+ @Override
+ public boolean isCorrectMachinePart(ItemStack aStack) {
+ return true;
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack aStack) {
+ return 10000;
+ }
+
+ @Override
+ public int getDamageToComponent(ItemStack aStack) {
+ return 0;
+ }
+
+ @Override
+ public boolean explodesOnComponentBreak(ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_OilCracker(this.mName);
+ }
+
+ private void replaceDeprecatedCoils(IGregTechTileEntity aBaseMetaTileEntity) {
+ final int xDir = aBaseMetaTileEntity.getBackFacing().offsetX;
+ final int zDir = aBaseMetaTileEntity.getBackFacing().offsetZ;
+ final int tX = aBaseMetaTileEntity.getXCoord() + xDir;
+ final int tY = aBaseMetaTileEntity.getYCoord();
+ final int tZ = aBaseMetaTileEntity.getZCoord() + zDir;
+ for (int xPos = tX - 1; xPos <= tX + 1; xPos += (xDir != 0 ? 1 : 2))
+ for (int yPos = tY - 1; yPos <= tY + 1; yPos++)
+ for (int zPos = tZ - 1; zPos <= tZ + 1; zPos += (xDir != 0 ? 2 : 1)) {
+ if ((yPos == tY) && (xPos == tX || zPos == tZ)) continue;
+ final byte tUsedMeta = aBaseMetaTileEntity.getMetaID(xPos, yPos, zPos);
+ if (tUsedMeta < 12) continue;
+ if (tUsedMeta > 14) continue;
+ if (aBaseMetaTileEntity.getBlock(xPos, yPos, zPos) != GregTech_API.sBlockCasings1) continue;
+
+ aBaseMetaTileEntity.getWorld()
+ .setBlock(xPos, yPos, zPos, GregTech_API.sBlockCasings5, tUsedMeta - 12, 3);
+ }
+ }
+
+ @Override
+ public ArrayList<FluidStack> getStoredFluids() {
+ final ArrayList<FluidStack> rList = new ArrayList<>();
+ Map<Fluid, FluidStack> inputsFromME = new HashMap<>();
+ for (final GT_MetaTileEntity_Hatch_Input tHatch : filterValidMTEs(mInputHatches)) {
+ tHatch.mRecipeMap = getRecipeMap();
+ if (tHatch instanceof GT_MetaTileEntity_Hatch_Input_ME meHatch) {
+ for (FluidStack tFluid : meHatch.getStoredFluids()) {
+ if (tFluid != null && !getRecipeMap().getBackend()
+ .isValidCatalystFluid(tFluid)) {
+ inputsFromME.put(tFluid.getFluid(), tFluid);
+ }
+ }
+ } else if (tHatch instanceof GT_MetaTileEntity_Hatch_MultiInput) {
+ for (final FluidStack tFluid : ((GT_MetaTileEntity_Hatch_MultiInput) tHatch).getStoredFluid()) {
+ if (tFluid != null && !getRecipeMap().getBackend()
+ .isValidCatalystFluid(tFluid)) {
+ rList.add(tFluid);
+ }
+ }
+ } else {
+ if (tHatch.getFillableStack() != null) {
+ if (!getRecipeMap().getBackend()
+ .isValidCatalystFluid(tHatch.getFillableStack())) rList.add(tHatch.getFillableStack());
+ }
+ }
+ }
+ for (final GT_MetaTileEntity_Hatch_Input tHatch : filterValidMTEs(mMiddleInputHatches)) {
+ tHatch.mRecipeMap = getRecipeMap();
+ if (tHatch instanceof GT_MetaTileEntity_Hatch_Input_ME meHatch) {
+ for (FluidStack tFluid : meHatch.getStoredFluids()) {
+ if (tFluid != null && getRecipeMap().getBackend()
+ .isValidCatalystFluid(tFluid)) {
+ inputsFromME.put(tFluid.getFluid(), tFluid);
+ }
+ }
+ } else if (tHatch instanceof GT_MetaTileEntity_Hatch_MultiInput) {
+ for (final FluidStack tFluid : ((GT_MetaTileEntity_Hatch_MultiInput) tHatch).getStoredFluid()) {
+ if (tFluid != null && getRecipeMap().getBackend()
+ .isValidCatalystFluid(tFluid)) {
+ rList.add(tFluid);
+ }
+ }
+ } else {
+ if (tHatch.getFillableStack() != null) {
+ final FluidStack tStack = tHatch.getFillableStack();
+ if (getRecipeMap().getBackend()
+ .isValidCatalystFluid(tStack)) {
+ rList.add(tStack);
+ }
+ }
+ }
+ }
+ if (!inputsFromME.isEmpty()) {
+ rList.addAll(inputsFromME.values());
+ }
+ return rList;
+ }
+
+ @Override
+ public void construct(ItemStack stackSize, boolean hintsOnly) {
+ buildPiece(STRUCTURE_PIECE_MAIN, stackSize, hintsOnly, 2, 1, 0);
+ }
+
+ @Override
+ public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
+ if (mMachine) return -1;
+ return survivialBuildPiece(STRUCTURE_PIECE_MAIN, stackSize, 2, 1, 0, elementBudget, env, false, true);
+ }
+
+ @Override
+ public boolean supportsVoidProtection() {
+ return true;
+ }
+
+ @Override
+ protected void startRecipeProcessing() {
+ for (GT_MetaTileEntity_Hatch_Input hatch : filterValidMTEs(mMiddleInputHatches)) {
+ if (hatch instanceof IRecipeProcessingAwareHatch aware) {
+ aware.startRecipeProcessing();
+ }
+ }
+ super.startRecipeProcessing();
+ }
+
+ @Override
+ protected void endRecipeProcessing() {
+ super.endRecipeProcessing();
+ for (GT_MetaTileEntity_Hatch_Input hatch : filterValidMTEs(mMiddleInputHatches)) {
+ if (hatch instanceof IRecipeProcessingAwareHatch aware) {
+ setResultIfFailure(aware.endRecipeProcessing(this));
+ }
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilDrill1.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilDrill1.java
new file mode 100644
index 0000000000..1e37dcbac9
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilDrill1.java
@@ -0,0 +1,53 @@
+package gregtech.common.tileentities.machines.multi;
+
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Materials;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+
+public class GT_MetaTileEntity_OilDrill1 extends GT_MetaTileEntity_OilDrillBase {
+
+ public GT_MetaTileEntity_OilDrill1(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_OilDrill1(String aName) {
+ super(aName);
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ return createTooltip("I");
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_OilDrill1(mName);
+ }
+
+ @Override
+ protected ItemList getCasingBlockItem() {
+ return ItemList.Casing_SolidSteel;
+ }
+
+ @Override
+ protected Materials getFrameMaterial() {
+ return Materials.Steel;
+ }
+
+ @Override
+ protected int getCasingTextureIndex() {
+ return 16;
+ }
+
+ @Override
+ protected int getRangeInChunks() {
+ return 1;
+ }
+
+ @Override
+ protected int getMinTier() {
+ return 2;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilDrill2.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilDrill2.java
new file mode 100644
index 0000000000..10a64a6b1d
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilDrill2.java
@@ -0,0 +1,55 @@
+package gregtech.common.tileentities.machines.multi;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Materials;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_OilDrill2 extends GT_MetaTileEntity_OilDrillBase {
+
+ public GT_MetaTileEntity_OilDrill2(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_OilDrill2(String aName) {
+ super(aName);
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ return createTooltip("II");
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_OilDrill2(mName);
+ }
+
+ @Override
+ protected ItemList getCasingBlockItem() {
+ return ItemList.Casing_CleanStainlessSteel;
+ }
+
+ @Override
+ protected Materials getFrameMaterial() {
+ return Materials.StainlessSteel;
+ }
+
+ @Override
+ protected int getCasingTextureIndex() {
+ return GT_Utility.getCasingTextureIndex(GregTech_API.sBlockCasings4, 1);
+ }
+
+ @Override
+ protected int getRangeInChunks() {
+ return 2;
+ }
+
+ @Override
+ protected int getMinTier() {
+ return 3;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilDrill3.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilDrill3.java
new file mode 100644
index 0000000000..bcbe42d794
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilDrill3.java
@@ -0,0 +1,55 @@
+package gregtech.common.tileentities.machines.multi;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Materials;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_OilDrill3 extends GT_MetaTileEntity_OilDrillBase {
+
+ public GT_MetaTileEntity_OilDrill3(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_OilDrill3(String aName) {
+ super(aName);
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ return createTooltip("III");
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_OilDrill3(mName);
+ }
+
+ @Override
+ protected ItemList getCasingBlockItem() {
+ return ItemList.Casing_StableTitanium;
+ }
+
+ @Override
+ protected Materials getFrameMaterial() {
+ return Materials.Titanium;
+ }
+
+ @Override
+ protected int getCasingTextureIndex() {
+ return GT_Utility.getCasingTextureIndex(GregTech_API.sBlockCasings4, 2);
+ }
+
+ @Override
+ protected int getRangeInChunks() {
+ return 4;
+ }
+
+ @Override
+ protected int getMinTier() {
+ return 4;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilDrill4.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilDrill4.java
new file mode 100644
index 0000000000..802e9f1c5c
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilDrill4.java
@@ -0,0 +1,55 @@
+package gregtech.common.tileentities.machines.multi;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Materials;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_OilDrill4 extends GT_MetaTileEntity_OilDrillBase {
+
+ public GT_MetaTileEntity_OilDrill4(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_OilDrill4(String aName) {
+ super(aName);
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ return createTooltip("IV");
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_OilDrill4(mName);
+ }
+
+ @Override
+ protected ItemList getCasingBlockItem() {
+ return ItemList.Casing_RobustTungstenSteel;
+ }
+
+ @Override
+ protected Materials getFrameMaterial() {
+ return Materials.TungstenSteel;
+ }
+
+ @Override
+ protected int getCasingTextureIndex() {
+ return GT_Utility.getCasingTextureIndex(GregTech_API.sBlockCasings4, 0);
+ }
+
+ @Override
+ protected int getRangeInChunks() {
+ return 8;
+ }
+
+ @Override
+ protected int getMinTier() {
+ return 5;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilDrillBase.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilDrillBase.java
new file mode 100644
index 0000000000..075b4e19a1
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilDrillBase.java
@@ -0,0 +1,489 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static gregtech.api.enums.GT_HatchElement.Energy;
+import static gregtech.api.enums.GT_HatchElement.InputBus;
+import static gregtech.api.enums.GT_HatchElement.Maintenance;
+import static gregtech.api.enums.GT_HatchElement.OutputHatch;
+import static gregtech.api.enums.GT_Values.VN;
+import static gregtech.api.enums.GT_Values.debugDriller;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_OIL_DRILL;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_OIL_DRILL_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_OIL_DRILL_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_OIL_DRILL_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.getCasingTextureForId;
+import static gregtech.common.GT_UndergroundOil.undergroundOil;
+import static gregtech.common.GT_UndergroundOil.undergroundOilReadInformation;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.annotation.Nonnegative;
+
+import net.minecraft.entity.player.EntityPlayer;
+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.ChunkCoordIntPair;
+import net.minecraft.world.chunk.Chunk;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidRegistry;
+import net.minecraftforge.fluids.FluidStack;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.google.common.collect.ImmutableList;
+import com.gtnewhorizons.modularui.api.NumberFormatMUI;
+import com.gtnewhorizons.modularui.api.math.Alignment;
+import com.gtnewhorizons.modularui.common.widget.DynamicPositionedColumn;
+import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget;
+import com.gtnewhorizons.modularui.common.widget.SlotWidget;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.api.enums.SoundResource;
+import gregtech.api.interfaces.IHatchElement;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetricsExporter;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.objects.GT_ChunkManager;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Log;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.ValidationResult;
+import gregtech.api.util.ValidationType;
+
+public abstract class GT_MetaTileEntity_OilDrillBase extends GT_MetaTileEntity_DrillerBase implements IMetricsExporter {
+
+ private final ArrayList<Chunk> mOilFieldChunks = new ArrayList<>();
+ private int mOilId = 0;
+ private int mOilFlow = 0;
+
+ private int chunkRangeConfig = getRangeInChunks();
+
+ public GT_MetaTileEntity_OilDrillBase(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_OilDrillBase(String aName) {
+ super(aName);
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection aFacing,
+ int colorIndex, boolean aActive, boolean redstoneLevel) {
+ if (side == aFacing) {
+ if (aActive) return new ITexture[] { getCasingTextureForId(casingTextureIndex), TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_OIL_DRILL_ACTIVE)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_OIL_DRILL_ACTIVE_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ return new ITexture[] { getCasingTextureForId(casingTextureIndex), TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_OIL_DRILL)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_OIL_DRILL_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ }
+ return new ITexture[] { getCasingTextureForId(casingTextureIndex) };
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ aNBT.setInteger("mOilId", mOilId);
+ aNBT.setInteger("chunkRangeConfig", chunkRangeConfig);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ mOilId = aNBT.getInteger("mOilId");
+ if (aNBT.hasKey("chunkRangeConfig")) chunkRangeConfig = aNBT.getInteger("chunkRangeConfig");
+ }
+
+ protected GT_Multiblock_Tooltip_Builder createTooltip(String tierSuffix) {
+ String casings = getCasingBlockItem().get(0)
+ .getDisplayName();
+
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Pump")
+ .addInfo("Controller Block for the Oil/Gas/Fluid Drilling Rig " + (tierSuffix != null ? tierSuffix : ""))
+ .addInfo("Works on " + getRangeInChunks() + "x" + getRangeInChunks() + " chunks")
+ .addInfo("Use a Screwdriver to configure range")
+ .addInfo("Use Programmed Circuits to ignore near exhausted oil field")
+ .addInfo("If total circuit # is greater than output amount it will halt. If it worked right.") // doesn't
+ // work
+ .addSeparator()
+ .beginStructureBlock(3, 7, 3, false)
+ .addController("Front bottom")
+ .addOtherStructurePart(casings, "form the 3x1x3 Base")
+ .addOtherStructurePart(casings, "1x3x1 pillar above the center of the base (2 minimum total)")
+ .addOtherStructurePart(getFrameMaterial().mName + " Frame Boxes", "Each pillar's side and 1x3x1 on top")
+ .addEnergyHatch("1x " + VN[getMinTier()] + "+, Any base casing", 1)
+ .addMaintenanceHatch("Any base casing", 1)
+ .addInputBus("Mining Pipes or Circuits, optional, any base casing", 1)
+ .addOutputHatch("Any base casing", 1)
+ .toolTipFinisher("Gregtech");
+ return tt;
+ }
+
+ protected abstract int getRangeInChunks();
+
+ @Override
+ public void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ super.onScrewdriverRightClick(side, aPlayer, aX, aY, aZ);
+ int oldChunkRange = chunkRangeConfig;
+ if (aPlayer.isSneaking()) {
+ if (chunkRangeConfig > 0) {
+ chunkRangeConfig--;
+ }
+ if (chunkRangeConfig == 0) chunkRangeConfig = getRangeInChunks();
+ } else {
+ if (chunkRangeConfig <= getRangeInChunks()) {
+ chunkRangeConfig++;
+ }
+ if (chunkRangeConfig > getRangeInChunks()) chunkRangeConfig = 1;
+ }
+ if (oldChunkRange != chunkRangeConfig) mOilFieldChunks.clear();
+ GT_Utility.sendChatToPlayer(
+ aPlayer,
+ StatCollector.translateToLocal("GT5U.machines.workareaset") + " "
+ + chunkRangeConfig
+ + "x"
+ + chunkRangeConfig
+ + StatCollector.translateToLocal("GT5U.machines.chunks")); // TODO Add translation support
+ }
+
+ @Override
+ protected boolean checkHatches() {
+ return !mMaintenanceHatches.isEmpty() && !mOutputHatches.isEmpty() && mEnergyHatches.size() == 1;
+ }
+
+ @Override
+ protected List<IHatchElement<? super GT_MetaTileEntity_DrillerBase>> getAllowedHatches() {
+ return ImmutableList.of(InputBus, OutputHatch, Maintenance, Energy);
+ }
+
+ @Override
+ protected void setElectricityStats() {
+ this.mEfficiency = getCurrentEfficiency(null);
+ this.mEfficiencyIncrease = 10000;
+ int tier = Math.max(0, GT_Utility.getTier(getMaxInputVoltage()));
+ this.mEUt = -7 << (tier << 1); // (1/4) A of current tier when at bottom (7/8) A of current tier while mining
+ this.mMaxProgresstime = Math.max(
+ 1,
+ (workState == STATE_AT_BOTTOM ? (64 * (chunkRangeConfig * chunkRangeConfig)) >> (getMinTier() - 1) : 120)
+ >> tier);
+ }
+
+ protected float computeSpeed() {
+ return .5F + (GT_Utility.getTier(getMaxInputVoltage()) - getMinTier()) * .25F;
+ }
+
+ @Override
+ protected boolean workingAtBottom(ItemStack aStack, int xDrill, int yDrill, int zDrill, int xPipe, int zPipe,
+ int yHead, int oldYHead) {
+ switch (tryLowerPipeState(true)) {
+ case 0 -> {
+ workState = STATE_DOWNWARD;
+ setElectricityStats();
+ return true;
+ }
+ case 3 -> {
+ workState = STATE_UPWARD;
+ return true;
+ }
+ }
+
+ if (reachingVoidOrBedrock() && tryFillChunkList()) {
+ if (mWorkChunkNeedsReload) {
+ mCurrentChunk = new ChunkCoordIntPair(xDrill >> 4, zDrill >> 4);
+ GT_ChunkManager.requestChunkLoad((TileEntity) getBaseMetaTileEntity(), null);
+ mWorkChunkNeedsReload = false;
+ }
+ float speed = computeSpeed();
+ ValidationResult<FluidStack> pumpResult = tryPumpOil(speed);
+ if (pumpResult.getType() != ValidationType.VALID) {
+ mEUt = 0;
+ mMaxProgresstime = 0;
+ setRuntimeFailureReason(CheckRecipeResultRegistry.FLUID_OUTPUT_FULL);
+ return false;
+ }
+ FluidStack tFluid = pumpResult.getResult();
+ if (tFluid != null && tFluid.amount > getTotalConfigValue()) {
+ this.mOutputFluids = new FluidStack[] { tFluid };
+ return true;
+ }
+ }
+ GT_ChunkManager.releaseTicket((TileEntity) getBaseMetaTileEntity());
+ workState = STATE_UPWARD;
+ setShutdownReason(StatCollector.translateToLocal("GT5U.gui.text.drill_exhausted"));
+ return true;
+ }
+
+ private boolean tryFillChunkList() {
+ FluidStack tFluid, tOil;
+ if (mOilId <= 0) {
+ tFluid = undergroundOilReadInformation(getBaseMetaTileEntity());
+ if (tFluid == null) return false;
+ mOilId = tFluid.getFluidID();
+ }
+ if (debugDriller) {
+ GT_Log.out.println(" Driller on fluid = " + mOilId);
+ }
+
+ tOil = new FluidStack(FluidRegistry.getFluid(mOilId), 0);
+
+ if (mOilFieldChunks.isEmpty()) {
+ Chunk tChunk = getBaseMetaTileEntity().getWorld()
+ .getChunkFromBlockCoords(getBaseMetaTileEntity().getXCoord(), getBaseMetaTileEntity().getZCoord());
+ int range = chunkRangeConfig;
+ int xChunk = Math.floorDiv(tChunk.xPosition, range) * range; // Java was written by idiots. For negative
+ // values, / returns rounded towards zero.
+ // Fucking morons.
+ int zChunk = Math.floorDiv(tChunk.zPosition, range) * range;
+ if (debugDriller) {
+ GT_Log.out.println(
+ "tChunk.xPosition = " + tChunk.xPosition
+ + " tChunk.zPosition = "
+ + tChunk.zPosition
+ + " xChunk = "
+ + xChunk
+ + " zChunk = "
+ + zChunk);
+ }
+ for (int i = 0; i < range; i++) {
+ for (int j = 0; j < range; j++) {
+ if (debugDriller) {
+ GT_Log.out.println(" getChunkX = " + (xChunk + i) + " getChunkZ = " + (zChunk + j));
+ }
+ tChunk = getBaseMetaTileEntity().getWorld()
+ .getChunkFromChunkCoords(xChunk + i, zChunk + j);
+ tFluid = undergroundOilReadInformation(tChunk);
+ if (debugDriller) {
+ GT_Log.out.println(
+ " Fluid in chunk = " + tFluid.getFluid()
+ .getID());
+ }
+ if (tOil.isFluidEqual(tFluid) && tFluid.amount > 0) {
+ mOilFieldChunks.add(tChunk);
+ if (debugDriller) {
+ GT_Log.out.println(" Matching fluid, quantity = " + tFluid.amount);
+ }
+ }
+ }
+ }
+ }
+ if (debugDriller) {
+ GT_Log.out.println("mOilFieldChunks.size = " + mOilFieldChunks.size());
+ }
+ return !mOilFieldChunks.isEmpty();
+ }
+
+ /**
+ * Tries to pump oil, accounting for output space if void protection is enabled.
+ * <p>
+ * If pumped fluid will not fit in output hatches, it returns a result with INVALID.
+ * <p>
+ * If vein is depleted, it returns a result with VALID and null fluid.
+ */
+ protected ValidationResult<FluidStack> tryPumpOil(float speed) {
+ if (mOilId <= 0) return null;
+ if (debugDriller) {
+ GT_Log.out.println(" pump speed = " + speed);
+ }
+
+ // Even though it works fine without this check,
+ // it can save tiny amount of CPU time when void protection is disabled
+ if (protectsExcessFluid()) {
+ FluidStack simulatedOil = pumpOil(speed, true);
+ if (!canOutputAll(new FluidStack[] { simulatedOil })) {
+ return ValidationResult.of(ValidationType.INVALID, null);
+ }
+ }
+
+ FluidStack pumpedOil = pumpOil(speed, false);
+ mOilFlow = pumpedOil.amount;
+ return ValidationResult.of(ValidationType.VALID, pumpedOil.amount == 0 ? null : pumpedOil);
+ }
+
+ /**
+ * @param speed Speed to pump oil
+ * @param simulate If true, it actually does not consume vein
+ * @return Fluid pumped
+ */
+ protected FluidStack pumpOil(@Nonnegative float speed, boolean simulate) {
+ if (speed < 0) {
+ throw new IllegalArgumentException("Don't pass negative speed");
+ }
+
+ ArrayList<Chunk> emptyChunks = new ArrayList<>();
+ FluidStack returnOil = new FluidStack(FluidRegistry.getFluid(mOilId), 0);
+
+ for (Chunk tChunk : mOilFieldChunks) {
+ FluidStack pumped = undergroundOil(tChunk, simulate ? -speed : speed);
+ if (debugDriller) {
+ GT_Log.out.println(
+ " chunkX = " + tChunk.getChunkCoordIntPair().chunkXPos
+ + " chunkZ = "
+ + tChunk.getChunkCoordIntPair().chunkZPos);
+ if (pumped != null) {
+ GT_Log.out.println(" Fluid pumped = " + pumped.amount);
+ } else {
+ GT_Log.out.println(" No fluid pumped ");
+ }
+ }
+ if (pumped == null || pumped.amount < 1) {
+ emptyChunks.add(tChunk);
+ continue;
+ }
+ if (returnOil.isFluidEqual(pumped)) {
+ returnOil.amount += pumped.amount;
+ }
+ }
+ for (Chunk tChunk : emptyChunks) {
+ mOilFieldChunks.remove(tChunk);
+ }
+ return returnOil;
+ }
+
+ @Override
+ protected SoundResource getProcessStartSound() {
+ return SoundResource.IC2_MACHINES_PUMP_OP;
+ }
+
+ @Override
+ public String[] getInfoData() {
+ List<String> l = new ArrayList<>(
+ Arrays.asList(
+ EnumChatFormatting.BLUE + StatCollector.translateToLocal("GT5U.machines.oilfluidpump")
+ + EnumChatFormatting.RESET,
+ StatCollector.translateToLocal("GT5U.machines.workarea") + ": "
+ + EnumChatFormatting.GREEN
+ + GT_Utility.formatNumbers(chunkRangeConfig)
+ + " x "
+ + GT_Utility.formatNumbers(chunkRangeConfig)
+ + EnumChatFormatting.RESET
+ + " "
+ + StatCollector.translateToLocal("GT5U.machines.chunks"),
+ "Drilling fluid: " + EnumChatFormatting.GREEN + getFluidName() + EnumChatFormatting.RESET,
+ "Drilling flow: " + EnumChatFormatting.GREEN
+ + getFlowRatePerTick()
+ + EnumChatFormatting.RESET
+ + " L/t"));
+ l.addAll(Arrays.asList(super.getInfoData()));
+ return l.toArray(new String[0]);
+ }
+
+ @Override
+ public @NotNull List<String> reportMetrics() {
+ final boolean machineIsActive = getBaseMetaTileEntity().isActive();
+ final String failureReason = getFailureReason()
+ .map(reason -> StatCollector.translateToLocalFormatted("GT5U.gui.text.drill_offline_reason", reason))
+ .orElseGet(() -> StatCollector.translateToLocalFormatted("GT5U.gui.text.drill_offline_generic"));
+
+ if (workState == STATE_AT_BOTTOM) {
+ final ImmutableList.Builder<String> builder = ImmutableList.builder();
+ builder.add(StatCollector.translateToLocalFormatted("GT5U.gui.text.pump_fluid_type", getFluidName()));
+
+ if (machineIsActive) {
+ builder.add(
+ StatCollector.translateToLocalFormatted(
+ "GT5U.gui.text.pump_rate.1",
+ EnumChatFormatting.AQUA + numberFormat.format(getFlowRatePerTick()))
+ + StatCollector.translateToLocal("GT5U.gui.text.pump_rate.2"),
+ mOilFlow + StatCollector.translateToLocal("GT5U.gui.text.pump_recovery.2"));
+ } else {
+ builder.add(failureReason);
+ }
+
+ return builder.build();
+ }
+
+ if (machineIsActive) {
+ return switch (workState) {
+ case STATE_DOWNWARD -> ImmutableList.of(StatCollector.translateToLocal("GT5U.gui.text.deploying_pipe"));
+ case STATE_UPWARD, STATE_ABORT -> ImmutableList
+ .of(StatCollector.translateToLocal("GT5U.gui.text.retracting_pipe"));
+ default -> ImmutableList.of();
+ };
+ }
+
+ return ImmutableList.of(failureReason);
+ }
+
+ protected int getFlowRatePerTick() {
+ return this.mMaxProgresstime > 0 ? (mOilFlow / this.mMaxProgresstime) : 0;
+ }
+
+ @NotNull
+ private String getFluidName() {
+ if (mOilId > 0) {
+ final Fluid fluid = FluidRegistry.getFluid(mOilId);
+ return fluid.getLocalizedName(new FluidStack(fluid, 0));
+ }
+ return "None";
+ }
+
+ private @NotNull String clientFluidType = "";
+ private int clientFlowPerTick = 0;
+ private int clientFlowPerOperation = 0;
+
+ protected static final NumberFormatMUI numberFormat = new NumberFormatMUI();
+
+ @Override
+ protected void drawTexts(DynamicPositionedColumn screenElements, SlotWidget inventorySlot) {
+ super.drawTexts(screenElements, inventorySlot);
+ screenElements
+ .widget(
+ new TextWidget()
+ .setStringSupplier(
+ () -> EnumChatFormatting.GRAY
+ + StatCollector.translateToLocalFormatted("GT5U.gui.text.pump_fluid_type", clientFluidType))
+ .setTextAlignment(Alignment.CenterLeft)
+ .setEnabled(widget -> getBaseMetaTileEntity().isActive() && workState == STATE_AT_BOTTOM))
+ .widget(
+ new TextWidget()
+ .setStringSupplier(
+ () -> EnumChatFormatting.GRAY
+ + StatCollector.translateToLocalFormatted(
+ "GT5U.gui.text.pump_rate.1",
+ EnumChatFormatting.AQUA + numberFormat.format(clientFlowPerTick))
+ + EnumChatFormatting.GRAY
+ + StatCollector.translateToLocal("GT5U.gui.text.pump_rate.2"))
+ .setTextAlignment(Alignment.CenterLeft)
+ .setEnabled(widget -> getBaseMetaTileEntity().isActive() && workState == STATE_AT_BOTTOM))
+ .widget(
+ new TextWidget()
+ .setStringSupplier(
+ () -> EnumChatFormatting.GRAY
+ + StatCollector.translateToLocalFormatted(
+ "GT5U.gui.text.pump_recovery.1",
+ EnumChatFormatting.AQUA + numberFormat.format(clientFlowPerOperation))
+ + EnumChatFormatting.GRAY
+ + StatCollector.translateToLocal("GT5U.gui.text.pump_recovery.2"))
+ .setTextAlignment(Alignment.CenterLeft)
+ .setEnabled(widget -> getBaseMetaTileEntity().isActive() && workState == STATE_AT_BOTTOM))
+ .widget(new FakeSyncWidget.IntegerSyncer(() -> workState, newInt -> workState = newInt))
+ .widget(new FakeSyncWidget.StringSyncer(this::getFluidName, newString -> clientFluidType = newString))
+ .widget(new FakeSyncWidget.IntegerSyncer(this::getFlowRatePerTick, newInt -> clientFlowPerTick = newInt))
+ .widget(new FakeSyncWidget.IntegerSyncer(() -> mOilFlow, newInt -> clientFlowPerOperation = newInt));
+ }
+
+ @Override
+ public boolean supportsVoidProtection() {
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilDrillInfinite.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilDrillInfinite.java
new file mode 100644
index 0000000000..056577e8e8
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilDrillInfinite.java
@@ -0,0 +1,87 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static gregtech.api.enums.GT_Values.VN;
+
+import net.minecraftforge.fluids.FluidStack;
+
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Materials;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_OilDrillInfinite extends GT_MetaTileEntity_OilDrillBase {
+
+ public GT_MetaTileEntity_OilDrillInfinite(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_OilDrillInfinite(String aName) {
+ super(aName);
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ String casings = getCasingBlockItem().get(0)
+ .getDisplayName();
+
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Pump")
+ .addInfo("Controller Block for the Infinite Oil/Gas/Fluid Drilling Rig ")
+ .addInfo("Works on " + getRangeInChunks() + "x" + getRangeInChunks() + " chunks")
+ .addSeparator()
+ .beginStructureBlock(3, 7, 3, false)
+ .addController("Front bottom")
+ .addOtherStructurePart(casings, "form the 3x1x3 Base")
+ .addOtherStructurePart(casings, "1x3x1 pillar above the center of the base (2 minimum total)")
+ .addOtherStructurePart(getFrameMaterial().mName + " Frame Boxes", "Each pillar's side and 1x3x1 on top")
+ .addEnergyHatch("1x " + VN[getMinTier()] + "+, Any base casing", 1)
+ .addMaintenanceHatch("Any base casing", 1)
+ .addInputBus("Mining Pipes or Circuits, optional, any base casing", 1)
+ .addOutputHatch("Any base casing", 1)
+ .toolTipFinisher("Gregtech");
+ return tt;
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_OilDrillInfinite(mName);
+ }
+
+ @Override
+ protected FluidStack pumpOil(float speed, boolean simulate) {
+ // always simulate to not deplete vein
+ return super.pumpOil(speed, true);
+ }
+
+ @Override
+ protected ItemList getCasingBlockItem() {
+ return ItemList.Casing_MiningNeutronium;
+ }
+
+ @Override
+ protected Materials getFrameMaterial() {
+ return Materials.Neutronium;
+ }
+
+ @Override
+ protected int getCasingTextureIndex() {
+ return 178;
+ }
+
+ @Override
+ protected int getRangeInChunks() {
+ return 8;
+ }
+
+ @Override
+ protected float computeSpeed() {
+ return .5F + (GT_Utility.getTier(getMaxInputVoltage()) - getMinTier() + 5) * .25F;
+ }
+
+ @Override
+ protected int getMinTier() {
+ return 9;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OreDrillingPlant1.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OreDrillingPlant1.java
new file mode 100644
index 0000000000..50edf8928a
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OreDrillingPlant1.java
@@ -0,0 +1,60 @@
+package gregtech.common.tileentities.machines.multi;
+
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Materials;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+
+public class GT_MetaTileEntity_OreDrillingPlant1 extends GT_MetaTileEntity_OreDrillingPlantBase {
+
+ public GT_MetaTileEntity_OreDrillingPlant1(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ mTier = 1;
+ }
+
+ public GT_MetaTileEntity_OreDrillingPlant1(String aName) {
+ super(aName);
+ mTier = 1;
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ return createTooltip("I");
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_OreDrillingPlant1(mName);
+ }
+
+ @Override
+ protected ItemList getCasingBlockItem() {
+ return ItemList.Casing_SolidSteel;
+ }
+
+ @Override
+ protected Materials getFrameMaterial() {
+ return Materials.Steel;
+ }
+
+ @Override
+ protected int getCasingTextureIndex() {
+ return 16;
+ }
+
+ @Override
+ protected int getRadiusInChunks() {
+ return 3;
+ }
+
+ @Override
+ protected int getMinTier() {
+ return 2;
+ }
+
+ @Override
+ protected int getBaseProgressTime() {
+ return 960;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OreDrillingPlant2.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OreDrillingPlant2.java
new file mode 100644
index 0000000000..6a80c96d26
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OreDrillingPlant2.java
@@ -0,0 +1,60 @@
+package gregtech.common.tileentities.machines.multi;
+
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Materials;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+
+public class GT_MetaTileEntity_OreDrillingPlant2 extends GT_MetaTileEntity_OreDrillingPlantBase {
+
+ public GT_MetaTileEntity_OreDrillingPlant2(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ mTier = 2;
+ }
+
+ public GT_MetaTileEntity_OreDrillingPlant2(String aName) {
+ super(aName);
+ mTier = 2;
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ return createTooltip("II");
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_OreDrillingPlant2(mName);
+ }
+
+ @Override
+ protected ItemList getCasingBlockItem() {
+ return ItemList.Casing_StableTitanium;
+ }
+
+ @Override
+ protected Materials getFrameMaterial() {
+ return Materials.Titanium;
+ }
+
+ @Override
+ protected int getCasingTextureIndex() {
+ return 50;
+ }
+
+ @Override
+ protected int getRadiusInChunks() {
+ return 4;
+ }
+
+ @Override
+ protected int getMinTier() {
+ return 3;
+ }
+
+ @Override
+ protected int getBaseProgressTime() {
+ return 800;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OreDrillingPlant3.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OreDrillingPlant3.java
new file mode 100644
index 0000000000..2bb25b2254
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OreDrillingPlant3.java
@@ -0,0 +1,60 @@
+package gregtech.common.tileentities.machines.multi;
+
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Materials;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+
+public class GT_MetaTileEntity_OreDrillingPlant3 extends GT_MetaTileEntity_OreDrillingPlantBase {
+
+ public GT_MetaTileEntity_OreDrillingPlant3(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ mTier = 3;
+ }
+
+ public GT_MetaTileEntity_OreDrillingPlant3(String aName) {
+ super(aName);
+ mTier = 3;
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ return createTooltip("III");
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_OreDrillingPlant3(mName);
+ }
+
+ @Override
+ protected ItemList getCasingBlockItem() {
+ return ItemList.Casing_RobustTungstenSteel;
+ }
+
+ @Override
+ protected Materials getFrameMaterial() {
+ return Materials.TungstenSteel;
+ }
+
+ @Override
+ protected int getCasingTextureIndex() {
+ return 48;
+ }
+
+ @Override
+ protected int getRadiusInChunks() {
+ return 6;
+ }
+
+ @Override
+ protected int getMinTier() {
+ return 4;
+ }
+
+ @Override
+ protected int getBaseProgressTime() {
+ return 640;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OreDrillingPlant4.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OreDrillingPlant4.java
new file mode 100644
index 0000000000..7ba26b9500
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OreDrillingPlant4.java
@@ -0,0 +1,60 @@
+package gregtech.common.tileentities.machines.multi;
+
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Materials;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+
+public class GT_MetaTileEntity_OreDrillingPlant4 extends GT_MetaTileEntity_OreDrillingPlantBase {
+
+ public GT_MetaTileEntity_OreDrillingPlant4(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ mTier = 4;
+ }
+
+ public GT_MetaTileEntity_OreDrillingPlant4(String aName) {
+ super(aName);
+ mTier = 4;
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ return createTooltip("IV");
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_OreDrillingPlant4(mName);
+ }
+
+ @Override
+ protected ItemList getCasingBlockItem() {
+ return ItemList.Casing_MiningOsmiridium;
+ }
+
+ @Override
+ protected Materials getFrameMaterial() {
+ return Materials.Osmiridium;
+ }
+
+ @Override
+ protected int getCasingTextureIndex() {
+ return 62;
+ }
+
+ @Override
+ protected int getRadiusInChunks() {
+ return 9;
+ }
+
+ @Override
+ protected int getMinTier() {
+ return 5;
+ }
+
+ @Override
+ protected int getBaseProgressTime() {
+ return 480;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OreDrillingPlantBase.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OreDrillingPlantBase.java
new file mode 100644
index 0000000000..9c15d2b6eb
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OreDrillingPlantBase.java
@@ -0,0 +1,745 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static gregtech.api.enums.GT_HatchElement.Energy;
+import static gregtech.api.enums.GT_HatchElement.InputBus;
+import static gregtech.api.enums.GT_HatchElement.InputHatch;
+import static gregtech.api.enums.GT_HatchElement.Maintenance;
+import static gregtech.api.enums.GT_HatchElement.OutputBus;
+import static gregtech.api.enums.GT_Values.TIER_COLORS;
+import static gregtech.api.enums.GT_Values.VN;
+import static gregtech.api.metatileentity.BaseTileEntity.TOOLTIP_DELAY;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.player.EntityPlayer;
+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.ChunkCoordIntPair;
+import net.minecraft.world.ChunkPosition;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidStack;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.google.common.collect.ImmutableList;
+import com.gtnewhorizons.modularui.api.NumberFormatMUI;
+import com.gtnewhorizons.modularui.api.drawable.IDrawable;
+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.DynamicPositionedColumn;
+import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget;
+import com.gtnewhorizons.modularui.common.widget.SlotWidget;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.enums.SoundResource;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.gui.widgets.GT_LockedWhileActiveButton;
+import gregtech.api.interfaces.IHatchElement;
+import gregtech.api.interfaces.metatileentity.IMetricsExporter;
+import gregtech.api.objects.GT_ChunkManager;
+import gregtech.api.objects.ItemData;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_OreDictUnificator;
+import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.blocks.GT_Block_Ores_Abstract;
+import gregtech.common.blocks.GT_TileEntity_Ores;
+
+public abstract class GT_MetaTileEntity_OreDrillingPlantBase extends GT_MetaTileEntity_DrillerBase
+ implements IMetricsExporter {
+
+ private final List<ChunkPosition> oreBlockPositions = new ArrayList<>();
+ protected int mTier = 1;
+ private int chunkRadiusConfig = getRadiusInChunks();
+ private boolean replaceWithCobblestone = true;
+
+ /** Used to drive the remaining ores count in the UI. */
+ private int clientOreListSize = 0;
+
+ /** Used to drive the current chunk number in the UI. */
+ private int clientCurrentChunk = 0;
+
+ /** Used to drive the total chunk count in the UI. */
+ private int clientTotalChunks = 0;
+
+ /** Used to drive the drill's y-level in the UI. */
+ private int clientYHead = 0;
+
+ GT_MetaTileEntity_OreDrillingPlantBase(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ GT_MetaTileEntity_OreDrillingPlantBase(String aName) {
+ super(aName);
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ aNBT.setInteger("chunkRadiusConfig", chunkRadiusConfig);
+ aNBT.setBoolean("replaceWithCobblestone", replaceWithCobblestone);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ if (aNBT.hasKey("chunkRadiusConfig")) {
+ chunkRadiusConfig = aNBT.getInteger("chunkRadiusConfig");
+ }
+ if (aNBT.hasKey("replaceWithCobblestone")) {
+ replaceWithCobblestone = aNBT.getBoolean("replaceWithCobblestone");
+ }
+ }
+
+ private void adjustChunkRadius(boolean increase) {
+ if (increase) {
+ if (chunkRadiusConfig <= getRadiusInChunks()) {
+ chunkRadiusConfig++;
+ }
+ if (chunkRadiusConfig > getRadiusInChunks()) chunkRadiusConfig = 1;
+ } else {
+ if (chunkRadiusConfig > 0) {
+ chunkRadiusConfig--;
+ }
+ if (chunkRadiusConfig == 0) chunkRadiusConfig = getRadiusInChunks();
+ }
+
+ if (mCurrentChunk != null && mChunkLoadingEnabled) {
+ GT_ChunkManager.releaseChunk((TileEntity) getBaseMetaTileEntity(), mCurrentChunk);
+ }
+
+ oreBlockPositions.clear();
+ createInitialWorkingChunk();
+ }
+
+ @Override
+ public void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ super.onScrewdriverRightClick(side, aPlayer, aX, aY, aZ);
+
+ if (getBaseMetaTileEntity().isActive()) {
+ GT_Utility.sendChatToPlayer(aPlayer, StatCollector.translateToLocal("GT5U.machines.workarea_fail"));
+ } else {
+ adjustChunkRadius(!aPlayer.isSneaking());
+ GT_Utility.sendChatToPlayer(
+ aPlayer,
+ StatCollector.translateToLocal("GT5U.machines.workareaset") + " "
+ + GT_Utility.formatNumbers((long) chunkRadiusConfig << 4)
+ + " "
+ + StatCollector.translateToLocal("GT5U.machines.radius"));
+ }
+ }
+
+ @Override
+ public boolean onWireCutterRightClick(ForgeDirection side, ForgeDirection wrenchingSide, EntityPlayer aPlayer,
+ float aX, float aY, float aZ) {
+ replaceWithCobblestone = !replaceWithCobblestone;
+ GT_Utility.sendChatToPlayer(aPlayer, "Replace with cobblestone " + replaceWithCobblestone);
+ return true;
+ }
+
+ @Override
+ protected boolean workingDownward(ItemStack aStack, int xDrill, int yDrill, int zDrill, int xPipe, int zPipe,
+ int yHead, int oldYHead) {
+ if (yHead != oldYHead) oreBlockPositions.clear();
+
+ if (mWorkChunkNeedsReload && mChunkLoadingEnabled) { // ask to load machine itself
+ GT_ChunkManager.requestChunkLoad((TileEntity) getBaseMetaTileEntity(), null);
+ mWorkChunkNeedsReload = false;
+ }
+ fillMineListIfEmpty(xDrill, yDrill, zDrill, xPipe, zPipe, yHead);
+ if (oreBlockPositions.isEmpty()) {
+ switch (tryLowerPipeState()) {
+ case 2 -> {
+ mMaxProgresstime = 0;
+ setRuntimeFailureReason(CheckRecipeResultRegistry.MISSING_MINING_PIPE);
+ return false;
+ }
+ case 3 -> {
+ workState = STATE_UPWARD;
+ return true;
+ }
+ case 1 -> {
+ workState = STATE_AT_BOTTOM;
+ return true;
+ }
+ }
+ // new layer - fill again
+ fillMineListIfEmpty(xDrill, yDrill, zDrill, xPipe, zPipe, yHead);
+ }
+ return tryProcessOreList();
+ }
+
+ private boolean tryProcessOreList() {
+ // Even though it works fine without this check,
+ // it can save tiny amount of CPU time when void protection is disabled
+ if (protectsExcessItem()) {
+ boolean simulateResult = processOreList(true);
+ if (!simulateResult) {
+ mEUt = 0;
+ mMaxProgresstime = 0;
+ return false;
+ }
+ }
+
+ boolean result = processOreList(false);
+ if (!result) {
+ mEUt = 0;
+ mMaxProgresstime = 0;
+ return false;
+ }
+ return true;
+ }
+
+ private boolean processOreList(boolean simulate) {
+ ChunkPosition oreBlockPos = null;
+ List<ChunkPosition> oreBlockPositions = simulate ? copyOreBlockPositions(this.oreBlockPositions)
+ : this.oreBlockPositions;
+ int x = 0, y = 0, z = 0;
+ Block oreBlock = null;
+ int oreBlockMetadata = 0;
+
+ while ((oreBlock == null || !GT_Utility.isOre(oreBlock, oreBlockMetadata)) && !oreBlockPositions.isEmpty()) {
+ oreBlockPos = oreBlockPositions.remove(0);
+ x = oreBlockPos.chunkPosX;
+ y = oreBlockPos.chunkPosY;
+ z = oreBlockPos.chunkPosZ;
+ if (GT_Utility.eraseBlockByFakePlayer(getFakePlayer(getBaseMetaTileEntity()), x, y, z, true))
+ oreBlock = getBaseMetaTileEntity().getBlock(x, y, z);
+ oreBlockMetadata = getBaseMetaTileEntity().getWorld()
+ .getBlockMetadata(x, y, z);
+ }
+
+ if (!tryConsumeDrillingFluid(simulate)) {
+ oreBlockPositions.add(0, oreBlockPos);
+ setRuntimeFailureReason(CheckRecipeResultRegistry.NO_DRILLING_FLUID);
+ return false;
+ }
+ if (oreBlock != null && GT_Utility.isOre(oreBlock, oreBlockMetadata)) {
+ short metaData = 0;
+ TileEntity tTileEntity = getBaseMetaTileEntity().getTileEntity(x, y, z);
+ if (tTileEntity instanceof GT_TileEntity_Ores) {
+ metaData = ((GT_TileEntity_Ores) tTileEntity).mMetaData;
+ }
+
+ Collection<ItemStack> oreBlockDrops = getBlockDrops(oreBlock, x, y, z);
+ ItemStack cobble = GT_Utility.getCobbleForOre(oreBlock, metaData);
+ if (!simulate) {
+ if (replaceWithCobblestone) {
+ getBaseMetaTileEntity().getWorld()
+ .setBlock(x, y, z, Block.getBlockFromItem(cobble.getItem()), cobble.getItemDamage(), 3);
+ } else {
+ getBaseMetaTileEntity().getWorld()
+ .setBlockToAir(oreBlockPos.chunkPosX, oreBlockPos.chunkPosY, oreBlockPos.chunkPosZ);
+ }
+ }
+ ItemStack[] toOutput = getOutputByDrops(oreBlockDrops);
+ if (simulate && !canOutputAll(toOutput)) {
+ setRuntimeFailureReason(CheckRecipeResultRegistry.ITEM_OUTPUT_FULL);
+ return false;
+ }
+ mOutputItems = toOutput;
+ }
+ return true;
+ }
+
+ private static List<ChunkPosition> copyOreBlockPositions(List<ChunkPosition> oreBlockPositions) {
+ List<ChunkPosition> ret = new ArrayList<>();
+ for (ChunkPosition chunkPosition : oreBlockPositions) {
+ ret.add(new ChunkPosition(chunkPosition.chunkPosX, chunkPosition.chunkPosY, chunkPosition.chunkPosZ));
+ }
+ return ret;
+ }
+
+ @Override
+ protected boolean workingAtBottom(ItemStack aStack, int xDrill, int yDrill, int zDrill, int xPipe, int zPipe,
+ int yHead, int oldYHead) {
+ if (!mChunkLoadingEnabled)
+ return super.workingAtBottom(aStack, xDrill, yDrill, zDrill, xPipe, zPipe, yHead, oldYHead);
+
+ if (mCurrentChunk == null) {
+ createInitialWorkingChunk();
+ return true;
+ }
+
+ if (mWorkChunkNeedsReload) {
+ GT_ChunkManager.requestChunkLoad((TileEntity) getBaseMetaTileEntity(), mCurrentChunk);
+ mWorkChunkNeedsReload = false;
+ return true;
+ }
+ if (oreBlockPositions.isEmpty()) {
+ fillChunkMineList(yHead, yDrill);
+ if (oreBlockPositions.isEmpty()) {
+ GT_ChunkManager.releaseChunk((TileEntity) getBaseMetaTileEntity(), mCurrentChunk);
+ if (!moveToNextChunk(xDrill >> 4, zDrill >> 4)) workState = STATE_UPWARD;
+ return true;
+ }
+ }
+ return tryProcessOreList();
+ }
+
+ private void createInitialWorkingChunk() {
+ mCurrentChunk = getTopLeftChunkCoords();
+ if (mChunkLoadingEnabled) {
+ GT_ChunkManager.requestChunkLoad((TileEntity) getBaseMetaTileEntity(), mCurrentChunk);
+ mWorkChunkNeedsReload = false;
+ }
+ }
+
+ @NotNull
+ private ChunkCoordIntPair getTopLeftChunkCoords() {
+ return getCornerCoords(-1, -1);
+ }
+
+ @NotNull
+ private ChunkCoordIntPair getBottomRightChunkCoords() {
+ return getCornerCoords(1, 1);
+ }
+
+ @NotNull
+ private ChunkCoordIntPair getCornerCoords(int xMultiplier, int zMultiplier) {
+ final ChunkCoordIntPair drillPos = getDrillCoords();
+ // use corner closest to the drill as mining area center
+ return new ChunkCoordIntPair(
+ drillPos.chunkXPos + xMultiplier * chunkRadiusConfig
+ + ((getXDrill() - (drillPos.chunkXPos << 4)) < 8 ? 0 : 1),
+ drillPos.chunkZPos + zMultiplier * chunkRadiusConfig
+ + ((getZDrill() - (drillPos.chunkZPos << 4)) < 8 ? 0 : 1));
+ }
+
+ @NotNull
+ private ChunkCoordIntPair getDrillCoords() {
+ return new ChunkCoordIntPair(getXDrill() >> 4, getZDrill() >> 4);
+ }
+
+ private int getTotalChunkCount() {
+ final ChunkCoordIntPair topLeft = getTopLeftChunkCoords();
+ final ChunkCoordIntPair bottomRight = getBottomRightChunkCoords();
+ return (bottomRight.chunkXPos - topLeft.chunkXPos) * (bottomRight.chunkZPos - topLeft.chunkZPos);
+ }
+
+ /**
+ * Returns a number corresponding to which chunk the drill is operating on. Only really useful for driving outputs
+ * in the controller UI.
+ *
+ * @return 0 if the miner is not in operation, positive integer corresponding to the chunk currently being drilled
+ */
+ @SuppressWarnings("ExtractMethodRecommender")
+ private int getChunkNumber() {
+ if (mCurrentChunk == null) {
+ return 0;
+ }
+
+ final ChunkCoordIntPair topLeft = getTopLeftChunkCoords();
+ final ChunkCoordIntPair drillPos = getDrillCoords();
+
+ if (workState == STATE_DOWNWARD) {
+ return 1;
+ } else if (workState == STATE_UPWARD) {
+ // Technically, the miner isn't mining anything now; it's retracting the pipes in preparation to end
+ // operation.
+ return 0;
+ }
+
+ int chunkNumber = (chunkRadiusConfig * 2) * (mCurrentChunk.chunkZPos - topLeft.chunkZPos)
+ + mCurrentChunk.chunkXPos
+ - topLeft.chunkXPos
+ + 1;
+
+ // Drills mine the chunk they're in first, so if we're not there yet, bump the number to indicate that it
+ // was already mined.
+ if (mCurrentChunk.chunkZPos < drillPos.chunkZPos
+ || (mCurrentChunk.chunkZPos == drillPos.chunkZPos && mCurrentChunk.chunkXPos < drillPos.chunkXPos)) {
+ chunkNumber += 1;
+ }
+ return chunkNumber;
+ }
+
+ @Override
+ protected boolean workingUpward(ItemStack aStack, int xDrill, int yDrill, int zDrill, int xPipe, int zPipe,
+ int yHead, int oldYHead) {
+ boolean result;
+ if (!mChunkLoadingEnabled || oreBlockPositions.isEmpty()) {
+ result = super.workingUpward(aStack, xDrill, yDrill, zDrill, xPipe, zPipe, yHead, oldYHead);
+ } else {
+ result = tryProcessOreList();
+ if (oreBlockPositions.isEmpty()) GT_ChunkManager.releaseTicket((TileEntity) getBaseMetaTileEntity());
+ }
+
+ if (!result) {
+ setShutdownReason(StatCollector.translateToLocal("GT5U.gui.text.drill_exhausted"));
+ }
+
+ return result;
+ }
+
+ @Override
+ protected void onAbort() {
+ oreBlockPositions.clear();
+ if (mCurrentChunk != null) {
+ GT_ChunkManager.releaseChunk((TileEntity) getBaseMetaTileEntity(), mCurrentChunk);
+ }
+ mCurrentChunk = null;
+ }
+
+ private boolean moveToNextChunk(int centerX, int centerZ) {
+ if (mCurrentChunk == null) return false;
+ // use corner closest to the drill as mining area center
+ final int left = centerX - chunkRadiusConfig + ((getXDrill() - (centerX << 4)) < 8 ? 0 : 1);
+ final int right = left + chunkRadiusConfig * 2;
+ final int bottom = centerZ + chunkRadiusConfig + ((getZDrill() - (centerZ << 4)) < 8 ? 0 : 1);
+
+ int nextChunkX = mCurrentChunk.chunkXPos + 1;
+ int nextChunkZ = mCurrentChunk.chunkZPos;
+
+ // step to the next chunk
+ if (nextChunkX >= right) {
+ nextChunkX = left;
+ ++nextChunkZ;
+ }
+ // skip center chunk - dug in workingDownward()
+ if (nextChunkX == centerX && nextChunkZ == centerZ) {
+ ++nextChunkX;
+
+ if (nextChunkX >= right) {
+ nextChunkX = left;
+ ++nextChunkZ;
+ }
+ }
+
+ if (nextChunkZ >= bottom) {
+ mCurrentChunk = null;
+ return false;
+ }
+ mCurrentChunk = new ChunkCoordIntPair(nextChunkX, nextChunkZ);
+ GT_ChunkManager
+ .requestChunkLoad((TileEntity) getBaseMetaTileEntity(), new ChunkCoordIntPair(nextChunkX, nextChunkZ));
+ return true;
+ }
+
+ @Override
+ protected boolean checkHatches() {
+ return !mMaintenanceHatches.isEmpty() && !mInputHatches.isEmpty()
+ && !mOutputBusses.isEmpty()
+ && !mEnergyHatches.isEmpty();
+ }
+
+ @Override
+ protected List<IHatchElement<? super GT_MetaTileEntity_DrillerBase>> getAllowedHatches() {
+ return ImmutableList.of(InputHatch, InputBus, OutputBus, Maintenance, Energy);
+ }
+
+ @Override
+ protected void setElectricityStats() {
+ this.mEfficiency = getCurrentEfficiency(null);
+ this.mEfficiencyIncrease = 10000;
+ int tier = Math.max(1, GT_Utility.getTier(getMaxInputVoltage()));
+ this.mEUt = -3 * (1 << (tier << 1));
+ this.mMaxProgresstime = calculateMaxProgressTime(tier);
+ }
+
+ private int calculateMaxProgressTime(int tier) {
+ return Math.max(
+ 1,
+ ((workState == STATE_DOWNWARD || workState == STATE_AT_BOTTOM) ? getBaseProgressTime() : 80) / (1 << tier));
+ }
+
+ private ItemStack[] getOutputByDrops(Collection<ItemStack> oreBlockDrops) {
+ long voltage = getMaxInputVoltage();
+ Collection<ItemStack> outputItems = new HashSet<>();
+ oreBlockDrops.forEach(currentItem -> {
+ if (!doUseMaceratorRecipe(currentItem)) {
+ outputItems.add(multiplyStackSize(currentItem));
+ return;
+ }
+ GT_Recipe tRecipe = RecipeMaps.maceratorRecipes
+ .findRecipe(getBaseMetaTileEntity(), false, voltage, null, currentItem);
+ if (tRecipe == null) {
+ outputItems.add(currentItem);
+ return;
+ }
+ for (int i = 0; i < tRecipe.mOutputs.length; i++) {
+ ItemStack recipeOutput = tRecipe.mOutputs[i].copy();
+ if (getBaseMetaTileEntity().getRandomNumber(10000) < tRecipe.getOutputChance(i))
+ multiplyStackSize(recipeOutput);
+ outputItems.add(recipeOutput);
+ }
+ });
+ return outputItems.toArray(new ItemStack[0]);
+ }
+
+ private boolean doUseMaceratorRecipe(ItemStack currentItem) {
+ ItemData itemData = GT_OreDictUnificator.getItemData(currentItem);
+ return itemData == null || itemData.mPrefix != OrePrefixes.crushed && itemData.mPrefix != OrePrefixes.dustImpure
+ && itemData.mPrefix != OrePrefixes.dust
+ && itemData.mPrefix != OrePrefixes.gem
+ && itemData.mPrefix != OrePrefixes.gemChipped
+ && itemData.mPrefix != OrePrefixes.gemExquisite
+ && itemData.mPrefix != OrePrefixes.gemFlawed
+ && itemData.mPrefix != OrePrefixes.gemFlawless
+ && itemData.mMaterial.mMaterial != Materials.Oilsands;
+ }
+
+ private ItemStack multiplyStackSize(ItemStack itemStack) {
+ itemStack.stackSize *= getBaseMetaTileEntity().getRandomNumber(4) + 1;
+ return itemStack;
+ }
+
+ private Collection<ItemStack> getBlockDrops(final Block oreBlock, int posX, int posY, int posZ) {
+ final int blockMeta = getBaseMetaTileEntity().getMetaID(posX, posY, posZ);
+ if (oreBlock.canSilkHarvest(getBaseMetaTileEntity().getWorld(), null, posX, posY, posZ, blockMeta)) {
+ return Collections.singleton(new ItemStack(oreBlock, 1, blockMeta));
+ }
+ if (oreBlock instanceof GT_Block_Ores_Abstract) {
+ TileEntity tTileEntity = getBaseMetaTileEntity().getTileEntity(posX, posY, posZ);
+ if (tTileEntity instanceof GT_TileEntity_Ores && ((GT_TileEntity_Ores) tTileEntity).mMetaData >= 16000) {
+ // GT_Log.out.println("Running Small Ore");
+ return oreBlock.getDrops(getBaseMetaTileEntity().getWorld(), posX, posY, posZ, blockMeta, mTier + 3);
+ }
+ }
+ // GT_Log.out.println("Running Normal Ore");
+ return oreBlock.getDrops(getBaseMetaTileEntity().getWorld(), posX, posY, posZ, blockMeta, 0);
+ }
+
+ private boolean tryConsumeDrillingFluid(boolean simulate) {
+ return depleteInput(new FluidStack(ItemList.sDrillingFluid, 2000), simulate);
+ }
+
+ private void fillChunkMineList(int yHead, int yDrill) {
+ if (mCurrentChunk == null || !oreBlockPositions.isEmpty()) return;
+ final int minX = mCurrentChunk.chunkXPos << 4;
+ final int maxX = minX + 16;
+ final int minZ = mCurrentChunk.chunkZPos << 4;
+ final int maxZ = minZ + 16;
+ for (int x = minX; x < maxX; ++x)
+ for (int z = minZ; z < maxZ; ++z) for (int y = yHead; y < yDrill; ++y) tryAddOreBlockToMineList(x, y, z);
+ }
+
+ private void fillMineListIfEmpty(int xDrill, int yDrill, int zDrill, int xPipe, int zPipe, int yHead) {
+ if (!oreBlockPositions.isEmpty()) return;
+
+ tryAddOreBlockToMineList(xPipe, yHead - 1, zPipe);
+ if (yHead == yDrill) return; // skip controller block layer
+
+ if (mChunkLoadingEnabled) {
+ int startX = (xDrill >> 4) << 4;
+ int startZ = (zDrill >> 4) << 4;
+ for (int x = startX; x < (startX + 16); ++x)
+ for (int z = startZ; z < (startZ + 16); ++z) tryAddOreBlockToMineList(x, yHead, z);
+ } else {
+ int radius = chunkRadiusConfig << 4;
+ for (int xOff = -radius; xOff <= radius; xOff++) for (int zOff = -radius; zOff <= radius; zOff++)
+ tryAddOreBlockToMineList(xDrill + xOff, yHead, zDrill + zOff);
+ }
+ }
+
+ private void tryAddOreBlockToMineList(int x, int y, int z) {
+ Block block = getBaseMetaTileEntity().getBlock(x, y, z);
+ int blockMeta = getBaseMetaTileEntity().getMetaID(x, y, z);
+ ChunkPosition blockPos = new ChunkPosition(x, y, z);
+ if (!oreBlockPositions.contains(blockPos)) {
+ if (block instanceof GT_Block_Ores_Abstract) {
+ TileEntity tTileEntity = getBaseMetaTileEntity().getTileEntity(x, y, z);
+ if (tTileEntity instanceof GT_TileEntity_Ores && ((GT_TileEntity_Ores) tTileEntity).mNatural)
+ oreBlockPositions.add(blockPos);
+ } else if (GT_Utility.isOre(block, blockMeta)) oreBlockPositions.add(blockPos);
+ }
+ }
+
+ protected abstract int getRadiusInChunks();
+
+ protected abstract int getBaseProgressTime();
+
+ protected GT_Multiblock_Tooltip_Builder createTooltip(String tierSuffix) {
+ String casings = getCasingBlockItem().get(0)
+ .getDisplayName();
+
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ final int baseCycleTime = calculateMaxProgressTime(getMinTier());
+ tt.addMachineType("Miner")
+ .addInfo("Controller Block for the Ore Drilling Plant " + (tierSuffix != null ? tierSuffix : ""))
+ .addInfo("Use a Screwdriver to configure block radius")
+ .addInfo("Maximum radius is " + GT_Utility.formatNumbers((long) getRadiusInChunks() << 4) + " blocks")
+ .addInfo("Use Soldering iron to turn off chunk mode")
+ .addInfo("Use Wire Cutter to toggle replacing mined blocks with cobblestone")
+ .addInfo("In chunk mode, working area center is the chunk corner nearest to the drill")
+ .addInfo("Gives ~3x as much crushed ore vs normal processing")
+ .addInfo("Fortune bonus of " + GT_Utility.formatNumbers(mTier + 3) + ". Only works on small ores")
+ .addInfo("Minimum energy hatch tier: " + TIER_COLORS[getMinTier()] + VN[getMinTier()])
+ .addInfo(
+ "Base cycle time: " + (baseCycleTime < 20 ? GT_Utility.formatNumbers(baseCycleTime) + " ticks"
+ : GT_Utility.formatNumbers(baseCycleTime / 20) + " seconds"))
+ .addSeparator()
+ .beginStructureBlock(3, 7, 3, false)
+ .addController("Front bottom")
+ .addOtherStructurePart(casings, "form the 3x1x3 Base")
+ .addOtherStructurePart(casings, "1x3x1 pillar above the center of the base (2 minimum total)")
+ .addOtherStructurePart(getFrameMaterial().mName + " Frame Boxes", "Each pillar's side and 1x3x1 on top")
+ .addEnergyHatch(VN[getMinTier()] + "+, Any base casing", 1)
+ .addMaintenanceHatch("Any base casing", 1)
+ .addInputBus("Mining Pipes, optional, any base casing", 1)
+ .addInputHatch("Drilling Fluid, any base casing", 1)
+ .addOutputBus("Any base casing", 1)
+ .toolTipFinisher("Gregtech");
+ return tt;
+ }
+
+ protected static final NumberFormatMUI numberFormat = new NumberFormatMUI();
+
+ @Override
+ protected void drawTexts(DynamicPositionedColumn screenElements, SlotWidget inventorySlot) {
+ super.drawTexts(screenElements, inventorySlot);
+ screenElements
+ .widget(
+ new TextWidget()
+ .setStringSupplier(
+ () -> EnumChatFormatting.GRAY + StatCollector.translateToLocalFormatted(
+ "GT5U.gui.text.drill_ores_left_chunk",
+ numberFormat.format(clientOreListSize)))
+ .setTextAlignment(Alignment.CenterLeft)
+ .setEnabled(
+ widget -> getBaseMetaTileEntity().isActive() && clientOreListSize > 0
+ && workState == STATE_AT_BOTTOM))
+ .widget(
+ new TextWidget()
+ .setStringSupplier(
+ () -> EnumChatFormatting.GRAY + StatCollector.translateToLocalFormatted(
+ "GT5U.gui.text.drill_ores_left_layer",
+ numberFormat.format(clientYHead),
+ numberFormat.format(clientOreListSize)))
+ .setTextAlignment(Alignment.CenterLeft)
+ .setEnabled(
+ widget -> getBaseMetaTileEntity().isActive() && clientYHead > 0 && workState == STATE_DOWNWARD))
+ .widget(
+ new TextWidget()
+ .setStringSupplier(
+ () -> EnumChatFormatting.GRAY + StatCollector.translateToLocalFormatted(
+ "GT5U.gui.text.drill_chunks_left",
+ numberFormat.format(clientCurrentChunk),
+ numberFormat.format(clientTotalChunks)))
+ .setTextAlignment(Alignment.CenterLeft)
+ .setEnabled(
+ widget -> getBaseMetaTileEntity().isActive() && clientCurrentChunk > 0
+ && workState == STATE_AT_BOTTOM))
+ .widget(new FakeSyncWidget.IntegerSyncer(oreBlockPositions::size, (newInt) -> clientOreListSize = newInt))
+ .widget(new FakeSyncWidget.IntegerSyncer(this::getTotalChunkCount, (newInt) -> clientTotalChunks = newInt))
+ .widget(new FakeSyncWidget.IntegerSyncer(this::getChunkNumber, (newInt) -> clientCurrentChunk = newInt))
+ .widget(new FakeSyncWidget.IntegerSyncer(() -> workState, (newInt) -> workState = newInt))
+ .widget(new FakeSyncWidget.IntegerSyncer(this::getYHead, (newInt) -> clientYHead = newInt));
+ }
+
+ @Override
+ protected List<ButtonWidget> getAdditionalButtons(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ return ImmutableList.of(
+ (ButtonWidget) new GT_LockedWhileActiveButton(this.getBaseMetaTileEntity(), builder)
+ .setOnClick((clickData, widget) -> adjustChunkRadius(clickData.mouseButton == 0))
+ .setPlayClickSound(true)
+ .setBackground(GT_UITextures.BUTTON_STANDARD, GT_UITextures.OVERLAY_BUTTON_WORK_AREA)
+ .attachSyncer(
+ new FakeSyncWidget.IntegerSyncer(() -> chunkRadiusConfig, (val) -> chunkRadiusConfig = val),
+ builder,
+ (widget, val) -> widget.notifyTooltipChange())
+ .dynamicTooltip(
+ () -> ImmutableList.of(
+ StatCollector.translateToLocalFormatted(
+ "GT5U.gui.button.ore_drill_radius_1",
+ GT_Utility.formatNumbers((long) chunkRadiusConfig << 4)),
+ StatCollector.translateToLocal("GT5U.gui.button.ore_drill_radius_2")))
+ .setTooltipShowUpDelay(TOOLTIP_DELAY)
+ .setSize(16, 16),
+ (ButtonWidget) new GT_LockedWhileActiveButton(this.getBaseMetaTileEntity(), builder)
+ .setOnClick((clickData, widget) -> replaceWithCobblestone = !replaceWithCobblestone)
+ .setPlayClickSound(true)
+ .setBackground(() -> {
+ if (replaceWithCobblestone) {
+ return new IDrawable[] { GT_UITextures.BUTTON_STANDARD_PRESSED,
+ GT_UITextures.OVERLAY_BUTTON_REPLACE_COBBLE_ON };
+ }
+ return new IDrawable[] { GT_UITextures.BUTTON_STANDARD,
+ GT_UITextures.OVERLAY_BUTTON_REPLACE_COBBLE_OFF };
+ })
+ .attachSyncer(
+ new FakeSyncWidget.BooleanSyncer(
+ () -> replaceWithCobblestone,
+ (val) -> replaceWithCobblestone = val),
+ builder,
+ (widget, val) -> widget.notifyTooltipChange())
+ .dynamicTooltip(
+ () -> ImmutableList.of(
+ StatCollector.translateToLocal(
+ replaceWithCobblestone ? "GT5U.gui.button.ore_drill_cobblestone_on"
+ : "GT5U.gui.button.ore_drill_cobblestone_off")))
+ .setTooltipShowUpDelay(TOOLTIP_DELAY)
+ .setSize(16, 16));
+ }
+
+ @Override
+ protected SoundResource getProcessStartSound() {
+ return SoundResource.IC2_MACHINES_MINER_OP;
+ }
+
+ @Override
+ public String[] getInfoData() {
+ final String diameter = GT_Utility.formatNumbers(chunkRadiusConfig * 2L);
+ return new String[] {
+ EnumChatFormatting.BLUE + StatCollector.translateToLocal("GT5U.machines.minermulti")
+ + EnumChatFormatting.RESET,
+ StatCollector.translateToLocal("GT5U.machines.workarea") + ": "
+ + EnumChatFormatting.GREEN
+ + diameter
+ + "x"
+ + diameter
+ + EnumChatFormatting.RESET
+ + " "
+ + StatCollector.translateToLocal("GT5U.machines.chunks") };
+ }
+
+ @Override
+ public @NotNull List<String> reportMetrics() {
+ if (getBaseMetaTileEntity().isActive()) {
+ return switch (workState) {
+ case STATE_AT_BOTTOM -> ImmutableList.of(
+ StatCollector.translateToLocalFormatted(
+ "GT5U.gui.text.drill_ores_left_chunk",
+ GT_Utility.formatNumbers(oreBlockPositions.size())),
+ StatCollector.translateToLocalFormatted(
+ "GT5U.gui.text.drill_chunks_left",
+ GT_Utility.formatNumbers(getChunkNumber()),
+ GT_Utility.formatNumbers(getTotalChunkCount())));
+ case STATE_DOWNWARD -> ImmutableList.of(
+ StatCollector.translateToLocalFormatted(
+ "GT5U.gui.text.drill_ores_left_layer",
+ getYHead(),
+ GT_Utility.formatNumbers(oreBlockPositions.size())));
+ case STATE_UPWARD, STATE_ABORT -> ImmutableList
+ .of(StatCollector.translateToLocal("GT5U.gui.text.retracting_pipe"));
+
+ default -> ImmutableList.of();
+ };
+ }
+
+ return ImmutableList.of(
+ getFailureReason()
+ .map(reason -> StatCollector.translateToLocalFormatted("GT5U.gui.text.drill_offline_reason", reason))
+ .orElseGet(() -> StatCollector.translateToLocalFormatted("GT5U.gui.text.drill_offline_generic")));
+ }
+
+ @Override
+ public boolean supportsVoidProtection() {
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PCBFactory.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PCBFactory.java
new file mode 100644
index 0000000000..3616baf742
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PCBFactory.java
@@ -0,0 +1,1276 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.transpose;
+import static gregtech.api.enums.GT_HatchElement.Energy;
+import static gregtech.api.enums.GT_HatchElement.ExoticEnergy;
+import static gregtech.api.enums.GT_HatchElement.InputBus;
+import static gregtech.api.enums.GT_HatchElement.InputHatch;
+import static gregtech.api.enums.GT_HatchElement.Maintenance;
+import static gregtech.api.enums.GT_HatchElement.OutputBus;
+import static gregtech.api.enums.GT_Values.AuthorBlueWeabo;
+import static gregtech.api.enums.GT_Values.VN;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ASSEMBLY_LINE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ASSEMBLY_LINE_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ASSEMBLY_LINE_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ASSEMBLY_LINE_GLOW;
+import static gregtech.api.util.GT_StructureUtility.buildHatchAdder;
+import static gregtech.api.util.GT_StructureUtility.ofFrame;
+import static gregtech.api.util.GT_Utility.filterValidMTEs;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.StatCollector;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidStack;
+
+import org.jetbrains.annotations.NotNull;
+
+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.ISurvivalBuildEnvironment;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+import com.gtnewhorizons.modularui.api.drawable.IDrawable;
+import com.gtnewhorizons.modularui.api.drawable.Text;
+import com.gtnewhorizons.modularui.api.drawable.UITexture;
+import com.gtnewhorizons.modularui.api.math.Alignment;
+import com.gtnewhorizons.modularui.api.math.Color;
+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.CycleButtonWidget;
+import com.gtnewhorizons.modularui.common.widget.DrawableWidget;
+import com.gtnewhorizons.modularui.common.widget.DynamicPositionedColumn;
+import com.gtnewhorizons.modularui.common.widget.DynamicPositionedRow;
+import com.gtnewhorizons.modularui.common.widget.MultiChildWidget;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+import com.gtnewhorizons.modularui.common.widget.textfield.NumericWidget;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.enums.SoundResource;
+import gregtech.api.enums.Textures.BlockIcons;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.logic.ProcessingLogic;
+import gregtech.api.metatileentity.GregTechTileClientEvents;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_ExtendedPowerMultiBlockBase;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Input;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Muffler;
+import gregtech.api.multitileentity.multiblock.casing.Glasses;
+import gregtech.api.objects.ItemData;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.recipe.check.SimpleCheckRecipeResult;
+import gregtech.api.recipe.metadata.PCBFactoryTierKey;
+import gregtech.api.recipe.metadata.PCBFactoryUpgrade;
+import gregtech.api.recipe.metadata.PCBFactoryUpgradeKey;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_OreDictUnificator;
+import gregtech.api.util.GT_OverclockCalculator;
+import gregtech.api.util.GT_ParallelHelper;
+import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.shutdown.ShutDownReasonRegistry;
+import gregtech.common.blocks.GT_Block_Casings8;
+
+@SuppressWarnings("SpellCheckingInspection")
+public class GT_MetaTileEntity_PCBFactory extends
+ GT_MetaTileEntity_ExtendedPowerMultiBlockBase<GT_MetaTileEntity_PCBFactory> implements ISurvivalConstructable {
+
+ private static final String tier1 = "tier1";
+ private static final String tier2 = "tier2";
+ private static final String tier3 = "tier3";
+ private static final String bioUpgrade = "bioUpgrade";
+ private static final String ocTier1Upgrade = "ocTier1Upgrade";
+ private static final String ocTier2Upgrade = "ocTier2Upgrade";
+ private float mRoughnessMultiplier = 1;
+ private int mTier = 1, mSetTier = 1, mUpgradesInstalled = 0, mCurrentParallel = 0, mMaxParallel = 0;
+ private boolean mBioUpgrade = false, mBioRotate = false, mOCTier1 = false, mOCTier2 = false;
+ private final int[] mBioOffsets = new int[] { -5, -1 };
+ private final int[] mOCTier1Offsets = new int[] { 2, -11 };
+ private final int[] mOCTier2Offsets = new int[] { 2, -11 };
+ private GT_MetaTileEntity_Hatch_Input mCoolantInputHatch;
+ private static final int mBioRotateBitMap = 0b1000000;
+ private static final int mOCTier2BitMap = 0b100000;
+ private static final int mOCTier1BitMap = 0b10000;
+ private static final int mBioBitMap = 0b1000;
+ private static final int mTier3BitMap = 0b100;
+ private static final int mTier2BitMap = 0b10;
+ private static final int mTier1BitMap = 0b1;
+ private static final int COOLANT_CONSUMED_PER_SEC = 10;
+ private static final IStructureDefinition<GT_MetaTileEntity_PCBFactory> STRUCTURE_DEFINITION = StructureDefinition
+ .<GT_MetaTileEntity_PCBFactory>builder()
+ .addShape(
+ tier1,
+ transpose(
+ new String[][] {
+ // spotless:off
+ {" ","E E","E E","EEEEEEE","E E","E E"," "},
+ {"EEEEEEE","CAAAAAC","CAAAAAC","CCCCCCC","CCCCCCC","CCCCCCC","E E"},
+ {"EAAAAAE","C-----C","C-----C","C-----C","C-----C","C-----C","ECCCCCE"},
+ {"EAAAAAE","C-----C","B-----B","B-----B","B-----B","C-----C","ECCCCCE"},
+ {"EAAAAAE","C-----C","B-FFF-B","B-FFF-B","B-FFF-B","C-----C","EPPPPPE"},
+ {"ECC~CCE","CDDDDDC","CDDDDDC","CDDDDDC","CDDDDDC","CDDDDDC","EPPPPPE"}
+ //spotless:on
+ }))
+ .addShape(
+ tier2,
+ transpose(
+ new String[][] {
+ // spotless:off
+ {" "," "," ","HGGH","HGGH","HGGH","HGGH","HGGH"," "," "," "},
+ {" "," ","HGGH","GGGG","GGGG","GGGG","GGGG","GGGG","HGGH"," "," "},
+ {" ","HGGH","GGGG","G G","G G","G G","G G","G G","GGGG","HGGH"," "},
+ {" ","HGGH","G G","G G","G G","G G","G G","G G","G G","HGGH"," "},
+ {"HGGH","G G","G G","G G","G G","G G","G G","G G","G G","G G","HGGH"},
+ {"HGGH","G G","G G","G G","G G","G G","G G","G G","G G","G G","HGGH"},
+ {"HGGH","GGGG","GGGG","GGGG","GGGG","GGGG","GGGG","GGGG","GGGG","GGGG","HGGH"}
+ //spotless:on
+ }))
+ .addShape(
+ tier3,
+ transpose(
+ new String[][] {
+ // spotless:off
+ {" "," "," "," "," I "," I "," "," "," "," "},
+ {" "," "," "," I "," I "," I "," I "," "," "," "},
+ {" "," "," KKK "," KIK "," K K "," K K "," I "," "," "," "},
+ {" "," "," KKK "," K K "," K K "," K K "," I "," "," "," "},
+ {" "," III "," I I "," I I "," I I "," K K "," I "," "," "," "},
+ {" "," III "," I I "," I I "," I I "," K K "," I "," "," "," "},
+ {" "," III "," I I "," I I "," I I "," K K "," KIK "," "," "," "},
+ {" "," I I "," I K I "," I I "," I I "," K K "," KIK "," "," "," "},
+ {" "," I I "," I K I "," I I "," I I "," K K "," K K "," KKK "," "," "},
+ {" "," I I "," I K I "," I I "," I I "," K K "," K K "," KKK "," "," "},
+ {" "," III "," I I "," I I "," I I "," I I "," I I "," I I "," III "," "},
+ {" "," III "," I I "," K K "," K K "," K K "," K K "," I I "," III "," "},
+ {" "," III "," I I "," I I "," I I "," I I "," I I "," I I "," III "," "},
+ {" "," "," KKK "," K K "," K K "," I I "," I I "," I I "," III "," "},
+ {" "," "," KKK "," K K "," K K "," I I "," I I "," I I "," III "," "},
+ {" "," "," KKK "," K K "," K K "," I I "," I I "," I I "," III "," "},
+ {" "," III "," I I "," I I "," I I "," I I "," I I "," I I "," III "," "},
+ {" "," III "," I I "," I I "," I I "," I I "," I I "," I I "," III "," "},
+ {" "," III "," I I "," I I "," I I "," I I "," I I "," I I "," III "," "},
+ {" "," III "," I I "," I I "," I I "," I I "," I I "," I I "," III "," "},
+ {" "," III "," I I "," I I "," I I "," I I "," I I "," I I "," III "," "},
+ {" II~II ","IIJJJII","IJJJJJI","IJJJJJI","IJJJJJI","IJJJJJI","IJJJJJI","IJJJJJI","IIJJJII"," IIIII "}
+ //spotless:on
+ }))
+ .addShape(
+ bioUpgrade,
+ transpose(
+ new String[][] {
+ // spotless:off
+ {" "," "," LLLLLL "," "," "},
+ {" "," "," L L "," "," "},
+ {"E E E E"," LLL LLL "," LLL LLL "," LLL LLL ","E E E E"},
+ {"EAAAE EAAAE","A A A A","A A A A","A A A A","EAAAE EAAAE"},
+ {"EAAAE EAAAE","A A A A","A A A A","A A A A","EAAAE EAAAE"},
+ {"EAAAE EAAAE","A A A A","A A A A","A A A A","EAAAE EAAAE"},
+ {"ELLLE ELLLE","LLLLL LLLLL","LLLLL LLLLL","LLLLL LLLLL","ELLLE ELLLE"}
+ //spotless:on
+ }))
+ .addShape(
+ ocTier1Upgrade,
+ transpose(
+ new String[][] {
+ // spotless:off
+ {"EKKKE","K K","K K","K K","EKKKE"},
+ {"E E"," KKK "," K K "," KKK ","E E"},
+ {"E E"," NNN "," N N "," NNN ","E E"},
+ {"E E"," KKK "," K K "," KKK ","E E"},
+ {"E E"," KKK "," K K "," KKK ","E E"},
+ {"EOOOE","OKKKO","OK KO","OKKKO","EOOOE"},
+ {"E E"," KKK "," K K "," KKK ","E E"},
+ {"E E"," KKK "," K K "," KKK ","E E"},
+ {"ENNNE","NKKKN","NK KN","NKKKN","ENNNE"},
+ {"EGGGE","GGGGG","GGMGG","GGGGG","EGGGE"}
+ //spotless:on
+ }))
+ .addShape(
+ ocTier2Upgrade,
+ transpose(
+ new String[][] {
+ // spotless:off
+ {"RGGGR","G G","G G","G G","RGGGR"},
+ {"R R"," GGG "," GTG "," GGG ","R R"},
+ {"R R"," NNN "," NTN "," NNN ","R R"},
+ {"R R"," QQQ "," QTQ "," QQQ ","R R"},
+ {"R R"," QQQ "," QTQ "," QQQ ","R R"},
+ {"R R"," QQQ "," QTQ "," QQQ ","R R"},
+ {"R R"," QQQ "," QTQ "," QQQ ","R R"},
+ {"R R"," QQQ "," QTQ "," QQQ ","R R"},
+ {"RNNNR","NQQQN","NQTQN","NQQQN","RNNNR"},
+ {"RGGGR","GGGGG","GGSGG","GGGGG","RGGGR"}
+ //spotless:on
+ }))
+ .addElement('E', ofFrame(Materials.DamascusSteel))
+ .addElement('C', ofBlock(GregTech_API.sBlockCasings8, 11))
+ .addElement('D', ofBlock(GregTech_API.sBlockReinforced, 2))
+ .addElement('A', Glasses.chainAllGlasses())
+ .addElement('B', ofBlock(GregTech_API.sBlockCasings3, 10))
+ .addElement('F', ofFrame(Materials.VibrantAlloy))
+ .addElement(
+ 'P',
+ buildHatchAdder(GT_MetaTileEntity_PCBFactory.class)
+ .atLeast(InputHatch, OutputBus, InputBus, Maintenance, Energy.or(ExoticEnergy))
+ .dot(1)
+ .casingIndex(((GT_Block_Casings8) GregTech_API.sBlockCasings8).getTextureIndex(11))
+ .buildAndChain(GregTech_API.sBlockCasings8, 11))
+ .addElement('H', ofFrame(Materials.Duranium))
+ .addElement('G', ofBlock(GregTech_API.sBlockCasings8, 12))
+ .addElement('I', ofBlock(GregTech_API.sBlockCasings8, 13))
+ .addElement('K', ofBlock(GregTech_API.sBlockCasings8, 10))
+ .addElement(
+ 'J',
+ buildHatchAdder(GT_MetaTileEntity_PCBFactory.class)
+ .atLeast(InputHatch, OutputBus, InputBus, Maintenance, Energy.or(ExoticEnergy))
+ .dot(1)
+ .casingIndex(((GT_Block_Casings8) GregTech_API.sBlockCasings8).getTextureIndex(13))
+ .buildAndChain(GregTech_API.sBlockCasings8, 13))
+ .addElement('L', ofBlock(GregTech_API.sBlockCasings4, 1))
+ .addElement(
+ 'M',
+ buildHatchAdder(GT_MetaTileEntity_PCBFactory.class).hatchClass(GT_MetaTileEntity_Hatch_Input.class)
+ .adder(GT_MetaTileEntity_PCBFactory::addCoolantInputToMachineList)
+ .casingIndex(GT_Utility.getCasingTextureIndex(GregTech_API.sBlockCasings8, 12))
+ .dot(2)
+ .buildAndChain(GregTech_API.sBlockCasings8, 12))
+ .addElement('N', ofBlock(GregTech_API.sBlockCasings2, 15))
+ .addElement('O', ofBlock(GregTech_API.sBlockCasings8, 4))
+ .addElement(
+ 'S',
+ buildHatchAdder(GT_MetaTileEntity_PCBFactory.class).hatchClass(GT_MetaTileEntity_Hatch_Input.class)
+ .adder(GT_MetaTileEntity_PCBFactory::addCoolantInputToMachineList)
+ .casingIndex(GT_Utility.getCasingTextureIndex(GregTech_API.sBlockCasings8, 12))
+ .dot(2)
+ .buildAndChain(GregTech_API.sBlockCasings8, 12))
+ .addElement('R', ofFrame(Materials.Americium))
+ .addElement('Q', ofBlock(GregTech_API.sBlockCasings8, 14))
+ .addElement('T', ofBlock(GregTech_API.sBlockCasings1, 15))
+ .build();
+
+ @Override
+ public void construct(ItemStack stackSize, boolean hintsOnly) {
+ if (mSetTier < 3) {
+ buildPiece(tier1, stackSize, hintsOnly, 3, 5, 0);
+ if (mSetTier == 2) {
+ buildPiece(tier2, stackSize, hintsOnly, 7, 6, 2);
+ }
+ } else {
+ buildPiece(tier3, stackSize, hintsOnly, 3, 21, 0);
+ }
+
+ if (mBioUpgrade) {
+ if (mBioRotate) {
+ final IGregTechTileEntity tTile = getBaseMetaTileEntity();
+ getStructureDefinition().buildOrHints(
+ this,
+ stackSize,
+ bioUpgrade,
+ tTile.getWorld(),
+ transformFacing(getExtendedFacing()),
+ tTile.getXCoord(),
+ tTile.getYCoord(),
+ tTile.getZCoord(),
+ mBioOffsets[1],
+ 6,
+ mBioOffsets[0],
+ hintsOnly);
+ } else {
+ buildPiece(bioUpgrade, stackSize, hintsOnly, mBioOffsets[0], 6, mBioOffsets[1]);
+ }
+ }
+
+ if (mOCTier1 && !mOCTier2) {
+ buildPiece(ocTier1Upgrade, stackSize, hintsOnly, mOCTier1Offsets[0], 9, mOCTier1Offsets[1]);
+ }
+
+ if (!mOCTier1 && mOCTier2) {
+ buildPiece(ocTier2Upgrade, stackSize, hintsOnly, mOCTier2Offsets[0], 9, mOCTier2Offsets[1]);
+ }
+ }
+
+ public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
+ if (mMachine) return -1;
+ int built = 0;
+ if (mSetTier < 3) {
+ built += survivialBuildPiece(tier1, stackSize, 3, 5, 0, elementBudget, env, false, true);
+ if (mSetTier == 2) {
+ built += survivialBuildPiece(tier2, stackSize, 7, 6, 2, elementBudget, env, false, true);
+ }
+ } else {
+ built += survivialBuildPiece(tier3, stackSize, 3, 21, 0, elementBudget, env, false, true);
+ }
+
+ if (mBioUpgrade) {
+ if (mBioRotate) {
+ final IGregTechTileEntity tTile = getBaseMetaTileEntity();
+ getStructureDefinition().survivalBuild(
+ this,
+ stackSize,
+ bioUpgrade,
+ tTile.getWorld(),
+ transformFacing(getExtendedFacing()),
+ tTile.getXCoord(),
+ tTile.getYCoord(),
+ tTile.getZCoord(),
+ mBioOffsets[1],
+ 6,
+ mBioOffsets[0],
+ elementBudget,
+ env,
+ false);
+ } else {
+ built += survivialBuildPiece(
+ bioUpgrade,
+ stackSize,
+ mBioOffsets[0],
+ 6,
+ mBioOffsets[1],
+ elementBudget,
+ env,
+ false,
+ true);
+ }
+ }
+
+ if (mOCTier1 && !mOCTier2) {
+ built += survivialBuildPiece(
+ ocTier1Upgrade,
+ stackSize,
+ mOCTier1Offsets[0],
+ 9,
+ mOCTier1Offsets[1],
+ elementBudget,
+ env,
+ false,
+ true);
+ }
+ if (!mOCTier1 && mOCTier2) {
+ built += survivialBuildPiece(
+ ocTier2Upgrade,
+ stackSize,
+ mOCTier2Offsets[0],
+ 9,
+ mOCTier2Offsets[1],
+ elementBudget,
+ env,
+ false,
+ true);
+ }
+
+ return built;
+ }
+
+ public GT_MetaTileEntity_PCBFactory(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_PCBFactory(String aName) {
+ super(aName);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_PCBFactory(this.mName);
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity baseMetaTileEntity, ForgeDirection sideDirection,
+ ForgeDirection facingDirection, int colorIndex, boolean active, boolean redstoneLevel) {
+ if (sideDirection == facingDirection) {
+ if (active)
+ return new ITexture[] {
+ BlockIcons.getCasingTextureForId(
+ getTier() < 3 ? GT_Utility.getCasingTextureIndex(GregTech_API.sBlockCasings8, 11)
+ : GT_Utility.getCasingTextureIndex(GregTech_API.sBlockCasings8, 13)),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_ASSEMBLY_LINE_ACTIVE)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_ASSEMBLY_LINE_ACTIVE_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ return new ITexture[] {
+ BlockIcons.getCasingTextureForId(
+ getTier() < 3 ? GT_Utility.getCasingTextureIndex(GregTech_API.sBlockCasings8, 11)
+ : GT_Utility.getCasingTextureIndex(GregTech_API.sBlockCasings8, 13)),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_ASSEMBLY_LINE)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_ASSEMBLY_LINE_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ }
+ return new ITexture[] { BlockIcons.getCasingTextureForId(
+ mSetTier < 3 ? ((GT_Block_Casings8) GregTech_API.sBlockCasings8).getTextureIndex(11)
+ : ((GT_Block_Casings8) GregTech_API.sBlockCasings8).getTextureIndex(13)) };
+ }
+
+ @Override
+ public IStructureDefinition<GT_MetaTileEntity_PCBFactory> getStructureDefinition() {
+ return STRUCTURE_DEFINITION;
+ }
+
+ @Override
+ public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+ mTier = 0;
+ mUpgradesInstalled = 0;
+ mCoolantInputHatch = null;
+ if (mSetTier < 3) {
+ if (!checkPiece(tier1, 3, 5, 0)) {
+ return false;
+ }
+ if (mSetTier == 2) {
+ if (!checkPiece(tier2, 7, 6, 2)) {
+ return false;
+ }
+ mTier = 2;
+ } else {
+ mTier = 1;
+ }
+ } else {
+ if (!checkPiece(tier3, 3, 21, 0)) {
+ return false;
+ }
+ mTier = 3;
+ }
+
+ if (mBioUpgrade) {
+ if (mBioRotate) {
+ final IGregTechTileEntity tTile = getBaseMetaTileEntity();
+ if (!getStructureDefinition().check(
+ this,
+ bioUpgrade,
+ tTile.getWorld(),
+ transformFacing(getExtendedFacing()),
+ tTile.getXCoord(),
+ tTile.getYCoord(),
+ tTile.getZCoord(),
+ mBioOffsets[1],
+ 6,
+ mBioOffsets[0],
+ !mMachine)) {
+ return false;
+ }
+ } else {
+ if (!checkPiece(bioUpgrade, mBioOffsets[0], 6, mBioOffsets[1])) {
+ return false;
+ }
+ }
+ mUpgradesInstalled++;
+ }
+
+ if (mOCTier1 && !mOCTier2) {
+ if (!checkPiece(ocTier1Upgrade, mOCTier1Offsets[0], 9, mOCTier1Offsets[1])) {
+ return false;
+ }
+ if (mCoolantInputHatch == null) {
+ return false;
+ }
+ mUpgradesInstalled++;
+ }
+
+ if (mOCTier2 && !mOCTier1) {
+ if (!checkPiece(ocTier2Upgrade, mOCTier2Offsets[0], 9, mOCTier2Offsets[1])) {
+ return false;
+ }
+ if (mCoolantInputHatch == null) {
+ return false;
+ }
+ mUpgradesInstalled++;
+ }
+
+ getBaseMetaTileEntity().sendBlockEvent(GregTechTileClientEvents.CHANGE_CUSTOM_DATA, getUpdateData());
+
+ if (mMaintenanceHatches.size() != 1) {
+ return false;
+ }
+
+ if (!checkExoticAndNormalEnergyHatches()) {
+ return false;
+ }
+
+ return mTier > 0;
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.pcbFactoryRecipes;
+ }
+
+ @Override
+ protected ProcessingLogic createProcessingLogic() {
+ return new ProcessingLogic() {
+
+ @NotNull
+ @Override
+ protected CheckRecipeResult validateRecipe(@Nonnull GT_Recipe recipe) {
+ // Here we check the dynamic parallels, which depend on the recipe
+ int numberOfNanites = 0;
+ ItemStack aNanite = recipe.getRepresentativeInput(1);
+ ItemData naniteData = GT_OreDictUnificator.getAssociation(aNanite);
+ if (naniteData != null && naniteData.mPrefix != null && naniteData.mPrefix.equals(OrePrefixes.nanite)) {
+ for (ItemStack aItem : inputItems) {
+ if (aItem != null && aItem.isItemEqual(aNanite)) {
+ numberOfNanites += aItem.stackSize;
+ }
+ }
+ }
+ maxParallel = (int) Math.max(Math.ceil(Math.log(numberOfNanites) / Math.log(2) + 0.00001), 1);
+ mMaxParallel = maxParallel;
+
+ PCBFactoryUpgrade requiredUpgrade = recipe.getMetadata(PCBFactoryUpgradeKey.INSTANCE);
+ if (requiredUpgrade == PCBFactoryUpgrade.BIO && !mBioUpgrade)
+ return SimpleCheckRecipeResult.ofFailure("bio_upgrade_missing");
+
+ int requiredPCBTier = recipe.getMetadataOrDefault(PCBFactoryTierKey.INSTANCE, 1);
+ if (requiredPCBTier > mTier) return CheckRecipeResultRegistry.insufficientMachineTier(requiredPCBTier);
+
+ return CheckRecipeResultRegistry.SUCCESSFUL;
+ }
+
+ @Nonnull
+ @Override
+ protected GT_OverclockCalculator createOverclockCalculator(@Nonnull GT_Recipe recipe) {
+ return super.createOverclockCalculator(recipe).setNoOverclock(isNoOC())
+ .setEUtDiscount((float) Math.sqrt(mUpgradesInstalled == 0 ? 1 : mUpgradesInstalled))
+ .setSpeedBoost(getDurationMultiplierFromRoughness())
+ .setDurationDecreasePerOC(mOCTier2 ? 2 : 1);
+ }
+
+ @Nonnull
+ @Override
+ protected GT_ParallelHelper createParallelHelper(@Nonnull GT_Recipe recipe) {
+ return super.createParallelHelper(recipe)
+ .setEUtModifier((float) Math.sqrt(mUpgradesInstalled == 0 ? 1 : mUpgradesInstalled))
+ .setChanceMultiplier(mRoughnessMultiplier);
+ }
+ };
+ }
+
+ private boolean isNoOC() {
+ return !mOCTier1 && !mOCTier2;
+ }
+
+ private float getDurationMultiplierFromRoughness() {
+ return (float) Math.pow(mRoughnessMultiplier, 2);
+ }
+
+ private int ticker = 0;
+
+ @Override
+ public boolean onRunningTick(ItemStack aStack) {
+ if (!super.onRunningTick(aStack)) {
+ return false;
+ }
+
+ if (ticker % 20 == 0) {
+ if (!isNoOC()) {
+ FluidStack tFluid = mOCTier1 ? GT_ModHandler.getDistilledWater(COOLANT_CONSUMED_PER_SEC)
+ : Materials.SuperCoolant.getFluid(COOLANT_CONSUMED_PER_SEC);
+ if (!drain(mCoolantInputHatch, tFluid, true)) {
+ stopMachine(ShutDownReasonRegistry.outOfFluid(tFluid));
+ return false;
+ }
+ }
+ ticker = 0;
+ }
+
+ ticker++;
+
+ return true;
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ super.onPostTick(aBaseMetaTileEntity, aTick);
+ if (aBaseMetaTileEntity.isServerSide()) {
+ // TODO: Look for proper fix
+ // Updates every 10 sec
+ if (mUpdate <= -150) mUpdate = 50;
+ }
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack aStack) {
+ return (int) (10000f * mRoughnessMultiplier);
+ }
+
+ @Override
+ public int getDamageToComponent(ItemStack aStack) {
+ return 0;
+ }
+
+ private int getTier() {
+ return mSetTier;
+ }
+
+ @Override
+ public void receiveClientEvent(byte aEventID, byte aValue) {
+ if (aEventID == 1) {
+ if ((aValue & mTier1BitMap) == mTier1BitMap) {
+ mSetTier = 1;
+ }
+
+ if ((aValue & mTier2BitMap) == mTier2BitMap) {
+ mSetTier = 2;
+ }
+
+ if ((aValue & mTier3BitMap) == mTier3BitMap) {
+ mSetTier = 3;
+ }
+
+ if ((aValue & mBioBitMap) == mBioBitMap) {
+ mBioUpgrade = true;
+ }
+
+ if ((aValue & mBioRotateBitMap) == mBioRotateBitMap) {
+ mBioRotate = true;
+ }
+
+ if ((aValue & mOCTier1BitMap) == mOCTier1BitMap) {
+ mOCTier1 = true;
+ }
+
+ if ((aValue & mOCTier2BitMap) == mOCTier2BitMap) {
+ mOCTier2 = true;
+ }
+ }
+ }
+
+ private ExtendedFacing transformFacing(ExtendedFacing facing) {
+ ForgeDirection curDirection = facing.getDirection();
+ Rotation curRotation = facing.getRotation();
+ Flip curFlip = facing.getFlip();
+ ForgeDirection newDirection = curDirection;
+ Rotation newRotation = curRotation;
+ Flip newFlip = curFlip;
+
+ if (curDirection == ForgeDirection.UP || curDirection == ForgeDirection.DOWN) {
+ switch (curRotation) {
+ case CLOCKWISE, COUNTER_CLOCKWISE -> {
+ newFlip = curFlip == Flip.NONE ? Flip.HORIZONTAL : Flip.NONE;
+ newDirection = curDirection == ForgeDirection.UP ? ForgeDirection.NORTH : ForgeDirection.SOUTH;
+ }
+ case NORMAL -> {
+ newRotation = curDirection == ForgeDirection.UP ? Rotation.CLOCKWISE : Rotation.COUNTER_CLOCKWISE;
+ newDirection = curDirection == ForgeDirection.UP ? ForgeDirection.EAST : ForgeDirection.WEST;
+ newFlip = Flip.NONE;
+ }
+ case UPSIDE_DOWN -> {
+ newRotation = curDirection == ForgeDirection.UP ? Rotation.COUNTER_CLOCKWISE : Rotation.CLOCKWISE;
+ newDirection = curDirection == ForgeDirection.UP ? ForgeDirection.EAST : ForgeDirection.WEST;
+ newFlip = Flip.NONE;
+ }
+ }
+ } else if (curRotation == Rotation.CLOCKWISE || curRotation == Rotation.COUNTER_CLOCKWISE) {
+ newFlip = curRotation == Rotation.CLOCKWISE ? curFlip == Flip.NONE ? Flip.NONE : Flip.HORIZONTAL
+ : curFlip != Flip.NONE ? Flip.NONE : Flip.HORIZONTAL;
+ newDirection = curRotation == Rotation.CLOCKWISE ? ForgeDirection.UP : ForgeDirection.DOWN;
+ } else {
+ newDirection = switch (curDirection) {
+ case EAST -> ForgeDirection.SOUTH;
+ case NORTH -> ForgeDirection.EAST;
+ case WEST -> ForgeDirection.NORTH;
+ case SOUTH -> ForgeDirection.WEST;
+ default -> curDirection;
+ };
+ }
+
+ if (curRotation == Rotation.UPSIDE_DOWN) {
+ if (curDirection != ForgeDirection.UP && curDirection != ForgeDirection.DOWN) {
+ newFlip = curFlip == Flip.NONE ? Flip.HORIZONTAL : Flip.NONE;
+ }
+ }
+
+ return ExtendedFacing.of(newDirection, newRotation, newFlip);
+ }
+
+ @Override
+ public boolean explodesOnComponentBreak(ItemStack aStack) {
+ return false;
+ }
+
+ public boolean addCoolantInputToMachineList(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
+ if (aTileEntity == null) return false;
+ IMetaTileEntity aMetaTileEntity = aTileEntity.getMetaTileEntity();
+ if (aMetaTileEntity == null) return false;
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Input) {
+ ((GT_MetaTileEntity_Hatch) aMetaTileEntity).updateTexture(aBaseCasingIndex);
+ ((GT_MetaTileEntity_Hatch_Input) aMetaTileEntity).mRecipeMap = null;
+ mCoolantInputHatch = (GT_MetaTileEntity_Hatch_Input) aMetaTileEntity;
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ protected long getActualEnergyUsage() {
+ return (-this.lEUt * 10000) / Math.min(Math.max(1000, mEfficiency), 10000);
+ }
+
+ @Override
+ public void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ inputSeparation = !inputSeparation;
+ GT_Utility.sendChatToPlayer(
+ aPlayer,
+ StatCollector.translateToLocal("GT5U.machines.separatebus") + " " + inputSeparation);
+ }
+
+ @Override
+ public String[] getInfoData() {
+ int mPollutionReduction = 0;
+ for (GT_MetaTileEntity_Hatch_Muffler tHatch : filterValidMTEs(mMufflerHatches)) {
+ mPollutionReduction = Math.max(tHatch.calculatePollutionReduction(100), mPollutionReduction);
+ }
+
+ long storedEnergy = 0;
+ long maxEnergy = 0;
+ for (GT_MetaTileEntity_Hatch tHatch : getExoticAndNormalEnergyHatchList()) {
+ storedEnergy += tHatch.getBaseMetaTileEntity()
+ .getStoredEU();
+ maxEnergy += tHatch.getBaseMetaTileEntity()
+ .getEUCapacity();
+ }
+ long voltage = getAverageInputVoltage();
+ long amps = getMaxInputAmps();
+
+ return new String[] {
+ /* 1 */ StatCollector.translateToLocal("GT5U.multiblock.Progress") + ": "
+ + EnumChatFormatting.GREEN
+ + GT_Utility.formatNumbers(mProgresstime / 20)
+ + EnumChatFormatting.RESET
+ + " s / "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(mMaxProgresstime / 20)
+ + EnumChatFormatting.RESET
+ + " s",
+ /* 2 */ StatCollector.translateToLocal("GT5U.multiblock.energy") + ": "
+ + EnumChatFormatting.GREEN
+ + GT_Utility.formatNumbers(storedEnergy)
+ + EnumChatFormatting.RESET
+ + " EU / "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(maxEnergy)
+ + EnumChatFormatting.RESET
+ + " EU",
+ /* 3 */ StatCollector.translateToLocal("GT5U.multiblock.usage") + ": "
+ + EnumChatFormatting.RED
+ + GT_Utility.formatNumbers(getActualEnergyUsage())
+ + EnumChatFormatting.RESET
+ + " EU/t",
+ /* 4 */ StatCollector.translateToLocal("GT5U.multiblock.mei") + ": "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(voltage)
+ + EnumChatFormatting.RESET
+ + " EU/t(*"
+ + amps
+ + " A)"
+ + StatCollector.translateToLocal("GT5U.machines.tier")
+ + ": "
+ + EnumChatFormatting.YELLOW
+ + VN[GT_Utility.getTier(voltage)]
+ + EnumChatFormatting.RESET,
+ /* 5 */ StatCollector.translateToLocal("GT5U.multiblock.problems") + ": "
+ + EnumChatFormatting.RED
+ + (getIdealStatus() - getRepairStatus())
+ + EnumChatFormatting.RESET
+ + " "
+ + StatCollector.translateToLocal("GT5U.multiblock.efficiency")
+ + ": "
+ + EnumChatFormatting.YELLOW
+ + mEfficiency / 100.0F
+ + EnumChatFormatting.RESET
+ + " %",
+ /* 6 */ StatCollector.translateToLocal("GT5U.multiblock.pollution") + ": "
+ + EnumChatFormatting.GREEN
+ + mPollutionReduction
+ + EnumChatFormatting.RESET
+ + " %",
+ /* 7 */ StatCollector.translateToLocal("GT5U.multiblock.parallelism") + ": "
+ + EnumChatFormatting.GREEN
+ + mMaxParallel,
+ /* 8 */ StatCollector.translateToLocal("GT5U.multiblock.curparallelism") + ": "
+ + EnumChatFormatting.GREEN
+ + mCurrentParallel };
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Circuit Board Fabricator")
+ .addInfo("Controller for the PCB Factory")
+ .addInfo(
+ EnumChatFormatting.GOLD.toString() + EnumChatFormatting.BOLD
+ + "IMPORTANT!"
+ + " Check the configuration menu before building.")
+ .addInfo("Tier of the machine determines the available recipes.")
+ .addInfo("Machine tier (1-3) is set in the controller GUI.")
+ .addInfo("The configuration menu can be used to add upgrades.")
+ .addInfo("Each tier and upgrade requires additional structures.")
+ .addInfo("Power consumption is multiplied by Sqrt(structures).")
+ .addInfo("Tier 2 and 3 allow parallel by using extra nanites.")
+ .addInfo("Every doubling of nanites adds one parallel.")
+ .addInfo("1x->1, 2x->2, 4x->3, 8x->4 with no limit.")
+ .addInfo("Recipes require a cooling upgrade to be overclocked.")
+ .addInfo("Liquid Cooling uses 10 L/s of distilled water and enables default overclocks.")
+ .addInfo("Thermosink uses 10 L/s of Super Coolant and enables perfect overclocks.")
+ .addInfo("Trace size can be changed to modify the material usage and machine speed.")
+ .addInfo(AuthorBlueWeabo)
+ .beginStructureBlock(30, 38, 13, false)
+ .addSeparator()
+ .addMaintenanceHatch(EnumChatFormatting.GOLD + "1", 1)
+ .addEnergyHatch(
+ EnumChatFormatting.GOLD + "1"
+ + EnumChatFormatting.GRAY
+ + "-"
+ + EnumChatFormatting.GOLD
+ + "2"
+ + EnumChatFormatting.GRAY
+ + " or "
+ + EnumChatFormatting.GOLD
+ + "1"
+ + EnumChatFormatting.GRAY
+ + " TT energy hatch.",
+ 1)
+ .addInputBus(EnumChatFormatting.GOLD + "0" + EnumChatFormatting.GRAY + "+", 1)
+ .addOutputBus(EnumChatFormatting.GOLD + "0" + EnumChatFormatting.GRAY + "+", 1)
+ .addInputHatch(EnumChatFormatting.GOLD + "0" + EnumChatFormatting.GRAY + "+", 1)
+ .addStructureInfo(
+ "Coolant Hatch (Input Hatch): " + EnumChatFormatting.GOLD
+ + "1"
+ + EnumChatFormatting.GRAY
+ + " Center of the Liquid Cooling/Thermosink")
+ .addStructureInfo(
+ EnumChatFormatting.BLUE + "Base Multi (Tier "
+ + EnumChatFormatting.DARK_PURPLE
+ + 1
+ + EnumChatFormatting.BLUE
+ + "):")
+ .addStructureInfo(EnumChatFormatting.GOLD + "40" + EnumChatFormatting.GRAY + " Damascus Steel Frame Box")
+ .addStructureInfo(EnumChatFormatting.GOLD + "9" + EnumChatFormatting.GRAY + " Vibrant Alloy Frame Box")
+ .addStructureInfo(EnumChatFormatting.GOLD + "25" + EnumChatFormatting.GRAY + " Reinforced Glass")
+ .addStructureInfo(
+ EnumChatFormatting.GOLD + "77" + EnumChatFormatting.GRAY + " Basic Photolithography Framework Casing")
+ .addStructureInfo(EnumChatFormatting.GOLD + "12" + EnumChatFormatting.GRAY + " Grate Machine Casing")
+ .addStructureInfo(EnumChatFormatting.GOLD + "25" + EnumChatFormatting.GRAY + " Plascrete Block")
+ .addStructureInfo(
+ EnumChatFormatting.BLUE + "Tier "
+ + EnumChatFormatting.DARK_PURPLE
+ + 2
+ + EnumChatFormatting.BLUE
+ + " (Adds to Tier "
+ + EnumChatFormatting.DARK_PURPLE
+ + 1
+ + EnumChatFormatting.BLUE
+ + "):")
+ .addStructureInfo(EnumChatFormatting.GOLD + "34" + EnumChatFormatting.GRAY + " Duranium Frame Box")
+ .addStructureInfo(
+ EnumChatFormatting.GOLD + "158"
+ + EnumChatFormatting.GRAY
+ + " Reinforced Photolithography Framework Casing")
+ .addStructureInfo(
+ EnumChatFormatting.BLUE + "Tier " + EnumChatFormatting.DARK_PURPLE + 3 + EnumChatFormatting.BLUE + ":")
+ .addStructureInfo(
+ EnumChatFormatting.GOLD + "292"
+ + EnumChatFormatting.GRAY
+ + " Radiation Proof Photolithography Framework Casing")
+ .addStructureInfo(
+ EnumChatFormatting.GOLD + "76" + EnumChatFormatting.GRAY + " Radiant Naquadah Alloy Casing")
+ .addStructureInfo(EnumChatFormatting.BLUE + "Biochamber Upgrade")
+ .addStructureInfo(
+ EnumChatFormatting.GOLD + "68" + EnumChatFormatting.GRAY + " Clean Stainless Steel Machine Casing")
+ .addStructureInfo(EnumChatFormatting.GOLD + "40" + EnumChatFormatting.GRAY + " Damascus Steel Frame Box")
+ .addStructureInfo(EnumChatFormatting.GOLD + "72" + EnumChatFormatting.GRAY + " Reinforced Glass")
+ .addStructureInfo(
+ EnumChatFormatting.BLUE + "Liquid Cooling Tower (Tier "
+ + EnumChatFormatting.DARK_PURPLE
+ + 1
+ + EnumChatFormatting.BLUE
+ + "):")
+ .addStructureInfo(EnumChatFormatting.GOLD + "40" + EnumChatFormatting.GRAY + " Damascus Steel Frame Box")
+ .addStructureInfo(
+ EnumChatFormatting.GOLD + "68" + EnumChatFormatting.GRAY + " Radiant Naquadah Alloy Casing")
+ .addStructureInfo(
+ EnumChatFormatting.GOLD + "12" + EnumChatFormatting.GRAY + " Extreme Engine Intake Casing")
+ .addStructureInfo(EnumChatFormatting.GOLD + "20" + EnumChatFormatting.GRAY + " Tungstensteel Pipe Casing")
+ .addStructureInfo(
+ EnumChatFormatting.GOLD + "21"
+ + EnumChatFormatting.GRAY
+ + " Reinforced Photolithography Framework Casing")
+ .addStructureInfo(
+ EnumChatFormatting.BLUE + "Thermosink Radiator(Tier "
+ + EnumChatFormatting.DARK_PURPLE
+ + 2
+ + EnumChatFormatting.BLUE
+ + "):")
+ .addStructureInfo(EnumChatFormatting.GOLD + "40" + EnumChatFormatting.GRAY + " Americium Frame Box")
+ .addStructureInfo(
+ EnumChatFormatting.GOLD + "41"
+ + EnumChatFormatting.GRAY
+ + " Reinforced Photolithography Framework Casing")
+ .addStructureInfo(EnumChatFormatting.GOLD + "8" + EnumChatFormatting.GRAY + " Superconducting Coil Block")
+ .addStructureInfo(EnumChatFormatting.GOLD + "20" + EnumChatFormatting.GRAY + " Tungstensteel Pipe Casing")
+ .addStructureInfo(EnumChatFormatting.GOLD + "48" + EnumChatFormatting.GRAY + " Infinity Cooled Casing")
+ .toolTipFinisher("GregTech");
+ return tt;
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ aNBT.setBoolean("mBioUpgrade", mBioUpgrade);
+ aNBT.setBoolean("mBioRotate", mBioRotate);
+ aNBT.setInteger("mBioOffsetX", mBioOffsets[0]);
+ aNBT.setInteger("mBioOffsetZ", mBioOffsets[1]);
+ aNBT.setBoolean("mOCTier1Upgrade", mOCTier1);
+ aNBT.setInteger("mOCTier1OffsetX", mOCTier1Offsets[0]);
+ aNBT.setInteger("mOCTier1OffsetZ", mOCTier1Offsets[1]);
+ aNBT.setBoolean("mOCTier2Upgrade", mOCTier2);
+ aNBT.setInteger("mOCTier2OffsetX", mOCTier2Offsets[0]);
+ aNBT.setInteger("mOCTier2OffsetZ", mOCTier2Offsets[1]);
+ aNBT.setFloat("mRoughnessMultiplier", mRoughnessMultiplier);
+ aNBT.setInteger("mSetTier", mSetTier);
+ }
+
+ @Override
+ public void loadNBTData(final NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ if (aNBT.hasKey("mSeparate")) {
+ // backward compatibility
+ inputSeparation = aNBT.getBoolean("mSeparate");
+ }
+ mBioUpgrade = aNBT.getBoolean("mBioUpgrade");
+ mBioRotate = aNBT.getBoolean("mBioRotate");
+ mBioOffsets[0] = aNBT.getInteger("mBioOffsetX");
+ mBioOffsets[1] = aNBT.getInteger("mBioOffsetZ");
+ mOCTier1 = aNBT.getBoolean("mOCTier1Upgrade");
+ mOCTier1Offsets[0] = aNBT.getInteger("mOCTier1OffsetX");
+ mOCTier1Offsets[1] = aNBT.getInteger("mOCTier1OffsetZ");
+ mOCTier2 = aNBT.getBoolean("mOCTier2Upgrade");
+ mOCTier2Offsets[0] = aNBT.getInteger("mOCTier2OffsetX");
+ mOCTier2Offsets[1] = aNBT.getInteger("mOCTier2OffsetZ");
+ mRoughnessMultiplier = aNBT.getFloat("mRoughnessMultiplier");
+ mSetTier = aNBT.getInteger("mSetTier");
+ }
+
+ @Override
+ public boolean isCorrectMachinePart(ItemStack aStack) {
+ return true;
+ }
+
+ @Override
+ protected SoundResource getProcessStartSound() {
+ return SoundResource.IC2_MACHINES_MAGNETIZER_LOOP;
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ @Override
+ public byte getUpdateData() {
+ byte data = 0;
+ if (mSetTier == 1) {
+ data += mTier1BitMap;
+ } else if (mSetTier == 2) {
+ data += mTier2BitMap;
+ } else {
+ data += mTier3BitMap;
+ }
+
+ if (mBioUpgrade) {
+ data += mBioBitMap;
+ }
+
+ if (mBioRotate) {
+ data += mBioRotateBitMap;
+ }
+
+ if (mOCTier1) {
+ data += mOCTier1BitMap;
+ }
+
+ if (mOCTier2) {
+ data += mOCTier2BitMap;
+ }
+
+ return data;
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ super.addUIWidgets(builder, buildContext);
+ buildContext.addSyncedWindow(10, this::createConfigurationWindow);
+ builder.widget(
+ new ButtonWidget().setOnClick(
+ (clickData, widget) -> {
+ if (!widget.isClient()) widget.getContext()
+ .openSyncedWindow(10);
+ })
+ .setSize(16, 16)
+ .setBackground(() -> {
+ List<UITexture> ret = new ArrayList<>();
+ ret.add(GT_UITextures.BUTTON_STANDARD);
+ ret.add(GT_UITextures.OVERLAY_BUTTON_CYCLIC);
+ return ret.toArray(new IDrawable[0]);
+ })
+ .addTooltip("Configuration Menu")
+ .setPos(174, 130))
+ .widget(
+ new TextWidget(new Text("Tier")).setTextAlignment(Alignment.Center)
+ .setScale(0.91f)
+ .setSize(20, 16)
+ .setPos(173, 98))
+ .widget(
+ new NumericWidget().setGetter(() -> mSetTier)
+ .setSetter(val -> mSetTier = (int) val)
+ .setBounds(1, 3)
+ .setTextColor(Color.WHITE.normal)
+ .setTextAlignment(Alignment.Center)
+ .addTooltip("PCB Factory Tier")
+ .setBackground(GT_UITextures.BACKGROUND_TEXT_FIELD)
+ .setSize(18, 18)
+ .setPos(173, 110));
+ }
+
+ protected ModularWindow createConfigurationWindow(final EntityPlayer player) {
+ ModularWindow.Builder builder = ModularWindow.builder(200, 160);
+ builder.setBackground(GT_UITextures.BACKGROUND_SINGLEBLOCK_DEFAULT);
+ builder.setGuiTint(getGUIColorization());
+ builder.widget(
+ new DrawableWidget().setDrawable(GT_UITextures.OVERLAY_BUTTON_CYCLIC)
+ .setPos(5, 5)
+ .setSize(16, 16))
+ .widget(new TextWidget("Configuration Menu").setPos(25, 9))
+ .widget(
+ ButtonWidget.closeWindowButton(true)
+ .setPos(185, 3))
+ .widget(
+ new DynamicPositionedColumn().setSynced(false)
+ .widget(
+ new MultiChildWidget().addChild(new CycleButtonWidget().setToggle(() -> mBioUpgrade, val -> {
+ mBioUpgrade = val;
+ if (!mBioUpgrade) {
+ GT_Utility
+ .sendChatToPlayer(player, GT_Utility.trans("339.1", "Biochamber Upgrade Disabled"));
+ } else {
+ GT_Utility
+ .sendChatToPlayer(player, GT_Utility.trans("339", "Biochamber Upgrade Enabled"));
+ }
+ })
+ .setVariableBackground(GT_UITextures.BUTTON_STANDARD_TOGGLE)
+ .setSize(90, 18)
+ .addTooltip(
+ "Enables nanites to construct organic circuitry. Required for Bioware and Wetware boards."))
+ .addChild(
+ new DrawableWidget().setDrawable(GT_UITextures.OVERLAY_BUTTON_CYCLIC)
+ .setSize(18, 18))
+ .addChild(
+ new TextWidget("Biochamber").setTextAlignment(Alignment.Center)
+ .setPos(23, 5))
+ .setEnabled(widget -> !getBaseMetaTileEntity().isActive()))
+ .widget(new MultiChildWidget().addChild(new CycleButtonWidget().setToggle(() -> mBioRotate, val -> {
+ mBioRotate = val;
+ if (!mBioRotate) {
+ GT_Utility
+ .sendChatToPlayer(player, GT_Utility.trans("340.1", "Rotated biochamber disabled"));
+ } else {
+ GT_Utility.sendChatToPlayer(player, GT_Utility.trans("340", "Rotated biochamber enabled"));
+ }
+ })
+ .setVariableBackground(GT_UITextures.BUTTON_STANDARD_TOGGLE)
+ .setSize(90, 18)
+ .addTooltip("Rotates the biochamber by 90 degrees."))
+ .addChild(
+ new DrawableWidget().setDrawable(GT_UITextures.OVERLAY_BUTTON_CYCLIC)
+ .setSize(18, 18))
+ .addChild(
+ new TextWidget("Bio Rotation").setTextAlignment(Alignment.Center)
+ .setPos(23, 5))
+ .setEnabled(widget -> !getBaseMetaTileEntity().isActive()))
+ .widget(new MultiChildWidget().addChild(new CycleButtonWidget().setToggle(() -> mOCTier1, val -> {
+ mOCTier1 = val;
+ mOCTier2 = false;
+ if (!mOCTier1) {
+ GT_Utility.sendChatToPlayer(player, GT_Utility.trans("341.1", "Tier 1 cooling disabled"));
+ } else {
+ GT_Utility.sendChatToPlayer(player, GT_Utility.trans("341", "Tier 1 cooling enabled"));
+ }
+ })
+ .setVariableBackground(GT_UITextures.BUTTON_STANDARD_TOGGLE)
+ .setSize(90, 18)
+ .addTooltip(
+ "Allows for overclocking. Requires 10 L/s of distilled water. Cooling upgrades are mutually exclusive."))
+ .addChild(
+ new DrawableWidget().setDrawable(GT_UITextures.OVERLAY_BUTTON_CYCLIC)
+ .setSize(18, 18))
+ .addChild(
+ new TextWidget("Liquid Cooling").setTextAlignment(Alignment.Center)
+ .setPos(20, 5))
+ .setEnabled(widget -> !getBaseMetaTileEntity().isActive()))
+ .widget(new MultiChildWidget().addChild(new CycleButtonWidget().setToggle(() -> mOCTier2, val -> {
+ mOCTier2 = val;
+ mOCTier1 = false;
+ if (!mOCTier2) {
+ GT_Utility.sendChatToPlayer(player, GT_Utility.trans("342.1", "Tier 2 cooling disabled"));
+ } else {
+ GT_Utility.sendChatToPlayer(player, GT_Utility.trans("342", "Tier 2 cooling enabled"));
+ }
+ })
+ .setVariableBackground(GT_UITextures.BUTTON_STANDARD_TOGGLE)
+ .setSize(90, 18)
+ .addTooltip(
+ "Enables perfect overclocking by allowing nanites to work with extreme speed and efficiency. Uses 10 L/s of Super Coolant."))
+ .addChild(
+ new DrawableWidget().setDrawable(GT_UITextures.OVERLAY_BUTTON_CYCLIC)
+ .setSize(18, 18))
+ .addChild(
+ new TextWidget("Thermosink").setTextAlignment(Alignment.Center)
+ .setPos(20, 5))
+ .setEnabled(widget -> !getBaseMetaTileEntity().isActive()))
+ .widget(
+ new TextWidget(new Text("Trace Size")).setSize(90, 18)
+ .setEnabled(widget -> !getBaseMetaTileEntity().isActive())
+ .setPos(0, 4))
+ .widget(
+ new NumericWidget().setGetter(() -> (int) ((1f / mRoughnessMultiplier) * 100f))
+ .setSetter(val -> mRoughnessMultiplier = 100f / (int) val)
+ .setBounds(50, 200)
+ .setTextColor(Color.WHITE.normal)
+ .setTextAlignment(Alignment.Center)
+ .addTooltip(
+ "Set the trace size. Smaller traces allow material savings but take longer to fabricate. Larger traces waste material but are fast. 50-200 μm.")
+ .setBackground(GT_UITextures.BACKGROUND_TEXT_FIELD)
+ .setSize(90, 16))
+ .widget(
+ new DrawableWidget().setDrawable(GT_UITextures.OVERLAY_BUTTON_CROSS)
+ .setSize(18, 18)
+ .addTooltip(new Text("Can't change configuration when running !").color(Color.RED.dark(3)))
+ .setEnabled(widget -> getBaseMetaTileEntity().isActive()))
+ .setPos(10, 25))
+ .widget(
+ new DynamicPositionedColumn().setSynced(false)
+ .widget(
+ new TextWidget(new Text("Bio Upgrade Offsets")).setSize(72, 18)
+ .setEnabled(widget -> !getBaseMetaTileEntity().isActive()))
+ .widget(
+ new DynamicPositionedRow().setSynced(false)
+ .widget(
+ new NumericWidget().setGetter(() -> mBioOffsets[0])
+ .setSetter(val -> mBioOffsets[0] = (int) val)
+ .setBounds(-16, 16)
+ .setTextColor(Color.WHITE.normal)
+ .setTextAlignment(Alignment.Center)
+ .addTooltip("X Offset")
+ .setBackground(GT_UITextures.BACKGROUND_TEXT_FIELD)
+ .setSize(36, 18))
+ .widget(
+ new NumericWidget().setGetter(() -> mBioOffsets[1])
+ .setSetter(val -> mBioOffsets[1] = (int) val)
+ .setBounds(-16, 16)
+ .setTextColor(Color.WHITE.normal)
+ .setTextAlignment(Alignment.Center)
+ .addTooltip("Z Offset")
+ .setBackground(GT_UITextures.BACKGROUND_TEXT_FIELD)
+ .setSize(36, 18))
+ .setEnabled(widget -> !getBaseMetaTileEntity().isActive()))
+ .widget(
+ new TextWidget(new Text("Cooler Tier 1 Offsets")).setSize(72, 18)
+ .setEnabled(widget -> !getBaseMetaTileEntity().isActive()))
+ .widget(
+ new DynamicPositionedRow().setSynced(false)
+ .widget(
+ new NumericWidget().setGetter(() -> mOCTier1Offsets[0])
+ .setSetter(val -> mOCTier1Offsets[0] = (int) val)
+ .setBounds(-16, 16)
+ .setTextColor(Color.WHITE.normal)
+ .setTextAlignment(Alignment.Center)
+ .addTooltip("X Offset")
+ .setBackground(GT_UITextures.BACKGROUND_TEXT_FIELD)
+ .setSize(36, 18))
+ .widget(
+ new NumericWidget().setGetter(() -> mOCTier1Offsets[1])
+ .setSetter(val -> mOCTier1Offsets[1] = (int) val)
+ .setBounds(-16, 16)
+ .setTextColor(Color.WHITE.normal)
+ .setTextAlignment(Alignment.Center)
+ .addTooltip("Z Offset")
+ .setBackground(GT_UITextures.BACKGROUND_TEXT_FIELD)
+ .setSize(36, 18))
+ .setEnabled(widget -> !getBaseMetaTileEntity().isActive()))
+ .widget(
+ new TextWidget(new Text("Cooler Tier 2 Offsets")).setSize(72, 18)
+ .setEnabled(widget -> !getBaseMetaTileEntity().isActive()))
+ .widget(
+ new DynamicPositionedRow().setSynced(false)
+ .widget(
+ new NumericWidget().setGetter(() -> mOCTier2Offsets[0])
+ .setSetter(val -> mOCTier2Offsets[0] = (int) val)
+ .setBounds(-16, 16)
+ .setTextColor(Color.WHITE.normal)
+ .setTextAlignment(Alignment.Center)
+ .addTooltip("X Offset")
+ .setBackground(GT_UITextures.BACKGROUND_TEXT_FIELD)
+ .setSize(36, 18))
+ .widget(
+ new NumericWidget().setGetter(() -> mOCTier2Offsets[1])
+ .setSetter(val -> mOCTier2Offsets[1] = (int) val)
+ .setBounds(-16, 16)
+ .setTextColor(Color.WHITE.normal)
+ .setTextAlignment(Alignment.Center)
+ .addTooltip("Z Offset")
+ .setBackground(GT_UITextures.BACKGROUND_TEXT_FIELD)
+ .setSize(36, 18))
+ .setEnabled(widget -> !getBaseMetaTileEntity().isActive()))
+ .setPos(110, 25));
+ return builder.build();
+ }
+
+ @Override
+ public boolean supportsVoidProtection() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsInputSeparation() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsSingleRecipeLocking() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsBatchMode() {
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PlasmaForge.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PlasmaForge.java
new file mode 100644
index 0000000000..1eef27c8f1
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PlasmaForge.java
@@ -0,0 +1,986 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock;
+import static gregtech.api.enums.GT_HatchElement.Energy;
+import static gregtech.api.enums.GT_HatchElement.ExoticEnergy;
+import static gregtech.api.enums.GT_HatchElement.InputBus;
+import static gregtech.api.enums.GT_HatchElement.InputHatch;
+import static gregtech.api.enums.GT_HatchElement.Maintenance;
+import static gregtech.api.enums.GT_HatchElement.OutputBus;
+import static gregtech.api.enums.GT_HatchElement.OutputHatch;
+import static gregtech.api.enums.GT_Values.AuthorColen;
+import static gregtech.api.enums.GT_Values.VN;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_DTPF_OFF;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_DTPF_ON;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FUSION1_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.casingTexturePages;
+import static gregtech.api.util.GT_StructureUtility.buildHatchAdder;
+import static gregtech.api.util.GT_StructureUtility.ofCoil;
+import static gregtech.api.util.GT_Utility.filterValidMTEs;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.ResourceLocation;
+import net.minecraft.util.StatCollector;
+import net.minecraft.world.ChunkCoordIntPair;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidStack;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.HeatingCoilLevel;
+import gregtech.api.enums.MaterialsUEVplus;
+import gregtech.api.enums.SoundResource;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.logic.ProcessingLogic;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_ExtendedPowerMultiBlockBase;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Energy;
+import gregtech.api.objects.GT_ChunkManager;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_OverclockCalculator;
+import gregtech.api.util.GT_ParallelHelper;
+import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_PlasmaForge extends
+ GT_MetaTileEntity_ExtendedPowerMultiBlockBase<GT_MetaTileEntity_PlasmaForge> implements ISurvivalConstructable {
+
+ // 3600 seconds in an hour, 8 hours, 20 ticks in a second.
+ private static final double max_efficiency_time_in_ticks = 3600d * 8d * 20d;
+ // Multiplier for the efficiency decay rate
+ private static final double efficiency_decay_rate = 100;
+ private static final double maximum_discount = 0.5d;
+
+ // Valid fuels which the discount will get applied to.
+ private static final FluidStack[] valid_fuels = { MaterialsUEVplus.ExcitedDTEC.getFluid(1L),
+ MaterialsUEVplus.ExcitedDTRC.getFluid(1L), MaterialsUEVplus.ExcitedDTPC.getFluid(1L),
+ MaterialsUEVplus.ExcitedDTCC.getFluid(1L), MaterialsUEVplus.ExcitedDTSC.getFluid(1L) };
+
+ private static final int min_input_hatch = 0;
+ private static final int max_input_hatch = 7;
+ private static final int min_output_hatch = 0;
+ private static final int max_output_hatch = 2;
+ private static final int min_input_bus = 0;
+ private static final int max_input_bus = 6;
+ private static final int min_output_bus = 0;
+ private static final int max_output_bus = 1;
+
+ // Current discount rate. 1 = 0%, 0 = 100%.
+ private double discount = 1;
+ private int mHeatingCapacity = 0;
+ private long running_time = 0;
+ private HeatingCoilLevel mCoilLevel;
+
+ @SuppressWarnings("SpellCheckingInspection")
+ private static final String[][] structure_string = new String[][] { { " ",
+ " N N N N ", " N N N N ", " N N N N ",
+ " ", " ", " ",
+ " N N N N ", " N N N N ", " NNN NNN N N NNN NNN ",
+ " ", " ", " ",
+ " NNN NNN NNN NNN ", " ", " ",
+ " ", " ", " ",
+ " NNN NNN NNN NNN ", " ", " ",
+ " ", " NNN NNN NNN NNN " },
+ { " N N N N ", " bCCCb bCCCb ", " bCCCb bCCCb ",
+ " bCCCb bCCCb ", " N N N N ",
+ " ", " N N N N ",
+ " bCCCb bCCCb ", " bCCCb bCCCb ",
+ "NbbbN NbbNCCCb bCCCNbbN NbbbN", " CCC CCC N N CCC CCC ",
+ " CCC CCC CCC CCC ", " CCC CCC CCC CCC ",
+ "NbbbN NbbbN NbbbN NbbbN", " N N N N ",
+ " N N N N ", " ",
+ " N N N N ", " N N N N ",
+ "NbbbN NbbbN NbbbN NbbbN", " CCC CCC CCC CCC ",
+ " CCC CCC CCC CCC ", " CCC CCC CCC CCC ",
+ "NbbbN NbbbN N N NbbbN NbbbN", },
+ { " N N N N ", " bCCCb bCCCb ", " NNNbbbbbNNsNNbbbbbNNN ",
+ " ss bCCCb bCCCb ss ", " s N N N N s ",
+ " s s ", " N N N N N N ",
+ " N bCCCb bCCCb N ", " N sbbbbbNNsNNbbbbbs N ",
+ "NbbbN NbbNCCCb bCCCNbbN NbbbN", " CbC CbC N N CbC CbC ",
+ " CbC CbC CbC CbC ", " CbC CbC CbC CbC ",
+ "NbbbN NbbbN NbbbN NbbbN", " NNN NNN NNN NNN ",
+ " NNN NNN NNN NNN ", " s s s s ",
+ " NNN NNN NNN NNN ", " NNN NNN NNN NNN ",
+ "NbbbN NbbbN NbbbN NbbbN", " CbC CbC CbC CbC ",
+ " CbC CbC CbC CbC ", " CbC CbC CbC CbC ",
+ "NbbbN NbbbNNNNNsNsNNNNNbbbN NbbbN", },
+ { " N N N N ", " bCCCb bCCCb ", " ss bCCCb bCCCb ss ",
+ " bCCCb bCCCb ", " s NCCCN NCCCN s ",
+ " s NCCCN NCCCN s ", " NCCCN NCCCN ",
+ " bCCCb bCCCb ", " bCCCb bCCCb ",
+ "NbbbNNNbbNCCCb bCCCNbbNNNbbbN", " CCCCCCCCC N N CCCCCCCCC ",
+ " CCCCCCCCC CCCCCCCCC ", " CCCCCCCCC CCCCCCCCC ",
+ "NbbbNNNbbbN NbbbNNNbbbN", " N N N N ",
+ " N N N N ", " ",
+ " N N N N ", " N N N N ",
+ "NbbbNNNbbbN NbbbNNNbbbN", " CCCCCCCCC CCCCCCCCC ",
+ " CCCCCCCCC CCCCCCCCC ", " CCCCCCCCC CCCCCCCCC ",
+ "NbbbNNNbbbN NbN NbbbNNNbbbN", },
+ { " ", " N N N N ", " s N N N N s ",
+ " s NCCCN NCCCN s ", " ",
+ " ", " ",
+ " NCCCN NCCCN ", " N N N N ",
+ " NNN NN N N NN NNN ", " C C C C ",
+ " C C C C ", " C C C C ",
+ " NNN NNN NNN NNN ", " ",
+ " ", " ",
+ " ", " ",
+ " NNN NNN NNN NNN ", " C C C C ",
+ " C C C C ", " C C C C ",
+ " NNN NNN NbN NNN NNN ", },
+ { " ", " ", " s s ",
+ " s NCCCN NCCCN s ", " ",
+ " ", " ",
+ " NCCCN NCCCN ", " ",
+ " N N N N ", " C C C C ",
+ " C C C C ", " C C C C ",
+ " N N N N ", " ",
+ " ", " ",
+ " ", " ",
+ " N N N N ", " C C C C ",
+ " C C C C ", " C C C C ",
+ " N N NbN N N ", },
+ { " ", " N N N N ", " N N N N N N ",
+ " NCCCN NCCCN ", " ",
+ " ", " ",
+ " NCCCN NCCCN ", " N N N N ",
+ " NNN NN N N NN NNN ", " C C C C ",
+ " C C C C ", " C C C C ",
+ " NNN NNN NNN NNN ", " ",
+ " ", " ",
+ " ", " ",
+ " NNN NNN NNN NNN ", " C C C C ",
+ " C C C C ", " C C C C ",
+ " NNN NNN NbN NNN NNN ", },
+ { " N N N N ", " bCCCb bCCCb ", " N bCCCb bCCCb N ",
+ " bCCCb bCCCb ", " NCCCN NCCCN ",
+ " NCCCN NCCCN ", " NCCCN NCCCN ",
+ " bCCCb bCCCb ", " bCCCb bCCCb ",
+ "NbbbNNNbbNCCCb bCCCNbbNNNbbbN", " CCCCCCCCC N N CCCCCCCCC ",
+ " CCCCCCCCC CCCCCCCCC ", " CCCCCCCCC CCCCCCCCC ",
+ "NbbbNNNbbbN NbbbNNNbbbN", " N N N N ",
+ " N N N N ", " ",
+ " N N N N ", " N N N N ",
+ "NbbbNNNbbbN NbbbNNNbbbN", " CCCCCCCCC CCCCCCCCC ",
+ " CCCCCCCCC CCCCCCCCC ", " CCCCCCCCC CCCCCCCCC ",
+ "NbbbNNNbbbN NbN NbbbNNNbbbN", },
+ { " N N N N ", " bCCCb bCCCb ", " N sbbbbbNNsNNbbbbbs N ",
+ " bCCCb bCCCb ", " N N N N ",
+ " ", " N N N N ",
+ " bCCCb bCCCb ", " s sbbbbbNNsNNbbbbbs s ",
+ "NbbbN NbbNCCCb bCCCNbbN NbbbN", " CbC CbC N N CbC CbC ",
+ " CbC CbC CbC CbC ", " CbC CbC CbC CbC ",
+ "NbbbN NbbbN NbbbN NbbbN", " NNN NNN NNN NNN ",
+ " NNN NNN NNN NNN ", " s s s s ",
+ " NNN NNN NNN NNN ", " NNN NNN NNN NNN ",
+ "NbbbN NbbbN NbbbN NbbbN", " CbC CbC CbC CbC ",
+ " CbC CbC CbC CbC ", " CbC CbC CbC CbC ",
+ "NbbbN NbbbNNNNNsNsNNNNNbbbN NbbbN", },
+ { " NNN NNN N N NNN NNN ", "NbbbN NbbNCCCb bCCCNbbN NbbbN", "NbbbN NbbNCCCb bCCCNbbN NbbbN",
+ "NbbbNNNbbNCCCb bCCCNbbNNNbbbN", " NNN NNN N N NNN NNN ",
+ " N N N N ", " NNN NNN N N NNN NNN ",
+ "NbbbNNNbbNCCCb bCCCNbbNNNbbbN", "NbbbN NbbNCCCb bCCCNbbN NbbbN",
+ "NNNN NNNCCCb bCCCNNN NNNN", " CCC CCC N N CCC CCC ",
+ " CCC CCC CCC CCC ", " CCC CCC CCC CCC ",
+ "NbbbN NbbbN NbbbN NbbbN", " N N N N ",
+ " N N N N ", " ",
+ " N N N N ", " N N N N ",
+ "NbbbN NbbbN NbbbN NbbbN", " CCC CCC CCC CCC ",
+ " CCC CCC CCC CCC ", " CCC CCC CCC CCC ",
+ "NbbbN NbbbN NbN NbbbN NbbbN", },
+ { " ", " CCC CCC N N CCC CCC ", " CbC CbC N N CbC CbC ",
+ " CCCCCCCCC N N CCCCCCCCC ", " C C C C ",
+ " C C C C ", " C C C C ",
+ " CCCCCCCCC N N CCCCCCCCC ", " CbC CbC N N CbC CbC ",
+ " CCC CCC N N CCC CCC ", " ",
+ " ", " ",
+ " NNN NNN NNN NNN ", " ",
+ " ", " ",
+ " ", " ",
+ " NNN NNN NNN NNN ", " ",
+ " ", " ",
+ " NNN NNN NbN NNN NNN ", },
+ { " ", " CCC CCC CCC CCC ", " CbC CbC CbC CbC ",
+ " CCCCCCCCC CCCCCCCCC ", " C C C C ",
+ " C C C C ", " C C C C ",
+ " CCCCCCCCC CCCCCCCCC ", " CbC CbC CbC CbC ",
+ " CCC CCC CCC CCC ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " N N NbN N N ", },
+ { " ", " CCC CCC CCC CCC ", " CbC CbC CbC CbC ",
+ " CCCCCCCCC CCCCCCCCC ", " C C C C ",
+ " C C C C ", " C C C C ",
+ " CCCCCCCCC CCCCCCCCC ", " CbC CbC CbC CbC ",
+ " CCC CCC CCC CCC ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " N N NbN N N ", },
+ { " NNN NNN NNN NNN ", "NbbbN NbbbN NbbbN NbbbN", "NbbbN NbbbN NbbbN NbbbN",
+ "NbbbNNNbbbN NbbbNNNbbbN", " NNN NNN NNN NNN ",
+ " N N N N ", " NNN NNN NNN NNN ",
+ "NbbbNNNbbbN NbbbNNNbbbN", "NbbbN NbbbN NbbbN NbbbN",
+ "NbbbN NbbbN NbbbN NbbbN", " NNN NNN NNN NNN ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " N N NsNsN N N ", },
+ { " ", " ", " N N N N ",
+ " ", " ",
+ " ", " ",
+ " ", " N N N N ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " N N NbbbbbN N N ", },
+ { " ", " ", " N N N N ",
+ " ", " ",
+ " ", " ",
+ " ", " N N N N ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " N ",
+ " NsNNNNNsNNNNsbbbbbsNNNNsNNNNNsN ", },
+ { " ", " ", " s s s s ",
+ " ", " ",
+ " ", " ",
+ " ", " s s s s ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ~ ", " NNN ",
+ " NbbbbbNbbbbNbbbbbNbbbbNbbbbbN ", },
+ { " ", " ", " N N N N ",
+ " ", " ",
+ " ", " ",
+ " ", " N N N N ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " N ",
+ " NsNNNNNsNNNNsbbbbbsNNNNsNNNNNsN ", },
+ { " ", " ", " N N N N ",
+ " ", " ",
+ " ", " ",
+ " ", " N N N N ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " N N NbbbbbN N N ", },
+ { " NNN NNN NNN NNN ", "NbbbN NbbbN NbbbN NbbbN", "NbbbN NbbbN NbbbN NbbbN",
+ "NbbbNNNbbbN NbbbNNNbbbN", " NNN NNN NNN NNN ",
+ " N N N N ", " NNN NNN NNN NNN ",
+ "NbbbNNNbbbN NbbbNNNbbbN", "NbbbN NbbbN NbbbN NbbbN",
+ "NbbbN NbbbN NbbbN NbbbN", " NNN NNN NNN NNN ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " N N NsNsN N N ", },
+ { " ", " CCC CCC CCC CCC ", " CbC CbC CbC CbC ",
+ " CCCCCCCCC CCCCCCCCC ", " C C C C ",
+ " C C C C ", " C C C C ",
+ " CCCCCCCCC CCCCCCCCC ", " CbC CbC CbC CbC ",
+ " CCC CCC CCC CCC ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " N N NbN N N ", },
+ { " ", " CCC CCC CCC CCC ", " CbC CbC CbC CbC ",
+ " CCCCCCCCC CCCCCCCCC ", " C C C C ",
+ " C C C C ", " C C C C ",
+ " CCCCCCCCC CCCCCCCCC ", " CbC CbC CbC CbC ",
+ " CCC CCC CCC CCC ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " N N NbN N N ", },
+ { " ", " CCC CCC N N CCC CCC ", " CbC CbC N N CbC CbC ",
+ " CCCCCCCCC N N CCCCCCCCC ", " C C C C ",
+ " C C C C ", " C C C C ",
+ " CCCCCCCCC N N CCCCCCCCC ", " CbC CbC N N CbC CbC ",
+ " CCC CCC N N CCC CCC ", " ",
+ " ", " ",
+ " NNN NNN NNN NNN ", " ",
+ " ", " ",
+ " ", " ",
+ " NNN NNN NNN NNN ", " ",
+ " ", " ",
+ " NNN NNN NbN NNN NNN ", },
+ { " NNN NNN N N NNN NNN ", "NbbbN NbbNCCCb bCCCNbbN NbbbN", "NbbbN NbbNCCCb bCCCNbbN NbbbN",
+ "NbbbNNNbbNCCCb bCCCNbbNNNbbbN", " NNN NNN N N NNN NNN ",
+ " N N N N ", " NNN NNN N N NNN NNN ",
+ "NbbbNNNbbNCCCb bCCCNbbNNNbbbN", "NbbbN NbbNCCCb bCCCNbbN NbbbN",
+ "NNNN NNNCCCb bCCCNNN NNNN", " CCC CCC N N CCC CCC ",
+ " CCC CCC CCC CCC ", " CCC CCC CCC CCC ",
+ "NbbbN NbbbN NbbbN NbbbN", " N N N N ",
+ " N N N N ", " ",
+ " N N N N ", " N N N N ",
+ "NbbbN NbbbN NbbbN NbbbN", " CCC CCC CCC CCC ",
+ " CCC CCC CCC CCC ", " CCC CCC CCC CCC ",
+ "NbbbN NbbbN NbN NbbbN NbbbN", },
+ { " N N N N ", " bCCCb bCCCb ", " N sbbbbbNNsNNbbbbbs N ",
+ " bCCCb bCCCb ", " N N N N ",
+ " ", " N N N N ",
+ " bCCCb bCCCb ", " s sbbbbbNNsNNbbbbbs s ",
+ "NbbbN NbbNCCCb bCCCNbbN NbbbN", " CbC CbC N N CbC CbC ",
+ " CbC CbC CbC CbC ", " CbC CbC CbC CbC ",
+ "NbbbN NbbbN NbbbN NbbbN", " NNN NNN NNN NNN ",
+ " NNN NNN NNN NNN ", " s s s s ",
+ " NNN NNN NNN NNN ", " NNN NNN NNN NNN ",
+ "NbbbN NbbbN NbbbN NbbbN", " CbC CbC CbC CbC ",
+ " CbC CbC CbC CbC ", " CbC CbC CbC CbC ",
+ "NbbbN NbbbNNNNNsNsNNNNNbbbN NbbbN", },
+ { " N N N N ", " bCCCb bCCCb ", " N bCCCb bCCCb N ",
+ " bCCCb bCCCb ", " NCCCN NCCCN ",
+ " NCCCN NCCCN ", " NCCCN NCCCN ",
+ " bCCCb bCCCb ", " bCCCb bCCCb ",
+ "NbbbNNNbbNCCCb bCCCNbbNNNbbbN", " CCCCCCCCC N N CCCCCCCCC ",
+ " CCCCCCCCC CCCCCCCCC ", " CCCCCCCCC CCCCCCCCC ",
+ "NbbbNNNbbbN NbbbNNNbbbN", " N N N N ",
+ " N N N N ", " ",
+ " N N N N ", " N N N N ",
+ "NbbbNNNbbbN NbbbNNNbbbN", " CCCCCCCCC CCCCCCCCC ",
+ " CCCCCCCCC CCCCCCCCC ", " CCCCCCCCC CCCCCCCCC ",
+ "NbbbNNNbbbN NbN NbbbNNNbbbN", },
+ { " ", " N N N N ", " N N N N N N ",
+ " NCCCN NCCCN ", " ",
+ " ", " ",
+ " NCCCN NCCCN ", " N N N N ",
+ " NNN NN N N NN NNN ", " C C C C ",
+ " C C C C ", " C C C C ",
+ " NNN NNN NNN NNN ", " ",
+ " ", " ",
+ " ", " ",
+ " NNN NNN NNN NNN ", " C C C C ",
+ " C C C C ", " C C C C ",
+ " NNN NNN NbN NNN NNN ", },
+ { " ", " ", " s s ",
+ " s NCCCN NCCCN s ", " ",
+ " ", " ",
+ " NCCCN NCCCN ", " ",
+ " N N N N ", " C C C C ",
+ " C C C C ", " C C C C ",
+ " N N N N ", " ",
+ " ", " ",
+ " ", " ",
+ " N N N N ", " C C C C ",
+ " C C C C ", " C C C C ",
+ " N N NbN N N ", },
+ { " ", " N N N N ", " s N N N N s ",
+ " s NCCCN NCCCN s ", " ",
+ " ", " ",
+ " NCCCN NCCCN ", " N N N N ",
+ " NNN NN N N NN NNN ", " C C C C ",
+ " C C C C ", " C C C C ",
+ " NNN NNN NNN NNN ", " ",
+ " ", " ",
+ " ", " ",
+ " NNN NNN NNN NNN ", " C C C C ",
+ " C C C C ", " C C C C ",
+ " NNN NNN NbN NNN NNN ", },
+ { " N N N N ", " bCCCb bCCCb ", " ss bCCCb bCCCb ss ",
+ " bCCCb bCCCb ", " s NCCCN NCCCN s ",
+ " s NCCCN NCCCN s ", " NCCCN NCCCN ",
+ " bCCCb bCCCb ", " bCCCb bCCCb ",
+ "NbbbNNNbbNCCCb bCCCNbbNNNbbbN", " CCCCCCCCC N N CCCCCCCCC ",
+ " CCCCCCCCC CCCCCCCCC ", " CCCCCCCCC CCCCCCCCC ",
+ "NbbbNNNbbbN NbbbNNNbbbN", " N N N N ",
+ " N N N N ", " ",
+ " N N N N ", " N N N N ",
+ "NbbbNNNbbbN NbbbNNNbbbN", " CCCCCCCCC CCCCCCCCC ",
+ " CCCCCCCCC CCCCCCCCC ", " CCCCCCCCC CCCCCCCCC ",
+ "NbbbNNNbbbN NbN NbbbNNNbbbN", },
+ { " N N N N ", " bCCCb bCCCb ", " NNNbbbbbNNsNNbbbbbNNN ",
+ " ss bCCCb bCCCb ss ", " s N N N N s ",
+ " s s ", " N N N N N N ",
+ " N bCCCb bCCCb N ", " N sbbbbbNNsNNbbbbbs N ",
+ "NbbbN NbbNCCCb bCCCNbbN NbbbN", " CbC CbC N N CbC CbC ",
+ " CbC CbC CbC CbC ", " CbC CbC CbC CbC ",
+ "NbbbN NbbbN NbbbN NbbbN", " NNN NNN NNN NNN ",
+ " NNN NNN NNN NNN ", " s s s s ",
+ " NNN NNN NNN NNN ", " NNN NNN NNN NNN ",
+ "NbbbN NbbbN NbbbN NbbbN", " CbC CbC CbC CbC ",
+ " CbC CbC CbC CbC ", " CbC CbC CbC CbC ",
+ "NbbbN NbbbNNNNNsNsNNNNNbbbN NbbbN", },
+ { " N N N N ", " bCCCb bCCCb ", " bCCCb bCCCb ",
+ " bCCCb bCCCb ", " N N N N ",
+ " ", " N N N N ",
+ " bCCCb bCCCb ", " bCCCb bCCCb ",
+ "NbbbN NbbNCCCb bCCCNbbN NbbbN", " CCC CCC N N CCC CCC ",
+ " CCC CCC CCC CCC ", " CCC CCC CCC CCC ",
+ "NbbbN NbbbN NbbbN NbbbN", " N N N N ",
+ " N N N N ", " ",
+ " N N N N ", " N N N N ",
+ "NbbbN NbbbN NbbbN NbbbN", " CCC CCC CCC CCC ",
+ " CCC CCC CCC CCC ", " CCC CCC CCC CCC ",
+ "NbbbN NbbbN N N NbbbN NbbbN", },
+ { " ", " N N N N ", " N N N N ",
+ " N N N N ", " ",
+ " ", " ",
+ " N N N N ", " N N N N ",
+ " NNN NNN N N NNN NNN ", " ",
+ " ", " ",
+ " NNN NNN NNN NNN ", " ",
+ " ", " ",
+ " ", " ",
+ " NNN NNN NNN NNN ", " ",
+ " ", " ",
+ " NNN NNN NNN NNN ", } };
+
+ protected static final int DIM_TRANS_CASING = 12;
+ protected static final int DIM_INJECTION_CASING = 13;
+ protected static final int DIM_BRIDGE_CASING = 14;
+
+ private boolean isMultiChunkloaded = true;
+
+ protected static final String STRUCTURE_PIECE_MAIN = "main";
+ private static final IStructureDefinition<GT_MetaTileEntity_PlasmaForge> STRUCTURE_DEFINITION = StructureDefinition
+ .<GT_MetaTileEntity_PlasmaForge>builder()
+ .addShape(STRUCTURE_PIECE_MAIN, structure_string)
+ .addElement(
+ 'C',
+ ofCoil(GT_MetaTileEntity_PlasmaForge::setCoilLevel, GT_MetaTileEntity_PlasmaForge::getCoilLevel))
+ .addElement(
+ 'b',
+ buildHatchAdder(GT_MetaTileEntity_PlasmaForge.class)
+ .atLeast(InputHatch, OutputHatch, InputBus, OutputBus, Energy, ExoticEnergy, Maintenance)
+ .casingIndex(DIM_INJECTION_CASING)
+ .dot(3)
+ .buildAndChain(GregTech_API.sBlockCasings1, DIM_INJECTION_CASING))
+ .addElement('N', ofBlock(GregTech_API.sBlockCasings1, DIM_TRANS_CASING))
+ .addElement('s', ofBlock(GregTech_API.sBlockCasings1, DIM_BRIDGE_CASING))
+ .build();
+
+ public GT_MetaTileEntity_PlasmaForge(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_PlasmaForge(String aName) {
+ super(aName);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_PlasmaForge(mName);
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addInfo("Transcending Dimensional Boundaries.")
+ .addInfo(
+ "Takes " + EnumChatFormatting.RED
+ + GT_Utility.formatNumbers(max_efficiency_time_in_ticks / (3600 * 20))
+ + EnumChatFormatting.GRAY
+ + " hours of continuous run time to fully breach dimensional")
+ .addInfo("boundaries and achieve maximum efficiency. This reduces fuel")
+ .addInfo(
+ "consumption by up to " + EnumChatFormatting.RED
+ + GT_Utility.formatNumbers(100 * maximum_discount)
+ + "%"
+ + EnumChatFormatting.GRAY
+ + ". Supports overclocking beyond MAX voltage.")
+ .addInfo(
+ "When no recipe is running, fuel discount decays x" + EnumChatFormatting.RED
+ + GT_Utility.formatNumbers(efficiency_decay_rate)
+ + EnumChatFormatting.GRAY
+ + " as fast as it builds up.")
+ .addInfo(AuthorColen)
+ .addSeparator()
+ .beginStructureBlock(33, 24, 33, false)
+ .addStructureInfo("DTPF Structure is too complex! See schematic for details.")
+ .addStructureInfo(EnumChatFormatting.GOLD + "2,112" + EnumChatFormatting.GRAY + " Heating coils required.")
+ .addStructureInfo(
+ EnumChatFormatting.GOLD + "120" + EnumChatFormatting.GRAY + " Dimensional bridge blocks required.")
+ .addStructureInfo(
+ EnumChatFormatting.GOLD + "1,270"
+ + EnumChatFormatting.GRAY
+ + " Dimensional injection casings required.")
+ .addStructureInfo(
+ EnumChatFormatting.GOLD + "2,121"
+ + EnumChatFormatting.GRAY
+ + " Dimensionally transcendent casings required.")
+ .addStructureInfo("--------------------------------------------")
+ .addStructureInfo(
+ "Requires " + EnumChatFormatting.GOLD
+ + "1"
+ + EnumChatFormatting.GRAY
+ + "-"
+ + EnumChatFormatting.GOLD
+ + "2"
+ + EnumChatFormatting.GRAY
+ + " energy hatches or "
+ + EnumChatFormatting.GOLD
+ + "1"
+ + EnumChatFormatting.GRAY
+ + " TT energy hatch.")
+ .addStructureInfo(
+ "Requires " + EnumChatFormatting.GOLD + "1" + EnumChatFormatting.GRAY + " maintenance hatch.")
+ .addStructureInfo(
+ "Requires " + EnumChatFormatting.GOLD
+ + min_input_hatch
+ + EnumChatFormatting.GRAY
+ + "-"
+ + EnumChatFormatting.GOLD
+ + max_input_hatch
+ + EnumChatFormatting.GRAY
+ + " input hatches.")
+ .addStructureInfo(
+ "Requires " + EnumChatFormatting.GOLD
+ + min_output_hatch
+ + EnumChatFormatting.GRAY
+ + "-"
+ + EnumChatFormatting.GOLD
+ + max_output_hatch
+ + EnumChatFormatting.GRAY
+ + " output hatches.")
+ .addStructureInfo(
+ "Requires " + EnumChatFormatting.GOLD
+ + min_input_bus
+ + EnumChatFormatting.GRAY
+ + "-"
+ + EnumChatFormatting.GOLD
+ + max_input_bus
+ + EnumChatFormatting.GRAY
+ + " input busses.")
+ .addStructureInfo(
+ "Requires " + EnumChatFormatting.GOLD
+ + min_output_bus
+ + EnumChatFormatting.GRAY
+ + "-"
+ + EnumChatFormatting.GOLD
+ + max_input_bus
+ + EnumChatFormatting.GRAY
+ + " output busses.")
+ .addStructureInfo("--------------------------------------------")
+ .toolTipFinisher("Gregtech");
+ return tt;
+ }
+
+ @Override
+ public boolean addToMachineList(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
+ boolean exotic = addExoticEnergyInputToMachineList(aTileEntity, aBaseCasingIndex);
+ return super.addToMachineList(aTileEntity, aBaseCasingIndex) || exotic;
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection aFacing,
+ int colorIndex, boolean aActive, boolean redstoneLevel) {
+ if (side == aFacing) {
+ if (aActive) return new ITexture[] { casingTexturePages[0][DIM_BRIDGE_CASING], TextureFactory.builder()
+ .addIcon(OVERLAY_DTPF_ON)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FUSION1_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ return new ITexture[] { casingTexturePages[0][DIM_BRIDGE_CASING], TextureFactory.builder()
+ .addIcon(OVERLAY_DTPF_OFF)
+ .extFacing()
+ .build() };
+ }
+ return new ITexture[] { casingTexturePages[0][DIM_BRIDGE_CASING] };
+ }
+
+ @Override
+ public int getPollutionPerSecond(ItemStack aStack) {
+ return 0;
+ }
+
+ @Override
+ public int getDamageToComponent(ItemStack aStack) {
+ return 0;
+ }
+
+ @Override
+ public boolean explodesOnComponentBreak(ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.plasmaForgeRecipes;
+ }
+
+ @Override
+ public boolean isCorrectMachinePart(ItemStack aStack) {
+ return true;
+ }
+
+ @Override
+ public IStructureDefinition<GT_MetaTileEntity_PlasmaForge> getStructureDefinition() {
+ return STRUCTURE_DEFINITION;
+ }
+
+ @Override
+ @NotNull
+ public CheckRecipeResult checkProcessing() {
+ CheckRecipeResult recipe_process = super.checkProcessing();
+ if (recipe_process.wasSuccessful()) {
+ running_time = Math.min(running_time + mMaxProgresstime, (long) max_efficiency_time_in_ticks);
+ }
+ return recipe_process;
+ }
+
+ @Override
+ protected ProcessingLogic createProcessingLogic() {
+ return new ProcessingLogic() {
+
+ @Nonnull
+ @Override
+ protected GT_OverclockCalculator createOverclockCalculator(@Nonnull GT_Recipe recipe) {
+ return super.createOverclockCalculator(recipe).setRecipeHeat(recipe.mSpecialValue)
+ .setMachineHeat(mHeatingCapacity);
+ }
+
+ @NotNull
+ @Override
+ protected GT_ParallelHelper createParallelHelper(@Nonnull GT_Recipe recipe) {
+ return super.createParallelHelper(recipeAfterDiscount(recipe));
+ }
+
+ @Override
+ protected @Nonnull CheckRecipeResult validateRecipe(@Nonnull GT_Recipe recipe) {
+ return recipe.mSpecialValue <= mHeatingCapacity ? CheckRecipeResultRegistry.SUCCESSFUL
+ : CheckRecipeResultRegistry.insufficientHeat(recipe.mSpecialValue);
+ }
+ };
+ }
+
+ @Nonnull
+ protected GT_Recipe recipeAfterDiscount(@Nonnull GT_Recipe recipe) {
+ GT_Recipe tRecipe = recipe.copy();
+ outside: for (int i = 0; i < recipe.mFluidInputs.length; i++) {
+ for (FluidStack fuel : valid_fuels) {
+ if (tRecipe.mFluidInputs[i].isFluidEqual(fuel)) {
+ recalculateDiscount();
+ tRecipe.mFluidInputs[i].amount = (int) Math.round(tRecipe.mFluidInputs[i].amount * discount);
+ break outside;
+ }
+ }
+ }
+ return tRecipe;
+ }
+
+ @Override
+ public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+
+ // Reset heating capacity.
+ mHeatingCapacity = 0;
+
+ // Get heating capacity from coils in structure.
+ setCoilLevel(HeatingCoilLevel.None);
+
+ // Check the main structure
+ if (!checkPiece(STRUCTURE_PIECE_MAIN, 16, 21, 16)) return false;
+
+ if (getCoilLevel() == HeatingCoilLevel.None) return false;
+
+ // Item input bus check.
+ if (mInputBusses.size() > max_input_bus) return false;
+
+ // Item output bus check.
+ if (mOutputBusses.size() > max_output_bus) return false;
+
+ // Fluid input hatch check.
+ if (mInputHatches.size() > max_input_hatch) return false;
+
+ // Fluid output hatch check.
+ if (mOutputHatches.size() > max_output_hatch) return false;
+
+ // If there is more than 1 TT energy hatch, the structure check will fail.
+ // If there is a TT hatch and a normal hatch, the structure check will fail.
+ if (mExoticEnergyHatches.size() > 0) {
+ if (mEnergyHatches.size() > 0) return false;
+ if (mExoticEnergyHatches.size() > 1) return false;
+ }
+
+ // If there is 0 or more than 2 energy hatches structure check will fail.
+ if (mEnergyHatches.size() > 0) {
+ if (mEnergyHatches.size() > 2) return false;
+
+ // Check will also fail if energy hatches are not of the same tier.
+ byte tier_of_hatch = mEnergyHatches.get(0).mTier;
+ for (GT_MetaTileEntity_Hatch_Energy energyHatch : mEnergyHatches) {
+ if (energyHatch.mTier != tier_of_hatch) {
+ return false;
+ }
+ }
+ }
+
+ // If there are no energy hatches or TT energy hatches, structure will fail to form.
+ if ((mEnergyHatches.size() == 0) && (mExoticEnergyHatches.size() == 0)) return false;
+
+ // One maintenance hatch only. Mandatory.
+ if (mMaintenanceHatches.size() != 1) return false;
+
+ // Heat capacity of coils used on multi. No free heat from extra EU!
+ mHeatingCapacity = (int) getCoilLevel().getHeat();
+
+ // All structure checks passed, return true.
+ return true;
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack aStack) {
+ return 10000;
+ }
+
+ @Override
+ public void clearHatches() {
+ super.clearHatches();
+ mExoticEnergyHatches.clear();
+ }
+
+ @Override
+ public boolean addOutput(FluidStack aLiquid) {
+ if (aLiquid == null) return false;
+ FluidStack tLiquid = aLiquid.copy();
+
+ return dumpFluid(mOutputHatches, tLiquid, true) || dumpFluid(mOutputHatches, tLiquid, false);
+ }
+
+ @Override
+ public String[] getInfoData() {
+
+ long storedEnergy = 0;
+ long maxEnergy = 0;
+
+ for (GT_MetaTileEntity_Hatch tHatch : filterValidMTEs(mExoticEnergyHatches)) {
+ storedEnergy += tHatch.getBaseMetaTileEntity()
+ .getStoredEU();
+ maxEnergy += tHatch.getBaseMetaTileEntity()
+ .getEUCapacity();
+ }
+ long voltage = getAverageInputVoltage();
+ long amps = getMaxInputAmps();
+
+ // Calculate discount to make sure it is shown properly even when machine is off but decaying
+ recalculateDiscount();
+
+ return new String[] { "------------ Critical Information ------------",
+ StatCollector.translateToLocal("GT5U.multiblock.Progress") + ": "
+ + EnumChatFormatting.GREEN
+ + GT_Utility.formatNumbers(mProgresstime)
+ + EnumChatFormatting.RESET
+ + "t / "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(mMaxProgresstime)
+ + EnumChatFormatting.RESET
+ + "t",
+ StatCollector.translateToLocal("GT5U.multiblock.energy") + ": "
+ + EnumChatFormatting.GREEN
+ + GT_Utility.formatNumbers(storedEnergy)
+ + EnumChatFormatting.RESET
+ + " EU / "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(maxEnergy)
+ + EnumChatFormatting.RESET
+ + " EU",
+ StatCollector.translateToLocal("GT5U.multiblock.usage") + ": "
+ + EnumChatFormatting.RED
+ + GT_Utility.formatNumbers(getActualEnergyUsage())
+ + EnumChatFormatting.RESET
+ + " EU/t",
+ StatCollector.translateToLocal("GT5U.multiblock.mei") + ": "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(voltage)
+ + EnumChatFormatting.RESET
+ + " EU/t(*"
+ + EnumChatFormatting.YELLOW
+ + amps
+ + EnumChatFormatting.RESET
+ + "A) "
+ + StatCollector.translateToLocal("GT5U.machines.tier")
+ + ": "
+ + EnumChatFormatting.YELLOW
+ + VN[GT_Utility.getTier(voltage)]
+ + EnumChatFormatting.RESET,
+ StatCollector.translateToLocal("GT5U.EBF.heat") + ": "
+ + EnumChatFormatting.GREEN
+ + GT_Utility.formatNumbers(mHeatingCapacity)
+ + EnumChatFormatting.RESET
+ + " K",
+ "Ticks run: " + EnumChatFormatting.GREEN
+ + GT_Utility.formatNumbers(running_time)
+ + EnumChatFormatting.RESET
+ + ", Fuel Discount: "
+ + EnumChatFormatting.RED
+ + GT_Utility.formatNumbers(100 * (1 - discount))
+ + EnumChatFormatting.RESET
+ + "%",
+ "-----------------------------------------" };
+ }
+
+ private void recalculateDiscount() {
+ double time_percentage = running_time / max_efficiency_time_in_ticks;
+ time_percentage = Math.min(time_percentage, 1.0d);
+ // Multiplied by 0.5 because that is the maximum achievable discount
+ discount = 1 - time_percentage * 0.5;
+ discount = Math.max(maximum_discount, discount);
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ if (aBaseMetaTileEntity.isServerSide() && !aBaseMetaTileEntity.isAllowedToWork()) {
+ // If machine has stopped, stop chunkloading.
+ GT_ChunkManager.releaseTicket((TileEntity) aBaseMetaTileEntity);
+ isMultiChunkloaded = false;
+ } else if (aBaseMetaTileEntity.isServerSide() && aBaseMetaTileEntity.isAllowedToWork() && !isMultiChunkloaded) {
+ // Load a 3x3 area centered on controller when machine is running.
+ GT_ChunkManager.releaseTicket((TileEntity) aBaseMetaTileEntity);
+
+ int ControllerXCoordinate = ((TileEntity) aBaseMetaTileEntity).xCoord;
+ int ControllerZCoordinate = ((TileEntity) aBaseMetaTileEntity).zCoord;
+
+ GT_ChunkManager.requestChunkLoad(
+ (TileEntity) aBaseMetaTileEntity,
+ new ChunkCoordIntPair(ControllerXCoordinate, ControllerZCoordinate));
+ GT_ChunkManager.requestChunkLoad(
+ (TileEntity) aBaseMetaTileEntity,
+ new ChunkCoordIntPair(ControllerXCoordinate + 16, ControllerZCoordinate));
+ GT_ChunkManager.requestChunkLoad(
+ (TileEntity) aBaseMetaTileEntity,
+ new ChunkCoordIntPair(ControllerXCoordinate - 16, ControllerZCoordinate));
+ GT_ChunkManager.requestChunkLoad(
+ (TileEntity) aBaseMetaTileEntity,
+ new ChunkCoordIntPair(ControllerXCoordinate, ControllerZCoordinate + 16));
+ GT_ChunkManager.requestChunkLoad(
+ (TileEntity) aBaseMetaTileEntity,
+ new ChunkCoordIntPair(ControllerXCoordinate, ControllerZCoordinate - 16));
+ GT_ChunkManager.requestChunkLoad(
+ (TileEntity) aBaseMetaTileEntity,
+ new ChunkCoordIntPair(ControllerXCoordinate + 16, ControllerZCoordinate + 16));
+ GT_ChunkManager.requestChunkLoad(
+ (TileEntity) aBaseMetaTileEntity,
+ new ChunkCoordIntPair(ControllerXCoordinate + 16, ControllerZCoordinate - 16));
+ GT_ChunkManager.requestChunkLoad(
+ (TileEntity) aBaseMetaTileEntity,
+ new ChunkCoordIntPair(ControllerXCoordinate - 16, ControllerZCoordinate + 16));
+ GT_ChunkManager.requestChunkLoad(
+ (TileEntity) aBaseMetaTileEntity,
+ new ChunkCoordIntPair(ControllerXCoordinate - 16, ControllerZCoordinate - 16));
+
+ isMultiChunkloaded = true;
+ }
+
+ super.onPostTick(aBaseMetaTileEntity, aTick);
+
+ if (aBaseMetaTileEntity.isServerSide()) {
+ if (mMaxProgresstime == 0) {
+ running_time = Math.max(0, running_time - (long) efficiency_decay_rate);
+ }
+ }
+ }
+
+ @Override
+ public void construct(ItemStack stackSize, boolean hintsOnly) {
+ buildPiece(STRUCTURE_PIECE_MAIN, stackSize, hintsOnly, 16, 21, 16);
+ }
+
+ @Override
+ public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
+ if (mMachine) return -1;
+ int realBudget = elementBudget >= 200 ? elementBudget : Math.min(200, elementBudget * 5);
+ return survivialBuildPiece(STRUCTURE_PIECE_MAIN, stackSize, 16, 21, 16, realBudget, env, false, true);
+ }
+
+ @SideOnly(Side.CLIENT)
+ @Override
+ protected ResourceLocation getActivitySoundLoop() {
+ return SoundResource.GT_MACHINES_PLASMAFORGE_LOOP.resourceLocation;
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ aNBT.setLong("eRunningTime", running_time);
+ aNBT.setDouble("eLongDiscountValue", discount);
+ super.saveNBTData(aNBT);
+ }
+
+ @Override
+ public void loadNBTData(final NBTTagCompound aNBT) {
+ running_time = aNBT.getLong("eRunningTime");
+ discount = aNBT.getDouble("eLongDiscountValue");
+ super.loadNBTData(aNBT);
+ }
+
+ public HeatingCoilLevel getCoilLevel() {
+ return mCoilLevel;
+ }
+
+ public void setCoilLevel(HeatingCoilLevel aCoilLevel) {
+ mCoilLevel = aCoilLevel;
+ }
+
+ @Override
+ public boolean supportsVoidProtection() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsBatchMode() {
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PrimitiveBlastFurnace.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PrimitiveBlastFurnace.java
new file mode 100644
index 0000000000..e69d2c2921
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PrimitiveBlastFurnace.java
@@ -0,0 +1,526 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.isAir;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.lazy;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlockAnyMeta;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofChain;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.transpose;
+import static gregtech.api.objects.XSTR.XSTR_INSTANCE;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.gtnewhorizon.structurelib.StructureLibAPI;
+import com.gtnewhorizon.structurelib.alignment.IAlignment;
+import com.gtnewhorizon.structurelib.alignment.IAlignmentLimits;
+import com.gtnewhorizon.structurelib.alignment.IAlignmentProvider;
+import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
+import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.common.widget.ProgressBar;
+import com.gtnewhorizons.modularui.common.widget.SlotWidget;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.GT_Mod;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.ParticleFX;
+import gregtech.api.enums.SteamVariant;
+import gregtech.api.gui.modularui.GT_UIInfos;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.gui.modularui.GUITextureSet;
+import gregtech.api.interfaces.modularui.IAddUIWidgets;
+import gregtech.api.interfaces.modularui.IGetTitleColor;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.interfaces.tileentity.RecipeMapWorkable;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.objects.GT_ItemStack;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.WorldSpawnedEventBuilder;
+import gregtech.api.util.WorldSpawnedEventBuilder.ParticleEventBuilder;
+import gregtech.common.GT_Pollution;
+
+public abstract class GT_MetaTileEntity_PrimitiveBlastFurnace extends MetaTileEntity
+ implements IAlignment, ISurvivalConstructable, RecipeMapWorkable, IAddUIWidgets, IGetTitleColor {
+
+ public static final int INPUT_SLOTS = 3, OUTPUT_SLOTS = 3;
+ private static final ClassValue<IStructureDefinition<GT_MetaTileEntity_PrimitiveBlastFurnace>> STRUCTURE_DEFINITION = new ClassValue<>() {
+
+ @Override
+ protected IStructureDefinition<GT_MetaTileEntity_PrimitiveBlastFurnace> computeValue(Class<?> type) {
+ return IStructureDefinition.<GT_MetaTileEntity_PrimitiveBlastFurnace>builder()
+ .addShape(
+ "main",
+ transpose(
+ new String[][] { { "ccc", "c-c", "ccc" }, { "ccc", "clc", "ccc" }, { "c~c", "clc", "ccc" },
+ { "ccc", "ccc", "ccc" }, }))
+ .addElement('c', lazy(t -> ofBlock(t.getCasingBlock(), t.getCasingMetaID())))
+ .addElement(
+ 'l',
+ ofChain(isAir(), ofBlockAnyMeta(Blocks.lava, 1), ofBlockAnyMeta(Blocks.flowing_lava, 1)))
+ .build();
+ }
+ };
+
+ public int mMaxProgresstime = 0;
+ private volatile boolean mUpdated;
+ public int mUpdate = 5;
+ public int mProgresstime = 0;
+ public boolean mMachine = false;
+
+ public ItemStack[] mOutputItems = new ItemStack[OUTPUT_SLOTS];
+
+ public GT_MetaTileEntity_PrimitiveBlastFurnace(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional, INPUT_SLOTS + OUTPUT_SLOTS);
+ }
+
+ public GT_MetaTileEntity_PrimitiveBlastFurnace(String aName) {
+ super(aName, INPUT_SLOTS + OUTPUT_SLOTS);
+ }
+
+ @Override
+ public boolean isTeleporterCompatible() {
+ return false;
+ }
+
+ @Override
+ public boolean isFacingValid(ForgeDirection facing) {
+ return (facing.flag & (ForgeDirection.UP.flag | ForgeDirection.DOWN.flag)) == 0;
+ }
+
+ @Override
+ public boolean isAccessAllowed(EntityPlayer aPlayer) {
+ return true;
+ }
+
+ @Override
+ public int getProgresstime() {
+ return this.mProgresstime;
+ }
+
+ @Override
+ public int maxProgresstime() {
+ return this.mMaxProgresstime;
+ }
+
+ @Override
+ public int increaseProgress(int aProgress) {
+ this.mProgresstime += aProgress;
+ return this.mMaxProgresstime - this.mProgresstime;
+ }
+
+ @Override
+ public boolean allowCoverOnSide(ForgeDirection side, GT_ItemStack aCoverID) {
+ return (GregTech_API.getCoverBehaviorNew(aCoverID.toStack())
+ .isSimpleCover()) && (super.allowCoverOnSide(side, aCoverID));
+ }
+
+ @Override
+ public abstract MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity);
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ aNBT.setInteger("mProgresstime", this.mProgresstime);
+ aNBT.setInteger("mMaxProgresstime", this.mMaxProgresstime);
+ if (this.mOutputItems != null) {
+ for (int i = 0; i < mOutputItems.length; i++) {
+ if (this.mOutputItems[i] != null) {
+ NBTTagCompound tNBT = new NBTTagCompound();
+ this.mOutputItems[i].writeToNBT(tNBT);
+ aNBT.setTag("mOutputItem" + i, tNBT);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ this.mUpdate = 5;
+ this.mProgresstime = aNBT.getInteger("mProgresstime");
+ this.mMaxProgresstime = aNBT.getInteger("mMaxProgresstime");
+ this.mOutputItems = new ItemStack[OUTPUT_SLOTS];
+ for (int i = 0; i < OUTPUT_SLOTS; i++) {
+ this.mOutputItems[i] = GT_Utility.loadItem(aNBT, "mOutputItem" + i);
+ }
+ }
+
+ @Override
+ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) {
+ GT_UIInfos.openGTTileEntityUI(aBaseMetaTileEntity, aPlayer);
+ return true;
+ }
+
+ @Override
+ public ExtendedFacing getExtendedFacing() {
+ return ExtendedFacing.of(getBaseMetaTileEntity().getFrontFacing());
+ }
+
+ @Override
+ public void setExtendedFacing(ExtendedFacing alignment) {
+ getBaseMetaTileEntity().setFrontFacing(alignment.getDirection());
+ }
+
+ @Override
+ public IAlignmentLimits getAlignmentLimits() {
+ return (d, r, f) -> (d.flag & (ForgeDirection.UP.flag | ForgeDirection.DOWN.flag)) == 0 && r.isNotRotated()
+ && f.isNotFlipped();
+ }
+
+ private boolean checkMachine() {
+ return STRUCTURE_DEFINITION.get(this.getClass())
+ .check(
+ this,
+ "main",
+ getBaseMetaTileEntity().getWorld(),
+ getExtendedFacing(),
+ getBaseMetaTileEntity().getXCoord(),
+ getBaseMetaTileEntity().getYCoord(),
+ getBaseMetaTileEntity().getZCoord(),
+ 1,
+ 2,
+ 0,
+ !mMachine);
+ }
+
+ protected abstract Block getCasingBlock();
+
+ protected abstract int getCasingMetaID();
+
+ @Override
+ public void onMachineBlockUpdate() {
+ mUpdated = true;
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTimer) {
+ final int lavaX = aBaseMetaTileEntity.getOffsetX(aBaseMetaTileEntity.getBackFacing(), 1);
+ final int lavaZ = aBaseMetaTileEntity.getOffsetZ(aBaseMetaTileEntity.getBackFacing(), 1);
+ if ((aBaseMetaTileEntity.isClientSide()) && (aBaseMetaTileEntity.isActive())) {
+
+ new WorldSpawnedEventBuilder.ParticleEventBuilder().setMotion(0D, 0.3D, 0D)
+ .setIdentifier(ParticleFX.LARGE_SMOKE)
+ .setPosition(
+ lavaX + XSTR_INSTANCE.nextFloat(),
+ aBaseMetaTileEntity.getOffsetY(aBaseMetaTileEntity.getBackFacing(), 1),
+ lavaZ + XSTR_INSTANCE.nextFloat())
+ .setWorld(getBaseMetaTileEntity().getWorld())
+ .run();
+ }
+ if (aBaseMetaTileEntity.isServerSide()) {
+ if (mUpdated) {
+ // duct tape fix for too many updates on an overloaded server, causing the structure check to not run
+ if (mUpdate < 0) mUpdate = 5;
+ mUpdated = false;
+ }
+ if (this.mUpdate-- == 0) {
+ this.mMachine = checkMachine();
+ }
+ if (this.mMachine) {
+ if (this.mMaxProgresstime > 0) {
+ if (++this.mProgresstime >= this.mMaxProgresstime) {
+ addOutputProducts();
+ this.mOutputItems = null;
+ this.mProgresstime = 0;
+ this.mMaxProgresstime = 0;
+ GT_Mod.achievements.issueAchievement(
+ aBaseMetaTileEntity.getWorld()
+ .getPlayerEntityByName(aBaseMetaTileEntity.getOwnerName()),
+ "steel");
+ }
+ } else if (aBaseMetaTileEntity.isAllowedToWork()) {
+ checkRecipe();
+ }
+ }
+ if (this.mMaxProgresstime > 0 && (aTimer % 20L == 0L)) {
+ GT_Pollution.addPollution(
+ this.getBaseMetaTileEntity(),
+ GT_Mod.gregtechproxy.mPollutionPrimitveBlastFurnacePerSecond);
+ }
+
+ aBaseMetaTileEntity.setActive((this.mMaxProgresstime > 0) && (this.mMachine));
+ final short lavaY = aBaseMetaTileEntity.getYCoord();
+ if (aBaseMetaTileEntity.isActive()) {
+ if (aBaseMetaTileEntity.getAir(lavaX, lavaY, lavaZ)) {
+ aBaseMetaTileEntity.getWorld()
+ .setBlock(lavaX, lavaY, lavaZ, Blocks.lava, 1, 2);
+ this.mUpdate = 1;
+ }
+ if (aBaseMetaTileEntity.getAir(lavaX, lavaY + 1, lavaZ)) {
+ aBaseMetaTileEntity.getWorld()
+ .setBlock(lavaX, lavaY + 1, lavaZ, Blocks.lava, 1, 2);
+ this.mUpdate = 1;
+ }
+ } else {
+ Block lowerLava = aBaseMetaTileEntity.getBlock(lavaX, lavaY, lavaZ);
+ Block upperLava = aBaseMetaTileEntity.getBlock(lavaX, lavaY + 1, lavaZ);
+ if (lowerLava == Blocks.lava) {
+ aBaseMetaTileEntity.getWorld()
+ .setBlock(lavaX, lavaY, lavaZ, Blocks.air, 0, 2);
+ this.mUpdate = 1;
+ }
+ if (upperLava == Blocks.lava) {
+ aBaseMetaTileEntity.getWorld()
+ .setBlock(lavaX, lavaY + 1, lavaZ, Blocks.air, 0, 2);
+ this.mUpdate = 1;
+ }
+ }
+ }
+ }
+
+ @Override
+ public void onFirstTick(IGregTechTileEntity aBaseMetaTileEntity) {
+ super.onFirstTick(aBaseMetaTileEntity);
+ if (aBaseMetaTileEntity.isClientSide())
+ StructureLibAPI.queryAlignment((IAlignmentProvider) aBaseMetaTileEntity);
+ }
+
+ /**
+ * Draws random flames and smoke particles in front of Primitive Blast Furnace when active
+ *
+ * @param aBaseMetaTileEntity The entity that will handle the {@link Block#randomDisplayTick}
+ */
+ @SideOnly(Side.CLIENT)
+ @Override
+ public void onRandomDisplayTick(IGregTechTileEntity aBaseMetaTileEntity) {
+ if (aBaseMetaTileEntity.isActive()) {
+
+ final ForgeDirection frontFacing = aBaseMetaTileEntity.getFrontFacing();
+
+ final double oX = aBaseMetaTileEntity.getOffsetX(frontFacing, 1) + 0.5D;
+ final double oY = aBaseMetaTileEntity.getOffsetY(frontFacing, 1);
+ final double oZ = aBaseMetaTileEntity.getOffsetZ(frontFacing, 1) + 0.5D;
+ final double offset = -0.48D;
+ final double horizontal = XSTR_INSTANCE.nextFloat() * 8D / 16D - 4D / 16D;
+
+ final double x, y, z;
+
+ y = oY + XSTR_INSTANCE.nextFloat() * 10D / 16D + 5D / 16D;
+
+ if (frontFacing == ForgeDirection.WEST) {
+ x = oX - offset;
+ z = oZ + horizontal;
+ } else if (frontFacing == ForgeDirection.EAST) {
+ x = oX + offset;
+ z = oZ + horizontal;
+ } else if (frontFacing == ForgeDirection.NORTH) {
+ x = oX + horizontal;
+ z = oZ - offset;
+ } else // if (frontFacing == ForgeDirection.SOUTH.ordinal())
+ {
+ x = oX + horizontal;
+ z = oZ + offset;
+ }
+
+ ParticleEventBuilder particleEventBuilder = (new ParticleEventBuilder()).setMotion(0D, 0D, 0D)
+ .setPosition(x, y, z)
+ .setWorld(getBaseMetaTileEntity().getWorld());
+ particleEventBuilder.setIdentifier(ParticleFX.SMOKE)
+ .run();
+ particleEventBuilder.setIdentifier(ParticleFX.FLAME)
+ .run();
+ }
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.primitiveBlastRecipes;
+ }
+
+ private void addOutputProducts() {
+ if (this.mOutputItems == null) {
+ return;
+ }
+ int limit = Math.min(mOutputItems.length, OUTPUT_SLOTS);
+ for (int i = 0; i < limit; i++) {
+ int absi = INPUT_SLOTS + i;
+ if (this.mInventory[absi] == null) {
+ this.mInventory[absi] = GT_Utility.copyOrNull(this.mOutputItems[i]);
+ } else if (GT_Utility.areStacksEqual(this.mInventory[absi], this.mOutputItems[i])) {
+ this.mInventory[absi].stackSize = Math.min(
+ this.mInventory[absi].getMaxStackSize(),
+ this.mInventory[absi].stackSize + this.mOutputItems[i].stackSize);
+ }
+ }
+ }
+
+ private boolean spaceForOutput(ItemStack outputStack, int relativeOutputSlot) {
+ int absoluteSlot = relativeOutputSlot + INPUT_SLOTS;
+ if (this.mInventory[absoluteSlot] == null || outputStack == null) {
+ return true;
+ }
+ return ((this.mInventory[absoluteSlot].stackSize + outputStack.stackSize
+ <= this.mInventory[absoluteSlot].getMaxStackSize())
+ && (GT_Utility.areStacksEqual(this.mInventory[absoluteSlot], outputStack)));
+ }
+
+ private boolean checkRecipe() {
+ if (!this.mMachine) {
+ return false;
+ }
+ ItemStack[] inputs = new ItemStack[INPUT_SLOTS];
+ System.arraycopy(mInventory, 0, inputs, 0, INPUT_SLOTS);
+ GT_Recipe recipe = getRecipeMap().findRecipe(getBaseMetaTileEntity(), false, 0, null, inputs);
+ if (recipe == null) {
+ this.mOutputItems = null;
+ return false;
+ }
+ for (int i = 0; i < OUTPUT_SLOTS; i++) {
+ if (!spaceForOutput(recipe.getOutput(i), i)) {
+ this.mOutputItems = null;
+ return false;
+ }
+ }
+
+ if (!recipe.isRecipeInputEqual(true, null, inputs)) {
+ this.mOutputItems = null;
+ return false;
+ }
+ for (int i = 0; i < INPUT_SLOTS; i++) {
+ if (mInventory[i] != null && mInventory[i].stackSize == 0) {
+ mInventory[i] = null;
+ }
+ }
+
+ this.mMaxProgresstime = recipe.mDuration;
+ this.mOutputItems = recipe.mOutputs;
+ return true;
+ }
+
+ @Override
+ public boolean allowPullStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return aIndex > INPUT_SLOTS;
+ }
+
+ @Override
+ public boolean allowPutStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return !GT_Utility.areStacksEqual(aStack, this.mInventory[0]);
+ }
+
+ @Override
+ public byte getTileEntityBaseType() {
+ return 0;
+ }
+
+ public abstract String getName();
+
+ @Override
+ public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
+ if (mMachine) return -1;
+ return STRUCTURE_DEFINITION.get(getClass())
+ .survivalBuild(
+ this,
+ stackSize,
+ "main",
+ getBaseMetaTileEntity().getWorld(),
+ getExtendedFacing(),
+ getBaseMetaTileEntity().getXCoord(),
+ getBaseMetaTileEntity().getYCoord(),
+ getBaseMetaTileEntity().getZCoord(),
+ 1,
+ 2,
+ 0,
+ elementBudget,
+ env,
+ false);
+ }
+
+ @Override
+ public IStructureDefinition<?> getStructureDefinition() {
+ return STRUCTURE_DEFINITION.get(getClass());
+ }
+
+ @Override
+ public void construct(ItemStack stackSize, boolean hintsOnly) {
+ STRUCTURE_DEFINITION.get(getClass())
+ .buildOrHints(
+ this,
+ stackSize,
+ "main",
+ getBaseMetaTileEntity().getWorld(),
+ getExtendedFacing(),
+ getBaseMetaTileEntity().getXCoord(),
+ getBaseMetaTileEntity().getYCoord(),
+ getBaseMetaTileEntity().getZCoord(),
+ 1,
+ 2,
+ 0,
+ hintsOnly);
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ builder
+ .widget(
+ new SlotWidget(inventoryHandler, 0)
+ .setBackground(
+ getGUITextureSet().getItemSlot(),
+ GT_UITextures.OVERLAY_SLOT_INGOT_STEAM.get(getSteamVariant()))
+ .setPos(33, 15))
+ .widget(
+ new SlotWidget(inventoryHandler, 1)
+ .setBackground(
+ getGUITextureSet().getItemSlot(),
+ GT_UITextures.OVERLAY_SLOT_DUST_STEAM.get(getSteamVariant()))
+ .setPos(33, 33))
+ .widget(
+ new SlotWidget(inventoryHandler, 2)
+ .setBackground(
+ getGUITextureSet().getItemSlot(),
+ GT_UITextures.OVERLAY_SLOT_FURNACE_STEAM.get(getSteamVariant()))
+ .setPos(33, 51))
+ .widget(
+ new SlotWidget(inventoryHandler, 3).setAccess(true, false)
+ .setBackground(
+ getGUITextureSet().getItemSlot(),
+ GT_UITextures.OVERLAY_SLOT_INGOT_STEAM.get(getSteamVariant()))
+ .setPos(85, 24))
+ .widget(
+ new SlotWidget(inventoryHandler, 4).setAccess(true, false)
+ .setBackground(
+ getGUITextureSet().getItemSlot(),
+ GT_UITextures.OVERLAY_SLOT_DUST_STEAM.get(getSteamVariant()))
+ .setPos(103, 24))
+ .widget(
+ new SlotWidget(inventoryHandler, 5).setAccess(true, false)
+ .setBackground(
+ getGUITextureSet().getItemSlot(),
+ GT_UITextures.OVERLAY_SLOT_DUST_STEAM.get(getSteamVariant()))
+ .setPos(121, 24))
+ .widget(
+ new ProgressBar().setTexture(GT_UITextures.PROGRESSBAR_ARROW_2_STEAM.get(getSteamVariant()), 20)
+ .setProgress(() -> (float) mProgresstime / mMaxProgresstime)
+ .setNEITransferRect(
+ getRecipeMap().getFrontend()
+ .getUIProperties().neiTransferRectId)
+ .setPos(58, 24)
+ .setSize(20, 18));
+ }
+
+ @Override
+ public GUITextureSet getGUITextureSet() {
+ return GUITextureSet.STEAM.apply(getSteamVariant());
+ }
+
+ @Override
+ public int getTitleColor() {
+ return getSteamVariant() == SteamVariant.BRONZE ? COLOR_TITLE.get() : COLOR_TITLE_WHITE.get();
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ProcessingArray.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ProcessingArray.java
new file mode 100644
index 0000000000..5f818c075b
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ProcessingArray.java
@@ -0,0 +1,545 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.lazy;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofChain;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.onElementPass;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.transpose;
+import static gregtech.api.enums.GT_HatchElement.Energy;
+import static gregtech.api.enums.GT_HatchElement.ExoticEnergy;
+import static gregtech.api.enums.GT_HatchElement.InputBus;
+import static gregtech.api.enums.GT_HatchElement.InputHatch;
+import static gregtech.api.enums.GT_HatchElement.Maintenance;
+import static gregtech.api.enums.GT_HatchElement.OutputBus;
+import static gregtech.api.enums.GT_HatchElement.OutputHatch;
+import static gregtech.api.enums.GT_Values.VN;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_PROCESSING_ARRAY;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_PROCESSING_ARRAY_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_PROCESSING_ARRAY_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_PROCESSING_ARRAY_GLOW;
+import static gregtech.api.metatileentity.BaseTileEntity.TOOLTIP_DELAY;
+import static gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachine.isValidForLowGravity;
+import static gregtech.api.util.GT_Utility.filterValidMTEs;
+
+import java.util.List;
+
+import javax.annotation.Nonnull;
+
+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.common.util.ForgeDirection;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.google.common.collect.ImmutableList;
+import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+import com.gtnewhorizons.modularui.api.drawable.IDrawable;
+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.FakeSyncWidget;
+
+import gregtech.GT_Mod;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.enums.SoundResource;
+import gregtech.api.enums.Textures;
+import gregtech.api.enums.Textures.BlockIcons;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.IHatchElement;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.logic.ProcessingLogic;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_ExtendedPowerMultiBlockBase;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Input;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_InputBus;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_TieredMachineBlock;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.recipe.check.SimpleCheckRecipeResult;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_ExoticEnergyInputHelper;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_ProcessingArray_Manager;
+import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.GT_StructureUtility;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.blocks.GT_Item_Machines;
+import mcp.mobius.waila.api.IWailaConfigHandler;
+import mcp.mobius.waila.api.IWailaDataAccessor;
+
+@Deprecated
+public class GT_MetaTileEntity_ProcessingArray extends
+ GT_MetaTileEntity_ExtendedPowerMultiBlockBase<GT_MetaTileEntity_ProcessingArray> implements ISurvivalConstructable {
+
+ private static final String STRUCTURE_PIECE_MAIN = "main";
+ private static final IStructureDefinition<GT_MetaTileEntity_ProcessingArray> STRUCTURE_DEFINITION = StructureDefinition
+ .<GT_MetaTileEntity_ProcessingArray>builder()
+ .addShape(
+ STRUCTURE_PIECE_MAIN,
+ transpose(new String[][] { { "hhh", "hhh", "hhh" }, { "h~h", "h-h", "hhh" }, { "hhh", "hhh", "hhh" }, }))
+ .addElement(
+ 'h',
+ ofChain(
+ lazy(
+ t -> GT_StructureUtility.<GT_MetaTileEntity_ProcessingArray>buildHatchAdder()
+ .atLeastList(t.getAllowedHatches())
+ .casingIndex(48)
+ .dot(1)
+ .build()),
+ onElementPass(t -> t.mCasingAmount++, ofBlock(GregTech_API.sBlockCasings4, 0))))
+ .build();
+
+ private int mCasingAmount = 0;
+
+ private RecipeMap<?> mLastRecipeMap;
+ private ItemStack lastControllerStack;
+ private int tTier = 0;
+ private int mMult = 0;
+ private boolean downtierUEV = true;
+
+ public GT_MetaTileEntity_ProcessingArray(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_ProcessingArray(String aName) {
+ super(aName);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_ProcessingArray(this.mName);
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Processing Array")
+ .addInfo("Runs supplied machines as if placed in the world")
+ .addInfo("Place up to 64 singleblock GT machines into the controller")
+ .addInfo("Note that you still need to supply power to them all")
+ .addInfo("Use a screwdriver to enable separate input busses")
+ .addInfo("Use a wire cutter to disable UEV+ downtiering")
+ .addInfo("Doesn't work on certain machines, deal with it")
+ .addInfo("Use it if you hate GT++, or want even more speed later on")
+ .addInfo(
+ EnumChatFormatting.GOLD
+ + "On the way to be slowly removed. Use it strictly if you have no alternative.")
+ .addSeparator()
+ .beginStructureBlock(3, 3, 3, true)
+ .addController("Front center")
+ .addCasingInfoRange("Robust Tungstensteel Machine Casing", 14, 24, false)
+ .addEnergyHatch("Any casing", 1)
+ .addMaintenanceHatch("Any casing", 1)
+ .addInputBus("Any casing", 1)
+ .addInputHatch("Any casing", 1)
+ .addOutputBus("Any casing", 1)
+ .addOutputHatch("Any casing", 1)
+ .toolTipFinisher("Gregtech");
+ return tt;
+ }
+
+ @Override
+ public boolean addToMachineList(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
+ return super.addToMachineList(aTileEntity, aBaseCasingIndex)
+ || addExoticEnergyInputToMachineList(aTileEntity, aBaseCasingIndex);
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection aFacing,
+ int colorIndex, boolean aActive, boolean redstoneLevel) {
+ if (side == aFacing) {
+ if (aActive) return new ITexture[] { BlockIcons.casingTexturePages[0][48], TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_PROCESSING_ARRAY_ACTIVE)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_PROCESSING_ARRAY_ACTIVE_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ return new ITexture[] { BlockIcons.casingTexturePages[0][48], TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_PROCESSING_ARRAY)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_PROCESSING_ARRAY_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ }
+ return new ITexture[] { Textures.BlockIcons.casingTexturePages[0][48] };
+ }
+
+ private RecipeMap<?> fetchRecipeMap() {
+ if (isCorrectMachinePart(getControllerSlot())) {
+ // Gets the recipe map for the given machine through its unlocalized name
+ return GT_ProcessingArray_Manager
+ .giveRecipeMap(GT_ProcessingArray_Manager.getMachineName(getControllerSlot()));
+ }
+ return null;
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return mLastRecipeMap;
+ }
+
+ @Override
+ public boolean isCorrectMachinePart(ItemStack aStack) {
+ return aStack != null && aStack.getUnlocalizedName()
+ .startsWith("gt.blockmachines.");
+ }
+
+ @Override
+ protected void sendStartMultiBlockSoundLoop() {
+ SoundResource sound = GT_ProcessingArray_Manager
+ .getSoundResource(GT_ProcessingArray_Manager.getMachineName(getControllerSlot()));
+ if (sound != null) {
+ sendLoopStart((byte) sound.id);
+ }
+ }
+
+ @Override
+ public void startSoundLoop(byte aIndex, double aX, double aY, double aZ) {
+ super.startSoundLoop(aIndex, aX, aY, aZ);
+ SoundResource sound = SoundResource.get(aIndex < 0 ? aIndex + 256 : 0);
+ if (sound != null) {
+ GT_Utility.doSoundAtClient(sound, getTimeBetweenProcessSounds(), 1.0F, aX, aY, aZ);
+ }
+ }
+
+ @Override
+ @NotNull
+ public CheckRecipeResult checkProcessing() {
+ if (!GT_Utility.areStacksEqual(lastControllerStack, getControllerSlot())) {
+ // controller slot has changed
+ lastControllerStack = getControllerSlot();
+ mLastRecipeMap = fetchRecipeMap();
+ setTierAndMult();
+ }
+ if (mLastRecipeMap == null) return SimpleCheckRecipeResult.ofFailure("no_machine");
+ if (mLockedToSingleRecipe && mSingleRecipeCheck != null) {
+ if (mSingleRecipeCheck.getRecipeMap() != mLastRecipeMap) {
+ return SimpleCheckRecipeResult.ofFailure("machine_mismatch");
+ }
+ }
+
+ return super.checkProcessing();
+ }
+
+ @Override
+ protected ProcessingLogic createProcessingLogic() {
+ return new ProcessingLogic() {
+
+ @Nonnull
+ @Override
+ protected CheckRecipeResult validateRecipe(@Nonnull GT_Recipe recipe) {
+ if (GT_Mod.gregtechproxy.mLowGravProcessing && recipe.mSpecialValue == -100
+ && !isValidForLowGravity(recipe, getBaseMetaTileEntity().getWorld().provider.dimensionId)) {
+ return SimpleCheckRecipeResult.ofFailure("high_gravity");
+ }
+ if (recipe.mEUt > availableVoltage) return CheckRecipeResultRegistry.insufficientPower(recipe.mEUt);
+ return CheckRecipeResultRegistry.SUCCESSFUL;
+ }
+ }.setMaxParallelSupplier(this::getMaxParallel);
+ }
+
+ @Override
+ protected boolean canUseControllerSlotForRecipe() {
+ return false;
+ }
+
+ @Override
+ protected void setProcessingLogicPower(ProcessingLogic logic) {
+ logic.setAvailableVoltage(GT_Values.V[tTier] * (mLastRecipeMap != null ? mLastRecipeMap.getAmperage() : 1));
+ logic.setAvailableAmperage(getMaxParallel());
+ logic.setAmperageOC(false);
+ }
+
+ private void setTierAndMult() {
+ IMetaTileEntity aMachine = GT_Item_Machines.getMetaTileEntity(getControllerSlot());
+ if (aMachine instanceof GT_MetaTileEntity_TieredMachineBlock) {
+ tTier = ((GT_MetaTileEntity_TieredMachineBlock) aMachine).mTier;
+ } else {
+ tTier = 0;
+ }
+ mMult = 0;
+ if (downtierUEV && tTier > 9) {
+ tTier--; // Lowers down the tier by 1 to allow for bigger parallel
+ mMult = 2; // Multiplies Parallels by 4x, keeping the energy cost
+ }
+ }
+
+ private int getMaxParallel() {
+ if (getControllerSlot() == null) {
+ return 0;
+ }
+ return getControllerSlot().stackSize << mMult;
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ super.onPostTick(aBaseMetaTileEntity, aTick);
+ if (mMachine && aTick % 20 == 0) {
+ for (GT_MetaTileEntity_Hatch_InputBus tInputBus : mInputBusses) {
+ tInputBus.mRecipeMap = mLastRecipeMap;
+ }
+ for (GT_MetaTileEntity_Hatch_Input tInputHatch : mInputHatches) {
+ tInputHatch.mRecipeMap = mLastRecipeMap;
+ }
+ }
+ }
+
+ @Override
+ public IStructureDefinition<GT_MetaTileEntity_ProcessingArray> getStructureDefinition() {
+ return STRUCTURE_DEFINITION;
+ }
+
+ @Override
+ public void construct(ItemStack aStack, boolean aHintsOnly) {
+ buildPiece(STRUCTURE_PIECE_MAIN, aStack, aHintsOnly, 1, 1, 0);
+ }
+
+ @Override
+ public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
+ if (mMachine) return -1;
+ return survivialBuildPiece(STRUCTURE_PIECE_MAIN, stackSize, 1, 1, 0, elementBudget, env, false, true);
+ }
+
+ private boolean checkHatches() {
+ return mMaintenanceHatches.size() == 1;
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ aNBT.setBoolean("downtierUEV", downtierUEV);
+ }
+
+ @Override
+ public void loadNBTData(final NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ if (aNBT.hasKey("mSeparate")) {
+ // backward compatibility
+ inputSeparation = aNBT.getBoolean("mSeparate");
+ }
+ if (aNBT.hasKey("mUseMultiparallelMode")) {
+ // backward compatibility
+ batchMode = aNBT.getBoolean("mUseMultiparallelMode");
+ }
+ downtierUEV = aNBT.getBoolean("downtierUEV");
+ }
+
+ @Override
+ public final void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ if (aPlayer.isSneaking()) {
+ // Lock to single recipe
+ super.onScrewdriverRightClick(side, aPlayer, aX, aY, aZ);
+ } else {
+ inputSeparation = !inputSeparation;
+ GT_Utility.sendChatToPlayer(
+ aPlayer,
+ StatCollector.translateToLocal("GT5U.machines.separatebus") + " " + inputSeparation);
+ }
+ }
+
+ @Override
+ public boolean onWireCutterRightClick(ForgeDirection side, ForgeDirection wrenchingSide, EntityPlayer aPlayer,
+ float aX, float aY, float aZ) {
+ if (aPlayer.isSneaking()) {
+ batchMode = !batchMode;
+ if (batchMode) {
+ GT_Utility.sendChatToPlayer(aPlayer, "Batch recipes");
+ } else {
+ GT_Utility.sendChatToPlayer(aPlayer, "Don't batch recipes");
+ }
+ } else {
+ downtierUEV = !downtierUEV;
+ GT_Utility.sendChatToPlayer(aPlayer, "Treat UEV+ machines as multiple UHV " + downtierUEV);
+ }
+ return true;
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack aStack) {
+ return 10000;
+ }
+
+ @Override
+ public int getDamageToComponent(ItemStack aStack) {
+ return 0;
+ }
+
+ @Override
+ public boolean explodesOnComponentBreak(ItemStack aStack) {
+ return false;
+ }
+
+ private List<IHatchElement<? super GT_MetaTileEntity_ProcessingArray>> getAllowedHatches() {
+ return ImmutableList.of(InputHatch, OutputHatch, InputBus, OutputBus, Maintenance, Energy, ExoticEnergy);
+ }
+
+ @Override
+ public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+ mExoticEnergyHatches.clear();
+ mCasingAmount = 0;
+ return checkPiece(STRUCTURE_PIECE_MAIN, 1, 1, 0) && mCasingAmount >= 14 && checkHatches();
+ }
+
+ @Override
+ public String[] getInfoData() {
+ long storedEnergy = 0;
+ long maxEnergy = 0;
+ for (GT_MetaTileEntity_Hatch tHatch : filterValidMTEs(mExoticEnergyHatches)) {
+ storedEnergy += tHatch.getBaseMetaTileEntity()
+ .getStoredEU();
+ maxEnergy += tHatch.getBaseMetaTileEntity()
+ .getEUCapacity();
+ }
+
+ return new String[] {
+ StatCollector.translateToLocal("GT5U.multiblock.Progress") + ": "
+ + EnumChatFormatting.GREEN
+ + GT_Utility.formatNumbers(mProgresstime / 20)
+ + EnumChatFormatting.RESET
+ + " s / "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(mMaxProgresstime / 20)
+ + EnumChatFormatting.RESET
+ + " s",
+ StatCollector.translateToLocal("GT5U.multiblock.energy") + ": "
+ + EnumChatFormatting.GREEN
+ + GT_Utility.formatNumbers(storedEnergy)
+ + EnumChatFormatting.RESET
+ + " EU / "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(maxEnergy)
+ + EnumChatFormatting.RESET
+ + " EU",
+ StatCollector.translateToLocal("GT5U.multiblock.usage") + ": "
+ + EnumChatFormatting.RED
+ + GT_Utility.formatNumbers(-lEUt)
+ + EnumChatFormatting.RESET
+ + " EU/t",
+ StatCollector.translateToLocal("GT5U.multiblock.mei") + ": "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(
+ GT_ExoticEnergyInputHelper.getMaxInputVoltageMulti(getExoticAndNormalEnergyHatchList()))
+ + EnumChatFormatting.RESET
+ + " EU/t(*"
+ + GT_Utility
+ .formatNumbers(GT_ExoticEnergyInputHelper.getMaxInputAmpsMulti(getExoticAndNormalEnergyHatchList()))
+ + "A) "
+ + StatCollector.translateToLocal("GT5U.machines.tier")
+ + ": "
+ + EnumChatFormatting.YELLOW
+ + VN[GT_Utility
+ .getTier(GT_ExoticEnergyInputHelper.getMaxInputVoltageMulti(getExoticAndNormalEnergyHatchList()))]
+ + EnumChatFormatting.RESET,
+ StatCollector.translateToLocal("GT5U.multiblock.problems") + ": "
+ + EnumChatFormatting.RED
+ + (getIdealStatus() - getRepairStatus())
+ + EnumChatFormatting.RESET
+ + " "
+ + StatCollector.translateToLocal("GT5U.multiblock.efficiency")
+ + ": "
+ + EnumChatFormatting.YELLOW
+ + mEfficiency / 100.0F
+ + EnumChatFormatting.RESET
+ + " %",
+ StatCollector.translateToLocal("GT5U.PA.machinetier") + ": "
+ + EnumChatFormatting.GREEN
+ + tTier
+ + EnumChatFormatting.RESET
+ + " "
+ + StatCollector.translateToLocal("GT5U.PA.discount")
+ + ": "
+ + EnumChatFormatting.GREEN
+ + 1
+ + EnumChatFormatting.RESET
+ + " x",
+ StatCollector.translateToLocal("GT5U.PA.parallel") + ": "
+ + EnumChatFormatting.GREEN
+ + GT_Utility.formatNumbers(getMaxParallel())
+ + EnumChatFormatting.RESET };
+ }
+
+ @Override
+ public boolean supportsInputSeparation() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsBatchMode() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsSingleRecipeLocking() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsVoidProtection() {
+ return true;
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ super.addUIWidgets(builder, buildContext);
+
+ builder.widget(new ButtonWidget().setOnClick((clickData, widget) -> {
+ downtierUEV = !downtierUEV;
+ setTierAndMult();
+ })
+ .setPlayClickSound(true)
+ .setBackground(() -> {
+ if (downtierUEV) {
+ return new IDrawable[] { GT_UITextures.BUTTON_STANDARD_PRESSED,
+ GT_UITextures.OVERLAY_BUTTON_DOWN_TIERING_ON };
+ } else {
+ return new IDrawable[] { GT_UITextures.BUTTON_STANDARD,
+ GT_UITextures.OVERLAY_BUTTON_DOWN_TIERING_OFF };
+ }
+ })
+ .setPos(80, 91)
+ .setSize(16, 16)
+ .addTooltip(StatCollector.translateToLocal("GT5U.gui.button.down_tier"))
+ .setTooltipShowUpDelay(TOOLTIP_DELAY))
+ .widget(new FakeSyncWidget.BooleanSyncer(() -> downtierUEV, val -> downtierUEV = val));
+ }
+
+ @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);
+ if (mLastRecipeMap != null && getControllerSlot() != null) {
+ tag.setString("type", getControllerSlot().getDisplayName());
+ }
+ }
+
+ @Override
+ public void getWailaBody(ItemStack itemStack, List<String> currentTip, IWailaDataAccessor accessor,
+ IWailaConfigHandler config) {
+ super.getWailaBody(itemStack, currentTip, accessor, config);
+ final NBTTagCompound tag = accessor.getNBTData();
+ if (tag.hasKey("type")) {
+ currentTip.add("Machine: " + EnumChatFormatting.YELLOW + tag.getString("type"));
+ } else {
+ currentTip.add("Machine: " + EnumChatFormatting.YELLOW + "None");
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PyrolyseOven.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PyrolyseOven.java
new file mode 100644
index 0000000000..ff84a69b44
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PyrolyseOven.java
@@ -0,0 +1,263 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlockUnlocalizedName;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.onElementPass;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.transpose;
+import static gregtech.api.enums.GT_HatchElement.Energy;
+import static gregtech.api.enums.GT_HatchElement.InputBus;
+import static gregtech.api.enums.GT_HatchElement.InputHatch;
+import static gregtech.api.enums.GT_HatchElement.Maintenance;
+import static gregtech.api.enums.GT_HatchElement.Muffler;
+import static gregtech.api.enums.GT_HatchElement.OutputBus;
+import static gregtech.api.enums.GT_HatchElement.OutputHatch;
+import static gregtech.api.enums.Mods.NewHorizonsCoreMod;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_PYROLYSE_OVEN;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_PYROLYSE_OVEN_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_PYROLYSE_OVEN_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_PYROLYSE_OVEN_GLOW;
+import static gregtech.api.util.GT_StructureUtility.buildHatchAdder;
+import static gregtech.api.util.GT_StructureUtility.ofCoil;
+
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.IStructureElement;
+import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+
+import gregtech.GT_Mod;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.HeatingCoilLevel;
+import gregtech.api.enums.Textures;
+import gregtech.api.enums.Textures.BlockIcons;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.logic.ProcessingLogic;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_EnhancedMultiBlockBase;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+
+public class GT_MetaTileEntity_PyrolyseOven
+ extends GT_MetaTileEntity_EnhancedMultiBlockBase<GT_MetaTileEntity_PyrolyseOven> implements ISurvivalConstructable {
+
+ private HeatingCoilLevel coilHeat;
+ private static final int CASING_INDEX = 1090;
+ private static final IStructureDefinition<GT_MetaTileEntity_PyrolyseOven> STRUCTURE_DEFINITION = createStructureDefinition();
+
+ private static IStructureDefinition<GT_MetaTileEntity_PyrolyseOven> createStructureDefinition() {
+ IStructureElement<GT_MetaTileEntity_PyrolyseOven> tCasingElement = NewHorizonsCoreMod.isModLoaded()
+ ? ofBlockUnlocalizedName(NewHorizonsCoreMod.ID, "gt.blockcasingsNH", 2)
+ : ofBlock(GregTech_API.sBlockCasings1, 0);
+
+ return StructureDefinition.<GT_MetaTileEntity_PyrolyseOven>builder()
+ .addShape(
+ "main",
+ transpose(
+ new String[][] { { "ccccc", "ctttc", "ctttc", "ctttc", "ccccc" },
+ { "ccccc", "c---c", "c---c", "c---c", "ccccc" },
+ { "ccccc", "c---c", "c---c", "c---c", "ccccc" },
+ { "bb~bb", "bCCCb", "bCCCb", "bCCCb", "bbbbb" }, }))
+ .addElement('c', onElementPass(GT_MetaTileEntity_PyrolyseOven::onCasingAdded, tCasingElement))
+ .addElement(
+ 'C',
+ ofCoil(GT_MetaTileEntity_PyrolyseOven::setCoilLevel, GT_MetaTileEntity_PyrolyseOven::getCoilLevel))
+ .addElement(
+ 'b',
+ buildHatchAdder(GT_MetaTileEntity_PyrolyseOven.class)
+ .atLeast(OutputBus, OutputHatch, Energy, Maintenance)
+ .casingIndex(CASING_INDEX)
+ .dot(1)
+ .buildAndChain(onElementPass(GT_MetaTileEntity_PyrolyseOven::onCasingAdded, tCasingElement)))
+ .addElement(
+ 't',
+ buildHatchAdder(GT_MetaTileEntity_PyrolyseOven.class).atLeast(InputBus, InputHatch, Muffler)
+ .casingIndex(CASING_INDEX)
+ .dot(1)
+ .buildAndChain(onElementPass(GT_MetaTileEntity_PyrolyseOven::onCasingAdded, tCasingElement)))
+ .build();
+ }
+
+ private int mCasingAmount;
+
+ public GT_MetaTileEntity_PyrolyseOven(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_PyrolyseOven(String aName) {
+ super(aName);
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Coke Oven")
+ .addInfo("Controller block for the Pyrolyse Oven")
+ .addInfo("Industrial Charcoal producer")
+ .addInfo("Processing speed scales linearly with Coil tier:")
+ .addInfo("CuNi: 50%, FeAlCr: 100%, Ni4Cr: 150%, TPV: 200%, etc.")
+ .addInfo("EU/t is not affected by Coil tier")
+ .addPollutionAmount(getPollutionPerSecond(null))
+ .addSeparator()
+ .beginStructureBlock(5, 4, 5, true)
+ .addController("Front center")
+ .addCasingInfoRange("Pyrolyse Oven Casing", 60, 80, false)
+ .addOtherStructurePart("Heating Coils", "Center 3x1x3 of the bottom layer")
+ .addEnergyHatch("Any bottom layer casing", 1)
+ .addMaintenanceHatch("Any bottom layer casing", 1)
+ .addMufflerHatch("Center 3x1x3 area in top layer", 2)
+ .addInputBus("Center 3x1x3 area in top layer", 2)
+ .addInputHatch("Center 3x1x3 area in top layer", 2)
+ .addOutputBus("Any bottom layer casing", 1)
+ .addOutputHatch("Any bottom layer casing", 1)
+ .toolTipFinisher("Gregtech");
+ return tt;
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity baseMetaTileEntity, ForgeDirection sideDirection,
+ ForgeDirection facingDirection, int colorIndex, boolean active, boolean redstoneLevel) {
+ if (sideDirection == facingDirection) {
+ if (active) return new ITexture[] { BlockIcons.casingTexturePages[8][66], TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_PYROLYSE_OVEN_ACTIVE)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_PYROLYSE_OVEN_ACTIVE_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ return new ITexture[] { BlockIcons.casingTexturePages[8][66], TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_PYROLYSE_OVEN)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_PYROLYSE_OVEN_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ }
+ return new ITexture[] { Textures.BlockIcons.casingTexturePages[8][66] };
+ }
+
+ @Override
+ public boolean supportsSingleRecipeLocking() {
+ return true;
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.pyrolyseRecipes;
+ }
+
+ @Override
+ protected ProcessingLogic createProcessingLogic() {
+ return new ProcessingLogic() {
+
+ @NotNull
+ @Override
+ public CheckRecipeResult process() {
+ setSpeedBonus(2f / (1 + coilHeat.getTier()));
+ return super.process();
+ }
+ };
+ }
+
+ @Override
+ public IStructureDefinition<GT_MetaTileEntity_PyrolyseOven> getStructureDefinition() {
+ return STRUCTURE_DEFINITION;
+ }
+
+ private void onCasingAdded() {
+ mCasingAmount++;
+ }
+
+ public HeatingCoilLevel getCoilLevel() {
+ return coilHeat;
+ }
+
+ private void setCoilLevel(HeatingCoilLevel aCoilLevel) {
+ coilHeat = aCoilLevel;
+ }
+
+ @Override
+ public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+ coilHeat = HeatingCoilLevel.None;
+ mCasingAmount = 0;
+ replaceDeprecatedCoils(aBaseMetaTileEntity);
+ return checkPiece("main", 2, 3, 0) && mCasingAmount >= 60
+ && mMaintenanceHatches.size() == 1
+ && !mMufflerHatches.isEmpty();
+ }
+
+ @Override
+ public boolean isCorrectMachinePart(ItemStack aStack) {
+ return true;
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack aStack) {
+ return 10000;
+ }
+
+ @Override
+ public int getPollutionPerSecond(ItemStack aStack) {
+ return GT_Mod.gregtechproxy.mPollutionPyrolyseOvenPerSecond;
+ }
+
+ @Override
+ public int getDamageToComponent(ItemStack aStack) {
+ return 0;
+ }
+
+ @Override
+ public boolean explodesOnComponentBreak(ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_PyrolyseOven(this.mName);
+ }
+
+ private void replaceDeprecatedCoils(IGregTechTileEntity aBaseMetaTileEntity) {
+ final int xDir = aBaseMetaTileEntity.getBackFacing().offsetX;
+ final int zDir = aBaseMetaTileEntity.getBackFacing().offsetZ;
+ final int tX = aBaseMetaTileEntity.getXCoord() + xDir * 2;
+ final int tY = aBaseMetaTileEntity.getYCoord();
+ final int tZ = aBaseMetaTileEntity.getZCoord() + zDir * 2;
+ for (int xPos = tX - 1; xPos <= tX + 1; xPos++) {
+ for (int zPos = tZ - 1; zPos <= tZ + 1; zPos++) {
+ if (aBaseMetaTileEntity.getBlock(xPos, tY, zPos) == GregTech_API.sBlockCasings1
+ && aBaseMetaTileEntity.getMetaID(xPos, tY, zPos) == 13) {
+ aBaseMetaTileEntity.getWorld()
+ .setBlock(xPos, tY, zPos, GregTech_API.sBlockCasings5, 1, 3);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void construct(ItemStack stackSize, boolean hintsOnly) {
+ buildPiece("main", stackSize, hintsOnly, 2, 3, 0);
+ }
+
+ @Override
+ public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
+ if (mMachine) return -1;
+ return survivialBuildPiece("main", stackSize, 2, 3, 0, elementBudget, env, false, true);
+ }
+
+ @Override
+ public boolean supportsVoidProtection() {
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_TranscendentPlasmaMixer.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_TranscendentPlasmaMixer.java
new file mode 100644
index 0000000000..7d038666d6
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_TranscendentPlasmaMixer.java
@@ -0,0 +1,288 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock;
+import static gregtech.api.enums.GT_HatchElement.InputBus;
+import static gregtech.api.enums.GT_HatchElement.InputHatch;
+import static gregtech.api.enums.GT_HatchElement.Maintenance;
+import static gregtech.api.enums.GT_HatchElement.OutputHatch;
+import static gregtech.api.enums.GT_Values.AuthorColen;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_DTPF_OFF;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_DTPF_ON;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FUSION1_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.casingTexturePages;
+import static gregtech.api.util.GT_StructureUtility.buildHatchAdder;
+import static gregtech.common.misc.WirelessNetworkManager.addEUToGlobalEnergyMap;
+import static gregtech.common.misc.WirelessNetworkManager.getUserEU;
+import static gregtech.common.misc.WirelessNetworkManager.processInitialSettings;
+import static gregtech.common.tileentities.machines.multi.GT_MetaTileEntity_PlasmaForge.DIM_BRIDGE_CASING;
+import static gregtech.common.tileentities.machines.multi.GT_MetaTileEntity_PlasmaForge.DIM_INJECTION_CASING;
+import static gregtech.common.tileentities.machines.multi.GT_MetaTileEntity_PlasmaForge.DIM_TRANS_CASING;
+import static java.lang.Math.max;
+import static net.minecraft.util.EnumChatFormatting.GOLD;
+import static net.minecraft.util.EnumChatFormatting.GRAY;
+
+import java.math.BigInteger;
+import java.util.UUID;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.logic.ProcessingLogic;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_EnhancedMultiBlockBase;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_OverclockCalculator;
+import gregtech.api.util.GT_Recipe;
+import gregtech.common.items.GT_IntegratedCircuit_Item;
+
+public class GT_MetaTileEntity_TranscendentPlasmaMixer
+ extends GT_MetaTileEntity_EnhancedMultiBlockBase<GT_MetaTileEntity_TranscendentPlasmaMixer>
+ implements ISurvivalConstructable {
+
+ private static final String[][] structure = new String[][] {
+ { " CAC ", " ABA ", " ABA ", " A~A ", " ABA ", " ABA ", " CAC " },
+ { "CBBBC", "A A", "A A", "A A", "A A", "A A", "CBBBC" },
+ { "ABBBA", "B B", "B B", "B B", "B B", "B B", "ABBBA" },
+ { "CBBBC", "A A", "A A", "A A", "A A", "A A", "CBBBC" },
+ { " CAC ", " ABA ", " ABA ", " ABA ", " ABA ", " ABA ", " CAC " } };
+
+ private static final String STRUCTURE_PIECE_MAIN = "MAIN";
+ private static final IStructureDefinition<GT_MetaTileEntity_TranscendentPlasmaMixer> STRUCTURE_DEFINITION = StructureDefinition
+ .<GT_MetaTileEntity_TranscendentPlasmaMixer>builder()
+ .addShape(STRUCTURE_PIECE_MAIN, structure)
+ .addElement(
+ 'B',
+ buildHatchAdder(GT_MetaTileEntity_TranscendentPlasmaMixer.class)
+ .atLeast(InputHatch, OutputHatch, InputBus, Maintenance)
+ .casingIndex(DIM_INJECTION_CASING)
+ .dot(1)
+ .buildAndChain(GregTech_API.sBlockCasings1, DIM_INJECTION_CASING))
+ .addElement('A', ofBlock(GregTech_API.sBlockCasings1, DIM_TRANS_CASING))
+ .addElement('C', ofBlock(GregTech_API.sBlockCasings1, DIM_BRIDGE_CASING))
+ .build();
+
+ private UUID ownerUUID;
+
+ public GT_MetaTileEntity_TranscendentPlasmaMixer(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_TranscendentPlasmaMixer(String aName) {
+ super(aName);
+ }
+
+ @Override
+ public IStructureDefinition<GT_MetaTileEntity_TranscendentPlasmaMixer> getStructureDefinition() {
+ return STRUCTURE_DEFINITION;
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Transcendent Mixer")
+ .addInfo("Assisting in all your DTPF needs.")
+ .addInfo("This multiblock will run in parallel according to the circuit provided to the")
+ .addInfo("controller slot. E.g. 3x Circuit #16 = 48x parallel. All inputs will scale,")
+ .addInfo("except time. All EU is deducted from wireless EU networks only.")
+ .addInfo(AuthorColen)
+ .addInfo("Controller slot and circuit slot are separate.")
+ .addSeparator()
+ .beginStructureBlock(5, 7, 5, false)
+ .addStructureInfo(GOLD + "1+ " + GRAY + "Input Hatch")
+ .addStructureInfo(GOLD + "1+ " + GRAY + "Output Hatch")
+ .addStructureInfo(GOLD + "1+ " + GRAY + "Input Bus")
+ .addStructureInfo(GOLD + "1 " + GRAY + "Maintenance Hatch")
+ .toolTipFinisher("Gregtech");
+ return tt;
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_TranscendentPlasmaMixer(mName);
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection aFacing,
+ int colorIndex, boolean aActive, boolean redstoneLevel) {
+ if (side == aFacing) {
+ if (aActive) return new ITexture[] { casingTexturePages[0][DIM_TRANS_CASING], TextureFactory.builder()
+ .addIcon(OVERLAY_DTPF_ON)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FUSION1_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ return new ITexture[] { casingTexturePages[0][DIM_TRANS_CASING], TextureFactory.builder()
+ .addIcon(OVERLAY_DTPF_OFF)
+ .extFacing()
+ .build() };
+ }
+
+ return new ITexture[] { casingTexturePages[0][DIM_TRANS_CASING] };
+ }
+
+ @Override
+ public boolean isCorrectMachinePart(ItemStack aStack) {
+ return true;
+ }
+
+ int multiplier = 1;
+ long mWirelessEUt = 0;
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.transcendentPlasmaMixerRecipes;
+ }
+
+ @Override
+ protected ProcessingLogic createProcessingLogic() {
+ return new ProcessingLogic() {
+
+ @NotNull
+ @Override
+ protected CheckRecipeResult validateRecipe(@Nonnull GT_Recipe recipe) {
+ mWirelessEUt = 10L * (long) recipe.mEUt * (long) multiplier;
+ if (getUserEU(ownerUUID).compareTo(BigInteger.valueOf(mWirelessEUt * recipe.mDuration)) < 0) {
+ return CheckRecipeResultRegistry.insufficientPower(mWirelessEUt * recipe.mDuration);
+ }
+ return CheckRecipeResultRegistry.SUCCESSFUL;
+ }
+
+ @NotNull
+ @Override
+ protected CheckRecipeResult onRecipeStart(@Nonnull GT_Recipe recipe) {
+ mWirelessEUt = 10L * (long) recipe.mEUt * (long) multiplier;
+ // This will void the inputs if wireless energy has dropped
+ // below the required amount between validateRecipe and here.
+ if (!addEUToGlobalEnergyMap(ownerUUID, -mWirelessEUt * recipe.mDuration)) {
+ return CheckRecipeResultRegistry.insufficientPower(mWirelessEUt * recipe.mDuration);
+ }
+ // Energy consumed all at once from wireless net.
+ setCalculatedEut(0);
+ return CheckRecipeResultRegistry.SUCCESSFUL;
+ }
+
+ @Nonnull
+ @Override
+ protected GT_OverclockCalculator createOverclockCalculator(@Nonnull GT_Recipe recipe) {
+ return GT_OverclockCalculator.ofNoOverclock(recipe);
+ }
+ }.setMaxParallelSupplier(() -> {
+ ItemStack controllerStack = getControllerSlot();
+ if (controllerStack != null && controllerStack.getItem() instanceof GT_IntegratedCircuit_Item) {
+ multiplier = controllerStack.stackSize * max(1, controllerStack.getItemDamage());
+ }
+ return multiplier;
+ });
+ }
+
+ @Override
+ protected void setProcessingLogicPower(ProcessingLogic logic) {
+ // The voltage is only used for recipe finding
+ logic.setAvailableVoltage(Long.MAX_VALUE);
+ logic.setAvailableAmperage(1);
+ logic.setAmperageOC(false);
+ }
+
+ @Override
+ protected long getActualEnergyUsage() {
+ return mWirelessEUt;
+ }
+
+ private static final int HORIZONTAL_OFFSET = 2;
+ private static final int VERTICAL_OFFSET = 3;
+ private static final int DEPTH_OFFSET = 0;
+
+ @Override
+ public void construct(ItemStack stackSize, boolean hintsOnly) {
+ buildPiece(STRUCTURE_PIECE_MAIN, stackSize, hintsOnly, HORIZONTAL_OFFSET, VERTICAL_OFFSET, DEPTH_OFFSET);
+ }
+
+ @Override
+ public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
+ return survivialBuildPiece(
+ STRUCTURE_PIECE_MAIN,
+ stackSize,
+ HORIZONTAL_OFFSET,
+ VERTICAL_OFFSET,
+ DEPTH_OFFSET,
+ elementBudget,
+ env,
+ false,
+ true);
+ }
+
+ @Override
+ public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+
+ // Check the main structure
+ if (!checkPiece(STRUCTURE_PIECE_MAIN, HORIZONTAL_OFFSET, VERTICAL_OFFSET, DEPTH_OFFSET)) {
+ return false;
+ }
+
+ return (mMaintenanceHatches.size() == 1);
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack aStack) {
+ return 0;
+ }
+
+ @Override
+ public int getDamageToComponent(ItemStack aStack) {
+ return 0;
+ }
+
+ @Override
+ public boolean explodesOnComponentBreak(ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public void onPreTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+
+ super.onPreTick(aBaseMetaTileEntity, aTick);
+
+ if (aBaseMetaTileEntity.isServerSide() && (aTick == 1)) {
+ // Adds player to the wireless network if they do not already exist on it.
+ ownerUUID = processInitialSettings(aBaseMetaTileEntity);
+ }
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ aNBT.setInteger("eMultiplier", multiplier);
+ super.saveNBTData(aNBT);
+ }
+
+ @Override
+ public void loadNBTData(final NBTTagCompound aNBT) {
+ multiplier = aNBT.getInteger("eMultiplier");
+ super.loadNBTData(aNBT);
+ }
+
+ @Override
+ public boolean supportsVoidProtection() {
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_VacuumFreezer.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_VacuumFreezer.java
new file mode 100644
index 0000000000..499da54bc3
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_VacuumFreezer.java
@@ -0,0 +1,163 @@
+package gregtech.common.tileentities.machines.multi;
+
+import static gregtech.api.enums.GT_HatchElement.Energy;
+import static gregtech.api.enums.GT_HatchElement.InputBus;
+import static gregtech.api.enums.GT_HatchElement.InputHatch;
+import static gregtech.api.enums.GT_HatchElement.Maintenance;
+import static gregtech.api.enums.GT_HatchElement.OutputBus;
+import static gregtech.api.enums.GT_HatchElement.OutputHatch;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_VACUUM_FREEZER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_VACUUM_FREEZER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_VACUUM_FREEZER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_VACUUM_FREEZER_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.casingTexturePages;
+
+import java.util.List;
+
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.google.common.collect.ImmutableList;
+import com.gtnewhorizon.structurelib.structure.IStructureElement;
+import com.gtnewhorizon.structurelib.structure.StructureUtility;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.interfaces.IHatchElement;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.logic.ProcessingLogic;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_CubicMultiBlockBase;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+
+public class GT_MetaTileEntity_VacuumFreezer
+ extends GT_MetaTileEntity_CubicMultiBlockBase<GT_MetaTileEntity_VacuumFreezer> {
+
+ public GT_MetaTileEntity_VacuumFreezer(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_VacuumFreezer(String aName) {
+ super(aName);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_VacuumFreezer(this.mName);
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Vacuum Freezer")
+ .addInfo("Controller Block for the Vacuum Freezer")
+ .addInfo("Cools hot ingots and cells")
+ .addSeparator()
+ .beginStructureBlock(3, 3, 3, true)
+ .addController("Front center")
+ .addCasingInfoRange("Frost Proof Machine Casing", 16, 24, false)
+ .addEnergyHatch("Any casing", 1)
+ .addMaintenanceHatch("Any casing", 1)
+ .addInputHatch("Any casing", 1)
+ .addOutputHatch("Any casing", 1)
+ .addInputBus("Any casing", 1)
+ .addOutputBus("Any casing", 1)
+ .toolTipFinisher("Gregtech");
+ return tt;
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection aFacing,
+ int colorIndex, boolean aActive, boolean redstoneLevel) {
+ ITexture[] rTexture;
+ if (side == aFacing) {
+ if (aActive) {
+ rTexture = new ITexture[] { casingTexturePages[0][17], TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_VACUUM_FREEZER_ACTIVE)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_VACUUM_FREEZER_ACTIVE_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ } else {
+ rTexture = new ITexture[] { casingTexturePages[0][17], TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_VACUUM_FREEZER)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_VACUUM_FREEZER_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ }
+ } else {
+ rTexture = new ITexture[] { casingTexturePages[0][17] };
+ }
+ return rTexture;
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.vacuumFreezerRecipes;
+ }
+
+ @Override
+ public boolean isCorrectMachinePart(ItemStack aStack) {
+ return true;
+ }
+
+ @Override
+ protected ProcessingLogic createProcessingLogic() {
+ return new ProcessingLogic();
+ }
+
+ @Override
+ protected IStructureElement<GT_MetaTileEntity_CubicMultiBlockBase<?>> getCasingElement() {
+ return StructureUtility.ofBlock(GregTech_API.sBlockCasings2, 1);
+ }
+
+ @Override
+ protected List<IHatchElement<? super GT_MetaTileEntity_CubicMultiBlockBase<?>>> getAllowedHatches() {
+ return ImmutableList.of(InputHatch, OutputHatch, InputBus, OutputBus, Maintenance, Energy);
+ }
+
+ @Override
+ protected int getHatchTextureIndex() {
+ return 17;
+ }
+
+ @Override
+ protected int getRequiredCasingCount() {
+ return 16;
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack aStack) {
+ return 10000;
+ }
+
+ @Override
+ public int getDamageToComponent(ItemStack aStack) {
+ return 0;
+ }
+
+ @Override
+ public boolean explodesOnComponentBreak(ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public boolean supportsVoidProtection() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsBatchMode() {
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/drone/DroneConnection.java b/src/main/java/gregtech/common/tileentities/machines/multi/drone/DroneConnection.java
new file mode 100644
index 0000000000..92b1c65032
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/drone/DroneConnection.java
@@ -0,0 +1,143 @@
+package gregtech.common.tileentities.machines.multi.drone;
+
+import static gregtech.GT_Mod.gregtechproxy;
+
+import java.util.Optional;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.ChunkCoordinates;
+import net.minecraft.world.World;
+import net.minecraftforge.common.DimensionManager;
+
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_MultiBlockBase;
+import gregtech.api.util.GT_LanguageManager;
+import gregtech.api.util.GT_Util;
+import gregtech.api.util.GT_Utility;
+
+public class DroneConnection {
+
+ String customName;
+ String unlocalizedName;
+ GT_MetaTileEntity_MultiBlockBase machine;
+ ItemStack machineItem;
+ ChunkCoordinates machineCoord;
+ GT_MetaTileEntity_DroneCentre centre;
+ ChunkCoordinates centreCoord;
+ World world;
+
+ public DroneConnection(GT_MetaTileEntity_MultiBlockBase machine, GT_MetaTileEntity_DroneCentre centre) {
+ this.machine = machine;
+ this.machineItem = machine.getStackForm(1);
+ machineCoord = machine.getBaseMetaTileEntity()
+ .getCoords();
+ this.centre = centre;
+ centreCoord = centre.getBaseMetaTileEntity()
+ .getCoords();
+ this.world = centre.getBaseMetaTileEntity()
+ .getWorld();
+ unlocalizedName = machine.mName;
+ customName = Optional.ofNullable(centre.tempNameList.remove(machineCoord.toString()))
+ .orElse(machine.getLocalName());
+ }
+
+ public DroneConnection(NBTTagCompound aNBT) {
+ NBTTagCompound machineTag = aNBT.getCompoundTag("machine");
+ NBTTagCompound centreTag = aNBT.getCompoundTag("centre");
+ if (!gregtechproxy.isClientSide()) {
+ this.world = DimensionManager.getWorld(aNBT.getInteger("worldID"));
+ } else {
+ this.world = Minecraft.getMinecraft().thePlayer.worldObj;
+ }
+ machineItem = ItemStack.loadItemStackFromNBT(aNBT.getCompoundTag("item"));
+ machineCoord = new ChunkCoordinates(
+ machineTag.getInteger("x"),
+ machineTag.getInteger("y"),
+ machineTag.getInteger("z"));
+ this.machine = getLoadedGT_BaseMachineAt(machineCoord, world, true);
+ centreCoord = new ChunkCoordinates(
+ centreTag.getInteger("x"),
+ centreTag.getInteger("y"),
+ centreTag.getInteger("z"));
+ this.centre = (GT_MetaTileEntity_DroneCentre) getLoadedGT_BaseMachineAt(centreCoord, world, true);
+ this.customName = aNBT.getString("name");
+ this.unlocalizedName = aNBT.getString("unlocalizedName");
+ }
+
+ public GT_MetaTileEntity_MultiBlockBase getMachine() {
+ return machine;
+ }
+
+ public boolean reCheckConnection() {
+ if (machine == null) this.machine = getLoadedGT_BaseMachineAt(machineCoord, world, true);
+ if (centre == null)
+ this.centre = (GT_MetaTileEntity_DroneCentre) getLoadedGT_BaseMachineAt(centreCoord, world, true);
+ if (machine != null && centre != null
+ && !centre.getConnectionList()
+ .contains(this))
+ centre.getConnectionList()
+ .add(this);
+ return isValid();
+ }
+
+ public String getCustomName(boolean localized) {
+ if (localized) return GT_LanguageManager.getTranslation("gt.blockmachines." + unlocalizedName + ".name");
+ return customName;
+ }
+
+ public float getDistanceSquared() {
+ return centreCoord.getDistanceSquaredToChunkCoordinates(machineCoord);
+ }
+
+ public void setCustomName(String name) {
+ customName = name;
+ }
+
+ public boolean isMachineShutdown() {
+ return machine != null && machine.shouldDisplayShutDownReason()
+ && !machine.getBaseMetaTileEntity()
+ .isActive()
+ && GT_Utility.isStringValid(
+ machine.getBaseMetaTileEntity()
+ .getLastShutDownReason()
+ .getDisplayString())
+ && machine.getBaseMetaTileEntity()
+ .wasShutdown();
+ }
+
+ public NBTTagCompound transConnectionToNBT() {
+ NBTTagCompound aNBT = new NBTTagCompound();
+ aNBT.setTag("machine", transCoordsToNBT(machineCoord));
+ aNBT.setTag("centre", transCoordsToNBT(centreCoord));
+ aNBT.setTag("item", machineItem.writeToNBT(new NBTTagCompound()));
+ aNBT.setInteger(
+ "worldID",
+ centre.getBaseMetaTileEntity()
+ .getWorld().provider.dimensionId);
+ aNBT.setString("name", getCustomName(false));
+ aNBT.setString("unlocalizedName", unlocalizedName);
+ return aNBT;
+ }
+
+ public GT_MetaTileEntity_MultiBlockBase getLoadedGT_BaseMachineAt(ChunkCoordinates coords, World world,
+ boolean isLoaded) {
+ TileEntity te = GT_Util.getTileEntity(world, coords, isLoaded);
+ if (te == null) return null;
+ return (GT_MetaTileEntity_MultiBlockBase) ((IGregTechTileEntity) te).getMetaTileEntity();
+ }
+
+ private NBTTagCompound transCoordsToNBT(ChunkCoordinates coord) {
+ NBTTagCompound tag = new NBTTagCompound();
+ tag.setInteger("x", coord.posX);
+ tag.setInteger("y", coord.posY);
+ tag.setInteger("z", coord.posZ);
+ return tag;
+ }
+
+ public boolean isValid() {
+ return machine != null && machine.isValid() && centre != null && centre.isValid();
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/drone/GT_MetaTileEntity_DroneCentre.java b/src/main/java/gregtech/common/tileentities/machines/multi/drone/GT_MetaTileEntity_DroneCentre.java
new file mode 100644
index 0000000000..2bb224cdb7
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/drone/GT_MetaTileEntity_DroneCentre.java
@@ -0,0 +1,912 @@
+package gregtech.common.tileentities.machines.multi.drone;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.onElementPass;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.transpose;
+import static gregtech.api.enums.GT_HatchElement.InputBus;
+import static gregtech.api.enums.GT_Values.AuthorSilverMoon;
+import static gregtech.api.multitileentity.multiblock.casing.Glasses.chainAllGlasses;
+import static gregtech.api.objects.XSTR.XSTR_INSTANCE;
+import static gregtech.api.util.GT_StructureUtility.buildHatchAdder;
+
+import java.io.IOException;
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.entity.item.EntityItem;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.network.PacketBuffer;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.ChatComponentTranslation;
+import net.minecraft.util.ChunkCoordinates;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.StatCollector;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.google.common.collect.HashMultimap;
+import com.gtnewhorizon.structurelib.alignment.IAlignmentLimits;
+import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
+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.drawable.IDrawable;
+import com.gtnewhorizons.modularui.api.drawable.UITexture;
+import com.gtnewhorizons.modularui.api.forge.ItemStackHandler;
+import com.gtnewhorizons.modularui.api.math.Alignment;
+import com.gtnewhorizons.modularui.api.math.Color;
+import com.gtnewhorizons.modularui.api.math.MainAxisAlignment;
+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.DrawableWidget;
+import com.gtnewhorizons.modularui.common.widget.DynamicPositionedRow;
+import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget;
+import com.gtnewhorizons.modularui.common.widget.Scrollable;
+import com.gtnewhorizons.modularui.common.widget.SlotWidget;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+import com.gtnewhorizons.modularui.common.widget.textfield.TextFieldWidget;
+
+import appeng.api.util.DimensionalCoord;
+import appeng.api.util.WorldCoord;
+import appeng.client.render.BlockPosHighlighter;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.SoundResource;
+import gregtech.api.enums.Textures;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_ExtendedPowerMultiBlockBase;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_MultiBlockBase;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.SimpleCheckRecipeResult;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Log;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.shutdown.ShutDownReason;
+import gregtech.api.util.shutdown.ShutDownReasonRegistry;
+import gregtech.common.gui.modularui.widget.ShutDownReasonSyncer;
+import gregtech.common.items.GT_TierDrone;
+import mcp.mobius.waila.api.IWailaConfigHandler;
+import mcp.mobius.waila.api.IWailaDataAccessor;
+
+public class GT_MetaTileEntity_DroneCentre extends
+ GT_MetaTileEntity_ExtendedPowerMultiBlockBase<GT_MetaTileEntity_DroneCentre> implements ISurvivalConstructable {
+
+ private static final IIconContainer ACTIVE = new Textures.BlockIcons.CustomIcon("iconsets/DRONE_CENTRE_ACTIVE");
+ private static final IIconContainer FACE = new Textures.BlockIcons.CustomIcon("iconsets/DRONE_CENTRE_FACE");
+ private static final IIconContainer INACTIVE = new Textures.BlockIcons.CustomIcon("iconsets/DRONE_CENTRE_INACTIVE");
+ private final int MACHINE_LIST_WINDOW_ID = 10;
+ private final int CUSTOM_NAME_WINDOW_ID = 11;
+ private static final int CASINGS_MIN = 85;
+ private int mCasingAmount = 0;
+ private Vec3Impl centreCoord;
+ private int droneLevel = 0;
+ private int buttonID;
+ private String searchFilter = "";
+ private boolean useRender = true;
+ private boolean showLocalizedName = false;
+ private String sort = "distance";
+ private List<DroneConnection> connectionList = new ArrayList<>();
+ public HashMap<String, String> tempNameList = new HashMap<>();
+ // Save centre by dimID
+ private static final HashMultimap<Integer, GT_MetaTileEntity_DroneCentre> droneMap = HashMultimap.create();
+ // spotless off
+ private static final IStructureDefinition<GT_MetaTileEntity_DroneCentre> STRUCTURE_DEFINITION = StructureDefinition
+ .<GT_MetaTileEntity_DroneCentre>builder()
+ .addShape(
+ "main",
+ transpose(
+ new String[][] { { " ", " ", " ", " ", "CCCCC", "CCCCC", "CCCCC", "CCCCC", "CCCCC" },
+ { "CC~CC", "C C", "C C", "C C", "CAAAC", "CCCCC", "CAAAC", "C C", "CCCCC" },
+ { "CCCCC", "CBBBC", "CBDBC", "CBBBC", "CCCCC", "CCCCC", "CCCCC", "CCCCC", "CCCCC" },
+ { "C C", " ", " ", " ", " ", " ", " ", " ", "C C" } }))
+ .addElement(
+ 'C',
+ buildHatchAdder(GT_MetaTileEntity_DroneCentre.class).atLeast(InputBus)
+ .casingIndex(59)
+ .dot(1)
+ .buildAndChain(
+ onElementPass(
+ GT_MetaTileEntity_DroneCentre::onCasingAdded,
+ ofBlock(GregTech_API.sBlockCasings4, 2))))
+ .addElement('A', chainAllGlasses())
+ .addElement('B', ofBlock(GregTech_API.sBlockCasings1, 11))
+ .addElement('D', ofBlock(GregTech_API.sBlockCasings4, 0))
+ .build();
+
+ // spotless on
+ public GT_MetaTileEntity_DroneCentre(String name) {
+ super(name);
+ }
+
+ public GT_MetaTileEntity_DroneCentre(int ID, String Name, String NameRegional) {
+ super(ID, Name, NameRegional);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_DroneCentre(super.mName);
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection aFacing,
+ int colorIndex, boolean aActive, boolean redstoneLevel) {
+ if (side == aFacing) {
+ if (getBaseMetaTileEntity().isActive()) {
+ return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(59), TextureFactory.builder()
+ .addIcon(ACTIVE)
+ .extFacing()
+ .build() };
+ } else {
+ return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(59), TextureFactory.builder()
+ .addIcon(INACTIVE)
+ .extFacing()
+ .build() };
+ }
+ } else if (side == aFacing.getOpposite()) {
+ return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(59), TextureFactory.builder()
+ .addIcon(FACE)
+ .extFacing()
+ .build() };
+ }
+ return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(59) };
+ }
+
+ @Override
+ public IStructureDefinition<GT_MetaTileEntity_DroneCentre> getStructureDefinition() {
+ return STRUCTURE_DEFINITION;
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Drone Centre")
+ .addInfo("Drone Center Controller")
+ .addInfo(EnumChatFormatting.AQUA + "Drone #10032, cleared for takeoff!")
+ .addInfo("Monitors multiblock machines in range.")
+ .addInfo("Replace maintenance hatch on other multi with drone downlink module.")
+ .addInfo("Provides maintenance, power control, monitoring and etc.")
+ .addInfo("Range is determined by drone tier: T1-128, T2-512, T3-4096")
+ .addInfo("Place drones in input bus; only one needed to operate.")
+ .addInfo("Automatically upgrade based on the drone level in the input bus.")
+ .addInfo("There is a chance per second that the drone will crash.")
+ .addInfo("Chance is determined by drone tier: T1-1/28800, T2-1/172800, T3-0")
+ .addInfo("If machine is too far, remote control would not available")
+ .addInfo(AuthorSilverMoon)
+ .addSeparator()
+ .beginStructureBlock(5, 4, 9, false)
+ .addController("Front center")
+ .addCasingInfoRange("Stable Titanium Machine Casing", CASINGS_MIN, 91, false)
+ .addCasingInfoExactly("Heat Proof Machine Casing", 8, false)
+ .addCasingInfoExactly("Robust Tungstensteel Machine Casing", 1, false)
+ .addCasingInfoExactly("Any tiered glass", 6, false)
+ .addInputBus("Any Titanium Casing", 1)
+ .addStructureInfo("No maintenance hatch needed")
+ .addSeparator()
+ .toolTipFinisher("Gregtech");
+ return tt;
+ }
+
+ @Override
+ public void construct(ItemStack stackSize, boolean hintsOnly) {
+ buildPiece("main", stackSize, hintsOnly, 2, 1, 0);
+ }
+
+ @Override
+ public int survivalConstruct(ItemStack stack, int elementBudget, ISurvivalBuildEnvironment env) {
+ if (mMachine) return -1;
+ return survivialBuildPiece("main", stack, 2, 1, 0, elementBudget, env, false, true);
+ }
+
+ @Override
+ protected IAlignmentLimits getInitialAlignmentLimits() {
+ // I don't think a drone can take off HORIZONTALLY!
+ return (d, r, f) -> (d.flag & (ForgeDirection.UP.flag | ForgeDirection.DOWN.flag)) == 0 && r.isNotRotated()
+ && !f.isVerticallyFliped();
+ }
+
+ @Override
+ public boolean isCorrectMachinePart(ItemStack aStack) {
+ return true;
+ }
+
+ private void onCasingAdded() {
+ mCasingAmount++;
+ }
+
+ @Override
+ public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+ mCasingAmount = 0;
+ return checkPiece("main", 2, 1, 0) && mCasingAmount >= CASINGS_MIN;
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack aStack) {
+ return 10000;
+ }
+
+ @Override
+ public final void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ super.onScrewdriverRightClick(side, aPlayer, aX, aY, aZ);
+ useRender = !useRender;
+ aPlayer.addChatComponentMessage(
+ new ChatComponentTranslation(
+ "GT5U.machines.dronecentre." + (useRender ? "enableRender" : "disableRender")));
+ if (useRender) {
+ createRenderBlock();
+ } else {
+ destroyRenderBlock();
+ }
+ }
+
+ @Override
+ public int getDamageToComponent(ItemStack aStack) {
+ return 0;
+ }
+
+ @Override
+ public boolean explodesOnComponentBreak(ItemStack aStack) {
+ return true;
+ }
+
+ @Override
+ public void stopMachine(@NotNull ShutDownReason reason) {
+ destroyRenderBlock();
+ super.stopMachine(reason);
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ if (aBaseMetaTileEntity.isServerSide()) {
+ fixAll();
+ if (aTick % 20 == 0) {
+ if (switch (droneLevel) {
+ case 1 -> getBaseMetaTileEntity().getRandomNumber(28800);
+ case 2 -> getBaseMetaTileEntity().getRandomNumber(172800);
+ default -> 1;
+ } == 0) {
+ droneLevel = 0;
+ startRecipeProcessing();
+ if (!tryConsumeDrone()) stopMachine(ShutDownReasonRegistry.outOfStuff("Any Drone", 1));
+ endRecipeProcessing();
+ }
+ }
+ // Clean invalid connections every 4 seconds
+ if (aTick % 80 == 0) connectionList.removeIf(v -> !v.isValid());
+ }
+ if (mMaxProgresstime > 0 && mMaxProgresstime - mProgresstime == 1) destroyRenderBlock();
+ super.onPostTick(aBaseMetaTileEntity, aTick);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ droneLevel = aNBT.getInteger("drone");
+ useRender = aNBT.getBoolean("useRender");
+ sort = aNBT.getString("sort");
+ NBTTagCompound nameList = aNBT.getCompoundTag("conList");
+ for (String s : nameList.func_150296_c()) {
+ tempNameList.put(s, nameList.getString(s));
+ }
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ aNBT.setInteger("drone", droneLevel);
+ aNBT.setBoolean("useRender", useRender);
+ aNBT.setString("sort", sort);
+ NBTTagCompound conList = new NBTTagCompound();
+ for (DroneConnection con : connectionList) {
+ if (!con.customName.equals(con.machine.getLocalName()))
+ conList.setString(con.machineCoord.toString(), con.customName);
+ }
+ aNBT.setTag("conList", conList);
+ }
+
+ @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("connectionCount", connectionList.size());
+ if (droneLevel != 0) tag.setInteger("droneLevel", droneLevel);
+ }
+
+ @Override
+ public void getWailaBody(ItemStack itemStack, List<String> currenttip, IWailaDataAccessor accessor,
+ IWailaConfigHandler config) {
+ NBTTagCompound tag = accessor.getNBTData();
+ currenttip.add(
+ EnumChatFormatting.AQUA + StatCollector.translateToLocal("GT5U.waila.drone_downlink.droneLevel")
+ + tag.getInteger("droneLevel"));
+ currenttip.add(
+ StatCollector.translateToLocal("GT5U.waila.drone_downlink.connectionCount")
+ + tag.getInteger("connectionCount"));
+ super.getWailaBody(itemStack, currenttip, accessor, config);
+ }
+
+ @Override
+ @NotNull
+ public CheckRecipeResult checkProcessing() {
+ if (droneLevel == 0) {
+ if (!tryConsumeDrone()) return SimpleCheckRecipeResult.ofFailure("drone_noDrone");
+ }
+ if (droneLevel == 1 || droneLevel == 2) tryUpdateDrone();
+ mMaxProgresstime = 200 * droneLevel;
+ createRenderBlock();
+ return SimpleCheckRecipeResult.ofSuccess("drone_operating");
+ }
+
+ @Override
+ public void onFirstTick(IGregTechTileEntity aBaseMetaTileEntity) {
+ super.onFirstTick(aBaseMetaTileEntity);
+ if (aBaseMetaTileEntity.isServerSide()) {
+ if (droneMap.containsValue(this)) return;
+ centreCoord = new Vec3Impl(
+ getBaseMetaTileEntity().getXCoord(),
+ getBaseMetaTileEntity().getYCoord(),
+ getBaseMetaTileEntity().getZCoord());
+ droneMap.put(getBaseMetaTileEntity().getWorld().provider.dimensionId, this);
+ }
+ }
+
+ @Override
+ public void onBlockDestroyed() {
+ destroyRenderBlock();
+ connectionList.clear();
+ if (droneLevel != 0) spawnDroneItem();
+ super.onBlockDestroyed();
+ }
+
+ private void spawnDroneItem() {
+ ItemStack insideDrone = new ItemStack(switch (droneLevel) {
+ case 1:
+ yield ItemList.TierdDrone0.getItem();
+ case 2:
+ yield ItemList.TierdDrone1.getItem();
+ case 3:
+ yield ItemList.TierdDrone2.getItem();
+ default:
+ yield null;
+ }, 1);
+ final EntityItem tItemEntity = new EntityItem(
+ getBaseMetaTileEntity().getWorld(),
+ getBaseMetaTileEntity().getXCoord() + XSTR_INSTANCE.nextFloat() * 0.8F + 0.1F,
+ getBaseMetaTileEntity().getYCoord() + XSTR_INSTANCE.nextFloat() * 0.8F + 0.1F,
+ getBaseMetaTileEntity().getZCoord() + XSTR_INSTANCE.nextFloat() * 0.8F + 0.1F,
+ insideDrone);
+ tItemEntity.motionX = (XSTR_INSTANCE.nextGaussian() * 0.05D);
+ tItemEntity.motionY = (XSTR_INSTANCE.nextGaussian() * 0.25D);
+ tItemEntity.motionZ = (XSTR_INSTANCE.nextGaussian() * 0.05D);
+ getBaseMetaTileEntity().getWorld()
+ .spawnEntityInWorld(tItemEntity);
+ }
+
+ @Override
+ public void onRemoval() {
+ droneMap.remove(getBaseMetaTileEntity().getWorld().provider.dimensionId, this);
+ }
+
+ public List<DroneConnection> getConnectionList() {
+ return connectionList;
+ }
+
+ public int getRange() {
+ return switch (droneLevel) {
+ case 1 -> 128;
+ case 2 -> 512;
+ case 3 -> 4096;
+ default -> 0;
+ };
+ }
+
+ public Vec3Impl getCoords() {
+ return centreCoord;
+ }
+
+ private boolean tryConsumeDrone() {
+ List<ItemStack> inputs = getStoredInputs();
+ if (inputs.isEmpty()) return false;
+ for (ItemStack item : inputs) {
+ if (item != null && item.getItem() instanceof GT_TierDrone drone) {
+ this.droneLevel = drone.getLevel();
+ item.stackSize--;
+ updateSlots();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void tryUpdateDrone() {
+ List<ItemStack> inputs = getStoredInputs();
+ if (inputs.isEmpty()) return;
+ for (ItemStack item : inputs) {
+ if (item != null && item.getItem() instanceof GT_TierDrone drone) {
+ if (drone.getLevel() <= this.droneLevel) continue;
+ this.droneLevel = drone.getLevel();
+ item.stackSize--;
+ updateSlots();
+ return;
+ }
+ }
+ }
+
+ private void createRenderBlock() {
+ if (!useRender) return;
+ int x = getBaseMetaTileEntity().getXCoord();
+ int y = getBaseMetaTileEntity().getYCoord();
+ int z = getBaseMetaTileEntity().getZCoord();
+
+ double xOffset = 2 * getExtendedFacing().getRelativeBackInWorld().offsetX;
+ double zOffset = 2 * getExtendedFacing().getRelativeBackInWorld().offsetZ;
+ double yOffset = 2 * getExtendedFacing().getRelativeBackInWorld().offsetY;
+
+ this.getBaseMetaTileEntity()
+ .getWorld()
+ .setBlock((int) (x + xOffset), (int) (y + yOffset), (int) (z + zOffset), Blocks.air);
+ this.getBaseMetaTileEntity()
+ .getWorld()
+ .setBlock((int) (x + xOffset), (int) (y + yOffset), (int) (z + zOffset), GregTech_API.sDroneRender);
+ }
+
+ private void destroyRenderBlock() {
+ int x = getBaseMetaTileEntity().getXCoord();
+ int y = getBaseMetaTileEntity().getYCoord();
+ int z = getBaseMetaTileEntity().getZCoord();
+
+ double xOffset = 2 * getExtendedFacing().getRelativeBackInWorld().offsetX;
+ double zOffset = 2 * getExtendedFacing().getRelativeBackInWorld().offsetZ;
+ double yOffset = 2 * getExtendedFacing().getRelativeBackInWorld().offsetY;
+
+ this.getBaseMetaTileEntity()
+ .getWorld()
+ .setBlock((int) (x + xOffset), (int) (y + yOffset), (int) (z + zOffset), Blocks.air);
+ }
+
+ private void fixAll() {
+ this.mWrench = this.mScrewdriver = this.mSoftHammer = this.mHardHammer = this.mCrowbar = this.mSolderingTool = true;
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ super.addUIWidgets(builder, buildContext);
+ buildContext.addSyncedWindow(MACHINE_LIST_WINDOW_ID, this::createMachineListWindow);
+ buildContext.addSyncedWindow(CUSTOM_NAME_WINDOW_ID, this::createCustomNameWindow);
+ builder.widget(// Machine List
+ new ButtonWidget().setOnClick(
+ (clickData, widget) -> {
+ if (!widget.isClient()) widget.getContext()
+ .openSyncedWindow(MACHINE_LIST_WINDOW_ID);
+ })
+ .setSize(16, 16)
+ .setBackground(() -> {
+ List<UITexture> UI = new ArrayList<>();
+ UI.add(GT_UITextures.BUTTON_STANDARD);
+ UI.add(GT_UITextures.OVERLAY_BUTTON_WHITELIST);
+ return UI.toArray(new IDrawable[0]);
+ })
+ .addTooltip(StatCollector.translateToLocal("GT5U.gui.button.drone_open_list"))
+ .setPos(94, 91)
+ .setEnabled(var -> getBaseMetaTileEntity().isActive()))
+ .widget(// Turn on ALL machines
+ new ButtonWidget().setOnClick((clickData, widget) -> {
+ if (!widget.isClient()) {
+ if (!getBaseMetaTileEntity().isActive()) {
+ widget.getContext()
+ .getPlayer()
+ .addChatComponentMessage(
+ new ChatComponentTranslation("GT5U.machines.dronecentre.shutdown"));
+ return;
+ }
+ for (DroneConnection mte : connectionList) {
+ mte.machine.getBaseMetaTileEntity()
+ .enableWorking();
+ }
+ widget.getContext()
+ .getPlayer()
+ .addChatComponentMessage(new ChatComponentTranslation("GT5U.machines.dronecentre.turnon"));
+ widget.getContext()
+ .getPlayer()
+ .closeScreen();
+ }
+ })
+ .setSize(16, 16)
+ .setBackground(() -> {
+ List<UITexture> UI = new ArrayList<>();
+ UI.add(GT_UITextures.BUTTON_STANDARD);
+ UI.add(GT_UITextures.OVERLAY_BUTTON_POWER_SWITCH_ON);
+ return UI.toArray(new IDrawable[0]);
+ })
+ .addTooltip(StatCollector.translateToLocal("GT5U.gui.button.drone_poweron_all"))
+ .setPos(146, 91)
+ .setEnabled(var -> getBaseMetaTileEntity().isActive()))
+ .widget(// Turn off ALL machines
+ new ButtonWidget().setOnClick((clickData, widget) -> {
+ if (!widget.isClient()) {
+ if (!getBaseMetaTileEntity().isActive()) {
+ widget.getContext()
+ .getPlayer()
+ .addChatComponentMessage(
+ new ChatComponentTranslation("GT5U.machines.dronecentre.shutdown"));
+ return;
+ }
+ for (DroneConnection mte : connectionList) {
+ mte.machine.getBaseMetaTileEntity()
+ .disableWorking();
+ }
+ widget.getContext()
+ .getPlayer()
+ .addChatComponentMessage(new ChatComponentTranslation("GT5U.machines.dronecentre.turnoff"));
+ widget.getContext()
+ .getPlayer()
+ .closeScreen();
+ }
+ })
+ .setSize(16, 16)
+ .setBackground(() -> {
+ List<UITexture> UI = new ArrayList<>();
+ UI.add(GT_UITextures.BUTTON_STANDARD);
+ UI.add(GT_UITextures.OVERLAY_BUTTON_POWER_SWITCH_OFF);
+ return UI.toArray(new IDrawable[0]);
+ })
+ .addTooltip(StatCollector.translateToLocal("GT5U.gui.button.drone_poweroff_all"))
+ .setPos(120, 91)
+ .setEnabled(var -> getBaseMetaTileEntity().isActive()))
+ .widget(new FakeSyncWidget.ListSyncer<>(() -> connectionList, var1 -> {
+ connectionList.clear();
+ connectionList.addAll(var1);
+ }, (buffer, j) -> {
+ try {
+ buffer.writeNBTTagCompoundToBuffer(j.transConnectionToNBT());
+ } catch (IOException e) {
+ GT_Log.err.println(e.getCause());
+ }
+ }, buffer -> {
+ try {
+ return new DroneConnection(buffer.readNBTTagCompoundFromBuffer());
+ } catch (IOException e) {
+ GT_Log.err.println(e.getCause());
+ }
+ return null;
+ }));
+ }
+
+ protected ModularWindow createMachineListWindow(final EntityPlayer player) {
+ int heightCoff = getBaseMetaTileEntity().isServerSide() ? 0
+ : Minecraft.getMinecraft().currentScreen.height - 40;
+ ModularWindow.Builder builder = ModularWindow.builder(260, heightCoff);
+ builder.setBackground(GT_UITextures.BACKGROUND_SINGLEBLOCK_DEFAULT);
+ builder.setGuiTint(getGUIColorization());
+ builder.widget(
+ ButtonWidget.closeWindowButton(true)
+ .setPos(245, 3));
+ builder.widget(
+ new TextWidget(EnumChatFormatting.BOLD + StatCollector.translateToLocal("GT5U.gui.text.drone_title"))
+ .setScale(2)
+ .setTextAlignment(Alignment.Center)
+ .setPos(0, 10)
+ .setSize(260, 8));
+ // SearchBar
+ builder.widget(new TextFieldWidget() {
+
+ @Override
+ public void onRemoveFocus() {
+ super.onRemoveFocus();
+ syncToServer(2, buffer -> {});
+ }
+
+ // Refresh
+ @Override
+ public void readOnServer(int id, PacketBuffer buf) {
+ switch (id) {
+ case 1 -> super.readOnServer(id, buf);
+ case 2 -> {
+ getContext().closeWindow(MACHINE_LIST_WINDOW_ID);
+ getContext().openSyncedWindow(MACHINE_LIST_WINDOW_ID);
+ }
+ }
+ }
+ }.setGetter(() -> searchFilter)
+ .setSetter(var -> searchFilter = var)
+ .setTextAlignment(Alignment.CenterLeft)
+ .setTextColor(Color.WHITE.dark(1))
+ .setFocusOnGuiOpen(false)
+ .setBackground(GT_UITextures.BACKGROUND_TEXT_FIELD_LIGHT_GRAY.withOffset(-1, -1, 2, 2))
+ .addTooltip(StatCollector.translateToLocal("GT5U.gui.text.drone_search"))
+ .setPos(50, 30)
+ .setSize(200, 16))
+ // Sort button
+ .widget(new ButtonWidget() {
+
+ @Override
+ public ClickResult onClick(int buttonId, boolean doubleClick) {
+ ClickResult result = super.onClick(buttonId, doubleClick);
+ syncToServer(2, buffer -> {});
+ return result;
+ }
+
+ @Override
+ public void readOnServer(int id, PacketBuffer buf) {
+ switch (id) {
+ case 1 -> super.readOnServer(id, buf);
+ case 2 -> {
+ getContext().closeWindow(MACHINE_LIST_WINDOW_ID);
+ getContext().openSyncedWindow(MACHINE_LIST_WINDOW_ID);
+ }
+ }
+ }
+ }.setOnClick((clickData, widget) -> {
+ switch (sort) {
+ case "name" -> sort = "distance";
+ case "distance" -> sort = "error";
+ case "error" -> sort = "name";
+ }
+ })
+ .addTooltip(StatCollector.translateToLocal("GT5U.gui.button.drone_" + sort))
+ .setBackground(
+ () -> new IDrawable[] { GT_UITextures.BUTTON_STANDARD, GT_UITextures.OVERLAY_BUTTON_SORTING_MODE })
+ .setPos(10, 30)
+ .setSize(16, 16))
+ .widget(new FakeSyncWidget.StringSyncer(() -> sort, var1 -> sort = var1))
+ // Localized Button
+ .widget(new ButtonWidget() {
+
+ @Override
+ public ClickResult onClick(int buttonId, boolean doubleClick) {
+ ClickResult result = super.onClick(buttonId, doubleClick);
+ syncToServer(2, buffer -> {});
+ return result;
+ }
+
+ @Override
+ public void readOnServer(int id, PacketBuffer buf) {
+ switch (id) {
+ case 1 -> super.readOnServer(id, buf);
+ case 2 -> {
+ getContext().closeWindow(MACHINE_LIST_WINDOW_ID);
+ getContext().openSyncedWindow(MACHINE_LIST_WINDOW_ID);
+ }
+ }
+ }
+ }.setOnClick((clickData, widget) -> showLocalizedName = !showLocalizedName)
+ .addTooltip(StatCollector.translateToLocal("GT5U.gui.button.drone_showLocalName"))
+ .setBackground(
+ () -> new IDrawable[] {
+ showLocalizedName ? GT_UITextures.BUTTON_STANDARD_PRESSED : GT_UITextures.BUTTON_STANDARD,
+ GT_UITextures.OVERLAY_BUTTON_CYCLIC })
+ .setPos(30, 30)
+ .setSize(16, 16));
+ // Sort first
+ switch (sort) {
+ case "name" -> connectionList = connectionList.stream()
+ .sorted(
+ (o1, o2) -> Collator.getInstance(Locale.UK)
+ .compare(o1.getCustomName(false), o2.getCustomName(false)))
+ .collect(Collectors.toList());
+ case "distance" -> connectionList = connectionList.stream()
+ .sorted(Comparator.comparing(DroneConnection::getDistanceSquared))
+ .collect(Collectors.toList());
+ case "error" -> connectionList = connectionList.stream()
+ .sorted(
+ Comparator.comparing(DroneConnection::isMachineShutdown)
+ .reversed()
+ .thenComparing(DroneConnection::getDistanceSquared))
+ .collect(Collectors.toList());
+ }
+
+ Scrollable MachineContainer = new Scrollable().setVerticalScroll();
+ int posY = 0;
+ for (int i = 0; i < connectionList.size(); i++) {
+ DroneConnection connection = connectionList.get(i);
+ if (!connection.customName.toLowerCase()
+ .contains(searchFilter.toLowerCase())) continue;
+ ItemStackHandler drawitem = new ItemStackHandler(1);
+ drawitem.setStackInSlot(0, connection.machineItem);
+ DynamicPositionedRow row = new DynamicPositionedRow().setSynced(false);
+ GT_MetaTileEntity_MultiBlockBase coreMachine = connection.machine;
+ int finalI = i;
+ row.widget(
+ SlotWidget.phantom(drawitem, 0)
+ .disableInteraction()
+ .setPos(0, 0))
+ .widget(new ButtonWidget().setOnClick((clickData, widget) -> {
+ buttonID = finalI;
+ if (!widget.isClient()) widget.getContext()
+ .openSyncedWindow(CUSTOM_NAME_WINDOW_ID);
+ })
+ .addTooltip(StatCollector.translateToLocal("GT5U.gui.button.drone_setname"))
+ .setBackground(
+ () -> new IDrawable[] { GT_UITextures.BUTTON_STANDARD, GT_UITextures.OVERLAY_BUTTON_PRINT })
+ .setSize(16, 16));
+ // Client can't handle unloaded machines
+ row.widget(
+ new ButtonWidget().setOnClick(
+ (clickData, widget) -> Optional.ofNullable(coreMachine)
+ .ifPresent(machine -> {
+ if (!getBaseMetaTileEntity().isActive()) {
+ player.addChatComponentMessage(
+ new ChatComponentTranslation("GT5U.machines.dronecentre.shutdown"));
+ return;
+ }
+ if (machine.isAllowedToWork()) {
+ machine.disableWorking();
+ } else {
+ machine.enableWorking();
+ }
+ }))
+ .setPlayClickSoundResource(
+ () -> Optional.ofNullable(coreMachine)
+ .filter(GT_MetaTileEntity_MultiBlockBase::isAllowedToWork)
+ .map(var -> SoundResource.GUI_BUTTON_UP.resourceLocation)
+ .orElse(SoundResource.GUI_BUTTON_DOWN.resourceLocation))
+ .setBackground(
+ () -> Optional.ofNullable(coreMachine)
+ .map(
+ machine -> machine.isAllowedToWork()
+ ? new IDrawable[] { GT_UITextures.BUTTON_STANDARD_PRESSED,
+ GT_UITextures.OVERLAY_BUTTON_POWER_SWITCH_ON }
+ : new IDrawable[] { GT_UITextures.BUTTON_STANDARD,
+ GT_UITextures.OVERLAY_BUTTON_POWER_SWITCH_OFF })
+ .orElse(new IDrawable[] { GT_UITextures.OVERLAY_BUTTON_CROSS }))
+ .attachSyncer(
+ new FakeSyncWidget.BooleanSyncer(
+ () -> Optional.ofNullable(coreMachine)
+ .map(GT_MetaTileEntity_MultiBlockBase::isAllowedToWork)
+ .orElse(false),
+ var -> Optional.ofNullable(coreMachine)
+ .ifPresent(machine -> {
+ if (var) machine.enableWorking();
+ else machine.disableWorking();
+ })),
+ builder)
+ .addTooltip(
+ coreMachine != null ? StatCollector.translateToLocal("GT5U.gui.button.power_switch")
+ : StatCollector.translateToLocal("GT5U.gui.button.drone_outofrange"))
+ .setSize(16, 16))
+ .widget(new ButtonWidget().setOnClick((clickData, widget) -> {
+ if (widget.isClient()) {
+ highlightMachine(player, connection.machineCoord);
+ player.closeScreen();
+ }
+ })
+ .addTooltip(StatCollector.translateToLocal("GT5U.gui.button.drone_highlight"))
+ .setBackground(
+ new IDrawable[] { GT_UITextures.BUTTON_STANDARD, GT_UITextures.OVERLAY_BUTTON_INVERT_REDSTONE })
+ .setSize(16, 16));
+ // Show the reason why the machine shutdown
+ row.widget(
+ new DrawableWidget().dynamicTooltip(
+ () -> Collections.singletonList(
+ Optional.ofNullable(coreMachine)
+ .map(
+ machine -> machine.getBaseMetaTileEntity()
+ .getLastShutDownReason()
+ .getDisplayString())
+ .orElse("")))
+ .setBackground(GT_UITextures.PICTURE_STALLED_ELECTRICITY)
+ .setSize(16, 16)
+ .setEnabled(
+ var -> coreMachine != null && coreMachine.shouldDisplayShutDownReason()
+ && !coreMachine.getBaseMetaTileEntity()
+ .isActive()
+ && GT_Utility.isStringValid(
+ coreMachine.getBaseMetaTileEntity()
+ .getLastShutDownReason()
+ .getDisplayString())
+ && coreMachine.getBaseMetaTileEntity()
+ .wasShutdown())
+ .attachSyncer(
+ new ShutDownReasonSyncer(
+ () -> Optional.ofNullable(coreMachine)
+ .map(
+ var -> coreMachine.getBaseMetaTileEntity()
+ .getLastShutDownReason())
+ .orElse(ShutDownReasonRegistry.NONE),
+ reason -> Optional.ofNullable(coreMachine)
+ .ifPresent(
+ machine -> coreMachine.getBaseMetaTileEntity()
+ .setShutDownReason(reason))),
+ builder)
+ .attachSyncer(
+ new FakeSyncWidget.BooleanSyncer(
+ () -> Optional.ofNullable(coreMachine)
+ .map(
+ var -> coreMachine.getBaseMetaTileEntity()
+ .wasShutdown())
+ .orElse(false),
+ wasShutDown -> Optional.ofNullable(coreMachine)
+ .ifPresent(
+ machine -> coreMachine.getBaseMetaTileEntity()
+ .setShutdownStatus(wasShutDown))),
+ builder));
+ row.widget(
+ new TextWidget(
+ connectionList.get(i)
+ .getCustomName(showLocalizedName)).setTextAlignment(Alignment.CenterLeft)
+ .setPos(0, 4));
+ MachineContainer.widget(
+ row.setAlignment(MainAxisAlignment.SPACE_BETWEEN)
+ .setSpace(4)
+ .setPos(0, posY));
+ posY += 20;
+ }
+ return builder.widget(
+ MachineContainer.setPos(10, 50)
+ .setSize(240, heightCoff - 60))
+ .setDraggable(false)
+ .build();
+ }
+
+ protected ModularWindow createCustomNameWindow(final EntityPlayer player) {
+ ModularWindow.Builder builder = ModularWindow.builder(150, 40);
+ builder.setBackground(GT_UITextures.BACKGROUND_SINGLEBLOCK_DEFAULT);
+ builder.setGuiTint(getGUIColorization());
+ return builder.widget(
+ ButtonWidget.closeWindowButton(true)
+ .setPos(135, 3))
+ .widget(
+ new TextWidget(StatCollector.translateToLocal("GT5U.gui.text.drone_custom_name"))
+ .setTextAlignment(Alignment.Center)
+ .setPos(0, 5)
+ .setSize(150, 8))
+ .widget(new TextFieldWidget() {
+
+ @Override
+ public void onDestroy() {
+ if (isClient()) return;
+ getContext().closeWindow(MACHINE_LIST_WINDOW_ID);
+ getContext().openSyncedWindow(MACHINE_LIST_WINDOW_ID);
+ }
+ }.setGetter(
+ () -> connectionList.get(buttonID)
+ .getCustomName(false))
+ .setSetter(
+ var -> connectionList.get(buttonID)
+ .setCustomName(var))
+ .setTextAlignment(Alignment.CenterLeft)
+ .setTextColor(Color.WHITE.dark(1))
+ .setFocusOnGuiOpen(true)
+ .setBackground(GT_UITextures.BACKGROUND_TEXT_FIELD_LIGHT_GRAY.withOffset(-1, -1, 2, 2))
+ .setPos(10, 16)
+ .setSize(130, 16))
+ .build();
+ }
+
+ // Just like HIGHLIGHT_INTERFACE (and exactly from it)
+ private void highlightMachine(EntityPlayer player, ChunkCoordinates machineCoord) {
+ DimensionalCoord blockPos = new DimensionalCoord(
+ machineCoord.posX,
+ machineCoord.posY,
+ machineCoord.posZ,
+ player.dimension);
+ WorldCoord blockPos2 = new WorldCoord((int) player.posX, (int) player.posY, (int) player.posZ);
+ BlockPosHighlighter.highlightBlock(
+ blockPos,
+ System.currentTimeMillis() + 500 * WorldCoord.getTaxicabDistance(blockPos, blockPos2));
+ }
+
+ public static HashMultimap<Integer, GT_MetaTileEntity_DroneCentre> getCentreMap() {
+ return droneMap;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/drone/GT_MetaTileEntity_Hatch_DroneDownLink.java b/src/main/java/gregtech/common/tileentities/machines/multi/drone/GT_MetaTileEntity_Hatch_DroneDownLink.java
new file mode 100644
index 0000000000..959b6874ba
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/drone/GT_MetaTileEntity_Hatch_DroneDownLink.java
@@ -0,0 +1,340 @@
+package gregtech.common.tileentities.machines.multi.drone;
+
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import net.minecraft.block.Block;
+import net.minecraft.client.renderer.texture.IIconRegister;
+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.ChatComponentTranslation;
+import net.minecraft.util.ChunkCoordinates;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.StatCollector;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.FakePlayer;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.gtnewhorizon.structurelib.util.Vec3Impl;
+import com.gtnewhorizons.modularui.api.math.Alignment;
+import com.gtnewhorizons.modularui.api.math.Color;
+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.TextWidget;
+import com.gtnewhorizons.modularui.common.widget.textfield.TextFieldWidget;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.Textures;
+import gregtech.api.gui.modularui.GT_UIInfos;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.interfaces.tileentity.IMachineBlockUpdateable;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Maintenance;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_MultiBlockBase;
+import gregtech.api.render.TextureFactory;
+import mcp.mobius.waila.api.IWailaConfigHandler;
+import mcp.mobius.waila.api.IWailaDataAccessor;
+
+public class GT_MetaTileEntity_Hatch_DroneDownLink extends GT_MetaTileEntity_Hatch_Maintenance {
+
+ private Vec3Impl downlinkCoord;
+ private DroneConnection connection;
+ // This has to be existed for doing random damage.
+ private GT_MetaTileEntity_MultiBlockBase machine;
+ private static final IIconContainer moduleActive = new Textures.BlockIcons.CustomIcon(
+ "iconsets/OVERLAY_DRONE_MODULE_ACTIVE");
+
+ public GT_MetaTileEntity_Hatch_DroneDownLink(int aID, String aName, String aNameRegional, int aTier) {
+ super(aID, aName, aNameRegional, aTier);
+ }
+
+ public GT_MetaTileEntity_Hatch_DroneDownLink(String aName, int aTier, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures, false);
+ }
+
+ @Override
+ public String[] getDescription() {
+ return new String[] { "Built-in powerful navigation beacon!" };
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void registerIcons(IIconRegister aBlockIconRegister) {
+ super.registerIcons(aBlockIconRegister);
+ }
+
+ @Override
+ public ITexture[] getTexturesActive(ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture, TextureFactory.of(moduleActive) };
+ }
+
+ @Override
+ public ITexture[] getTexturesInactive(ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture, TextureFactory.of(moduleActive) };
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Hatch_DroneDownLink(
+ this.mName,
+ this.mTier,
+ this.mDescriptionArray,
+ this.mTextures);
+ }
+
+ @Override
+ public void onFirstTick(IGregTechTileEntity aBaseMetaTileEntity) {
+ downlinkCoord = new Vec3Impl(
+ getBaseMetaTileEntity().getXCoord(),
+ getBaseMetaTileEntity().getYCoord(),
+ getBaseMetaTileEntity().getZCoord());
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ if (aBaseMetaTileEntity.isServerSide()) {
+ if (hasConnection()) {
+ if (connection.centre.getBaseMetaTileEntity()
+ .isActive()) {
+ doNormalMaintain();
+ } else {
+ // Centre offline? ...do nothing.
+ // doRandomIssue();
+ }
+ } else {
+ // If the connection invalid, set it to null.
+ // Find connection every 10 second
+ if (aTick % 200 == 0) {
+ connection = null;
+ tryFindConnection();
+ // Let's have some "surprise". Sorry, surprise party is over.
+ // if (this.machine != null && this.machine.isValid()) {
+ // doRandomIssue();
+ }
+ }
+ }
+ }
+
+ private void doNormalMaintain() {
+ this.mWrench = this.mScrewdriver = this.mSoftHammer = this.mHardHammer = this.mCrowbar = this.mSolderingTool = true;
+ connection.machine.mWrench = connection.machine.mScrewdriver = connection.machine.mSoftHammer = connection.machine.mHardHammer = connection.machine.mCrowbar = connection.machine.mSolderingTool = true;
+ }
+
+ @Override
+ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer, ForgeDirection side,
+ float aX, float aY, float aZ) {
+ if (aBaseMetaTileEntity.isClientSide()) return true;
+ if (side == aBaseMetaTileEntity.getFrontFacing()) {
+ if (aPlayer instanceof FakePlayer) return false;
+ if (connection == null || !connection.isValid()) {
+ aPlayer.addChatComponentMessage(new ChatComponentTranslation("GT5U.machines.dronecentre.noconnection"));
+ return false;
+ }
+ GT_UIInfos.openGTTileEntityUI(aBaseMetaTileEntity, aPlayer);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean allowPullStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public boolean allowPutStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public void onRemoval() {
+ if (hasConnection()) connection.machine = null;
+ }
+
+ private boolean hasConnection() {
+ if (connection == null) return false;
+ if (connection.isValid()) return true;
+ return connection.reCheckConnection();
+ }
+
+ /**
+ * Find a drone connection. This will search for all DC in the same dimension, then find one in range.
+ */
+ private void tryFindConnection() {
+ if (GT_MetaTileEntity_DroneCentre.getCentreMap()
+ .containsKey(getBaseMetaTileEntity().getWorld().provider.dimensionId)) {
+ List<GT_MetaTileEntity_DroneCentre> target = GT_MetaTileEntity_DroneCentre.getCentreMap()
+ .get(getBaseMetaTileEntity().getWorld().provider.dimensionId)
+ .stream()
+ .collect(Collectors.toList());
+ for (GT_MetaTileEntity_DroneCentre centre : target) {
+ if (centre.getCoords()
+ .withinDistance(this.downlinkCoord, centre.getRange())
+ && centre.getBaseMetaTileEntity()
+ .isActive()) {
+ GT_MetaTileEntity_MultiBlockBase machine = tryFindCoreGTMultiBlock();
+ if (machine != null && machine.isValid()) {
+ this.machine = machine;
+ connection = new DroneConnection(machine, centre);
+ connection.centre.getConnectionList()
+ .add(connection);
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ private void doRandomIssue() {
+ switch (getBaseMetaTileEntity().getRandomNumber(6)) {
+ case 0 -> machine.mWrench = !machine.mWrench;
+ case 1 -> machine.mScrewdriver = !machine.mScrewdriver;
+ case 2 -> machine.mSoftHammer = !machine.mSoftHammer;
+ case 3 -> machine.mCrowbar = !machine.mCrowbar;
+ case 4 -> machine.mSolderingTool = !connection.machine.mSolderingTool;
+ case 5 -> machine.mHardHammer = !connection.machine.mHardHammer;
+ }
+ }
+
+ // Find mainframe. Mainly from a method in GT_API——This will cause performance issue! Do not call it frequently.
+ private GT_MetaTileEntity_MultiBlockBase tryFindCoreGTMultiBlock() {
+ Queue<ChunkCoordinates> tQueue = new LinkedList<>();
+ Set<ChunkCoordinates> visited = new HashSet<>(80);
+ tQueue.add(
+ this.getBaseMetaTileEntity()
+ .getCoords());
+ World world = this.getBaseMetaTileEntity()
+ .getWorld();
+ while (!tQueue.isEmpty()) {
+ final ChunkCoordinates aCoords = tQueue.poll();
+ final TileEntity tTileEntity;
+ final boolean isMachineBlock;
+ tTileEntity = world.getTileEntity(aCoords.posX, aCoords.posY, aCoords.posZ);
+ Block block = world.getBlock(aCoords.posX, aCoords.posY, aCoords.posZ);
+ // Plascrete block isn't registered as machineBlock, therefore we have to check it manually so that drone
+ // can work with cleanroom.
+ // Todo: loading cleanroom's config for other blocks
+ isMachineBlock = GregTech_API
+ .isMachineBlock(block, world.getBlockMetadata(aCoords.posX, aCoords.posY, aCoords.posZ))
+ || (block == GregTech_API.sBlockReinforced
+ && world.getBlockMetadata(aCoords.posX, aCoords.posY, aCoords.posZ) == 2);
+ // See if the block itself is MultiBlock, also the one we need.
+ if (tTileEntity instanceof IGregTechTileEntity te
+ && te.getMetaTileEntity() instanceof GT_MetaTileEntity_MultiBlockBase mte)
+ if (mte.mMaintenanceHatches.contains(this)) return mte;
+
+ // Now see if we should add the nearby blocks to the queue:
+ // 1) If we've visited less than 5 blocks, then yes
+ // 2) If the tile says we should recursively update (pipes don't, machine blocks do)
+ // 3) If the block at the coordinates is marked as a machine block
+ if (visited.size() < 5
+ || (tTileEntity instanceof IMachineBlockUpdateable
+ && ((IMachineBlockUpdateable) tTileEntity).isMachineBlockUpdateRecursive())
+ || isMachineBlock) {
+ ChunkCoordinates tCoords;
+
+ if (visited.add(tCoords = new ChunkCoordinates(aCoords.posX + 1, aCoords.posY, aCoords.posZ)))
+ tQueue.add(tCoords);
+ if (visited.add(tCoords = new ChunkCoordinates(aCoords.posX - 1, aCoords.posY, aCoords.posZ)))
+ tQueue.add(tCoords);
+ if (visited.add(tCoords = new ChunkCoordinates(aCoords.posX, aCoords.posY + 1, aCoords.posZ)))
+ tQueue.add(tCoords);
+ if (visited.add(tCoords = new ChunkCoordinates(aCoords.posX, aCoords.posY - 1, aCoords.posZ)))
+ tQueue.add(tCoords);
+ if (visited.add(tCoords = new ChunkCoordinates(aCoords.posX, aCoords.posY, aCoords.posZ + 1)))
+ tQueue.add(tCoords);
+ if (visited.add(tCoords = new ChunkCoordinates(aCoords.posX, aCoords.posY, aCoords.posZ - 1)))
+ tQueue.add(tCoords);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean doesBindPlayerInventory() {
+ return false;
+ }
+
+ @Override
+ public int getGUIWidth() {
+ return 150;
+ }
+
+ @Override
+ public int getGUIHeight() {
+ return 40;
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ builder.setBackground(GT_UITextures.BACKGROUND_SINGLEBLOCK_DEFAULT);
+ builder.setGuiTint(getGUIColorization());
+ builder.widget(
+ ButtonWidget.closeWindowButton(true)
+ .setPos(135, 3))
+ .widget(
+ new TextWidget(StatCollector.translateToLocal("GT5U.gui.text.drone_custom_name"))
+ .setTextAlignment(Alignment.Center)
+ .setPos(0, 5)
+ .setSize(150, 8))
+ .widget(
+ new TextFieldWidget().setGetter(() -> connection == null ? "" : connection.getCustomName(false))
+ .setSetter(var -> { if (connection != null) connection.setCustomName(var); })
+ .setTextAlignment(Alignment.CenterLeft)
+ .setTextColor(Color.WHITE.dark(1))
+ .setFocusOnGuiOpen(true)
+ .setBackground(GT_UITextures.BACKGROUND_TEXT_FIELD_LIGHT_GRAY.withOffset(-1, -1, 2, 2))
+ .setPos(10, 16)
+ .setSize(130, 16))
+ .build();
+ }
+
+ @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("connection", connection == null);
+ if (connection != null) {
+ tag.setInteger("x", connection.centreCoord.posX);
+ tag.setInteger("y", connection.centreCoord.posY);
+ tag.setInteger("z", connection.centreCoord.posZ);
+ tag.setString("name", connection.customName);
+ }
+ }
+
+ @Override
+ public void getWailaBody(ItemStack itemStack, List<String> currenttip, IWailaDataAccessor accessor,
+ IWailaConfigHandler config) {
+ NBTTagCompound tag = accessor.getNBTData();
+ if (tag.getBoolean("connection")) {
+ currenttip
+ .add(EnumChatFormatting.RED + StatCollector.translateToLocal("GT5U.waila.drone_downlink.noConnection"));
+ } else {
+ currenttip.add(
+ EnumChatFormatting.AQUA + StatCollector.translateToLocal("GT5U.waila.drone_downlink.connection")
+ + tag.getInteger("x")
+ + " "
+ + tag.getInteger("y")
+ + " "
+ + tag.getInteger("z"));
+ currenttip.add(EnumChatFormatting.YELLOW + tag.getString("name"));
+ }
+ super.getWailaBody(itemStack, currenttip, accessor, config);
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multiblock/AdvChemicalProcessor.java b/src/main/java/gregtech/common/tileentities/machines/multiblock/AdvChemicalProcessor.java
new file mode 100644
index 0000000000..87e986f941
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multiblock/AdvChemicalProcessor.java
@@ -0,0 +1,508 @@
+package gregtech.common.tileentities.machines.multiblock;
+
+import static com.google.common.primitives.Ints.saturatedCast;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock;
+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 static gregtech.api.util.GT_StructureUtilityMuTE.MOTOR_CASINGS;
+import static gregtech.api.util.GT_StructureUtilityMuTE.ofMuTECasings;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+
+import javax.annotation.Nonnull;
+
+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 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.math.Color;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.api.widget.IWidgetBuilder;
+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 com.gtnewhorizons.modularui.common.widget.textfield.NumericWidget;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.enums.HeatingCoilLevel;
+import gregtech.api.enums.Materials;
+import gregtech.api.fluid.FluidTankGT;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.multitileentity.enums.GT_MultiTileCasing;
+import gregtech.api.multitileentity.multiblock.base.ComplexParallelController;
+import gregtech.api.multitileentity.multiblock.casing.Glasses;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_StructureUtility;
+import gregtech.api.util.GT_StructureUtilityMuTE;
+import gregtech.common.tileentities.machines.multiblock.logic.AdvChemicalProcessorProcessingLogic;
+
+public class AdvChemicalProcessor
+ extends ComplexParallelController<AdvChemicalProcessor, AdvChemicalProcessorProcessingLogic> {
+
+ private static IStructureDefinition<AdvChemicalProcessor> STRUCTURE_DEFINITION = null;
+ protected static final String STRUCTURE_PIECE_T1 = "T1";
+ protected static final String STRUCTURE_PIECE_T2 = "T2";
+ protected static final String STRUCTURE_PIECE_T3 = "T3";
+ protected static final String STRUCTURE_PIECE_T4 = "T4";
+ protected static final String STRUCTURE_PIECE_T5_6 = "T5_6";
+ protected static final String STRUCTURE_PIECE_T7_8 = "T7_8";
+ protected static final Vec3Impl STRUCTURE_OFFSET_T1 = new Vec3Impl(3, 1, 0);
+ protected static final Vec3Impl STRUCTURE_OFFSET_T2 = new Vec3Impl(1, 4, -3);
+ protected static final Vec3Impl STRUCTURE_OFFSET_T3 = new Vec3Impl(8, 0, 5);
+ protected static final Vec3Impl STRUCTURE_OFFSET_T4 = new Vec3Impl(-14, 0, 0);
+ protected static final Vec3Impl STRUCTURE_OFFSET_T5 = new Vec3Impl(14, 0, -6);
+ protected static final Vec3Impl STRUCTURE_OFFSET_T6 = new Vec3Impl(-16, 0, 0);
+ protected static final Vec3Impl STRUCTURE_OFFSET_T7 = new Vec3Impl(16, 0, 15);
+ protected static final Vec3Impl STRUCTURE_OFFSET_T8 = new Vec3Impl(-16, 0, 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 = 8;
+ protected HeatingCoilLevel coilTier;
+ protected final ArrayList<HashSet<String>> processWhitelists = new ArrayList<>(MAX_PROCESSES);
+ protected final ArrayList<ItemStackHandler> processWhitelistInventoryHandlers = new ArrayList<>(MAX_PROCESSES);
+ protected final ArrayList<ArrayList<IFluidTank>> processFluidWhiteLists = new ArrayList<>(MAX_PROCESSES);
+ protected boolean wasWhitelistOpened = false;
+
+ public AdvChemicalProcessor() {
+ super();
+ for (int i = 0; i < MAX_PROCESSES; i++) {
+ processWhitelists.add(null);
+ processWhitelistInventoryHandlers.add(new ItemStackHandler(ITEM_WHITELIST_SLOTS));
+ ArrayList<IFluidTank> processFluidTanks = new ArrayList<>(FLUID_WHITELIST_SLOTS);
+ for (int j = 0; j < FLUID_WHITELIST_SLOTS; j++) {
+ processFluidTanks.add(new FluidTankGT());
+ }
+ processFluidWhiteLists.add(processFluidTanks);
+ }
+ setMaxComplexParallels(1, false);
+ }
+
+ @Override
+ public void readMultiTileNBT(NBTTagCompound nbt) {
+ super.readMultiTileNBT(nbt);
+ setMaxComplexParallels(nbt.getInteger("processors"), false);
+ 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++) {
+
+ if (processWhiteLists == null) {
+ continue;
+ }
+
+ 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) {
+ continue;
+ }
+
+ for (int j = 0; j < fluidList.tagCount(); j++) {
+ final NBTTagCompound fluid = fluidList.getCompoundTagAt(j);
+
+ if (fluid == null) {
+ continue;
+ }
+
+ 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);
+ nbt.setInteger("processors", maxComplexParallels);
+ 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 GT_MultiTileCasing.Chemical.getRegistryId();
+ }
+
+ @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 Processor")
+ .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("Disclaimer: Still WIP - Use at your own risk")
+ .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_T1;
+ }
+
+ @Override
+ public boolean checkMachine() {
+ setCoilTier(HeatingCoilLevel.None);
+ buildState.startBuilding(getStartingStructureOffset());
+ if (!checkPiece(STRUCTURE_PIECE_T1, buildState.getCurrentOffset())) return buildState.failBuilding();
+ if (maxComplexParallels > 1) {
+ buildState.addOffset(STRUCTURE_OFFSET_T2);
+ if (!checkPiece(STRUCTURE_PIECE_T2, buildState.getCurrentOffset())) return buildState.failBuilding();
+ }
+ if (maxComplexParallels > 2) {
+ buildState.addOffset(STRUCTURE_OFFSET_T3);
+ if (!checkPiece(STRUCTURE_PIECE_T3, buildState.getCurrentOffset())) return buildState.failBuilding();
+ }
+ if (maxComplexParallels > 3) {
+ buildState.addOffset(STRUCTURE_OFFSET_T4);
+ if (!checkPiece(STRUCTURE_PIECE_T4, buildState.getCurrentOffset())) return buildState.failBuilding();
+ }
+ if (maxComplexParallels > 4) {
+ buildState.addOffset(STRUCTURE_OFFSET_T5);
+ if (!checkPiece(STRUCTURE_PIECE_T5_6, buildState.getCurrentOffset())) return buildState.failBuilding();
+ }
+ if (maxComplexParallels > 5) {
+ buildState.addOffset(STRUCTURE_OFFSET_T6);
+ if (!checkPiece(STRUCTURE_PIECE_T5_6, buildState.getCurrentOffset())) return buildState.failBuilding();
+ }
+ if (maxComplexParallels > 6) {
+ buildState.addOffset(STRUCTURE_OFFSET_T7);
+ if (!checkPiece(STRUCTURE_PIECE_T7_8, buildState.getCurrentOffset())) return buildState.failBuilding();
+ }
+ if (maxComplexParallels > 7) {
+ buildState.addOffset(STRUCTURE_OFFSET_T8);
+ if (!checkPiece(STRUCTURE_PIECE_T7_8, buildState.getCurrentOffset())) return buildState.failBuilding();
+ }
+ buildState.stopBuilding();
+ return super.checkMachine();
+ }
+
+ @Override
+ public void construct(ItemStack trigger, boolean hintsOnly) {
+ buildState.startBuilding(getStartingStructureOffset());
+ buildPiece(STRUCTURE_PIECE_T1, trigger, hintsOnly, buildState.getCurrentOffset());
+ if (maxComplexParallels > 1) {
+ buildState.addOffset(STRUCTURE_OFFSET_T2);
+ buildPiece(STRUCTURE_PIECE_T2, trigger, hintsOnly, buildState.getCurrentOffset());
+ }
+ if (maxComplexParallels > 2) {
+ buildState.addOffset(STRUCTURE_OFFSET_T3);
+ buildPiece(STRUCTURE_PIECE_T3, trigger, hintsOnly, buildState.getCurrentOffset());
+ }
+ if (maxComplexParallels > 3) {
+ buildState.addOffset(STRUCTURE_OFFSET_T4);
+ buildPiece(STRUCTURE_PIECE_T4, trigger, hintsOnly, buildState.getCurrentOffset());
+ }
+ if (maxComplexParallels > 4) {
+ buildState.addOffset(STRUCTURE_OFFSET_T5);
+ buildPiece(STRUCTURE_PIECE_T5_6, trigger, hintsOnly, buildState.getCurrentOffset());
+ }
+ if (maxComplexParallels > 5) {
+ buildState.addOffset(STRUCTURE_OFFSET_T6);
+ buildPiece(STRUCTURE_PIECE_T5_6, trigger, hintsOnly, buildState.getCurrentOffset());
+ }
+ if (maxComplexParallels > 6) {
+ buildState.addOffset(STRUCTURE_OFFSET_T7);
+ buildPiece(STRUCTURE_PIECE_T7_8, trigger, hintsOnly, buildState.getCurrentOffset());
+ }
+ if (maxComplexParallels > 7) {
+ buildState.addOffset(STRUCTURE_OFFSET_T8);
+ buildPiece(STRUCTURE_PIECE_T7_8, trigger, hintsOnly, buildState.getCurrentOffset());
+ }
+
+ buildState.stopBuilding();
+ }
+
+ @Override
+ public IStructureDefinition<AdvChemicalProcessor> getStructureDefinition() {
+ if (STRUCTURE_DEFINITION == null) {
+ STRUCTURE_DEFINITION = StructureDefinition.<AdvChemicalProcessor>builder()
+ .addShape(
+ STRUCTURE_PIECE_T1,
+ transpose(
+ new String[][] { { "CPCPC", "CCCCC", "CPCPC" }, { "CGC~C", "GWWWU", "CGCCC" },
+ { "CPCPC", "CTTTC", "CPCPC" } }))
+ .addShape(
+ STRUCTURE_PIECE_T2,
+ new String[][] { { " ", " ", " ", " ", " ", " F F ", " B B " },
+ { " ", " ", " ", " ", " ", " F F ", " B B " },
+ { " ", " ", " ", " ", " ", " F F ", " BBB " },
+ { " C ", " CGC ", " CGC ", " CGC ", " CGC ", " CGC ", " BCCCB " },
+ { " BBB ", " C C ", " C C ", " C C ", " C C ", " C C ", "BCPPPCB" },
+ { " CBBBC ", " G W G ", " G W G ", " G W G ", " G W G ", " G W G ", "BCPCPCB" },
+ { " BBB ", " C C ", " C C ", " C C ", " C C ", " C C ", "BCPPPCB" },
+ { " C ", " CGC ", " CGC ", " CGC ", " CGC ", " CGC ", " BCCCB " },
+ { " ", " ", " ", " ", " ", " ", " BBB " } })
+ .addShape(
+ STRUCTURE_PIECE_T3,
+ new String[][] {
+ { " ", " ", " ", " ", " ", " ", " BBB " },
+ { " C ", " CGC ", " CGC ", " CGC ", " CGC ", " CGC ", " BCCCB " },
+ { " BBB ", " C C ", " C C ", " C C ", " C C ", " C CFFF", "BCPPPCBBB" },
+ { " CBBBC ", " G W G ", " G W G ", " G W G ", " G W G ", " G W G ", "BCPCPCB " },
+ { " BBB ", " C C ", " C C ", " C C ", " C C ", " C CFFF", "BCPPPCBBB" },
+ { " C ", " CGC ", " CGC ", " CGC ", " CGC ", " CGC ", " BCCCB " },
+ { " ", " ", " ", " ", " ", " ", " BBB " } })
+ .addShape(
+ STRUCTURE_PIECE_T4,
+ new String[][] {
+ { " ", " ", " ", " ", " ", " ", " BBB " },
+ { " C ", " CGC ", " CGC ", " CGC ", " CGC ", " CGC ", " BCCCB " },
+ { " BBB ", " C C ", " C C ", " C C ", " C C ", "FFFC C ", "BBBCPPPCB" },
+ { " CBBBC ", " G W G ", " G W G ", " G W G ", " G W G ", " G W G ", " BCPCPCB" },
+ { " BBB ", " C C ", " C C ", " C C ", " C C ", "FFFC C ", "BBBCPPPCB" },
+ { " C ", " CGC ", " CGC ", " CGC ", " CGC ", " CGC ", " BCCCB " },
+ { " ", " ", " ", " ", " ", " ", " BBB " } })
+ .addShape(
+ STRUCTURE_PIECE_T5_6,
+ new String[][] { { " ", " ", " ", " ", " ", " F F ", " " },
+ { " ", " ", " ", " ", " ", " F F ", " B B " },
+ { " ", " ", " ", " ", " ", " F F ", " B B " },
+ { " ", " ", " ", " ", " ", " F F ", " BBB " },
+ { " C ", " CGC ", " CGC ", " CGC ", " CGC ", " CGC ", " BCCCB " },
+ { " BBB ", " C C ", " C C ", " C C ", " C C ", " C C ", "BCPPPCB" },
+ { " CBBBC ", " G W G ", " G W G ", " G W G ", " G W G ", " G W G ", "BCPCPCB" },
+ { " BBB ", " C C ", " C C ", " C C ", " C C ", " C C ", "BCPPPCB" },
+ { " C ", " CGC ", " CGC ", " CGC ", " CGC ", " CGC ", " BCCCB " },
+ { " ", " ", " ", " ", " ", " ", " BBB " } })
+ .addShape(
+ STRUCTURE_PIECE_T7_8,
+ new String[][] { { " ", " ", " ", " ", " ", " ", " BBB " },
+ { " C ", " CGC ", " CGC ", " CGC ", " CGC ", " CGC ", " BCCCB " },
+ { " BBB ", " C C ", " C C ", " C C ", " C C ", " C C ", "BCPPPCB" },
+ { " CBBBC ", " G W G ", " G W G ", " G W G ", " G W G ", " G W G ", "BCPCPCB" },
+ { " BBB ", " C C ", " C C ", " C C ", " C C ", " C C ", "BCPPPCB" },
+ { " C ", " CGC ", " CGC ", " CGC ", " CGC ", " CGC ", " BCCCB " },
+ { " ", " ", " ", " ", " ", " F F ", " BBB " },
+ { " ", " ", " ", " ", " ", " F F ", " B B " },
+ { " ", " ", " ", " ", " ", " F F ", " B B " },
+ { " ", " ", " ", " ", " ", " F F ", " " } })
+ .addElement(
+ 'C',
+ ofMuTECasings(
+ FLUID_IN | ITEM_IN | FLUID_OUT | ITEM_OUT | ENERGY_IN,
+ GT_MultiTileCasing.Chemical.getCasing()))
+ .addElement('P', ofBlock(GregTech_API.sBlockCasings8, 1))
+ .addElement('T', ofMuTECasings(NOTHING, MOTOR_CASINGS))
+ .addElement(
+ 'W',
+ GT_StructureUtility.ofCoil(AdvChemicalProcessor::setCoilTier, AdvChemicalProcessor::getCoilTier))
+ .addElement('G', Glasses.chainAllGlasses())
+ .addElement('B', ofBlock(GregTech_API.sBlockCasings4, 1))
+ .addElement('F', GT_StructureUtility.ofFrame(Materials.Steel))
+ .addElement(
+ 'U',
+ ofMuTECasings(
+ FLUID_IN | ITEM_IN | FLUID_OUT | ITEM_OUT | ENERGY_IN,
+ GT_MultiTileCasing.Chemical.getCasing(),
+ GT_StructureUtilityMuTE.INVENTORY_CASINGS))
+ .build();
+ }
+ return STRUCTURE_DEFINITION;
+ }
+
+ @Override
+ protected void setMaxComplexParallels(int parallel, boolean stopMachine) {
+ super.setMaxComplexParallels(parallel, stopMachine);
+ onStructureChange();
+ }
+
+ protected MultiChildWidget createMainPage(IWidgetBuilder<?> builder) {
+ MultiChildWidget child = new MultiChildWidget();
+ 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)
+ .setEnabled((widget -> processIndex < maxComplexParallels))
+ .setPos(20 * (i % 4) + 18, 18 + (i / 4) * 20));
+ }
+ child.addChild(
+ new NumericWidget().setGetter(() -> maxComplexParallels)
+ .setSetter(parallel -> setMaxComplexParallels((int) parallel, true))
+ .setBounds(1, MAX_PROCESSES)
+ .setTextColor(Color.WHITE.normal)
+ .setTextAlignment(Alignment.Center)
+ .addTooltip("Tier")
+ .setBackground(GT_UITextures.BACKGROUND_TEXT_FIELD)
+ .setSize(18, 18)
+ .setPos(130, 85));
+ 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.advchemicalprocessor";
+ }
+
+ @Override
+ public String getLocalName() {
+ return "Advanced Chemical Processor";
+ }
+
+ 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<String> 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;
+ }
+
+ @Override
+ @Nonnull
+ protected AdvChemicalProcessorProcessingLogic createProcessingLogic() {
+ return new AdvChemicalProcessorProcessingLogic();
+ }
+}
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..06fc7b42b1
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multiblock/CokeOven.java
@@ -0,0 +1,153 @@
+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 static gregtech.api.util.GT_StructureUtilityMuTE.ofMuTECasings;
+
+import java.util.List;
+
+import javax.annotation.Nonnull;
+
+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.common.internal.network.NetworkUtils;
+import com.gtnewhorizons.modularui.common.widget.DrawableWidget;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.GT_Mod;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.multitileentity.enums.GT_MultiTileCasing;
+import gregtech.api.multitileentity.multiblock.base.Controller;
+import gregtech.api.task.tasks.PollutionTask;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.common.tileentities.machines.multiblock.logic.CokeOvenProcessingLogic;
+
+public class CokeOven extends Controller<CokeOven, CokeOvenProcessingLogic> {
+
+ private static IStructureDefinition<CokeOven> STRUCTURE_DEFINITION = null;
+ private static final Vec3Impl OFFSET = new Vec3Impl(1, 1, 0);
+ private static final String MAIN = "Main";
+ private static final int POLLUTION_AMOUNT = 10;
+
+ public CokeOven() {
+ super();
+ setElectric(false);
+ new PollutionTask<>(this).setPollutionPerSecond(POLLUTION_AMOUNT);
+ }
+
+ @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_AMOUNT)
+ .toolTipFinisher(GT_Values.AuthorBlueWeabo);
+ return tt;
+ }
+
+ @Override
+ public Vec3Impl getStartingStructureOffset() {
+ return OFFSET;
+ }
+
+ @Override
+ public IStructureDefinition<CokeOven> getStructureDefinition() {
+ if (STRUCTURE_DEFINITION == null) {
+ STRUCTURE_DEFINITION = StructureDefinition.<CokeOven>builder()
+ .addShape(
+ MAIN,
+ new String[][] { { "AAA", "A~A", "AAA" }, { "AAA", "A-A", "AAA" }, { "AAA", "AAA", "AAA" } })
+ .addElement('A', ofMuTECasings(ITEM_IN | ITEM_OUT, GT_MultiTileCasing.CokeOven.getCasing()))
+ .build();
+ }
+ return STRUCTURE_DEFINITION;
+ }
+
+ @Override
+ public boolean hasFluidInput() {
+ return false;
+ }
+
+ @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;
+ final List<String> titleLines = fontRenderer
+ .listFormattedStringToWidth(title, getGUIWidth() - (TAB_PADDING + TITLE_PADDING) * 2);
+ titleWidth = titleLines.size() > 1 ? getGUIWidth() - (TAB_PADDING + TITLE_PADDING) * 2
+ : fontRenderer.getStringWidth(title);
+ 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
+ @Nonnull
+ protected CokeOvenProcessingLogic createProcessingLogic() {
+ return new CokeOvenProcessingLogic();
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multiblock/DistillationTower.java b/src/main/java/gregtech/common/tileentities/machines/multiblock/DistillationTower.java
new file mode 100644
index 0000000000..326bfcc9ee
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multiblock/DistillationTower.java
@@ -0,0 +1,174 @@
+package gregtech.common.tileentities.machines.multiblock;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.*;
+import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.*;
+import static gregtech.api.util.GT_StructureUtilityMuTE.MOTOR_CASINGS;
+import static gregtech.api.util.GT_StructureUtilityMuTE.ofMuTECasings;
+
+import javax.annotation.Nonnull;
+
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+import com.gtnewhorizon.structurelib.util.Vec3Impl;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.enums.HeatingCoilLevel;
+import gregtech.api.enums.Materials;
+import gregtech.api.multitileentity.enums.GT_MultiTileCasing;
+import gregtech.api.multitileentity.multiblock.base.StackableController;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_StructureUtility;
+import gregtech.common.tileentities.machines.multiblock.logic.DistillationTowerProcessingLogic;
+
+public class DistillationTower extends StackableController<DistillationTower, DistillationTowerProcessingLogic> {
+
+ private static IStructureDefinition<DistillationTower> STRUCTURE_DEFINITION_MEGA = null;
+ private static final Vec3Impl STRUCTURE_OFFSET_MEGA = new Vec3Impl(8, 3, 0);
+ private static final Vec3Impl STRUCTURE_OFFSET_MEGA_START = new Vec3Impl(0, 3, 0);
+ private static final Vec3Impl STRUCTURE_OFFSET_MEGA_STOP = new Vec3Impl(0, 5, 0);
+ private static final Vec3Impl STRUCTURE_OFFSET_MEGA_STACK = new Vec3Impl(0, 3, 0);
+ private static final String STACKABLE_MIDDLE_1 = "STACKABLE_MIDDLE_1";
+ private static final String STACKABLE_MIDDLE_2 = "STACKABLE_MIDDLE_2";
+ private boolean isMega = true;
+
+ @Override
+ public short getCasingRegistryID() {
+ return 0;
+ }
+
+ @Override
+ public int getCasingMeta() {
+ return GT_MultiTileCasing.Distillation.getId();
+ }
+
+ @Override
+ public GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Distillation Tower")
+ .addInfo("Controller block for the Distillation Tower")
+ .addInfo("Can be specialised to be a mega structure")
+ .addInfo(GT_Values.Authorminecraft7771)
+ .addSeparator()
+ .beginStructureBlock(5, 3, 3, false)
+ .addController("Front center")
+ .toolTipFinisher("Gregtech");
+ return tt;
+ }
+
+ @Override
+ public Vec3Impl getStartingStructureOffset() {
+ return STRUCTURE_OFFSET_MEGA;
+ }
+
+ @Override
+ public IStructureDefinition<DistillationTower> getStructureDefinition() {
+ if (STRUCTURE_DEFINITION_MEGA == null) {
+ STRUCTURE_DEFINITION_MEGA = StructureDefinition.<DistillationTower>builder()
+ .addShape(
+ STACKABLE_START,
+ transpose(
+ // spotless:off
+ new String[][]{
+ {" "," "," "," "," "," ECCCCCE "," CCCCCCC "," C C "," EC CE "," CC CC "," CC CC ABA "," CC CC B B "," CC CC ABA "," CC CC "," EC CE "," C C "," CCCCCCC "," ECCCCCE "," "},
+ {" "," EEE "," E "," E "," E "," E E E "," CCCCCCC "," C C "," EC CE "," C C "," C C ABA "," C C B B "," C C ABA "," C C "," EC CE "," C C "," CCCCCCC "," E E "," "},
+ {" CCCCC "," CCCCC "," CCCCC "," "," "," E E "," CCCCCCC "," C C "," EC CE "," C C "," C C ABA "," C C B B "," C C ABA "," C C "," EC CE "," C C "," CCCCCCC "," E E "," "},
+ {" CXC~C "," BDDDB "," CBCBC "," B B "," B B "," E B B E "," CCCCCCC "," C C "," EC CE "," C C "," C C AAA "," C C A A "," C C AAA "," C C "," EC CE "," C C "," CCCCCCC "," E E "," "},
+ {" CCCCC "," CCCCC "," CCCCC "," "," CCCCCCCCCCC "," CAAAAAAAAAC ","CCCACCCCCCCACCC ","CAACAAAAAAACAAC ","CACAADDDDDAACAC ","CACADDDDDDDACACCCCC","CACADDAAADDACACCCCC","CACADDAAADDACACCCCC","CACADDAAADDACACCCCC","CACADDDDDDDACACCCCC","CACAADDDDDAACAC ","CAACAAAAAAACAAC ","CCCACCCCCCCACCC "," CAAAAAAAAAC "," CCCCCCCCCCC "}
+ }))
+ .addShape(
+ STACKABLE_STOP,
+ transpose(
+ new String[][]{
+ {" "," "," "," "," "," "," "," "," "," "," CCC "," CCC "," CCC "," "," "," "," "," "," "},
+ {" "," "," "," "," "," E E "," E E "," E E "," EEEEAAAAAEEEE "," AAAAAAA "," AA AA "," AA AA "," AA AA "," AAAAAAA "," EEEEAAAAAEEEE "," E E "," E E "," E E "," "},
+ {" "," "," "," "," "," ECCCCCE "," CCCCCCCCC "," CCCCCCCCCCC "," ECCC CCCE "," CCC CCC "," CCC CCC "," CCC CCC "," CCC CCC "," CCC CCC "," ECCC CCCE "," CCCCCCCCCCC "," CCCCCCCCC "," ECCCCCE "," "},
+ {" "," "," "," "," "," E E "," CCCCCCC "," C C "," EC CE "," C C "," C C "," C C "," C C "," C C "," EC CE "," C C "," CCCCCCC "," E E "," "},
+ {" "," "," "," "," "," E E "," CCCCCCC "," C C "," EC CE "," C C "," C CAAAAA "," C CABBBA "," C CAAAAA "," C C "," EC CE "," C C "," CCCCCCC "," E E "," "},
+ {" "," "," "," "," "," ECCCCCE "," CCCCCCC "," C C "," EC CE "," CC CC "," CC CABBBA "," CC C B "," CC CABBBA "," CC CC "," EC CE "," C C "," CCCCCCC "," ECCCCCE "," "},
+ {" "," "," "," "," "," E E "," CCCCCCC "," C C "," EC CE "," C C "," C CAAABA "," C CAAA B "," C CAAABA "," C C "," EC CE "," C C "," CCCCCCC "," E E "," "},
+ {" "," "," "," "," "," E E "," CCCCCCC "," C C "," EC CE "," C C "," C C ABA "," C C A B "," C C ABA "," C C "," EC CE "," C C "," CCCCCCC "," E E "," "},
+ }))
+ .addShape(
+ STACKABLE_MIDDLE_1,
+ transpose(
+ new String[][]{
+ {" "," "," "," "," "," E E "," CCCCCCC "," C C "," EC CE "," C C "," C C ABA "," C C B B "," C C ABA "," C C "," EC CE "," C C "," CCCCCCC "," E E "," "},
+ {" "," "," "," "," "," E E "," CCCCCCC "," C C "," EC CE "," C C "," C C ABA "," C C B B "," C C ABA "," C C "," EC CE "," C C "," CCCCCCC "," E E "," "},
+ {" "," "," "," "," "," E E "," CCCCCCC "," C C "," EC CE "," C C "," C C ABA "," C C B B "," C C ABA "," C C "," EC CE "," C C "," CCCCCCC "," E E "," "},
+ }))
+ .addShape(
+ STACKABLE_MIDDLE_2,
+ transpose(
+ new String[][]{
+ {" "," "," "," "," "," ECCCCCE "," CCCCCCC "," C C "," EC CE "," CC CC "," CC CC ABA "," CC CC B B "," CC CC ABA "," CC CC "," EC CE "," C C "," CCCCCCC "," ECCCCCE "," "},
+ {" "," "," "," "," "," E E "," CCCCCCC "," C C "," EC CE "," C C "," C C ABA "," C C B B "," C C ABA "," C C "," EC CE "," C C "," CCCCCCC "," E E "," "},
+ {" "," "," "," "," "," E E "," CCCCCCC "," C C "," EC CE "," C C "," C C ABA "," C C B B "," C C ABA "," C C "," EC CE "," C C "," CCCCCCC "," E E "," "},
+ }))
+ // spotless:on
+ .addElement(
+ 'C',
+ ofMuTECasings(
+ FLUID_IN | ITEM_IN | FLUID_OUT | ITEM_OUT | ENERGY_IN,
+ GT_MultiTileCasing.Distillation.getCasing()))
+ .addElement('E', GT_StructureUtility.ofFrame(Materials.StainlessSteel))
+ .addElement('A', ofBlock(GregTech_API.sBlockCasings2, 0))
+ .addElement('B', ofBlock(GregTech_API.sBlockCasings2, 13))
+ .addElement('X', ofMuTECasings(NOTHING, MOTOR_CASINGS))
+ .addElement('D', GT_StructureUtility.ofCoil((tile, meta) -> {}, (tile) -> HeatingCoilLevel.None))
+ .build();
+ }
+ return STRUCTURE_DEFINITION_MEGA;
+ }
+
+ @Override
+ public int getFluidOutputCount() {
+ return 12;
+ }
+
+ @Override
+ public int getMinStacks() {
+ return 0;
+ }
+
+ @Override
+ public int getMaxStacks() {
+ return 9;
+ }
+
+ @Override
+ public Vec3Impl getStartingStackOffset() {
+ return STRUCTURE_OFFSET_MEGA_START;
+ }
+
+ @Override
+ public Vec3Impl getPerStackOffset() {
+ return STRUCTURE_OFFSET_MEGA_STACK;
+ }
+
+ @Override
+ public Vec3Impl getAfterLastStackOffset() {
+ return STRUCTURE_OFFSET_MEGA_STOP;
+ }
+
+ @Override
+ public String getTileEntityName() {
+ return "gt.multitileentity.multiblock.distillationtower";
+ }
+
+ @Override
+ public String getLocalName() {
+ return "Distillation Tower";
+ }
+
+ @Override
+ protected String getStackableMiddle(int stackIndex) {
+ return stackIndex % 2 == 0 ? STACKABLE_MIDDLE_1 : STACKABLE_MIDDLE_2;
+ }
+
+ @Override
+ @Nonnull
+ protected DistillationTowerProcessingLogic createProcessingLogic() {
+ return new DistillationTowerProcessingLogic();
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multiblock/LaserEngraver.java b/src/main/java/gregtech/common/tileentities/machines/multiblock/LaserEngraver.java
new file mode 100644
index 0000000000..d4a7283f3e
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multiblock/LaserEngraver.java
@@ -0,0 +1,305 @@
+package gregtech.common.tileentities.machines.multiblock;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.*;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlockUnlocalizedName;
+import static gregtech.api.enums.Mods.*;
+import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.*;
+import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.ENERGY_IN;
+import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.FLUID_OUT;
+import static gregtech.api.util.GT_StructureUtilityMuTE.*;
+
+import java.util.UUID;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+import com.gtnewhorizon.structurelib.util.Vec3Impl;
+import com.gtnewhorizons.modularui.api.math.Alignment;
+import com.gtnewhorizons.modularui.api.math.Color;
+import com.gtnewhorizons.modularui.api.widget.IWidgetBuilder;
+import com.gtnewhorizons.modularui.common.widget.ButtonWidget;
+import com.gtnewhorizons.modularui.common.widget.MultiChildWidget;
+import com.gtnewhorizons.modularui.common.widget.textfield.NumericWidget;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.enums.Materials;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.multitileentity.enums.GT_MultiTileCasing;
+import gregtech.api.multitileentity.multiblock.base.ComplexParallelController;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_StructureUtility;
+import gregtech.common.tileentities.machines.multiblock.logic.LaserEngraverProcessingLogic;
+
+public class LaserEngraver extends ComplexParallelController<LaserEngraver, LaserEngraverProcessingLogic> {
+
+ private static IStructureDefinition<LaserEngraver> STRUCTURE_DEFINITION = null;
+ protected static final String STRUCTURE_MAIN = "Main";
+ protected static final String STRUCTURE_PIECE_T1 = "T1";
+ protected static final String STRUCTURE_PIECE_T2 = "T2";
+ protected static final String STRUCTURE_PIECE_T3 = "T3";
+ protected static final String STRUCTURE_PIECE_T4 = "T4";
+ protected static final String STRUCTURE_PIECE_T5 = "T5";
+ protected static final String STRUCTURE_PIECE_T6 = "T6";
+ protected static final int PROCESS_WINDOW_BASE_ID = 100;
+ protected static final Vec3Impl STRUCTURE_OFFSET_T1 = new Vec3Impl(3, 1, 0);
+ protected static final Vec3Impl STRUCTURE_OFFSET_T2 = new Vec3Impl(1, 3, 0);
+ protected static final Vec3Impl STRUCTURE_OFFSET_T3 = new Vec3Impl(-6, 0, -5);
+ protected static final Vec3Impl STRUCTURE_OFFSET_T4 = new Vec3Impl(18, 0, 0);
+ protected static final Vec3Impl STRUCTURE_OFFSET_T5 = new Vec3Impl(-18, 0, 9);
+ protected static final Vec3Impl STRUCTURE_OFFSET_T6 = new Vec3Impl(18, 0, 0);
+ protected static final int MAX_PROCESSES = 6;
+ protected RecipeMap<?> recipeMap;
+ private UUID LaserEngraver;
+
+ @Override
+ public String getTileEntityName() {
+ return "gt.multitileentity.multiblock.laserengraver";
+ }
+
+ @Override
+ public Vec3Impl getStartingStructureOffset() {
+ return STRUCTURE_OFFSET_T1;
+ }
+
+ @Override
+ public boolean checkMachine() {
+ buildState.startBuilding(getStartingStructureOffset());
+ if (!checkPiece(STRUCTURE_PIECE_T1, buildState.getCurrentOffset())) return buildState.failBuilding();
+ if (maxComplexParallels > 1) {
+ buildState.addOffset(STRUCTURE_OFFSET_T2);
+ if (!checkPiece(STRUCTURE_PIECE_T2, buildState.getCurrentOffset())) return buildState.failBuilding();
+ }
+ if (maxComplexParallels > 2) {
+ buildState.addOffset(STRUCTURE_OFFSET_T3);
+ if (!checkPiece(STRUCTURE_PIECE_T3, buildState.getCurrentOffset())) return buildState.failBuilding();
+ }
+ if (maxComplexParallels > 3) {
+ buildState.addOffset(STRUCTURE_OFFSET_T4);
+ if (!checkPiece(STRUCTURE_PIECE_T4, buildState.getCurrentOffset())) return buildState.failBuilding();
+ }
+ if (maxComplexParallels > 4) {
+ buildState.addOffset(STRUCTURE_OFFSET_T5);
+ if (!checkPiece(STRUCTURE_PIECE_T5, buildState.getCurrentOffset())) return buildState.failBuilding();
+ }
+ if (maxComplexParallels > 5) {
+ buildState.addOffset(STRUCTURE_OFFSET_T6);
+ if (!checkPiece(STRUCTURE_PIECE_T6, buildState.getCurrentOffset())) return buildState.failBuilding();
+ }
+ buildState.stopBuilding();
+ return super.checkMachine();
+ }
+
+ @Override
+ public void construct(ItemStack trigger, boolean hintsOnly) {
+ buildState.startBuilding(getStartingStructureOffset());
+ buildPiece(STRUCTURE_PIECE_T1, trigger, hintsOnly, buildState.getCurrentOffset());
+ if (maxComplexParallels > 1) {
+ buildState.addOffset(STRUCTURE_OFFSET_T2);
+ buildPiece(STRUCTURE_PIECE_T2, trigger, hintsOnly, buildState.getCurrentOffset());
+ }
+ if (maxComplexParallels > 2) {
+ buildState.addOffset(STRUCTURE_OFFSET_T3);
+ buildPiece(STRUCTURE_PIECE_T3, trigger, hintsOnly, buildState.getCurrentOffset());
+ }
+ if (maxComplexParallels > 3) {
+ buildState.addOffset(STRUCTURE_OFFSET_T4);
+ buildPiece(STRUCTURE_PIECE_T4, trigger, hintsOnly, buildState.getCurrentOffset());
+ }
+ if (maxComplexParallels > 4) {
+ buildState.addOffset(STRUCTURE_OFFSET_T5);
+ buildPiece(STRUCTURE_PIECE_T5, trigger, hintsOnly, buildState.getCurrentOffset());
+ }
+ if (maxComplexParallels > 5) {
+ buildState.addOffset(STRUCTURE_OFFSET_T6);
+ buildPiece(STRUCTURE_PIECE_T6, trigger, hintsOnly, buildState.getCurrentOffset());
+ }
+ buildState.stopBuilding();
+ }
+
+ @Override
+ public IStructureDefinition<LaserEngraver> getStructureDefinition() {
+ if (STRUCTURE_DEFINITION == null) {
+ STRUCTURE_DEFINITION = StructureDefinition.<LaserEngraver>builder()
+ .addShape(
+ STRUCTURE_PIECE_T1,
+ transpose(
+ // spotless:off
+ new String[][]{{"ACADA", "AAAAA", "AAAAA"}, {"GGA~A", "H I", "GGAAA"},
+ {"AAAAA", "ABBBA", "AAAAA"}}))
+ .addShape(
+ STRUCTURE_PIECE_T2,
+ new String[][]{{" ", " ", " ", " ", " ", " "},
+ {" K ", " K ", " K ", " ", " ", " "},
+ {" K ", " ", " ", " ", " ", " "},
+ {" K ", " ", " ", " ", " ", " "},
+ {" K ", " ", " ", " ", " ", " "},
+ {" K ", "FBF FBF", " G G ", " G G ", " G G ", "FBF FBF"},
+ {" KKKKK ", "BIB BIB", "G G G G", "G G G G", "G G G G", "BHB BHB"},
+ {" K K ", "FBF FBF", " G G ", " G G ", " G G ", "FBF FBF"},
+ {" K K ", " ", " ", " ", " ", " "},
+ {" K K ", "FBF FBF", " G G ", " G G ", " G G ", "FBF FBF"},
+ {" KKKKK ", "BIB BIB", "G G G G", "G G G G", "G G G G", "BHB BHB"},
+ {" ", "FBF FBF", " G G ", " G G ", " G G ", "FBF FBF",}})
+ .addShape(
+ STRUCTURE_PIECE_T3,
+ new String[][]{
+ {" ", " BBBBB FBF ", " BGGGB G ", " BGGGB G ", " BMLMB G ", " BBBBB FBF "},
+ {" KKKKKKK ", " BBAAABB BIB ", " B B G G ", " B B G G ", " B B G G ", " BBBBBBB BHB "},
+ {" K ", " BABBBAB FBF ", " G G G ", " G G G ", " M HHH M G ", " BBBBBBB FBF "},
+ {"KKKKKK ", " BABIBAB ", " G G ", " G G ", " L HHH L ", " BBBBBBB "},
+ {" K ", " BABBBAB FBF ", " G G G ", " G G G ", " M HHH M G ", " BBBBBBB FBF "},
+ {" KKKKKKK ", " BBAAABB BIB ", " B B G G ", " B B G G ", " B B G G ", " BBBBBBB BHB "},
+ {" ", " BBBBB FBF ", " BGGGB G ", " BGGGB G ", " BMLMB G ", " BBBBB FBF "}})
+ .addShape(
+ STRUCTURE_PIECE_T4,
+ new String[][]{
+ {" ", "FBF BBBBB ", " G BGGGB ", " G BGGGB ", " G BNLNB ", "FBF BBBBB "},
+ {" KKKKKKK ", "BIB BBAAABB ", "G G B B ", "G G B B ", "G G B B ", "BHB BBBBBBB "},
+ {" K ", "FBF BABBBAB ", " G G G ", " G G G ", " G N HHH N ", "FBF BBBBBBB "},
+ {" KKKKKK", " BABIBAB ", " G G ", " G G ", " L HHH L ", " BBBBBBB "},
+ {" K ", "FBF BABBBAB ", " G G G ", " G G G ", " G N HHH N ", "FBF BBBBBBB "},
+ {" KKKKKKK ", "BIB BBAAABB ", "G G B B ", "G G B B ", "G G B B ", "BHB BBBBBBB "},
+ {" ", "FBF BBBBB ", " G BGGGB ", " G BGGGB ", " G BNLNB ", "FBF BBBBB "}})
+ .addShape(
+ STRUCTURE_PIECE_T5,
+ new String[][]{
+ {" ", " BBBBB FBF ", " BGGGB G ", " BGGGB G ", " BOLOB G ", " BBBBB FBF "},
+ {" KKKKKKK ", " BBAAABB BIB ", " B B G G ", " B B G G ", " B B G G ", " BBBBBBB BHB "},
+ {" K ", " BABBBAB FBF ", " G G G ", " G G G ", " O HHH O G ", " BBBBBBB FBF "},
+ {" K ", " BABIBAB ", " G G ", " G G ", " L HHH L ", " BBBBBBB "},
+ {" K ", " BABBBAB FBF ", " G G G ", " G G G ", " O HHH O G ", " BBBBBBB FBF "},
+ {" KKKKKKK ", " BBAAABB BIB ", " B B G G ", " B B G G ", " B B G G ", " BBBBBBB BHB "},
+ {" K ", " BBBBB FBF ", " BGGGB G ", " BGGGB G ", " BOLOB G ", " BBBBB FBF "},
+ {" K ", " ", " ", " ", " "},
+ {" K ", " ", " ", " ", " "},
+ {" K ", " ", " ", " ", " "}})
+ .addShape(
+ STRUCTURE_PIECE_T6,
+ new String[][]{
+ {" ", "FBF BBBBB ", " G BGGGB ", " G BGGGB ", " G BPLPB ", "FBF BBBBB "},
+ {" KKKKKKK ", "BIB BBAAABB ", "G G B B ", "G G B B ", "G G B B ", "BHB BBBBBBB "},
+ {" K ", "FBF BABBBAB ", " G G G ", " G G G ", " G P HHH P ", "FBF BBBBBBB "},
+ {" K ", " BABIBAB ", " G G ", " G G ", " L HHH L ", " BBBBBBB "},
+ {" K ", "FBF BABBBAB ", " G G G ", " G G G ", " G P HHH P ", "FBF BBBBBBB "},
+ {" KKKKKKK ", "BIB BBAAABB ", "G G B B ", "G G B B ", "G G B B ", "BHB BBBBBBB "},
+ {" K ", "FBF BBBBB ", " G BGGGB ", " G BGGGB ", " G BPLPB ", "FBF BBBBB "},
+ {" K ", " ", " ", " ", " "},
+ {" K ", " ", " ", " ", " "},
+ {" K ", " ", " ", " ", " "}})
+ // spotless:on
+ .addElement(
+ 'A',
+ ofMuTECasings(
+ FLUID_IN | ITEM_IN | FLUID_OUT | ITEM_OUT | ENERGY_IN,
+ GT_MultiTileCasing.LaserEngraver.getCasing()))
+ .addElement(
+ 'B',
+ ofMuTECasings(
+ FLUID_IN | ITEM_IN | FLUID_OUT | ITEM_OUT | ENERGY_IN,
+ GT_MultiTileCasing.BlackLaserEngraverCasing.getCasing()))
+ .addElement(
+ 'C',
+ ofMuTECasings(NOTHING, CLEANROOM_CASINGS, GT_MultiTileCasing.LaserEngraver.getCasing()))
+ .addElement('D', ofMuTECasings(NOTHING, WIRELESS_CASINGS, GT_MultiTileCasing.LaserEngraver.getCasing()))
+ .addElement('E', ofMuTECasings(NOTHING, MOTOR_CASINGS))
+ .addElement('F', GT_StructureUtility.ofFrame(Materials.Naquadah)
+
+ )
+ .addElement('H', ofMuTECasings(NOTHING, GT_MultiTileCasing.Mirror.getCasing()))
+
+ .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)))
+ .addElement('I', ofMuTECasings(NOTHING, EMITTER_CASINGS))
+ .addElement('K', ofBlock(GregTech_API.sBlockCasings3, 11))
+ .addElement('L', ofMuTECasings(NOTHING, ROBOT_ARM_CASINGS))
+ .addElement('M', ofMuTECasings(NOTHING, GT_MultiTileCasing.LaserEngraverUpgrade1.getCasing()))
+ .addElement('N', ofMuTECasings(NOTHING, GT_MultiTileCasing.LaserEngraverUpgrade2.getCasing()))
+ .addElement('O', ofMuTECasings(NOTHING, GT_MultiTileCasing.LaserEngraverUpgrade3.getCasing()))
+ .addElement('P', ofMuTECasings(NOTHING, GT_MultiTileCasing.LaserEngraverUpgrade4.getCasing()))
+ .build();
+ buildState.stopBuilding();
+ }
+ return STRUCTURE_DEFINITION;
+ }
+
+ protected MultiChildWidget createMainPage(IWidgetBuilder<?> builder) {
+ MultiChildWidget child = new MultiChildWidget();
+ 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)
+ .setEnabled((widget -> processIndex < maxComplexParallels))
+ .setPos(20 * (i % 4) + 18, 18 + (i / 4) * 20));
+ }
+ child.addChild(
+ new NumericWidget().setGetter(() -> maxComplexParallels)
+ .setSetter(parallel -> setMaxComplexParallels((int) parallel, true))
+ .setBounds(1, MAX_PROCESSES)
+ .setTextColor(Color.WHITE.normal)
+ .setTextAlignment(Alignment.Center)
+ .addTooltip("Tier")
+ .setBackground(GT_UITextures.BACKGROUND_TEXT_FIELD)
+ .setSize(18, 18)
+ .setPos(130, 85));
+ return child;
+ }
+
+ @Override
+ public short getCasingRegistryID() {
+ return 0;
+ }
+
+ @Override
+ public void readMultiTileNBT(NBTTagCompound nbt) {
+ super.readMultiTileNBT(nbt);
+ setMaxComplexParallels(nbt.getInteger("processors"), false);
+ }
+
+ @Override
+ public void writeMultiTileNBT(NBTTagCompound nbt) {
+ super.writeMultiTileNBT(nbt);
+ nbt.setInteger("processors", maxComplexParallels);
+ }
+
+ @Override
+ public int getCasingMeta() {
+ return GT_MultiTileCasing.LaserEngraver.getId();
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Laser Engraver")
+ .addInfo("Used for Engraving")
+ .addSeparator()
+ .beginStructureBlock(3, 3, 5, true)
+ .addController("Front right center")
+ .toolTipFinisher(GT_Values.AuthorTheEpicGamer274);
+ return tt;
+ }
+
+ @Override
+ @Nonnull
+ protected LaserEngraverProcessingLogic createProcessingLogic() {
+ return new LaserEngraverProcessingLogic();
+ }
+
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multiblock/LayeredCokeBattery.java b/src/main/java/gregtech/common/tileentities/machines/multiblock/LayeredCokeBattery.java
new file mode 100644
index 0000000000..3b00708e40
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multiblock/LayeredCokeBattery.java
@@ -0,0 +1,295 @@
+package gregtech.common.tileentities.machines.multiblock;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.*;
+import static gregtech.api.enums.Mods.*;
+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 static gregtech.api.util.GT_StructureUtilityMuTE.AMPERAGE_CASINGS;
+import static gregtech.api.util.GT_StructureUtilityMuTE.HEATER_CASINGS;
+import static gregtech.api.util.GT_StructureUtilityMuTE.INSULATOR_CASINGS;
+import static gregtech.api.util.GT_StructureUtilityMuTE.MOTOR_CASINGS;
+import static gregtech.api.util.GT_StructureUtilityMuTE.ofMuTECasings;
+
+import java.util.Arrays;
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.ResourceLocation;
+
+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.GregTech_API;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.SoundResource;
+import gregtech.api.multitileentity.enums.GT_MultiTileCasing;
+import gregtech.api.multitileentity.multiblock.base.StackableModularController;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_StructureUtility;
+import gregtech.api.util.GT_StructureUtilityMuTE.UpgradeCasings;
+import gregtech.common.tileentities.machines.multiblock.logic.LayeredCokeBatteryProcessingLogic;
+
+public class LayeredCokeBattery
+ extends StackableModularController<LayeredCokeBattery, LayeredCokeBatteryProcessingLogic> {
+
+ private static IStructureDefinition<LayeredCokeBattery> STRUCTURE_DEFINITION_MEGA = null;
+ protected static final String STRUCTURE_PIECE_BASE = "T1";
+ private static final Vec3Impl STRUCTURE_OFFSET_BASE = new Vec3Impl(2, 2, 0);
+ private static final Vec3Impl STRUCTURE_OFFSET_MEGA_POSITION = new Vec3Impl(4, 7, -4);
+ private static final Vec3Impl STRUCTURE_OFFSET_MEGA_START = new Vec3Impl(0, 0, -3);
+ private static final Vec3Impl STRUCTURE_OFFSET_MEGA_STACK = new Vec3Impl(0, 0, -2);
+ private static final Vec3Impl STRUCTURE_OFFSET_MEGA_STOP = new Vec3Impl(0, 0, -1);
+
+ @Override
+ public String getTileEntityName() {
+ return "gt.multitileentity.multiblock.layeredcokebattery";
+ }
+
+ @Override
+ public String getLocalName() {
+ return "Layered Coke Battery";
+ }
+
+ @Override
+ public Vec3Impl getStartingStructureOffset() {
+ return STRUCTURE_OFFSET_BASE;
+ }
+
+ public UpgradeCasings getBaseMucType() {
+ return UpgradeCasings.Heater;
+ }
+
+ public int getParallelFactor() {
+ return 2;
+ }
+
+ @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(STRUCTURE_PIECE_BASE, trigger, hintsOnly, buildState.getCurrentOffset());
+ buildState.addOffset(getMegaPositionOffset());
+
+ if (stackCount >= 1) {
+ buildPiece(STACKABLE_START, 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()) {
+ buildPiece(STACKABLE_STOP, trigger, hintsOnly, buildState.getCurrentOffset());
+ }
+ }
+
+ buildState.stopBuilding();
+ }
+
+ @Override
+ public IStructureDefinition<LayeredCokeBattery> getStructureDefinition() {
+ if (STRUCTURE_DEFINITION_MEGA == null) {
+ STRUCTURE_DEFINITION_MEGA = StructureDefinition.<LayeredCokeBattery>builder()
+ .addShape(
+ STRUCTURE_PIECE_BASE,
+ transpose(
+ new String[][] { { " AAA ", "AAAAA", "AEEEP", "AAAAA" }, { " AAA ", "A A", "A A", "AAAAA" },
+ { " A~A ", "A A", "A A", "AAAAA" }, { " AAA ", "A A", "A A", "AAAAA" },
+ { " AAA ", "AAAAA", "AAAAA", "AAAAA" } }))
+ .addShape(
+ STACKABLE_STOP,
+ transpose(
+ new String[][] { { "AHFFFFAFFFFHA", "AAAAAAAAAAAAA" }, { " B B B B B B ", "AFAFAFAFAFAFA" },
+ { "HB B B B B BH", "AFAFAFAFAFAFA" }, { " B B B B B B ", "AFAFAFAFAFAFA" },
+ { " B B B B B B ", "AFAFAFAFAFAFA" }, { " B B B B B B ", "AFAFAFAFAFAFA" },
+ { " B B B B B B ", "AFAFAFAFAFAFA" }, { " B B B B B B ", "AFAFAFAFAFAFA" },
+ { " B B B B B B ", "AFAFAFAFAFAFA" }, { "HB B B B B BH", "AFAFAFAFAFAFA" },
+ { " B B B B B B ", "AFAFAFAFAFAFA" }, { "AAAAAAAAAAAAA", "AAAAAAAAAAAAA" } }))
+ .addShape(
+ STACKABLE_MIDDLE,
+ transpose(
+ new String[][] { { "AHFFFFAFFFFHA", "AAAAAAAAAAAAA" }, { " B A B ", "AAAAAAAAAAAAA" },
+ { "HB A BH", "AAAAAAAAAAAAA" }, { " B A B ", "AAAAAAAAAAAAA" },
+ { " B A B ", "AAAAAAAAAAAAA" }, { " B A B ", "AAAAAAAAAAAAA" },
+ { " B A B ", "AAAAAAAAAAAAA" }, { " B A B ", "AAAAAAAAAAAAA" },
+ { " B A B ", "AAAAAAAAAAAAA" }, { "HB A BH", "AAAAAAAAAAAAA" },
+ { " B A B ", "AAAAAAAAAAAAA" }, { "AAAAAAAAAAAAA", "AAAAAAAAAAAAA" } }))
+ .addShape(
+ STACKABLE_START,
+ transpose(
+ new String[][] { { "AAAAAAAAAAAAA", "AHFFFFAFFFFHA", "AAAAAAAAAAAAA" },
+ { "AFAFAFAFAFAFA", " B B B B B B ", "AAAAAAAAAAAAA" },
+ { "AFAFAFAFAFAFA", "HB B B B B BH", "AAAAAAAAAAAAA" },
+ { "AFAFAFAFAFAFA", " B B B B B B ", "AAAAAAAAAAAAA" },
+ { "AFAFAFAFAFAFA", " B B B B B B ", "AAAAAAAAAAAAA" },
+ { "AFAFAFAFAFAFA", " B B B B B B ", "AAAAAAAAAAAAA" },
+ { "AFAFAFAFAFAFA", " B B B B B B ", "AAAAAAAAAAAAA" },
+ { "AFAFAFAFAFAFA", " B B B B B B ", "AAAAAAAAAAAAA" },
+ { "AFAFAFAFAFAFA", " B B B B B B ", "AAAAAAAAAAAAA" },
+ { "AFAFAFAFAFAFA", "HB B B B B BH", "AAAAAAAAAAAAA" },
+ { "AFAFAFAFAFAFA", " B B B B B B ", "AAAAAAAAAAAAA" },
+ { "AAAAAAAAAAAAA", "AAAAAAAAAAAAA", "AAAAAAAAAAAAA" } }))
+ .addElement(
+ 'A',
+ ofMuTECasings(
+ FLUID_IN | ITEM_IN | FLUID_OUT | ITEM_OUT | ENERGY_IN,
+ GT_MultiTileCasing.Chemical.getCasing()))
+ .addElement(
+ 'B',
+ ofMuTECasings(
+ FLUID_IN | ITEM_IN | FLUID_OUT | ITEM_OUT | ENERGY_IN,
+ GT_MultiTileCasing.Distillation.getCasing()))
+ .addElement('C', ofBlock(GregTech_API.sBlockCasings4, 1))
+ .addElement('D', GT_StructureUtility.ofFrame(Materials.Steel))
+ .addElement('E', ofMuTECasings(NOTHING, MOTOR_CASINGS))
+ .addElement(
+ 'F',
+ 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)))
+ .addElement('H', ofMuTECasings(NOTHING, HEATER_CASINGS, INSULATOR_CASINGS))
+ .addElement('P', ofMuTECasings(NOTHING, AMPERAGE_CASINGS))
+ .build();
+ }
+ return STRUCTURE_DEFINITION_MEGA;
+ }
+
+ public boolean checkMachine() {
+ stackCount = 0;
+ resetMucCount();
+
+ buildState.startBuilding(getStartingStructureOffset());
+ if (!checkPiece(STRUCTURE_PIECE_BASE, buildState.getCurrentOffset())) return buildState.failBuilding();
+
+ buildState.addOffset(getMegaPositionOffset());
+ if (!checkPiece(STACKABLE_START, buildState.getCurrentOffset())) {
+ return buildState.failBuilding();
+ }
+
+ buildState.addOffset(getStartingStackOffset());
+ for (int i = 0; i < getMaxStacks(); i++) {
+ if (!checkPiece(getStackableMiddle(i), buildState.getCurrentOffset())) {
+ break;
+ }
+
+ buildState.addOffset(getPerStackOffset());
+ stackCount++;
+ }
+ if (stackCount < getMinStacks()) return buildState.failBuilding();
+
+ if (!checkPiece(getStackableStop(), buildState.stopBuilding())) {
+ return buildState.failBuilding();
+ }
+
+ calculateTier();
+ if (!calculateMucMultipliers()) {
+ return false;
+ }
+ calculateParallels();
+ updatePowerLogic();
+ return tier > 0;
+ }
+
+ protected boolean calculateMucMultipliers() {
+ Map<UpgradeCasings, int[]> mucMap = getMucMap();
+ int[] heaterList = mucMap.get(UpgradeCasings.Heater);
+ int[] insulatorList = mucMap.get(UpgradeCasings.Insulator);
+ int totalHeaterCount = Arrays.stream(heaterList)
+ .sum();
+ int totalInsulatorCount = Arrays.stream(insulatorList)
+ .sum();
+ if (totalHeaterCount + totalInsulatorCount < stackCount || totalInsulatorCount > totalHeaterCount) {
+ return false;
+ }
+ if (totalInsulatorCount > 0) {
+ // To be improved later, when more MUCs are added
+ // durationMultiplier = 1.0 / totalHeaterCount;
+ euTickMultiplier = 1.0 / totalInsulatorCount;
+ }
+ return true;
+ }
+
+ @Override
+ public short getCasingRegistryID() {
+ return 0;
+ }
+
+ @Override
+ public int getCasingMeta() {
+ return GT_MultiTileCasing.Distillation.getId();
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Coke Oven")
+ .addInfo("Controller for the Layered Coke Battery")
+ .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 0;
+ }
+
+ @Override
+ public int getMaxStacks() {
+ return 20;
+ }
+
+ public Vec3Impl getMegaPositionOffset() {
+ return STRUCTURE_OFFSET_MEGA_POSITION;
+ }
+
+ @Override
+ public Vec3Impl getStartingStackOffset() {
+ return STRUCTURE_OFFSET_MEGA_START;
+ }
+
+ @Override
+ public Vec3Impl getPerStackOffset() {
+ return STRUCTURE_OFFSET_MEGA_STACK;
+ }
+
+ @Override
+ public Vec3Impl getAfterLastStackOffset() {
+ return STRUCTURE_OFFSET_MEGA_STOP;
+ }
+
+ @SideOnly(Side.CLIENT)
+ @Override
+ protected ResourceLocation getActivitySoundLoop() {
+ return SoundResource.IC2_MACHINES_MACERATOR_OP.resourceLocation;
+ }
+
+ @Override
+ @Nonnull
+ protected LayeredCokeBatteryProcessingLogic createProcessingLogic() {
+ return new LayeredCokeBatteryProcessingLogic();
+ }
+}
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..dfdacfe7f2
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multiblock/Macerator.java
@@ -0,0 +1,132 @@
+package gregtech.common.tileentities.machines.multiblock;
+
+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 static gregtech.api.util.GT_StructureUtilityMuTE.*;
+
+import javax.annotation.Nonnull;
+
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+import com.gtnewhorizon.structurelib.util.Vec3Impl;
+
+import gregtech.api.multitileentity.enums.GT_MultiTileCasing;
+import gregtech.api.multitileentity.multiblock.base.StackableController;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.common.tileentities.machines.multiblock.logic.MaceratorProcessingLogic;
+
+public class Macerator extends StackableController<Macerator, MaceratorProcessingLogic> {
+
+ private static IStructureDefinition<Macerator> STRUCTURE_DEFINITION = null;
+
+ public Macerator() {
+ super();
+ }
+
+ @Override
+ public String getTileEntityName() {
+ return "gt.multitileentity.multiblock.macerator";
+ }
+
+ @Override
+ public IStructureDefinition<Macerator> getStructureDefinition() {
+ if (STRUCTURE_DEFINITION == null) {
+ STRUCTURE_DEFINITION = StructureDefinition.<Macerator>builder()
+ .addShape(
+ STACKABLE_STOP,
+ transpose(new String[][] { { " CCC ", "CCCCC", "CCCCC", "CCCCC", " CCC " }, }))
+ .addShape(
+ STACKABLE_MIDDLE,
+ transpose(new String[][] { { " BBB ", " B---B ", "DC---CD", " B---B ", " BBB " }, }))
+ .addShape(
+ STACKABLE_START,
+ transpose(new String[][] { { " G~F ", "AAAAA", "AAAAA", "AAAAA", " AAA " }, }))
+ .addElement('A', ofMuTECasings(ENERGY_IN, GT_MultiTileCasing.Macerator.getCasing()))
+ .addElement(
+ 'B',
+ ofMuTECasings(FLUID_IN | ITEM_IN | FLUID_OUT | ITEM_OUT, GT_MultiTileCasing.Macerator.getCasing()))
+ .addElement('C', ofMuTECasings(NOTHING, GT_MultiTileCasing.Macerator.getCasing()))
+ .addElement('D', ofMuTECasings(NOTHING, GT_MultiTileCasing.Macerator.getCasing()))
+ .addElement('F', ofMuTECasings(NOTHING, MOTOR_CASINGS))
+ .addElement('G', ofMuTECasings(NOTHING, INVENTORY_CASINGS))
+ .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
+ @Nonnull
+ protected MaceratorProcessingLogic createProcessingLogic() {
+ return new MaceratorProcessingLogic();
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/AdvChemicalProcessorProcessingLogic.java b/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/AdvChemicalProcessorProcessingLogic.java
new file mode 100644
index 0000000000..59879e30c7
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/AdvChemicalProcessorProcessingLogic.java
@@ -0,0 +1,12 @@
+package gregtech.common.tileentities.machines.multiblock.logic;
+
+import gregtech.api.logic.ComplexParallelProcessingLogic;
+import gregtech.api.recipe.RecipeMaps;
+
+public class AdvChemicalProcessorProcessingLogic
+ extends ComplexParallelProcessingLogic<AdvChemicalProcessorProcessingLogic> {
+
+ public AdvChemicalProcessorProcessingLogic() {
+ setRecipeMap(RecipeMaps.multiblockChemicalReactorRecipes);
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/CokeOvenProcessingLogic.java b/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/CokeOvenProcessingLogic.java
new file mode 100644
index 0000000000..1534b05bc3
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/CokeOvenProcessingLogic.java
@@ -0,0 +1,79 @@
+package gregtech.common.tileentities.machines.multiblock.logic;
+
+import static gregtech.api.enums.Mods.Railcraft;
+import static net.minecraftforge.oredict.OreDictionary.getOreID;
+import static net.minecraftforge.oredict.OreDictionary.getOreIDs;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import net.minecraft.init.Items;
+import net.minecraft.item.ItemStack;
+
+import gregtech.api.logic.FluidInventoryLogic;
+import gregtech.api.logic.ItemInventoryLogic;
+import gregtech.api.logic.MuTEProcessingLogic;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_OreDictUnificator;
+
+public class CokeOvenProcessingLogic extends MuTEProcessingLogic<CokeOvenProcessingLogic> {
+
+ private static final int NORMAL_RECIPE_TIME = 1800;
+ private static final int WOOD_ORE_ID = getOreID("logWood");
+ private static final int COAL_ORE_ID = getOreID("coal");
+ private static final int COAL_BLOCK_ORE_ID = getOreID("blockCoal");
+ private static final int SUGARCANE_ORE_ID = getOreID("sugarcane");
+ private static final int CACTUS_ORE_ID = getOreID("blockCactus");
+ private static final int CACTUS_CHARCOAL_ORE_ID = getOreID("itemCharcoalCactus");
+ private static final int SUGAR_CHARCOAL_ORE_ID = getOreID("itemCharcoalSugar");
+ private int timeMultiplier = 1;
+
+ @Nonnull
+ @Override
+ protected Object findRecipe(@Nullable RecipeMap<?> map, @Nonnull ItemInventoryLogic itemInput,
+ @Nonnull FluidInventoryLogic fluidInput) {
+ for (ItemStack item : itemInput.getStoredItems()) {
+ ItemStack output = findRecipe(item);
+ if (output != null) {
+ ItemStack input = item.copy();
+ input.stackSize = 1;
+ return null;
+ // return FindRecipeResult.ofSuccess(
+ // GT_Values.RA.stdBuilder()
+ // .itemInputs(input)
+ // .itemOutputs(output)
+ // .noFluidInputs()
+ // .noFluidOutputs()
+ // .duration(NORMAL_RECIPE_TIME * timeMultiplier)
+ // .eut(0)
+ // .build()
+ // .get());
+ }
+ }
+ return null;
+ }
+
+ @Nullable
+ private ItemStack findRecipe(@Nonnull ItemStack input) {
+ for (int oreId : getOreIDs(input)) {
+ if (oreId == COAL_ORE_ID) {
+ return GT_OreDictUnificator.get("fuelCoke", null, 1);
+ } else if (oreId == COAL_BLOCK_ORE_ID) {
+ timeMultiplier = 9;
+ return GT_ModHandler.getModItem(Railcraft.ID, "cube", 1, 0);
+ } else if (oreId == WOOD_ORE_ID) {
+ return new ItemStack(Items.coal, 1, 1);
+ } else if (oreId == SUGARCANE_ORE_ID) {
+ return GT_OreDictUnificator.get("itemCharcoalSugar", null, 1);
+ } else if (oreId == SUGAR_CHARCOAL_ORE_ID) {
+ return GT_OreDictUnificator.get("itemCokeSugar", null, 1);
+ } else if (oreId == CACTUS_ORE_ID) {
+ return GT_OreDictUnificator.get("itemCharcoalCactus", null, 1);
+ } else if (oreId == CACTUS_CHARCOAL_ORE_ID) {
+ return GT_OreDictUnificator.get("itemCokeCactus", null, 1);
+ }
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/DistillationTowerProcessingLogic.java b/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/DistillationTowerProcessingLogic.java
new file mode 100644
index 0000000000..6f27c9a0e6
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/DistillationTowerProcessingLogic.java
@@ -0,0 +1,7 @@
+package gregtech.common.tileentities.machines.multiblock.logic;
+
+import gregtech.api.logic.ComplexParallelProcessingLogic;
+
+public class DistillationTowerProcessingLogic extends ComplexParallelProcessingLogic<DistillationTowerProcessingLogic> {
+
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/LaserEngraverProcessingLogic.java b/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/LaserEngraverProcessingLogic.java
new file mode 100644
index 0000000000..3f4a6bfe70
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/LaserEngraverProcessingLogic.java
@@ -0,0 +1,7 @@
+package gregtech.common.tileentities.machines.multiblock.logic;
+
+import gregtech.api.logic.ComplexParallelProcessingLogic;
+
+public class LaserEngraverProcessingLogic extends ComplexParallelProcessingLogic<LaserEngraverProcessingLogic> {
+
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/LayeredCokeBatteryProcessingLogic.java b/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/LayeredCokeBatteryProcessingLogic.java
new file mode 100644
index 0000000000..b2e43b6fa9
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/LayeredCokeBatteryProcessingLogic.java
@@ -0,0 +1,7 @@
+package gregtech.common.tileentities.machines.multiblock.logic;
+
+import gregtech.api.logic.MuTEProcessingLogic;
+
+public class LayeredCokeBatteryProcessingLogic extends MuTEProcessingLogic<LayeredCokeBatteryProcessingLogic> {
+
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/MaceratorProcessingLogic.java b/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/MaceratorProcessingLogic.java
new file mode 100644
index 0000000000..3f7d8a25f7
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/MaceratorProcessingLogic.java
@@ -0,0 +1,7 @@
+package gregtech.common.tileentities.machines.multiblock.logic;
+
+import gregtech.api.logic.MuTEProcessingLogic;
+
+public class MaceratorProcessingLogic extends MuTEProcessingLogic<MaceratorProcessingLogic> {
+
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_AlloySmelter_Bronze.java b/src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_AlloySmelter_Bronze.java
new file mode 100644
index 0000000000..9b2c6b3ada
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_AlloySmelter_Bronze.java
@@ -0,0 +1,139 @@
+package gregtech.common.tileentities.machines.steam;
+
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_ALLOY_SMELTER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_ALLOY_SMELTER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_ALLOY_SMELTER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_ALLOY_SMELTER_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_ALLOY_SMELTER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_ALLOY_SMELTER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_ALLOY_SMELTER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_ALLOY_SMELTER_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_ALLOY_SMELTER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_ALLOY_SMELTER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_ALLOY_SMELTER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_ALLOY_SMELTER_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_ALLOY_SMELTER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_ALLOY_SMELTER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_ALLOY_SMELTER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_ALLOY_SMELTER_GLOW;
+
+import gregtech.api.enums.SoundResource;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachine_Bronze;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_AlloySmelter_Bronze extends GT_MetaTileEntity_BasicMachine_Bronze {
+
+ public GT_MetaTileEntity_AlloySmelter_Bronze(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional, "Combination Smelter", 2, 1, false);
+ }
+
+ public GT_MetaTileEntity_AlloySmelter_Bronze(String aName, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aDescription, aTextures, 2, 1, false);
+ }
+
+ @Override
+ protected boolean isBricked() {
+ return true;
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_AlloySmelter_Bronze(mName, mDescriptionArray, mTextures);
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.alloySmelterRecipes;
+ }
+
+ @Override
+ public void startSoundLoop(byte aIndex, double aX, double aY, double aZ) {
+ super.startSoundLoop(aIndex, aX, aY, aZ);
+ if (aIndex == 1) {
+ GT_Utility.doSoundAtClient(SoundResource.IC2_MACHINES_INDUCTION_LOOP, 10, 1.0F, aX, aY, aZ);
+ }
+ }
+
+ @Override
+ public void startProcess() {
+ sendLoopStart((byte) 1);
+ }
+
+ @Override
+ public ITexture[] getSideFacingActive(byte aColor) {
+ return new ITexture[] { super.getSideFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_SIDE_STEAM_ALLOY_SMELTER_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_STEAM_ALLOY_SMELTER_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getSideFacingInactive(byte aColor) {
+ return new ITexture[] { super.getSideFacingInactive(aColor)[0],
+ TextureFactory.of(OVERLAY_SIDE_STEAM_ALLOY_SMELTER), TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_STEAM_ALLOY_SMELTER_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getFrontFacingActive(byte aColor) {
+ return new ITexture[] { super.getFrontFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_FRONT_STEAM_ALLOY_SMELTER_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_STEAM_ALLOY_SMELTER_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getFrontFacingInactive(byte aColor) {
+ return new ITexture[] { super.getFrontFacingInactive(aColor)[0],
+ TextureFactory.of(OVERLAY_FRONT_STEAM_ALLOY_SMELTER), TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_STEAM_ALLOY_SMELTER_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getTopFacingActive(byte aColor) {
+ return new ITexture[] { super.getTopFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_TOP_STEAM_ALLOY_SMELTER_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_STEAM_ALLOY_SMELTER_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getTopFacingInactive(byte aColor) {
+ return new ITexture[] { super.getTopFacingInactive(aColor)[0],
+ TextureFactory.of(OVERLAY_TOP_STEAM_ALLOY_SMELTER), TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_STEAM_ALLOY_SMELTER_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getBottomFacingActive(byte aColor) {
+ return new ITexture[] { super.getBottomFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_BOTTOM_STEAM_ALLOY_SMELTER_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_STEAM_ALLOY_SMELTER_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getBottomFacingInactive(byte aColor) {
+ return new ITexture[] { super.getBottomFacingInactive(aColor)[0],
+ TextureFactory.of(OVERLAY_BOTTOM_STEAM_ALLOY_SMELTER), TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_STEAM_ALLOY_SMELTER_GLOW)
+ .glow()
+ .build() };
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_AlloySmelter_Steel.java b/src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_AlloySmelter_Steel.java
new file mode 100644
index 0000000000..8b96906da1
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_AlloySmelter_Steel.java
@@ -0,0 +1,139 @@
+package gregtech.common.tileentities.machines.steam;
+
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_ALLOY_SMELTER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_ALLOY_SMELTER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_ALLOY_SMELTER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_ALLOY_SMELTER_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_ALLOY_SMELTER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_ALLOY_SMELTER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_ALLOY_SMELTER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_ALLOY_SMELTER_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_ALLOY_SMELTER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_ALLOY_SMELTER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_ALLOY_SMELTER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_ALLOY_SMELTER_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_ALLOY_SMELTER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_ALLOY_SMELTER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_ALLOY_SMELTER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_ALLOY_SMELTER_GLOW;
+
+import gregtech.api.enums.SoundResource;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachine_Steel;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_AlloySmelter_Steel extends GT_MetaTileEntity_BasicMachine_Steel {
+
+ public GT_MetaTileEntity_AlloySmelter_Steel(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional, "Combination Smelter", 2, 1, true);
+ }
+
+ public GT_MetaTileEntity_AlloySmelter_Steel(String aName, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aDescription, aTextures, 2, 1, true);
+ }
+
+ @Override
+ protected boolean isBricked() {
+ return true;
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_AlloySmelter_Steel(mName, mDescriptionArray, mTextures);
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.alloySmelterRecipes;
+ }
+
+ @Override
+ public void startSoundLoop(byte aIndex, double aX, double aY, double aZ) {
+ super.startSoundLoop(aIndex, aX, aY, aZ);
+ if (aIndex == 1) {
+ GT_Utility.doSoundAtClient(SoundResource.IC2_MACHINES_INDUCTION_LOOP, 10, 1.0F, aX, aY, aZ);
+ }
+ }
+
+ @Override
+ public void startProcess() {
+ sendLoopStart((byte) 1);
+ }
+
+ @Override
+ public ITexture[] getSideFacingActive(byte aColor) {
+ return new ITexture[] { super.getSideFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_SIDE_STEAM_ALLOY_SMELTER_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_STEAM_ALLOY_SMELTER_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getSideFacingInactive(byte aColor) {
+ return new ITexture[] { super.getSideFacingInactive(aColor)[0],
+ TextureFactory.of(OVERLAY_SIDE_STEAM_ALLOY_SMELTER), TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_STEAM_ALLOY_SMELTER_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getFrontFacingActive(byte aColor) {
+ return new ITexture[] { super.getFrontFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_FRONT_STEAM_ALLOY_SMELTER_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_STEAM_ALLOY_SMELTER_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getFrontFacingInactive(byte aColor) {
+ return new ITexture[] { super.getFrontFacingInactive(aColor)[0],
+ TextureFactory.of(OVERLAY_FRONT_STEAM_ALLOY_SMELTER), TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_STEAM_ALLOY_SMELTER_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getTopFacingActive(byte aColor) {
+ return new ITexture[] { super.getTopFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_TOP_STEAM_ALLOY_SMELTER_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_STEAM_ALLOY_SMELTER_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getTopFacingInactive(byte aColor) {
+ return new ITexture[] { super.getTopFacingInactive(aColor)[0],
+ TextureFactory.of(OVERLAY_TOP_STEAM_ALLOY_SMELTER), TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_STEAM_ALLOY_SMELTER_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getBottomFacingActive(byte aColor) {
+ return new ITexture[] { super.getBottomFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_BOTTOM_STEAM_ALLOY_SMELTER_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_STEAM_ALLOY_SMELTER_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getBottomFacingInactive(byte aColor) {
+ return new ITexture[] { super.getBottomFacingInactive(aColor)[0],
+ TextureFactory.of(OVERLAY_BOTTOM_STEAM_ALLOY_SMELTER), TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_STEAM_ALLOY_SMELTER_GLOW)
+ .glow()
+ .build() };
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_Compressor_Bronze.java b/src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_Compressor_Bronze.java
new file mode 100644
index 0000000000..ef91ed5baf
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_Compressor_Bronze.java
@@ -0,0 +1,134 @@
+package gregtech.common.tileentities.machines.steam;
+
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_COMPRESSOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_COMPRESSOR_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_COMPRESSOR_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_COMPRESSOR_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_COMPRESSOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_COMPRESSOR_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_COMPRESSOR_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_COMPRESSOR_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_COMPRESSOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_COMPRESSOR_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_COMPRESSOR_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_COMPRESSOR_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_COMPRESSOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_COMPRESSOR_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_COMPRESSOR_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_COMPRESSOR_GLOW;
+
+import gregtech.api.enums.SoundResource;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachine_Bronze;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_Compressor_Bronze extends GT_MetaTileEntity_BasicMachine_Bronze {
+
+ public GT_MetaTileEntity_Compressor_Bronze(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional, "Compressing Items", 1, 1, false);
+ }
+
+ public GT_MetaTileEntity_Compressor_Bronze(String aName, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aDescription, aTextures, 1, 1, false);
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Compressor_Bronze(this.mName, this.mDescriptionArray, this.mTextures);
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.compressorRecipes;
+ }
+
+ @Override
+ public void startSoundLoop(byte aIndex, double aX, double aY, double aZ) {
+ super.startSoundLoop(aIndex, aX, aY, aZ);
+ if (aIndex == 1) {
+ GT_Utility.doSoundAtClient(SoundResource.IC2_MACHINES_COMPRESSOR_OP, 10, 1.0F, aX, aY, aZ);
+ }
+ }
+
+ @Override
+ public void startProcess() {
+ sendLoopStart((byte) 1);
+ }
+
+ @Override
+ public ITexture[] getSideFacingActive(byte aColor) {
+ return new ITexture[] { super.getSideFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_SIDE_STEAM_COMPRESSOR_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_STEAM_COMPRESSOR_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getSideFacingInactive(byte aColor) {
+ return new ITexture[] { super.getSideFacingInactive(aColor)[0],
+ TextureFactory.of(OVERLAY_SIDE_STEAM_COMPRESSOR), TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_STEAM_COMPRESSOR_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getFrontFacingActive(byte aColor) {
+ return new ITexture[] { super.getFrontFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_FRONT_STEAM_COMPRESSOR_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_STEAM_COMPRESSOR_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getFrontFacingInactive(byte aColor) {
+ return new ITexture[] { super.getFrontFacingInactive(aColor)[0],
+ TextureFactory.of(OVERLAY_FRONT_STEAM_COMPRESSOR), TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_STEAM_COMPRESSOR_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getTopFacingActive(byte aColor) {
+ return new ITexture[] { super.getTopFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_TOP_STEAM_COMPRESSOR_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_STEAM_COMPRESSOR_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getTopFacingInactive(byte aColor) {
+ return new ITexture[] { super.getTopFacingInactive(aColor)[0], TextureFactory.of(OVERLAY_TOP_STEAM_COMPRESSOR),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_STEAM_COMPRESSOR_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getBottomFacingActive(byte aColor) {
+ return new ITexture[] { super.getBottomFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_BOTTOM_STEAM_COMPRESSOR_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_STEAM_COMPRESSOR_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getBottomFacingInactive(byte aColor) {
+ return new ITexture[] { super.getBottomFacingInactive(aColor)[0],
+ TextureFactory.of(OVERLAY_BOTTOM_STEAM_COMPRESSOR), TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_STEAM_COMPRESSOR_GLOW)
+ .glow()
+ .build() };
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_Compressor_Steel.java b/src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_Compressor_Steel.java
new file mode 100644
index 0000000000..c213cf04f5
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_Compressor_Steel.java
@@ -0,0 +1,134 @@
+package gregtech.common.tileentities.machines.steam;
+
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_COMPRESSOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_COMPRESSOR_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_COMPRESSOR_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_COMPRESSOR_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_COMPRESSOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_COMPRESSOR_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_COMPRESSOR_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_COMPRESSOR_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_COMPRESSOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_COMPRESSOR_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_COMPRESSOR_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_COMPRESSOR_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_COMPRESSOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_COMPRESSOR_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_COMPRESSOR_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_COMPRESSOR_GLOW;
+
+import gregtech.api.enums.SoundResource;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachine_Steel;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_Compressor_Steel extends GT_MetaTileEntity_BasicMachine_Steel {
+
+ public GT_MetaTileEntity_Compressor_Steel(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional, "Compressing Items", 1, 1, true);
+ }
+
+ public GT_MetaTileEntity_Compressor_Steel(String aName, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aDescription, aTextures, 1, 1, true);
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Compressor_Steel(this.mName, this.mDescriptionArray, this.mTextures);
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.compressorRecipes;
+ }
+
+ @Override
+ public void startSoundLoop(byte aIndex, double aX, double aY, double aZ) {
+ super.startSoundLoop(aIndex, aX, aY, aZ);
+ if (aIndex == 1) {
+ GT_Utility.doSoundAtClient(SoundResource.IC2_MACHINES_COMPRESSOR_OP, 10, 1.0F, aX, aY, aZ);
+ }
+ }
+
+ @Override
+ public void startProcess() {
+ sendLoopStart((byte) 1);
+ }
+
+ @Override
+ public ITexture[] getSideFacingActive(byte aColor) {
+ return new ITexture[] { super.getSideFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_SIDE_STEAM_COMPRESSOR_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_STEAM_COMPRESSOR_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getSideFacingInactive(byte aColor) {
+ return new ITexture[] { super.getSideFacingInactive(aColor)[0],
+ TextureFactory.of(OVERLAY_SIDE_STEAM_COMPRESSOR), TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_STEAM_COMPRESSOR_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getFrontFacingActive(byte aColor) {
+ return new ITexture[] { super.getFrontFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_FRONT_STEAM_COMPRESSOR_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_STEAM_COMPRESSOR_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getFrontFacingInactive(byte aColor) {
+ return new ITexture[] { super.getFrontFacingInactive(aColor)[0],
+ TextureFactory.of(OVERLAY_FRONT_STEAM_COMPRESSOR), TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_STEAM_COMPRESSOR_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getTopFacingActive(byte aColor) {
+ return new ITexture[] { super.getTopFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_TOP_STEAM_COMPRESSOR_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_STEAM_COMPRESSOR_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getTopFacingInactive(byte aColor) {
+ return new ITexture[] { super.getTopFacingInactive(aColor)[0], TextureFactory.of(OVERLAY_TOP_STEAM_COMPRESSOR),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_STEAM_COMPRESSOR_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getBottomFacingActive(byte aColor) {
+ return new ITexture[] { super.getBottomFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_BOTTOM_STEAM_COMPRESSOR_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_STEAM_COMPRESSOR_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getBottomFacingInactive(byte aColor) {
+ return new ITexture[] { super.getBottomFacingInactive(aColor)[0],
+ TextureFactory.of(OVERLAY_BOTTOM_STEAM_COMPRESSOR), TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_STEAM_COMPRESSOR_GLOW)
+ .glow()
+ .build() };
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_Extractor_Bronze.java b/src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_Extractor_Bronze.java
new file mode 100644
index 0000000000..6e986992f3
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_Extractor_Bronze.java
@@ -0,0 +1,134 @@
+package gregtech.common.tileentities.machines.steam;
+
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_EXTRACTOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_EXTRACTOR_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_EXTRACTOR_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_EXTRACTOR_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_EXTRACTOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_EXTRACTOR_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_EXTRACTOR_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_EXTRACTOR_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_EXTRACTOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_EXTRACTOR_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_EXTRACTOR_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_EXTRACTOR_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_EXTRACTOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_EXTRACTOR_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_EXTRACTOR_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_EXTRACTOR_GLOW;
+
+import gregtech.api.enums.SoundResource;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachine_Bronze;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_Extractor_Bronze extends GT_MetaTileEntity_BasicMachine_Bronze {
+
+ public GT_MetaTileEntity_Extractor_Bronze(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional, "Extracting your first Rubber", 1, 1, false);
+ }
+
+ public GT_MetaTileEntity_Extractor_Bronze(String aName, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aDescription, aTextures, 1, 1, false);
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Extractor_Bronze(this.mName, this.mDescriptionArray, this.mTextures);
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.extractorRecipes;
+ }
+
+ @Override
+ public void startSoundLoop(byte aIndex, double aX, double aY, double aZ) {
+ super.startSoundLoop(aIndex, aX, aY, aZ);
+ if (aIndex == 1) {
+ GT_Utility.doSoundAtClient(SoundResource.IC2_MACHINES_EXTRACTOR_OP, 10, 1.0F, aX, aY, aZ);
+ }
+ }
+
+ @Override
+ public void startProcess() {
+ sendLoopStart((byte) 1);
+ }
+
+ @Override
+ public ITexture[] getSideFacingActive(byte aColor) {
+ return new ITexture[] { super.getSideFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_SIDE_STEAM_EXTRACTOR_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_STEAM_EXTRACTOR_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getSideFacingInactive(byte aColor) {
+ return new ITexture[] { super.getSideFacingInactive(aColor)[0], TextureFactory.of(OVERLAY_SIDE_STEAM_EXTRACTOR),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_STEAM_EXTRACTOR_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getFrontFacingActive(byte aColor) {
+ return new ITexture[] { super.getFrontFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_FRONT_STEAM_EXTRACTOR_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_STEAM_EXTRACTOR_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getFrontFacingInactive(byte aColor) {
+ return new ITexture[] { super.getFrontFacingInactive(aColor)[0],
+ TextureFactory.of(OVERLAY_FRONT_STEAM_EXTRACTOR), TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_STEAM_EXTRACTOR_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getTopFacingActive(byte aColor) {
+ return new ITexture[] { super.getTopFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_TOP_STEAM_EXTRACTOR_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_STEAM_EXTRACTOR_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getTopFacingInactive(byte aColor) {
+ return new ITexture[] { super.getTopFacingInactive(aColor)[0], TextureFactory.of(OVERLAY_TOP_STEAM_EXTRACTOR),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_STEAM_EXTRACTOR_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getBottomFacingActive(byte aColor) {
+ return new ITexture[] { super.getBottomFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_BOTTOM_STEAM_EXTRACTOR_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_STEAM_EXTRACTOR_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getBottomFacingInactive(byte aColor) {
+ return new ITexture[] { super.getBottomFacingInactive(aColor)[0],
+ TextureFactory.of(OVERLAY_BOTTOM_STEAM_EXTRACTOR), TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_STEAM_EXTRACTOR_GLOW)
+ .glow()
+ .build() };
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_Extractor_Steel.java b/src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_Extractor_Steel.java
new file mode 100644
index 0000000000..6a3d024e25
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_Extractor_Steel.java
@@ -0,0 +1,134 @@
+package gregtech.common.tileentities.machines.steam;
+
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_EXTRACTOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_EXTRACTOR_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_EXTRACTOR_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_EXTRACTOR_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_EXTRACTOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_EXTRACTOR_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_EXTRACTOR_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_EXTRACTOR_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_EXTRACTOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_EXTRACTOR_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_EXTRACTOR_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_EXTRACTOR_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_EXTRACTOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_EXTRACTOR_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_EXTRACTOR_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_EXTRACTOR_GLOW;
+
+import gregtech.api.enums.SoundResource;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachine_Steel;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_Extractor_Steel extends GT_MetaTileEntity_BasicMachine_Steel {
+
+ public GT_MetaTileEntity_Extractor_Steel(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional, "Extracting your first Rubber", 1, 1, true);
+ }
+
+ public GT_MetaTileEntity_Extractor_Steel(String aName, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aDescription, aTextures, 1, 1, true);
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Extractor_Steel(this.mName, this.mDescriptionArray, this.mTextures);
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.extractorRecipes;
+ }
+
+ @Override
+ public void startSoundLoop(byte aIndex, double aX, double aY, double aZ) {
+ super.startSoundLoop(aIndex, aX, aY, aZ);
+ if (aIndex == 1) {
+ GT_Utility.doSoundAtClient(SoundResource.IC2_MACHINES_EXTRACTOR_OP, 10, 1.0F, aX, aY, aZ);
+ }
+ }
+
+ @Override
+ public void startProcess() {
+ sendLoopStart((byte) 1);
+ }
+
+ @Override
+ public ITexture[] getSideFacingActive(byte aColor) {
+ return new ITexture[] { super.getSideFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_SIDE_STEAM_EXTRACTOR_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_STEAM_EXTRACTOR_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getSideFacingInactive(byte aColor) {
+ return new ITexture[] { super.getSideFacingInactive(aColor)[0], TextureFactory.of(OVERLAY_SIDE_STEAM_EXTRACTOR),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_STEAM_EXTRACTOR_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getFrontFacingActive(byte aColor) {
+ return new ITexture[] { super.getFrontFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_FRONT_STEAM_EXTRACTOR_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_STEAM_EXTRACTOR_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getFrontFacingInactive(byte aColor) {
+ return new ITexture[] { super.getFrontFacingInactive(aColor)[0],
+ TextureFactory.of(OVERLAY_FRONT_STEAM_EXTRACTOR), TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_STEAM_EXTRACTOR_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getTopFacingActive(byte aColor) {
+ return new ITexture[] { super.getTopFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_TOP_STEAM_EXTRACTOR_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_STEAM_EXTRACTOR_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getTopFacingInactive(byte aColor) {
+ return new ITexture[] { super.getTopFacingInactive(aColor)[0], TextureFactory.of(OVERLAY_TOP_STEAM_EXTRACTOR),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_STEAM_EXTRACTOR_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getBottomFacingActive(byte aColor) {
+ return new ITexture[] { super.getBottomFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_BOTTOM_STEAM_EXTRACTOR_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_STEAM_EXTRACTOR_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getBottomFacingInactive(byte aColor) {
+ return new ITexture[] { super.getBottomFacingInactive(aColor)[0],
+ TextureFactory.of(OVERLAY_BOTTOM_STEAM_EXTRACTOR), TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_STEAM_EXTRACTOR_GLOW)
+ .glow()
+ .build() };
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_ForgeHammer_Bronze.java b/src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_ForgeHammer_Bronze.java
new file mode 100644
index 0000000000..b7d25ac172
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_ForgeHammer_Bronze.java
@@ -0,0 +1,202 @@
+package gregtech.common.tileentities.machines.steam;
+
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_HAMMER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_HAMMER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_HAMMER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_HAMMER_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_HAMMER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_HAMMER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_HAMMER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_HAMMER_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_HAMMER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_HAMMER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_HAMMER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_HAMMER_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_HAMMER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_HAMMER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_HAMMER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_HAMMER_GLOW;
+import static gregtech.api.objects.XSTR.XSTR_INSTANCE;
+
+import net.minecraft.block.Block;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.api.enums.ParticleFX;
+import gregtech.api.enums.SoundResource;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachine_Bronze;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.WorldSpawnedEventBuilder.ParticleEventBuilder;
+
+public class GT_MetaTileEntity_ForgeHammer_Bronze extends GT_MetaTileEntity_BasicMachine_Bronze {
+
+ public GT_MetaTileEntity_ForgeHammer_Bronze(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional, "Forge Hammer", 1, 1, false);
+ }
+
+ public GT_MetaTileEntity_ForgeHammer_Bronze(String aName, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aDescription, aTextures, 1, 1, false);
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_ForgeHammer_Bronze(this.mName, this.mDescriptionArray, this.mTextures);
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.hammerRecipes;
+ }
+
+ @Override
+ public void startSoundLoop(byte aIndex, double aX, double aY, double aZ) {
+ super.startSoundLoop(aIndex, aX, aY, aZ);
+ if (aIndex == 1) {
+ GT_Utility.doSoundAtClient(SoundResource.RANDOM_ANVIL_USE, 10, 1.0F, aX, aY, aZ);
+ }
+ }
+
+ @Override
+ public void startProcess() {
+ sendLoopStart((byte) 1);
+ }
+
+ @Override
+ public ITexture[] getSideFacingActive(byte aColor) {
+ return new ITexture[] { super.getSideFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_SIDE_STEAM_HAMMER_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_STEAM_HAMMER_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getSideFacingInactive(byte aColor) {
+ return new ITexture[] { super.getSideFacingInactive(aColor)[0], TextureFactory.of(OVERLAY_SIDE_STEAM_HAMMER),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_STEAM_HAMMER_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getFrontFacingActive(byte aColor) {
+ return new ITexture[] { super.getFrontFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_FRONT_STEAM_HAMMER_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_STEAM_HAMMER_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getFrontFacingInactive(byte aColor) {
+ return new ITexture[] { super.getFrontFacingInactive(aColor)[0], TextureFactory.of(OVERLAY_FRONT_STEAM_HAMMER),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_STEAM_HAMMER_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getTopFacingActive(byte aColor) {
+ return new ITexture[] { super.getTopFacingActive(aColor)[0], TextureFactory.of(OVERLAY_TOP_STEAM_HAMMER_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_STEAM_HAMMER_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getTopFacingInactive(byte aColor) {
+ return new ITexture[] { super.getTopFacingInactive(aColor)[0], TextureFactory.of(OVERLAY_TOP_STEAM_HAMMER),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_STEAM_HAMMER_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getBottomFacingActive(byte aColor) {
+ return new ITexture[] { super.getBottomFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_BOTTOM_STEAM_HAMMER_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_STEAM_HAMMER_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getBottomFacingInactive(byte aColor) {
+ return new ITexture[] { super.getBottomFacingInactive(aColor)[0],
+ TextureFactory.of(OVERLAY_BOTTOM_STEAM_HAMMER), TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_STEAM_HAMMER_GLOW)
+ .glow()
+ .build() };
+ }
+
+ /**
+ * Handles {@link Block#randomDisplayTick}. Draws Random Sparkles at main face.
+ *
+ * @param aBaseMetaTileEntity The entity that will handle the {@see Block#randomDisplayTick}
+ */
+ @SideOnly(Side.CLIENT)
+ @Override
+ public void onRandomDisplayTick(IGregTechTileEntity aBaseMetaTileEntity) {
+
+ // Random Sparkles at main face
+ if (aBaseMetaTileEntity.isActive() && XSTR_INSTANCE.nextInt(3) == 0) {
+
+ final ForgeDirection mainFacing = this.mMainFacing;
+
+ if ((mainFacing.flag & (ForgeDirection.UP.flag | ForgeDirection.DOWN.flag)) == 0
+ && aBaseMetaTileEntity.getCoverIDAtSide(mainFacing) == 0
+ && !aBaseMetaTileEntity.getOpacityAtSide(mainFacing)) {
+
+ final double oX = aBaseMetaTileEntity.getXCoord();
+ final double oY = aBaseMetaTileEntity.getYCoord();
+ final double oZ = aBaseMetaTileEntity.getZCoord();
+ final double offset = 0.02D;
+ final double horizontal = 0.5D + XSTR_INSTANCE.nextFloat() * 8D / 16D - 4D / 16D;
+
+ final double x, y, z, mX, mZ;
+
+ y = oY + XSTR_INSTANCE.nextFloat() * 10D / 16D + 5D / 16D;
+
+ if (mainFacing == ForgeDirection.WEST) {
+ x = oX - offset;
+ mX = -.05D;
+ z = oZ + horizontal;
+ mZ = 0D;
+ } else if (mainFacing == ForgeDirection.EAST) {
+ x = oX + offset;
+ mX = .05D;
+ z = oZ + horizontal;
+ mZ = 0D;
+ } else if (mainFacing == ForgeDirection.NORTH) {
+ x = oX + horizontal;
+ mX = 0D;
+ z = oZ - offset;
+ mZ = -.05D;
+ } else // if (frontFacing == ForgeDirection.SOUTH.ordinal())
+ {
+ x = oX + horizontal;
+ mX = 0D;
+ z = oZ + offset;
+ mZ = .05D;
+ }
+
+ ParticleEventBuilder particleEventBuilder = (new ParticleEventBuilder()).setMotion(mX, 0, mZ)
+ .setPosition(x, y, z)
+ .setWorld(getBaseMetaTileEntity().getWorld());
+ particleEventBuilder.setIdentifier(ParticleFX.LAVA)
+ .run();
+ }
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_ForgeHammer_Steel.java b/src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_ForgeHammer_Steel.java
new file mode 100644
index 0000000000..25785f3fa3
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_ForgeHammer_Steel.java
@@ -0,0 +1,202 @@
+package gregtech.common.tileentities.machines.steam;
+
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_HAMMER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_HAMMER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_HAMMER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_HAMMER_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_HAMMER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_HAMMER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_HAMMER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_HAMMER_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_HAMMER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_HAMMER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_HAMMER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_HAMMER_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_HAMMER;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_HAMMER_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_HAMMER_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_HAMMER_GLOW;
+import static gregtech.api.objects.XSTR.XSTR_INSTANCE;
+
+import net.minecraft.block.Block;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.api.enums.ParticleFX;
+import gregtech.api.enums.SoundResource;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachine_Steel;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.WorldSpawnedEventBuilder.ParticleEventBuilder;
+
+public class GT_MetaTileEntity_ForgeHammer_Steel extends GT_MetaTileEntity_BasicMachine_Steel {
+
+ public GT_MetaTileEntity_ForgeHammer_Steel(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional, "Forge Hammer", 1, 1, true);
+ }
+
+ public GT_MetaTileEntity_ForgeHammer_Steel(String aName, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aDescription, aTextures, 1, 1, true);
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_ForgeHammer_Steel(this.mName, this.mDescriptionArray, this.mTextures);
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.hammerRecipes;
+ }
+
+ @Override
+ public void startSoundLoop(byte aIndex, double aX, double aY, double aZ) {
+ super.startSoundLoop(aIndex, aX, aY, aZ);
+ if (aIndex == 1) {
+ GT_Utility.doSoundAtClient(SoundResource.RANDOM_ANVIL_USE, 10, 1.0F, aX, aY, aZ);
+ }
+ }
+
+ @Override
+ public void startProcess() {
+ sendLoopStart((byte) 1);
+ }
+
+ @Override
+ public ITexture[] getSideFacingActive(byte aColor) {
+ return new ITexture[] { super.getSideFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_SIDE_STEAM_HAMMER_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_STEAM_HAMMER_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getSideFacingInactive(byte aColor) {
+ return new ITexture[] { super.getSideFacingInactive(aColor)[0], TextureFactory.of(OVERLAY_SIDE_STEAM_HAMMER),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_STEAM_HAMMER_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getFrontFacingActive(byte aColor) {
+ return new ITexture[] { super.getFrontFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_FRONT_STEAM_HAMMER_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_STEAM_HAMMER_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getFrontFacingInactive(byte aColor) {
+ return new ITexture[] { super.getFrontFacingInactive(aColor)[0], TextureFactory.of(OVERLAY_FRONT_STEAM_HAMMER),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_STEAM_HAMMER_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getTopFacingActive(byte aColor) {
+ return new ITexture[] { super.getTopFacingActive(aColor)[0], TextureFactory.of(OVERLAY_TOP_STEAM_HAMMER_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_STEAM_HAMMER_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getTopFacingInactive(byte aColor) {
+ return new ITexture[] { super.getTopFacingInactive(aColor)[0], TextureFactory.of(OVERLAY_TOP_STEAM_HAMMER),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_STEAM_HAMMER_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getBottomFacingActive(byte aColor) {
+ return new ITexture[] { super.getBottomFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_BOTTOM_STEAM_HAMMER_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_STEAM_HAMMER_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getBottomFacingInactive(byte aColor) {
+ return new ITexture[] { super.getBottomFacingInactive(aColor)[0],
+ TextureFactory.of(OVERLAY_BOTTOM_STEAM_HAMMER), TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_STEAM_HAMMER_GLOW)
+ .glow()
+ .build() };
+ }
+
+ /**
+ * Handles {@link Block#randomDisplayTick}. Draws Random Sparkles at main face.
+ *
+ * @param aBaseMetaTileEntity The entity that will handle the {@see Block#randomDisplayTick}
+ */
+ @SideOnly(Side.CLIENT)
+ @Override
+ public void onRandomDisplayTick(IGregTechTileEntity aBaseMetaTileEntity) {
+
+ // Random Sparkles at main face
+ if (aBaseMetaTileEntity.isActive() && XSTR_INSTANCE.nextInt(3) == 0) {
+
+ final ForgeDirection mainFacing = this.mMainFacing;
+
+ if ((mainFacing.flag & (ForgeDirection.UP.flag | ForgeDirection.DOWN.flag)) == 0
+ && aBaseMetaTileEntity.getCoverIDAtSide(mainFacing) == 0
+ && !aBaseMetaTileEntity.getOpacityAtSide(mainFacing)) {
+
+ final double oX = aBaseMetaTileEntity.getXCoord();
+ final double oY = aBaseMetaTileEntity.getYCoord();
+ final double oZ = aBaseMetaTileEntity.getZCoord();
+ final double offset = 0.02D;
+ final double horizontal = 0.5D + XSTR_INSTANCE.nextFloat() * 8D / 16D - 4D / 16D;
+
+ final double x, y, z, mX, mZ;
+
+ y = oY + XSTR_INSTANCE.nextFloat() * 10D / 16D + 5D / 16D;
+
+ if (mainFacing == ForgeDirection.WEST) {
+ x = oX - offset;
+ mX = -.05D;
+ z = oZ + horizontal;
+ mZ = 0D;
+ } else if (mainFacing == ForgeDirection.EAST) {
+ x = oX + offset;
+ mX = .05D;
+ z = oZ + horizontal;
+ mZ = 0D;
+ } else if (mainFacing == ForgeDirection.NORTH) {
+ x = oX + horizontal;
+ mX = 0D;
+ z = oZ - offset;
+ mZ = -.05D;
+ } else // if (frontFacing == ForgeDirection.SOUTH.ordinal())
+ {
+ x = oX + horizontal;
+ mX = 0D;
+ z = oZ + offset;
+ mZ = .05D;
+ }
+
+ ParticleEventBuilder particleEventBuilder = (new ParticleEventBuilder()).setMotion(mX, 0, mZ)
+ .setPosition(x, y, z)
+ .setWorld(getBaseMetaTileEntity().getWorld());
+ particleEventBuilder.setIdentifier(ParticleFX.LAVA)
+ .run();
+ }
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_Furnace_Bronze.java b/src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_Furnace_Bronze.java
new file mode 100644
index 0000000000..51a91874a0
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_Furnace_Bronze.java
@@ -0,0 +1,161 @@
+package gregtech.common.tileentities.machines.steam;
+
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_FURNACE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_FURNACE_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_FURNACE_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_FURNACE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_FURNACE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_FURNACE_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_FURNACE_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_FURNACE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_FURNACE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_FURNACE_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_FURNACE_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_FURNACE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_FURNACE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_FURNACE_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_FURNACE_GLOW;
+
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.enums.SoundResource;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachine_Bronze;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_Furnace_Bronze extends GT_MetaTileEntity_BasicMachine_Bronze {
+
+ public GT_MetaTileEntity_Furnace_Bronze(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional, "Smelting things with compressed Steam", 1, 1, false);
+ }
+
+ public GT_MetaTileEntity_Furnace_Bronze(String aName, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aDescription, aTextures, 1, 1, false);
+ }
+
+ @Override
+ protected boolean isBricked() {
+ return true;
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Furnace_Bronze(this.mName, this.mDescriptionArray, this.mTextures);
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.furnaceRecipes;
+ }
+
+ @Override
+ public int checkRecipe() {
+ if (null != (this.mOutputItems[0] = GT_ModHandler.getSmeltingOutput(getInputAt(0), true, getOutputAt(0)))) {
+ this.mEUt = 4;
+ this.mMaxProgresstime = 256;
+ return FOUND_AND_SUCCESSFULLY_USED_RECIPE;
+ }
+ return DID_NOT_FIND_RECIPE;
+ }
+
+ @Override
+ protected boolean allowPutStackValidated(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return super.allowPutStackValidated(aBaseMetaTileEntity, aIndex, side, aStack)
+ && GT_ModHandler.getSmeltingOutput(GT_Utility.copyAmount(64, aStack), false, null) != null;
+ }
+
+ @Override
+ public void startSoundLoop(byte aIndex, double aX, double aY, double aZ) {
+ super.startSoundLoop(aIndex, aX, aY, aZ);
+ if (aIndex == 1) {
+ GT_Utility.doSoundAtClient(SoundResource.IC2_MACHINES_ELECTROFURNACE_LOOP, 10, 1.0F, aX, aY, aZ);
+ }
+ }
+
+ @Override
+ public void startProcess() {
+ sendLoopStart((byte) 1);
+ }
+
+ @Override
+ public ITexture[] getSideFacingActive(byte aColor) {
+ return new ITexture[] { super.getSideFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_SIDE_STEAM_FURNACE_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_STEAM_FURNACE_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getSideFacingInactive(byte aColor) {
+ return new ITexture[] { super.getSideFacingInactive(aColor)[0], TextureFactory.of(OVERLAY_SIDE_STEAM_FURNACE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_STEAM_FURNACE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getFrontFacingActive(byte aColor) {
+ return new ITexture[] { super.getFrontFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_FRONT_STEAM_FURNACE_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_STEAM_FURNACE_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getFrontFacingInactive(byte aColor) {
+ return new ITexture[] { super.getFrontFacingInactive(aColor)[0], TextureFactory.of(OVERLAY_FRONT_STEAM_FURNACE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_STEAM_FURNACE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getTopFacingActive(byte aColor) {
+ return new ITexture[] { super.getTopFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_TOP_STEAM_FURNACE_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_STEAM_FURNACE_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getTopFacingInactive(byte aColor) {
+ return new ITexture[] { super.getTopFacingInactive(aColor)[0], TextureFactory.of(OVERLAY_TOP_STEAM_FURNACE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_STEAM_FURNACE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getBottomFacingActive(byte aColor) {
+ return new ITexture[] { super.getBottomFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_BOTTOM_STEAM_FURNACE_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_STEAM_FURNACE_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getBottomFacingInactive(byte aColor) {
+ return new ITexture[] { super.getBottomFacingInactive(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(OVERLAY_BOTTOM_STEAM_FURNACE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_STEAM_FURNACE_GLOW)
+ .glow()
+ .build()) };
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_Furnace_Steel.java b/src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_Furnace_Steel.java
new file mode 100644
index 0000000000..a151c724f3
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_Furnace_Steel.java
@@ -0,0 +1,159 @@
+package gregtech.common.tileentities.machines.steam;
+
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_FURNACE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_FURNACE_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_FURNACE_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_FURNACE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_FURNACE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_FURNACE_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_FURNACE_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_FURNACE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_FURNACE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_FURNACE_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_FURNACE_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_FURNACE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_FURNACE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_FURNACE_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_FURNACE_GLOW;
+
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.enums.SoundResource;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachine_Steel;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_Furnace_Steel extends GT_MetaTileEntity_BasicMachine_Steel {
+
+ public GT_MetaTileEntity_Furnace_Steel(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional, "Smelting things with compressed Steam", 1, 1, true);
+ }
+
+ public GT_MetaTileEntity_Furnace_Steel(String aName, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aDescription, aTextures, 1, 1, true);
+ }
+
+ @Override
+ protected boolean isBricked() {
+ return true;
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Furnace_Steel(this.mName, this.mDescriptionArray, this.mTextures);
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.furnaceRecipes;
+ }
+
+ @Override
+ public int checkRecipe() {
+ if (null != (this.mOutputItems[0] = GT_ModHandler.getSmeltingOutput(getInputAt(0), true, getOutputAt(0)))) {
+ this.mEUt = 8;
+ this.mMaxProgresstime = 128;
+ return FOUND_AND_SUCCESSFULLY_USED_RECIPE;
+ }
+ return DID_NOT_FIND_RECIPE;
+ }
+
+ @Override
+ protected boolean allowPutStackValidated(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return super.allowPutStackValidated(aBaseMetaTileEntity, aIndex, side, aStack)
+ && GT_ModHandler.getSmeltingOutput(GT_Utility.copyAmount(64, aStack), false, null) != null;
+ }
+
+ @Override
+ public void startSoundLoop(byte aIndex, double aX, double aY, double aZ) {
+ super.startSoundLoop(aIndex, aX, aY, aZ);
+ if (aIndex == 1) {
+ GT_Utility.doSoundAtClient(SoundResource.IC2_MACHINES_ELECTROFURNACE_LOOP, 10, 1.0F, aX, aY, aZ);
+ }
+ }
+
+ @Override
+ public void startProcess() {
+ sendLoopStart((byte) 1);
+ }
+
+ @Override
+ public ITexture[] getSideFacingActive(byte aColor) {
+ return new ITexture[] { super.getSideFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_SIDE_STEAM_FURNACE_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_STEAM_FURNACE_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getSideFacingInactive(byte aColor) {
+ return new ITexture[] { super.getSideFacingInactive(aColor)[0], TextureFactory.of(OVERLAY_SIDE_STEAM_FURNACE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_STEAM_FURNACE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getFrontFacingActive(byte aColor) {
+ return new ITexture[] { super.getFrontFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_FRONT_STEAM_FURNACE_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_STEAM_FURNACE_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getFrontFacingInactive(byte aColor) {
+ return new ITexture[] { super.getFrontFacingInactive(aColor)[0], TextureFactory.of(OVERLAY_FRONT_STEAM_FURNACE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_STEAM_FURNACE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getTopFacingActive(byte aColor) {
+ return new ITexture[] { super.getTopFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_TOP_STEAM_FURNACE_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_STEAM_FURNACE_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getTopFacingInactive(byte aColor) {
+ return new ITexture[] { super.getTopFacingInactive(aColor)[0], TextureFactory.of(OVERLAY_TOP_STEAM_FURNACE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_STEAM_FURNACE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getBottomFacingActive(byte aColor) {
+ return new ITexture[] { super.getBottomFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_BOTTOM_STEAM_FURNACE_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_STEAM_FURNACE_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getBottomFacingInactive(byte aColor) {
+ return new ITexture[] { super.getBottomFacingInactive(aColor)[0],
+ TextureFactory.of(OVERLAY_BOTTOM_STEAM_FURNACE), TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_STEAM_FURNACE_GLOW)
+ .glow()
+ .build() };
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_Macerator_Bronze.java b/src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_Macerator_Bronze.java
new file mode 100644
index 0000000000..cdbf9f2123
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_Macerator_Bronze.java
@@ -0,0 +1,189 @@
+package gregtech.common.tileentities.machines.steam;
+
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_MACERATOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_MACERATOR_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_MACERATOR_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_MACERATOR_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_MACERATOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_MACERATOR_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_MACERATOR_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_MACERATOR_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_MACERATOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_MACERATOR_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_MACERATOR_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_MACERATOR_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_MACERATOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_MACERATOR_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_MACERATOR_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_MACERATOR_GLOW;
+import static gregtech.api.objects.XSTR.XSTR_INSTANCE;
+
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidStack;
+
+import gregtech.api.enums.ParticleFX;
+import gregtech.api.enums.SoundResource;
+import gregtech.api.enums.TierEU;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachine_Bronze;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.WorldSpawnedEventBuilder.ParticleEventBuilder;
+
+public class GT_MetaTileEntity_Macerator_Bronze extends GT_MetaTileEntity_BasicMachine_Bronze {
+
+ public GT_MetaTileEntity_Macerator_Bronze(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional, "Macerating your Ores", 1, 1, false);
+ }
+
+ public GT_MetaTileEntity_Macerator_Bronze(String aName, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aDescription, aTextures, 1, 1, false);
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Macerator_Bronze(this.mName, this.mDescriptionArray, this.mTextures);
+ }
+
+ @Override
+ public void onPreTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ super.onPreTick(aBaseMetaTileEntity, aTick);
+ if (aBaseMetaTileEntity.isClientSide() && aBaseMetaTileEntity.isActive()) {
+
+ if (aBaseMetaTileEntity.getFrontFacing() != ForgeDirection.UP
+ && aBaseMetaTileEntity.getCoverIDAtSide(ForgeDirection.UP) == 0
+ && !aBaseMetaTileEntity.getOpacityAtSide(ForgeDirection.UP)) {
+
+ new ParticleEventBuilder().setMotion(0.0D, 0.0D, 0.0D)
+ .setIdentifier(ParticleFX.SMOKE)
+ .setPosition(
+ aBaseMetaTileEntity.getXCoord() + 0.8F - XSTR_INSTANCE.nextFloat() * 0.6F,
+ aBaseMetaTileEntity.getYCoord() + 0.9F + XSTR_INSTANCE.nextFloat() * 0.2F,
+ aBaseMetaTileEntity.getZCoord() + 0.8F - XSTR_INSTANCE.nextFloat() * 0.6F)
+ .setWorld(getBaseMetaTileEntity().getWorld())
+ .run();
+ }
+ }
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.maceratorRecipes;
+ }
+
+ @Override
+ public int checkRecipe() {
+ GT_Recipe tRecipe = getRecipeMap()
+ .findRecipe(getBaseMetaTileEntity(), mLastRecipe, false, TierEU.LV, null, null, getAllInputs());
+ if (tRecipe == null) return DID_NOT_FIND_RECIPE;
+ if (tRecipe.mCanBeBuffered) mLastRecipe = tRecipe;
+ if (!canOutput(tRecipe)) {
+ mOutputBlocked++;
+ return FOUND_RECIPE_BUT_DID_NOT_MEET_REQUIREMENTS;
+ }
+
+ if (!tRecipe.isRecipeInputEqual(true, new FluidStack[] { getFillableStack() }, getAllInputs()))
+ return FOUND_RECIPE_BUT_DID_NOT_MEET_REQUIREMENTS;
+ if (tRecipe.getOutput(0) != null) mOutputItems[0] = tRecipe.getOutput(0);
+ calculateCustomOverclock(tRecipe);
+ return FOUND_AND_SUCCESSFULLY_USED_RECIPE;
+ }
+
+ @Override
+ protected boolean allowPutStackValidated(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return super.allowPutStackValidated(aBaseMetaTileEntity, aIndex, side, aStack)
+ && RecipeMaps.maceratorRecipes.containsInput(GT_Utility.copyAmount(64, aStack));
+ }
+
+ @Override
+ public void startSoundLoop(byte aIndex, double aX, double aY, double aZ) {
+ super.startSoundLoop(aIndex, aX, aY, aZ);
+ if (aIndex == 1) {
+ GT_Utility.doSoundAtClient(SoundResource.IC2_MACHINES_MACERATOR_OP, 10, 1.0F, aX, aY, aZ);
+ }
+ }
+
+ @Override
+ public void startProcess() {
+ sendLoopStart((byte) 1);
+ }
+
+ @Override
+ public ITexture[] getSideFacingActive(byte aColor) {
+ return new ITexture[] { super.getSideFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_SIDE_STEAM_MACERATOR_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_STEAM_MACERATOR_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getSideFacingInactive(byte aColor) {
+ return new ITexture[] { super.getSideFacingInactive(aColor)[0], TextureFactory.of(OVERLAY_SIDE_STEAM_MACERATOR),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_STEAM_MACERATOR_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getFrontFacingActive(byte aColor) {
+ return new ITexture[] { super.getFrontFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_FRONT_STEAM_MACERATOR_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_STEAM_MACERATOR_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getFrontFacingInactive(byte aColor) {
+ return new ITexture[] { super.getFrontFacingInactive(aColor)[0],
+ TextureFactory.of(OVERLAY_FRONT_STEAM_MACERATOR), TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_STEAM_MACERATOR_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getTopFacingActive(byte aColor) {
+ return new ITexture[] { super.getTopFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_TOP_STEAM_MACERATOR_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_STEAM_MACERATOR_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getTopFacingInactive(byte aColor) {
+ return new ITexture[] { super.getTopFacingInactive(aColor)[0], TextureFactory.of(OVERLAY_TOP_STEAM_MACERATOR),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_STEAM_MACERATOR_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getBottomFacingActive(byte aColor) {
+ return new ITexture[] { super.getBottomFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_BOTTOM_STEAM_MACERATOR_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_STEAM_MACERATOR_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getBottomFacingInactive(byte aColor) {
+ return new ITexture[] { super.getBottomFacingInactive(aColor)[0],
+ TextureFactory.of(OVERLAY_BOTTOM_STEAM_MACERATOR), TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_STEAM_MACERATOR_GLOW)
+ .glow()
+ .build() };
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_Macerator_Steel.java b/src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_Macerator_Steel.java
new file mode 100644
index 0000000000..95d510ffa3
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/steam/GT_MetaTileEntity_Macerator_Steel.java
@@ -0,0 +1,188 @@
+package gregtech.common.tileentities.machines.steam;
+
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_MACERATOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_MACERATOR_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_MACERATOR_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_BOTTOM_STEAM_MACERATOR_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_MACERATOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_MACERATOR_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_MACERATOR_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_STEAM_MACERATOR_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_MACERATOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_MACERATOR_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_MACERATOR_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SIDE_STEAM_MACERATOR_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_MACERATOR;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_MACERATOR_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_MACERATOR_ACTIVE_GLOW;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_TOP_STEAM_MACERATOR_GLOW;
+import static gregtech.api.objects.XSTR.XSTR_INSTANCE;
+
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidStack;
+
+import gregtech.api.enums.ParticleFX;
+import gregtech.api.enums.SoundResource;
+import gregtech.api.enums.TierEU;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachine_Steel;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.WorldSpawnedEventBuilder;
+
+public class GT_MetaTileEntity_Macerator_Steel extends GT_MetaTileEntity_BasicMachine_Steel {
+
+ public GT_MetaTileEntity_Macerator_Steel(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional, "Macerating your Ores", 1, 1, true);
+ }
+
+ public GT_MetaTileEntity_Macerator_Steel(String aName, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aDescription, aTextures, 1, 1, true);
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Macerator_Steel(this.mName, this.mDescriptionArray, this.mTextures);
+ }
+
+ @Override
+ public void onPreTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ super.onPreTick(aBaseMetaTileEntity, aTick);
+ if (aBaseMetaTileEntity.isClientSide() && aBaseMetaTileEntity.isActive()) {
+ if (aBaseMetaTileEntity.getFrontFacing() != ForgeDirection.UP
+ && aBaseMetaTileEntity.getCoverIDAtSide(ForgeDirection.UP) == 0
+ && !aBaseMetaTileEntity.getOpacityAtSide(ForgeDirection.UP)) {
+
+ new WorldSpawnedEventBuilder.ParticleEventBuilder().setMotion(0.0D, 0.0D, 0.0D)
+ .setIdentifier(ParticleFX.SMOKE)
+ .setPosition(
+ aBaseMetaTileEntity.getXCoord() + 0.8F - XSTR_INSTANCE.nextFloat() * 0.6F,
+ aBaseMetaTileEntity.getYCoord() + 0.9F + XSTR_INSTANCE.nextFloat() * 0.2F,
+ aBaseMetaTileEntity.getZCoord() + 0.8F - XSTR_INSTANCE.nextFloat() * 0.6F)
+ .setWorld(getBaseMetaTileEntity().getWorld())
+ .run();
+ }
+ }
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.maceratorRecipes;
+ }
+
+ @Override
+ public int checkRecipe() {
+ GT_Recipe tRecipe = getRecipeMap()
+ .findRecipe(getBaseMetaTileEntity(), mLastRecipe, false, TierEU.LV, null, null, getAllInputs());
+ if (tRecipe == null) return DID_NOT_FIND_RECIPE;
+ if (tRecipe.mCanBeBuffered) mLastRecipe = tRecipe;
+ if (!canOutput(tRecipe)) {
+ mOutputBlocked++;
+ return FOUND_RECIPE_BUT_DID_NOT_MEET_REQUIREMENTS;
+ }
+
+ if (!tRecipe.isRecipeInputEqual(true, new FluidStack[] { getFillableStack() }, getAllInputs()))
+ return FOUND_RECIPE_BUT_DID_NOT_MEET_REQUIREMENTS;
+ if (tRecipe.getOutput(0) != null) mOutputItems[0] = tRecipe.getOutput(0);
+ calculateCustomOverclock(tRecipe);
+ return FOUND_AND_SUCCESSFULLY_USED_RECIPE;
+ }
+
+ @Override
+ public boolean allowPutStackValidated(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return super.allowPutStackValidated(aBaseMetaTileEntity, aIndex, side, aStack)
+ && RecipeMaps.maceratorRecipes.containsInput(GT_Utility.copyAmount(64, aStack));
+ }
+
+ @Override
+ public void startSoundLoop(byte aIndex, double aX, double aY, double aZ) {
+ super.startSoundLoop(aIndex, aX, aY, aZ);
+ if (aIndex == 1) {
+ GT_Utility.doSoundAtClient(SoundResource.IC2_MACHINES_MACERATOR_OP, 10, 1.0F, aX, aY, aZ);
+ }
+ }
+
+ @Override
+ public void startProcess() {
+ sendLoopStart((byte) 1);
+ }
+
+ @Override
+ public ITexture[] getSideFacingActive(byte aColor) {
+ return new ITexture[] { super.getSideFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_SIDE_STEAM_MACERATOR_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_STEAM_MACERATOR_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getSideFacingInactive(byte aColor) {
+ return new ITexture[] { super.getSideFacingInactive(aColor)[0], TextureFactory.of(OVERLAY_SIDE_STEAM_MACERATOR),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_SIDE_STEAM_MACERATOR_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getFrontFacingActive(byte aColor) {
+ return new ITexture[] { super.getFrontFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_FRONT_STEAM_MACERATOR_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_STEAM_MACERATOR_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getFrontFacingInactive(byte aColor) {
+ return new ITexture[] { super.getFrontFacingInactive(aColor)[0],
+ TextureFactory.of(OVERLAY_FRONT_STEAM_MACERATOR), TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_STEAM_MACERATOR_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getTopFacingActive(byte aColor) {
+ return new ITexture[] { super.getTopFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_TOP_STEAM_MACERATOR_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_STEAM_MACERATOR_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getTopFacingInactive(byte aColor) {
+ return new ITexture[] { super.getTopFacingInactive(aColor)[0], TextureFactory.of(OVERLAY_TOP_STEAM_MACERATOR),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_TOP_STEAM_MACERATOR_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getBottomFacingActive(byte aColor) {
+ return new ITexture[] { super.getBottomFacingActive(aColor)[0],
+ TextureFactory.of(OVERLAY_BOTTOM_STEAM_MACERATOR_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_STEAM_MACERATOR_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getBottomFacingInactive(byte aColor) {
+ return new ITexture[] { super.getBottomFacingInactive(aColor)[0],
+ TextureFactory.of(OVERLAY_BOTTOM_STEAM_MACERATOR), TextureFactory.builder()
+ .addIcon(OVERLAY_BOTTOM_STEAM_MACERATOR_GLOW)
+ .glow()
+ .build() };
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/render/TileDrone.java b/src/main/java/gregtech/common/tileentities/render/TileDrone.java
new file mode 100644
index 0000000000..625157ff37
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/render/TileDrone.java
@@ -0,0 +1,24 @@
+package gregtech.common.tileentities.render;
+
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.AxisAlignedBB;
+
+public class TileDrone extends TileEntity {
+
+ public double rotation = 0;
+
+ @Override
+ public AxisAlignedBB getRenderBoundingBox() {
+ return INFINITE_EXTENT_AABB;
+ }
+
+ @Override
+ public double getMaxRenderDistanceSquared() {
+ return 65536;
+ }
+
+ @Override
+ public void updateEntity() {
+ rotation = (rotation + 50) % 360d;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_DigitalChestBase.java b/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_DigitalChestBase.java
new file mode 100644
index 0000000000..3d59aca28f
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_DigitalChestBase.java
@@ -0,0 +1,564 @@
+package gregtech.common.tileentities.storage;
+
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASINGS;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SCHEST;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_SCHEST_GLOW;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+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.common.util.Constants;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.gtnewhorizons.modularui.api.NumberFormatMUI;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.common.widget.DrawableWidget;
+import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget;
+import com.gtnewhorizons.modularui.common.widget.SlotWidget;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import appeng.api.storage.IMEMonitor;
+import appeng.api.storage.IMEMonitorHandlerReceiver;
+import appeng.api.storage.StorageChannel;
+import appeng.api.storage.data.IAEItemStack;
+import appeng.api.storage.data.IItemList;
+import appeng.util.item.AEItemStack;
+import appeng.util.item.ItemList;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.gui.modularui.GT_UIInfos;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.modularui.IAddUIWidgets;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_TieredMachineBlock;
+import gregtech.api.objects.AE2DigitalChestHandler;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_LanguageManager;
+import gregtech.api.util.GT_Utility;
+import mcp.mobius.waila.api.IWailaConfigHandler;
+import mcp.mobius.waila.api.IWailaDataAccessor;
+
+public abstract class GT_MetaTileEntity_DigitalChestBase extends GT_MetaTileEntity_TieredMachineBlock
+ implements IMEMonitor<IAEItemStack>, IAddUIWidgets {
+
+ protected boolean mVoidOverflow = false;
+ protected boolean mDisableFilter;
+ private Map<IMEMonitorHandlerReceiver<IAEItemStack>, Object> listeners = null;
+
+ public GT_MetaTileEntity_DigitalChestBase(int aID, String aName, String aNameRegional, int aTier) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ 3,
+ new String[] { "This Chest stores " + GT_Utility.formatNumbers(commonSizeCompute(aTier)) + " Blocks",
+ "Use a screwdriver to enable", "voiding items on overflow", "Will keep its contents when harvested", });
+ }
+
+ protected static int commonSizeCompute(int tier) {
+ return switch (tier) {
+ case 1 -> 4000000;
+ case 2 -> 8000000;
+ case 3 -> 16000000;
+ case 4 -> 32000000;
+ case 5 -> 64000000;
+ case 6 -> 128000000;
+ case 7 -> 256000000;
+ case 8 -> 512000000;
+ case 9 -> 1024000000;
+ case 10 -> 2147483640;
+ default -> 0;
+ };
+ }
+
+ public GT_MetaTileEntity_DigitalChestBase(String aName, int aTier, String aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, 3, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_DigitalChestBase(String aName, int aTier, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, 3, aDescription, aTextures);
+ }
+
+ @Override
+ public void addAdditionalTooltipInformation(ItemStack stack, List<String> tooltip) {
+ if (stack.hasTagCompound() && stack.stackTagCompound.hasKey("mItemStack")) {
+ final ItemStack tContents = ItemStack
+ .loadItemStackFromNBT(stack.stackTagCompound.getCompoundTag("mItemStack"));
+ final int tSize = stack.stackTagCompound.getInteger("mItemCount");
+ if (tContents != null && tSize > 0) {
+ tooltip.add(
+ GT_LanguageManager.addStringLocalization("TileEntity_CHEST_INFO", "Contains Item: ")
+ + EnumChatFormatting.YELLOW
+ + tContents.getDisplayName()
+ + EnumChatFormatting.GRAY);
+ tooltip.add(
+ GT_LanguageManager.addStringLocalization("TileEntity_CHEST_AMOUNT", "Item Amount: ")
+ + EnumChatFormatting.GREEN
+ + GT_Utility.formatNumbers(tSize)
+ + EnumChatFormatting.GRAY);
+ }
+ }
+ }
+
+ public static void registerAEIntegration() {
+ appeng.api.AEApi.instance()
+ .registries()
+ .externalStorage()
+ .addExternalStorageInterface(new AE2DigitalChestHandler());
+ }
+
+ @Override
+ public void addListener(IMEMonitorHandlerReceiver<IAEItemStack> imeMonitorHandlerReceiver, Object o) {
+ if (listeners == null) listeners = new HashMap<>();
+ listeners.put(imeMonitorHandlerReceiver, o);
+ }
+
+ @Override
+ public void removeListener(IMEMonitorHandlerReceiver<IAEItemStack> imeMonitorHandlerReceiver) {
+ if (listeners == null) listeners = new HashMap<>();
+ listeners.remove(imeMonitorHandlerReceiver);
+ }
+
+ @Override
+ public appeng.api.config.AccessRestriction getAccess() {
+ return appeng.api.config.AccessRestriction.READ_WRITE;
+ }
+
+ @Override
+ public boolean isPrioritized(IAEItemStack iaeItemStack) {
+ ItemStack s = getItemStack();
+ if (s == null || iaeItemStack == null) return false;
+ return iaeItemStack.isSameType(s);
+ }
+
+ @Override
+ public boolean canAccept(IAEItemStack iaeItemStack) {
+ ItemStack s = getItemStack();
+ if (s == null || iaeItemStack == null) return true;
+ return iaeItemStack.isSameType(s);
+ }
+
+ @Override
+ public int getPriority() {
+ return 0;
+ }
+
+ @Override
+ public int getSlot() {
+ return 0;
+ }
+
+ @Override
+ public boolean validForPass(int i) {
+ return true;
+ }
+
+ protected abstract ItemStack getItemStack();
+
+ protected abstract void setItemStack(ItemStack s);
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public IItemList<IAEItemStack> getAvailableItems(final IItemList out) {
+ ItemStack storedStack = getItemStack();
+ if (storedStack != null) {
+ AEItemStack s = AEItemStack.create(storedStack);
+ s.setStackSize(getItemCount());
+ out.add(s);
+ }
+ return out;
+ }
+
+ @Override
+ public IItemList<IAEItemStack> getStorageList() {
+ IItemList<IAEItemStack> res = new ItemList();
+ ItemStack storedStack = getItemStack();
+ if (storedStack != null) {
+ AEItemStack s = AEItemStack.create(storedStack);
+ s.setStackSize(getItemCount());
+ res.add(s);
+ }
+ return res;
+ }
+
+ protected abstract int getItemCount();
+
+ @Override
+ public abstract void setItemCount(int aCount);
+
+ @Override
+ public int getMaxItemCount() {
+ return commonSizeCompute(mTier);
+ }
+
+ @Override
+ public ITexture[][][] getTextureSet(ITexture[] aTextures) {
+ return new ITexture[0][0][0];
+ }
+
+ @Override
+ public IAEItemStack injectItems(final IAEItemStack input, final appeng.api.config.Actionable mode,
+ final appeng.api.networking.security.BaseActionSource src) {
+ if (getBaseMetaTileEntity() == null) return input;
+
+ final ItemStack inputStack = input.getItemStack();
+ final int maxCapacity = getMaxItemCount();
+ final int itemCount = getItemCount();
+ final long toAdd = input.getStackSize();
+ final ItemStack storedStack = getItemStack();
+
+ if (storedStack != null && !GT_Utility.areStacksEqual(storedStack, inputStack)) {
+ // Can't stack with existing item, just return the input.
+ return input;
+ }
+
+ // Number of items not added because there's too much to add.
+ final long notAdded = itemCount + toAdd - maxCapacity;
+
+ if (mode == appeng.api.config.Actionable.MODULATE) {
+ final int newCount = (int) Math.min((long) maxCapacity, itemCount + toAdd);
+
+ if (storedStack == null) {
+ setItemStack(inputStack.copy());
+ }
+ setItemCount(newCount);
+ getBaseMetaTileEntity().markDirty();
+ }
+ if (mVoidOverflow || notAdded <= 0) {
+ return null;
+ } else {
+ return input.copy()
+ .setStackSize(notAdded);
+ }
+ }
+
+ @Override
+ public IAEItemStack extractItems(final IAEItemStack request, final appeng.api.config.Actionable mode,
+ final appeng.api.networking.security.BaseActionSource src) {
+ if (request.isSameType(getItemStack())) {
+ if (getBaseMetaTileEntity() == null) return null;
+ if (mode != appeng.api.config.Actionable.SIMULATE) getBaseMetaTileEntity().markDirty();
+ if (request.getStackSize() >= getItemCount()) {
+ AEItemStack result = AEItemStack.create(getItemStack());
+ result.setStackSize(getItemCount());
+ if (mode != appeng.api.config.Actionable.SIMULATE) setItemCount(0);
+ return result;
+ } else {
+ if (mode != appeng.api.config.Actionable.SIMULATE)
+ setItemCount(getItemCount() - (int) request.getStackSize());
+ return request.copy();
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public StorageChannel getChannel() {
+ return StorageChannel.ITEMS;
+ }
+
+ @Override
+ public final void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ mVoidOverflow = !mVoidOverflow;
+ GT_Utility.sendChatToPlayer(
+ aPlayer,
+ StatCollector.translateToLocal(
+ mVoidOverflow ? "GT5U.machines.digitalchest.voidoverflow.enabled"
+ : "GT5U.machines.digitalchest.voidoverflow.disabled"));
+ }
+
+ @Override
+ public boolean onSolderingToolRightClick(ForgeDirection side, ForgeDirection wrenchingSide, EntityPlayer aPlayer,
+ float aX, float aY, float aZ) {
+ if (super.onSolderingToolRightClick(side, wrenchingSide, aPlayer, aX, aY, aZ)) return true;
+ mDisableFilter = !mDisableFilter;
+ GT_Utility.sendChatToPlayer(
+ aPlayer,
+ StatCollector.translateToLocal(
+ mDisableFilter ? "GT5U.machines.digitalchest.inputfilter.disabled"
+ : "GT5U.machines.digitalchest.inputfilter.enabled"));
+ return true;
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTimer) {
+
+ if (getBaseMetaTileEntity().isServerSide() && getBaseMetaTileEntity().isAllowedToWork()) {
+ if ((getItemCount() <= 0)) {
+ setItemStack(null);
+ setItemCount(0);
+ }
+ if (getItemStack() == null && mInventory[0] != null) {
+ setItemStack(mInventory[0].copy());
+ }
+ int count = getItemCount();
+ ItemStack stack = getItemStack();
+ int savedCount = count;
+
+ if ((mInventory[0] != null) && ((count < getMaxItemCount()) || mVoidOverflow)
+ && GT_Utility.areStacksEqual(mInventory[0], stack)) {
+ count += mInventory[0].stackSize;
+ if (count <= getMaxItemCount()) {
+ mInventory[0] = null;
+ } else {
+ if (mVoidOverflow) {
+ mInventory[0] = null;
+ } else {
+ mInventory[0].stackSize = (count - getMaxItemCount());
+ }
+ count = getMaxItemCount();
+ }
+ }
+ if (mInventory[1] == null && stack != null) {
+ mInventory[1] = stack.copy();
+ mInventory[1].stackSize = Math.min(stack.getMaxStackSize(), count);
+ count -= mInventory[1].stackSize;
+ } else if ((count > 0) && GT_Utility.areStacksEqual(mInventory[1], stack)
+ && mInventory[1].getMaxStackSize() > mInventory[1].stackSize) {
+ int tmp = Math.min(count, mInventory[1].getMaxStackSize() - mInventory[1].stackSize);
+ mInventory[1].stackSize += tmp;
+ count -= tmp;
+ }
+ setItemCount(count);
+ if (stack != null) {
+ mInventory[2] = stack.copy();
+ mInventory[2].stackSize = Math.min(stack.getMaxStackSize(), count);
+ } else {
+ mInventory[2] = null;
+ }
+
+ notifyListeners(count - savedCount, stack);
+ if (count != savedCount) getBaseMetaTileEntity().markDirty();
+ }
+ }
+
+ @Override
+ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) {
+ GT_UIInfos.openGTTileEntityUI(aBaseMetaTileEntity, aPlayer);
+ return true;
+ }
+
+ @Override
+ public boolean isFacingValid(ForgeDirection facing) {
+ return true;
+ }
+
+ @Override
+ public boolean isAccessAllowed(EntityPlayer aPlayer) {
+ return true;
+ }
+
+ @Override
+ public boolean isValidSlot(int aIndex) {
+ return aIndex != 2;
+ }
+
+ @Override
+ public boolean isSimpleMachine() {
+ return true;
+ }
+
+ @Override
+ public int getProgresstime() {
+ return getItemCount() + (mInventory[0] == null ? 0 : mInventory[0].stackSize)
+ + (mInventory[1] == null ? 0 : mInventory[1].stackSize);
+ }
+
+ @Override
+ public int maxProgresstime() {
+ return getMaxItemCount();
+ }
+
+ @Override
+ public boolean isGivingInformation() {
+ return true;
+ }
+
+ @Override
+ public String[] getInfoData() {
+
+ if (getItemStack() == null) {
+ return new String[] { EnumChatFormatting.BLUE + chestName() + EnumChatFormatting.RESET, "Stored Items:",
+ EnumChatFormatting.GOLD + "No Items" + EnumChatFormatting.RESET,
+ EnumChatFormatting.GREEN + "0"
+ + EnumChatFormatting.RESET
+ + " "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(getMaxItemCount())
+ + EnumChatFormatting.RESET };
+ }
+ return new String[] { EnumChatFormatting.BLUE + chestName() + EnumChatFormatting.RESET, "Stored Items:",
+ EnumChatFormatting.GOLD + getItemStack().getDisplayName() + EnumChatFormatting.RESET,
+ EnumChatFormatting.GREEN + GT_Utility.formatNumbers(getItemCount())
+ + EnumChatFormatting.RESET
+ + " "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(getMaxItemCount())
+ + EnumChatFormatting.RESET };
+ }
+
+ @Override
+ public ItemStack[] getStoredItemData() {
+ return mInventory;
+ }
+
+ protected abstract String chestName();
+
+ private void notifyListeners(int count, ItemStack stack) {
+ if (listeners == null) {
+ listeners = new HashMap<>();
+ return;
+ }
+ if (count == 0 || stack == null) return;
+ ItemList change = new ItemList();
+ AEItemStack s = AEItemStack.create(stack);
+ s.setStackSize(count);
+ change.add(s);
+ listeners.forEach((l, o) -> {
+ if (l.isValid(o)) l.postChange(this, change, null);
+ else removeListener(l);
+ });
+ }
+
+ private boolean hasActiveMEConnection() {
+ if (listeners == null || listeners.isEmpty()) return false;
+ for (Map.Entry<IMEMonitorHandlerReceiver<IAEItemStack>, Object> e : listeners.entrySet()) {
+ if ((e.getKey() instanceof appeng.api.parts.IPart)) {
+ appeng.api.networking.IGridNode n = ((appeng.api.parts.IPart) e.getKey()).getGridNode();
+ if (n != null && n.isActive()) return true;
+ }
+ }
+ // if there are no active storage buses - clear the listeners
+ listeners.clear();
+ return false;
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ aNBT.setInteger("mItemCount", getItemCount());
+ if (getItemStack() != null) aNBT.setTag("mItemStack", getItemStack().writeToNBT(new NBTTagCompound()));
+ aNBT.setBoolean("mVoidOverflow", mVoidOverflow);
+ aNBT.setBoolean("mDisableFilter", mDisableFilter);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ if (aNBT.hasKey("mItemCount")) setItemCount(aNBT.getInteger("mItemCount"));
+ if (aNBT.hasKey("mItemStack"))
+ setItemStack(ItemStack.loadItemStackFromNBT((NBTTagCompound) aNBT.getTag("mItemStack")));
+ mVoidOverflow = aNBT.getBoolean("mVoidOverflow");
+ mDisableFilter = aNBT.getBoolean("mDisableFilter");
+ }
+
+ @Override
+ public boolean allowPullStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ if (GT_Values.disableDigitalChestsExternalAccess && hasActiveMEConnection()) return false;
+ return aIndex == 1;
+ }
+
+ @Override
+ public boolean allowPutStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ if (GT_Values.disableDigitalChestsExternalAccess && hasActiveMEConnection()) return false;
+ if (aIndex != 0) return false;
+ if ((mInventory[0] != null && !GT_Utility.areStacksEqual(mInventory[0], aStack))) return false;
+ if (mDisableFilter) return true;
+ if (getItemStack() == null) return mInventory[1] == null || GT_Utility.areStacksEqual(mInventory[1], aStack);
+ return GT_Utility.areStacksEqual(getItemStack(), aStack);
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection aFacing,
+ int colorIndex, boolean aActive, boolean redstoneLevel) {
+ if (side != aFacing) return new ITexture[] { MACHINE_CASINGS[mTier][colorIndex + 1] };
+ return new ITexture[] { MACHINE_CASINGS[mTier][colorIndex + 1], TextureFactory.of(OVERLAY_SCHEST),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_SCHEST_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public void getWailaBody(ItemStack itemStack, List<String> currenttip, IWailaDataAccessor accessor,
+ IWailaConfigHandler config) {
+ super.getWailaBody(itemStack, currenttip, accessor, config);
+ final NBTTagCompound tag = accessor.getNBTData();
+ if (tag.hasKey("itemType", Constants.NBT.TAG_COMPOUND)) {
+ currenttip.add("Item Count: " + GT_Utility.parseNumberToString(tag.getInteger("itemCount")));
+ currenttip.add(
+ "Item Type: " + ItemStack.loadItemStackFromNBT(tag.getCompoundTag("itemType"))
+ .getDisplayName());
+ } else {
+ currenttip.add("Chest Empty");
+ }
+ }
+
+ @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);
+ ItemStack is = getItemStack();
+ if (GT_Utility.isStackInvalid(is)) return;
+ int realItemCount = getItemCount();
+ if (GT_Utility.isStackValid(mInventory[1]) && GT_Utility.areStacksEqual(mInventory[1], is))
+ realItemCount += mInventory[1].stackSize;
+ tag.setInteger("itemCount", realItemCount);
+ tag.setTag("itemType", is.writeToNBT(new NBTTagCompound()));
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ protected static final NumberFormatMUI numberFormat = new NumberFormatMUI();
+ protected int clientItemCount;
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ builder.widget(
+ new DrawableWidget().setDrawable(GT_UITextures.PICTURE_SCREEN_BLACK)
+ .setPos(7, 16)
+ .setSize(71, 45))
+ .widget(
+ new SlotWidget(inventoryHandler, 0)
+ .setBackground(getGUITextureSet().getItemSlot(), GT_UITextures.OVERLAY_SLOT_IN)
+ .setPos(79, 16))
+ .widget(
+ new SlotWidget(inventoryHandler, 1).setAccess(true, false)
+ .setBackground(getGUITextureSet().getItemSlot(), GT_UITextures.OVERLAY_SLOT_OUT)
+ .setPos(79, 52))
+ .widget(
+ SlotWidget.phantom(inventoryHandler, 2)
+ .disableInteraction()
+ .setBackground(GT_UITextures.TRANSPARENT)
+ .setPos(59, 42))
+ .widget(
+ new TextWidget("Item Amount").setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setPos(10, 20))
+ .widget(
+ new TextWidget().setStringSupplier(() -> numberFormat.format(clientItemCount))
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setPos(10, 30))
+ .widget(
+ new FakeSyncWidget.IntegerSyncer(
+ () -> this instanceof GT_MetaTileEntity_QuantumChest
+ ? ((GT_MetaTileEntity_QuantumChest) this).mItemCount
+ : 0,
+ value -> clientItemCount = value));
+
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_DigitalTankBase.java b/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_DigitalTankBase.java
new file mode 100644
index 0000000000..e94458c116
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_DigitalTankBase.java
@@ -0,0 +1,699 @@
+package gregtech.common.tileentities.storage;
+
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASINGS;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_PIPE;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_QTANK;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_QTANK_GLOW;
+import static gregtech.api.metatileentity.BaseTileEntity.TOOLTIP_DELAY;
+import static gregtech.api.util.GT_Utility.formatNumbers;
+
+import java.util.List;
+
+import javax.annotation.Nonnull;
+
+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.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidRegistry;
+import net.minecraftforge.fluids.FluidStack;
+import net.minecraftforge.fluids.FluidTankInfo;
+import net.minecraftforge.fluids.IFluidHandler;
+
+import com.gtnewhorizons.modularui.api.NumberFormatMUI;
+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.CycleButtonWidget;
+import com.gtnewhorizons.modularui.common.widget.DrawableWidget;
+import com.gtnewhorizons.modularui.common.widget.FluidSlotWidget;
+import com.gtnewhorizons.modularui.common.widget.SlotWidget;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.api.gui.modularui.GT_UIInfos;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IFluidLockable;
+import gregtech.api.interfaces.modularui.IAddGregtechLogo;
+import gregtech.api.interfaces.modularui.IAddUIWidgets;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicTank;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_LanguageManager;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.gui.modularui.widget.FluidLockWidget;
+import mcp.mobius.waila.api.IWailaConfigHandler;
+import mcp.mobius.waila.api.IWailaDataAccessor;
+
+public abstract class GT_MetaTileEntity_DigitalTankBase extends GT_MetaTileEntity_BasicTank
+ implements IFluidLockable, IAddUIWidgets, IAddGregtechLogo {
+
+ public boolean mOutputFluid = false, mVoidFluidPart = false, mVoidFluidFull = false, mLockFluid = false;
+ protected String lockedFluidName = null;
+ public boolean mAllowInputFromOutputSide = false;
+
+ public GT_MetaTileEntity_DigitalTankBase(int aID, String aName, String aNameRegional, int aTier) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ 3,
+ new String[] {
+ StatCollector.translateToLocalFormatted(
+ "GT5U.machines.digitaltank.tooltip",
+ formatNumbers(commonSizeCompute(aTier))),
+ StatCollector.translateToLocal("GT5U.machines.digitaltank.tooltip1"), });
+ }
+
+ protected static int commonSizeCompute(int tier) {
+ return switch (tier) {
+ case 1 -> 4000000;
+ case 2 -> 8000000;
+ case 3 -> 16000000;
+ case 4 -> 32000000;
+ case 5 -> 64000000;
+ case 6 -> 128000000;
+ case 7 -> 256000000;
+ case 8 -> 512000000;
+ case 9 -> 1024000000;
+ case 10 -> 2147483640;
+ default -> 0;
+ };
+ }
+
+ private static int tierPump(int tier) {
+ return switch (tier) {
+ case 1 -> 2;
+ case 2 -> 3;
+ case 3 -> 3;
+ case 4 -> 4;
+ case 5 -> 4;
+ case 6 -> 5;
+ case 7 -> 5;
+ case 8 -> 6;
+ case 9 -> 7;
+ case 10 -> 8;
+ default -> 0;
+ };
+ }
+
+ public GT_MetaTileEntity_DigitalTankBase(String aName, int aTier, String aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, 3, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_DigitalTankBase(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, 3, aDescription, aTextures);
+ }
+
+ @Override
+ public ITexture[][][] getTextureSet(ITexture[] aTextures) {
+ return new ITexture[0][0][0];
+ }
+
+ @Override
+ public void addAdditionalTooltipInformation(ItemStack stack, List<String> tooltip) {
+ if (stack.hasTagCompound()
+ && (stack.stackTagCompound.hasKey("mFluid") || stack.stackTagCompound.hasKey("lockedFluidName"))) {
+ final FluidStack tContents = FluidStack
+ .loadFluidStackFromNBT(stack.stackTagCompound.getCompoundTag("mFluid"));
+ if (tContents != null && tContents.amount > 0) {
+ tooltip.add(
+ GT_LanguageManager.addStringLocalization("TileEntity_TANK_INFO", "Contains Fluid: ")
+ + EnumChatFormatting.YELLOW
+ + tContents.getLocalizedName()
+ + EnumChatFormatting.GRAY);
+ tooltip.add(
+ GT_LanguageManager.addStringLocalization("TileEntity_TANK_AMOUNT", "Fluid Amount: ")
+ + EnumChatFormatting.GREEN
+ + formatNumbers(tContents.amount)
+ + " L"
+ + EnumChatFormatting.GRAY);
+ } else if (stack.stackTagCompound.hasKey("lockedFluidName")) {
+ String fluidName = stack.stackTagCompound.getString("lockedFluidName");
+ Fluid fluid = FluidRegistry.getFluid(fluidName);
+ if (fluid == null) return;
+ // noinspection deprecation
+ tooltip.add(
+ StatCollector.translateToLocalFormatted(
+ "GT5U.item.tank.locked_to",
+ EnumChatFormatting.YELLOW + fluid.getLocalizedName()));
+ }
+ }
+ }
+
+ @Override
+ public void setItemNBT(NBTTagCompound aNBT) {
+ if (mFluid != null && mFluid.amount >= 0) {
+ aNBT.setTag("mFluid", mFluid.writeToNBT(new NBTTagCompound()));
+ }
+ if (mOutputFluid) aNBT.setBoolean("mOutputFluid", true);
+ if (mVoidFluidPart) aNBT.setBoolean("mVoidOverflow", true);
+ if (mVoidFluidFull) aNBT.setBoolean("mVoidFluidFull", true);
+ if (mLockFluid) aNBT.setBoolean("mLockFluid", true);
+ if (mLockFluid && GT_Utility.isStringValid(lockedFluidName)) aNBT.setString("lockedFluidName", lockedFluidName);
+ if (this.mAllowInputFromOutputSide) aNBT.setBoolean("mAllowInputFromOutputSide", true);
+
+ super.setItemNBT(aNBT);
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ aNBT.setBoolean("mOutputFluid", this.mOutputFluid);
+ aNBT.setBoolean("mVoidOverflow", this.mVoidFluidPart);
+ aNBT.setBoolean("mVoidFluidFull", this.mVoidFluidFull);
+ aNBT.setBoolean("mLockFluid", mLockFluid);
+ if (mLockFluid && GT_Utility.isStringValid(lockedFluidName)) aNBT.setString("lockedFluidName", lockedFluidName);
+ else aNBT.removeTag("lockedFluidName");
+ aNBT.setBoolean("mAllowInputFromOutputSide", this.mAllowInputFromOutputSide);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ mOutputFluid = aNBT.getBoolean("mOutputFluid");
+ mVoidFluidPart = aNBT.getBoolean("mVoidOverflow");
+ mVoidFluidFull = aNBT.getBoolean("mVoidFluidFull");
+ mLockFluid = aNBT.getBoolean("mLockFluid");
+ if (mLockFluid) {
+ setLockedFluidName(aNBT.getString("lockedFluidName"));
+ } else {
+ setLockedFluidName(null);
+ }
+ mAllowInputFromOutputSide = aNBT.getBoolean("mAllowInputFromOutputSide");
+ }
+
+ @Override
+ public boolean isFluidInputAllowed(FluidStack aFluid) {
+ return !mLockFluid || lockedFluidName == null
+ || lockedFluidName.equals(
+ aFluid.getFluid()
+ .getName());
+ }
+
+ @Override
+ public boolean isFluidChangingAllowed() {
+ return !mLockFluid || lockedFluidName == null;
+ }
+
+ @Override
+ public void onEmptyingContainerWhenEmpty() {
+ if (this.lockedFluidName == null && this.mFluid != null && isFluidLocked()) {
+ setLockedFluidName(
+ this.mFluid.getFluid()
+ .getName());
+ }
+ }
+
+ @Override
+ public boolean isSimpleMachine() {
+ return true;
+ }
+
+ @Override
+ public boolean doesFillContainers() {
+ return true;
+ }
+
+ @Override
+ public boolean doesEmptyContainers() {
+ return true;
+ }
+
+ @Override
+ public boolean canTankBeFilled() {
+ return true;
+ }
+
+ @Override
+ public boolean canTankBeEmptied() {
+ return true;
+ }
+
+ @Override
+ public boolean displaysItemStack() {
+ return true;
+ }
+
+ @Override
+ public boolean displaysStackSize() {
+ return false;
+ }
+
+ @Override
+ public void setLockedFluidName(String lockedFluidName) {
+ lockedFluidName = GT_Utility.isStringInvalid(lockedFluidName) ? null : lockedFluidName;
+ this.lockedFluidName = lockedFluidName;
+ if (lockedFluidName != null) {
+ Fluid fluid = FluidRegistry.getFluid(lockedFluidName);
+ if (fluid != null) {
+ // create new FluidStack, otherwise existing 0-amount FluidStack will
+ // prevent new fluid from being locked
+ setFillableStack(new FluidStack(fluid, getFluidAmount()));
+ mLockFluid = true;
+ }
+ }
+ // Don't unlock if lockedFluidName == null,
+ // as player might explicitly enable fluid locking with no fluid contained
+ }
+
+ @Override
+ public String getLockedFluidName() {
+ return this.lockedFluidName;
+ }
+
+ @Override
+ public void lockFluid(boolean lock) {
+ this.mLockFluid = lock;
+ if (!lock) {
+ setLockedFluidName(null);
+ }
+ }
+
+ @Override
+ public boolean isFluidLocked() {
+ return this.mLockFluid;
+ }
+
+ @Override
+ public boolean acceptsFluidLock(String name) {
+ if (name == null || getFluidAmount() == 0) return true;
+ return mFluid != null && mFluid.getFluid()
+ .getName()
+ .equals(name);
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity baseMetaTileEntity, ForgeDirection sideDirection,
+ ForgeDirection facingDirection, int colorIndex, boolean active, boolean redstoneLevel) {
+ if (sideDirection != ForgeDirection.UP) {
+ if (sideDirection == baseMetaTileEntity.getFrontFacing()) {
+ return new ITexture[] { MACHINE_CASINGS[mTier][colorIndex + 1], TextureFactory.of(OVERLAY_PIPE) };
+ } else return new ITexture[] { MACHINE_CASINGS[mTier][colorIndex + 1] };
+ }
+ return new ITexture[] { MACHINE_CASINGS[mTier][colorIndex + 1], TextureFactory.of(OVERLAY_QTANK),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_QTANK_GLOW)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) {
+ GT_UIInfos.openGTTileEntityUI(aBaseMetaTileEntity, aPlayer);
+ return true;
+ }
+
+ @Override
+ public final void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ if (side == getBaseMetaTileEntity().getFrontFacing()) {
+ mAllowInputFromOutputSide = !mAllowInputFromOutputSide;
+ GT_Utility.sendChatToPlayer(
+ aPlayer,
+ mAllowInputFromOutputSide ? GT_Utility.getTrans("095") : GT_Utility.getTrans("096"));
+ }
+ }
+
+ @Override
+ public FluidStack setFillableStack(FluidStack aFluid) {
+ mFluid = aFluid;
+ if (mFluid != null) {
+ mFluid.amount = Math.min(mFluid.amount, getRealCapacity());
+ }
+ return mFluid;
+ }
+
+ @Override
+ public FluidStack setDrainableStack(FluidStack aFluid) {
+ mFluid = aFluid;
+ if (mFluid != null) {
+ mFluid.amount = Math.min(mFluid.amount, getRealCapacity());
+ }
+ return mFluid;
+ }
+
+ @Override
+ public void onPreTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ if (aBaseMetaTileEntity.isServerSide()) {
+ if (isFluidChangingAllowed() && getFillableStack() != null && getFillableStack().amount <= 0)
+ setFillableStack(null);
+
+ if (mVoidFluidFull && getFillableStack() != null) {
+ mVoidFluidPart = false;
+ mLockFluid = false;
+ setFillableStack(null);
+ }
+
+ if (doesEmptyContainers()) {
+ FluidStack tFluid = GT_Utility.getFluidForFilledItem(mInventory[getInputSlot()], true);
+ if (tFluid != null && isFluidInputAllowed(tFluid)) {
+ if (getFillableStack() == null) {
+ if (isFluidInputAllowed(tFluid)) {
+ if ((tFluid.amount <= getRealCapacity()) || mVoidFluidPart) {
+ tFluid = tFluid.copy();
+ if (aBaseMetaTileEntity.addStackToSlot(
+ getOutputSlot(),
+ GT_Utility.getContainerForFilledItem(mInventory[getInputSlot()], true),
+ 1)) {
+ setFillableStack(tFluid);
+ this.onEmptyingContainerWhenEmpty();
+ aBaseMetaTileEntity.decrStackSize(getInputSlot(), 1);
+ }
+ }
+ }
+ } else {
+ if (tFluid.isFluidEqual(getFillableStack())) {
+ if ((((long) tFluid.amount + getFillableStack().amount) <= (long) getRealCapacity())
+ || mVoidFluidPart
+ || mVoidFluidFull) {
+ if (aBaseMetaTileEntity.addStackToSlot(
+ getOutputSlot(),
+ GT_Utility.getContainerForFilledItem(mInventory[getInputSlot()], true),
+ 1)) {
+ getFillableStack().amount += Math
+ .min(tFluid.amount, getRealCapacity() - getFillableStack().amount);
+ aBaseMetaTileEntity.decrStackSize(getInputSlot(), 1);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (doesFillContainers()) {
+ ItemStack tOutput = GT_Utility
+ .fillFluidContainer(getDrainableStack(), mInventory[getInputSlot()], false, true);
+ if (tOutput != null && aBaseMetaTileEntity.addStackToSlot(getOutputSlot(), tOutput, 1)) {
+ FluidStack tFluid = GT_Utility.getFluidForFilledItem(tOutput, true);
+ aBaseMetaTileEntity.decrStackSize(getInputSlot(), 1);
+ if (tFluid != null) getDrainableStack().amount -= tFluid.amount;
+ if (getDrainableStack().amount <= 0 && isFluidChangingAllowed()) setDrainableStack(null);
+ }
+ }
+ }
+ }
+
+ @Override
+ public int fill(FluidStack aFluid, boolean doFill) {
+ if (aFluid == null || aFluid.getFluid()
+ .getID() <= 0 || aFluid.amount <= 0 || !canTankBeFilled() || !isFluidInputAllowed(aFluid)) return 0;
+ if (getFillableStack() != null && !getFillableStack().isFluidEqual(aFluid)) {
+ return 0;
+ }
+
+ FluidStack fillableStack = getFillableStack();
+ if (fillableStack == null) {
+ fillableStack = aFluid.copy();
+ fillableStack.amount = 0;
+ }
+
+ int amount = Math.min(aFluid.amount, getRealCapacity() - fillableStack.amount);
+ if (doFill) {
+ fillableStack.amount += amount;
+ if (getFillableStack() == null) setFillableStack(fillableStack);
+ getBaseMetaTileEntity().markDirty();
+ }
+ return (mVoidFluidPart || mVoidFluidFull) ? aFluid.amount : amount;
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ super.onPostTick(aBaseMetaTileEntity, aTick);
+ if (aBaseMetaTileEntity.isServerSide()) {
+ if (mOutputFluid && getDrainableStack() != null && (aTick % 20 == 0)) {
+ IFluidHandler tTank = aBaseMetaTileEntity.getITankContainerAtSide(aBaseMetaTileEntity.getFrontFacing());
+ if (tTank != null) {
+ FluidStack tDrained = drain(20 * (1 << (3 + 2 * tierPump(mTier))), false);
+ if (tDrained != null) {
+ int tFilledAmount = tTank.fill(aBaseMetaTileEntity.getBackFacing(), tDrained, false);
+ if (tFilledAmount > 0)
+ tTank.fill(aBaseMetaTileEntity.getBackFacing(), drain(tFilledAmount, true), true);
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public boolean isFacingValid(ForgeDirection side) {
+ return true;
+ }
+
+ @Override
+ public boolean isInputFacing(ForgeDirection side) {
+ return true;
+ }
+
+ @Override
+ public boolean isOutputFacing(ForgeDirection side) {
+ return false;
+ }
+
+ @Override
+ public boolean isLiquidInput(ForgeDirection side) {
+ return mAllowInputFromOutputSide || side != getBaseMetaTileEntity().getFrontFacing();
+ }
+
+ @Override
+ public boolean isLiquidOutput(ForgeDirection side) {
+ return true;
+ }
+
+ @Override
+ public boolean isAccessAllowed(EntityPlayer aPlayer) {
+ return true;
+ }
+
+ @Override
+ public int getTankPressure() {
+ return 100;
+ }
+
+ public boolean allowOverflow() {
+ return mVoidFluidPart || mVoidFluidFull;
+ }
+
+ @Override
+ public int getCapacity() {
+ return allowOverflow() ? Integer.MAX_VALUE : getRealCapacity();
+ }
+
+ @Override
+ public int getRealCapacity() {
+ return commonSizeCompute(mTier);
+ }
+
+ @Override
+ public boolean isGivingInformation() {
+ return true;
+ }
+
+ @Override
+ public FluidTankInfo getInfo() {
+ return new FluidTankInfo(getFluid(), getCapacity());
+ }
+
+ @Override
+ public FluidTankInfo[] getTankInfo(ForgeDirection side) {
+ return new FluidTankInfo[] { getInfo() };
+ }
+
+ @Nonnull
+ public FluidTankInfo[] getRealTankInfo(ForgeDirection side) {
+ return new FluidTankInfo[] { new FluidTankInfo(getFluid(), getRealCapacity()) };
+ }
+
+ @Override
+ public void getWailaBody(ItemStack itemStack, List<String> currenttip, IWailaDataAccessor accessor,
+ IWailaConfigHandler config) {
+ super.getWailaBody(itemStack, currenttip, accessor, config);
+
+ NBTTagCompound tag = accessor.getNBTData();
+ FluidStack fluid = tag.hasKey("mFluid") ? FluidStack.loadFluidStackFromNBT(tag.getCompoundTag("mFluid")) : null;
+ if (fluid != null && fluid.amount >= 0) {
+ currenttip.remove(0);
+ currenttip.add(
+ 0,
+ formatNumbers(fluid.amount) + " / "
+ + formatNumbers(getRealCapacity())
+ + " L "
+ + fluid.getLocalizedName());
+ } else {
+ currenttip.add(0, "Tank Empty");
+ }
+ }
+
+ @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);
+ FluidStack fluid = getFluid();
+ if (fluid != null) tag.setTag("mFluid", fluid.writeToNBT(new NBTTagCompound()));
+ else if (tag.hasKey("mFluid")) tag.removeTag("mFluid");
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ protected static final NumberFormatMUI numberFormat = new NumberFormatMUI();
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ fluidTank.setAllowOverflow(allowOverflow());
+ fluidTank.setPreventDraining(mLockFluid);
+
+ FluidSlotWidget fluidSlotWidget = new FluidSlotWidget(fluidTank);
+ builder.widget(
+ new DrawableWidget().setDrawable(GT_UITextures.PICTURE_SCREEN_BLACK)
+ .setPos(7, 16)
+ .setSize(71, 45))
+ .widget(
+ new SlotWidget(inventoryHandler, getInputSlot())
+ .setBackground(getGUITextureSet().getItemSlot(), GT_UITextures.OVERLAY_SLOT_IN)
+ .setPos(79, 16))
+ .widget(
+ new SlotWidget(inventoryHandler, getOutputSlot()).setAccess(true, false)
+ .setBackground(getGUITextureSet().getItemSlot(), GT_UITextures.OVERLAY_SLOT_OUT)
+ .setPos(79, 43))
+ .widget(
+ fluidSlotWidget.setOnClickContainer(widget -> onEmptyingContainerWhenEmpty())
+ .setBackground(GT_UITextures.TRANSPARENT)
+ .setPos(58, 41))
+ .widget(
+ new TextWidget(StatCollector.translateToLocal("GT5U.machines.digitaltank.fluid.amount"))
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setPos(10, 20))
+ .widget(
+ new TextWidget().setStringSupplier(() -> numberFormat.format(mFluid != null ? mFluid.amount : 0))
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setPos(10, 30))
+ .widget(
+ new DrawableWidget().setDrawable(GT_UITextures.PICTURE_SCREEN_BLACK)
+ .setPos(98, 16)
+ .setSize(71, 45))
+ .widget(new FluidLockWidget(this).setPos(149, 41))
+ .widget(
+ new TextWidget(StatCollector.translateToLocal("GT5U.machines.digitaltank.lockfluid.label"))
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setPos(101, 20))
+ .widget(TextWidget.dynamicString(() -> {
+ FluidStack fluidStack = FluidRegistry.getFluidStack(lockedFluidName, 1);
+ return fluidStack != null ? fluidStack.getLocalizedName()
+ : StatCollector.translateToLocal("GT5U.machines.digitaltank.lockfluid.empty");
+ })
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setTextAlignment(Alignment.CenterLeft)
+ .setMaxWidth(65)
+ .setPos(101, 30))
+ .widget(new CycleButtonWidget().setToggle(() -> mOutputFluid, val -> {
+ mOutputFluid = val;
+ if (!mOutputFluid) {
+ GT_Utility.sendChatToPlayer(
+ buildContext.getPlayer(),
+ GT_Utility.trans("262", "Fluid Auto Output Disabled"));
+ } else {
+ GT_Utility.sendChatToPlayer(
+ buildContext.getPlayer(),
+ GT_Utility.trans("263", "Fluid Auto Output Enabled"));
+ }
+ })
+ .setVariableBackground(GT_UITextures.BUTTON_STANDARD_TOGGLE)
+ .setStaticTexture(GT_UITextures.OVERLAY_BUTTON_AUTOOUTPUT_FLUID)
+ .setGTTooltip(() -> mTooltipCache.getData("GT5U.machines.digitaltank.autooutput.tooltip"))
+ .setTooltipShowUpDelay(TOOLTIP_DELAY)
+ .setPos(7, 63)
+ .setSize(18, 18))
+ .widget(new CycleButtonWidget().setToggle(() -> mLockFluid, val -> {
+ lockFluid(val);
+ fluidTank.setPreventDraining(mLockFluid);
+
+ String inBrackets;
+ if (mLockFluid) {
+ if (mFluid == null) {
+ setLockedFluidName(null);
+ inBrackets = GT_Utility
+ .trans("264", "currently none, will be locked to the next that is put in");
+ } else {
+ setLockedFluidName(
+ getDrainableStack().getFluid()
+ .getName());
+ inBrackets = getDrainableStack().getLocalizedName();
+ }
+ GT_Utility.sendChatToPlayer(
+ buildContext.getPlayer(),
+ String.format("%s (%s)", GT_Utility.trans("265", "1 specific Fluid"), inBrackets));
+ } else {
+ fluidTank.drain(0, true);
+ GT_Utility.sendChatToPlayer(
+ buildContext.getPlayer(),
+ GT_Utility.trans("266", "Lock Fluid Mode Disabled"));
+ }
+ fluidSlotWidget.notifyTooltipChange();
+ })
+ .setVariableBackground(GT_UITextures.BUTTON_STANDARD_TOGGLE)
+ .setStaticTexture(GT_UITextures.OVERLAY_BUTTON_LOCK)
+ .setGTTooltip(() -> mTooltipCache.getData("GT5U.machines.digitaltank.lockfluid.tooltip"))
+ .setTooltipShowUpDelay(TOOLTIP_DELAY)
+ .setPos(25, 63)
+ .setSize(18, 18))
+ .widget(new CycleButtonWidget().setToggle(() -> mAllowInputFromOutputSide, val -> {
+ mAllowInputFromOutputSide = val;
+ if (!mAllowInputFromOutputSide) {
+ GT_Utility.sendChatToPlayer(buildContext.getPlayer(), GT_Utility.getTrans("096"));
+ } else {
+ GT_Utility.sendChatToPlayer(buildContext.getPlayer(), GT_Utility.getTrans("095"));
+ }
+ })
+ .setVariableBackground(GT_UITextures.BUTTON_STANDARD_TOGGLE)
+ .setStaticTexture(GT_UITextures.OVERLAY_BUTTON_INPUT_FROM_OUTPUT_SIDE)
+ .setGTTooltip(() -> mTooltipCache.getData("GT5U.machines.digitaltank.inputfromoutput.tooltip"))
+ .setTooltipShowUpDelay(TOOLTIP_DELAY)
+ .setPos(43, 63)
+ .setSize(18, 18))
+ .widget(new CycleButtonWidget().setToggle(() -> mVoidFluidPart, val -> {
+ mVoidFluidPart = val;
+ fluidTank.setAllowOverflow(allowOverflow());
+ if (!mVoidFluidPart) {
+ GT_Utility.sendChatToPlayer(
+ buildContext.getPlayer(),
+ GT_Utility.trans("267", "Overflow Voiding Mode Disabled"));
+ } else {
+ GT_Utility.sendChatToPlayer(
+ buildContext.getPlayer(),
+ GT_Utility.trans("268", "Overflow Voiding Mode Enabled"));
+ }
+ })
+ .setVariableBackground(GT_UITextures.BUTTON_STANDARD_TOGGLE)
+ .setStaticTexture(GT_UITextures.OVERLAY_BUTTON_TANK_VOID_EXCESS)
+ .setGTTooltip(() -> mTooltipCache.getData("GT5U.machines.digitaltank.voidoverflow.tooltip"))
+ .setTooltipShowUpDelay(TOOLTIP_DELAY)
+ .setPos(98, 63)
+ .setSize(18, 18))
+ .widget(new CycleButtonWidget().setToggle(() -> mVoidFluidFull, val -> {
+ mVoidFluidFull = val;
+ fluidTank.setAllowOverflow(allowOverflow());
+ if (!mVoidFluidFull) {
+ GT_Utility
+ .sendChatToPlayer(buildContext.getPlayer(), GT_Utility.trans("269", "Void Full Mode Disabled"));
+ } else {
+ GT_Utility
+ .sendChatToPlayer(buildContext.getPlayer(), GT_Utility.trans("270", "Void Full Mode Enabled"));
+ }
+ })
+ .setVariableBackground(GT_UITextures.BUTTON_STANDARD_TOGGLE)
+ .setStaticTexture(GT_UITextures.OVERLAY_BUTTON_TANK_VOID_ALL)
+ .setGTTooltip(() -> mTooltipCache.getData("GT5U.machines.digitaltank.voidfull.tooltip"))
+ .setTooltipShowUpDelay(TOOLTIP_DELAY)
+ .setPos(116, 63)
+ .setSize(18, 18));
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_Locker.java b/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_Locker.java
new file mode 100644
index 0000000000..abce9514de
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_Locker.java
@@ -0,0 +1,283 @@
+package gregtech.common.tileentities.storage;
+
+import static gregtech.api.enums.Textures.BlockIcons.LOCKERS;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASINGS;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAYS_ENERGY_IN;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_LOCKER;
+
+import java.util.List;
+
+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.common.util.ForgeDirection;
+
+import gregtech.api.enums.SoundResource;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_TieredMachineBlock;
+import gregtech.api.objects.GT_ItemStack;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_Utility;
+import mcp.mobius.waila.api.IWailaConfigHandler;
+import mcp.mobius.waila.api.IWailaDataAccessor;
+
+public class GT_MetaTileEntity_Locker extends GT_MetaTileEntity_TieredMachineBlock {
+
+ private static final String CHARGE_SLOT_WAILA_TAG = "charge_slot_";
+ public byte mType = 0;
+
+ public GT_MetaTileEntity_Locker(int aID, String aName, String aNameRegional, int aTier) {
+ super(aID, aName, aNameRegional, aTier, 4, "Stores and recharges Armor");
+ }
+
+ public GT_MetaTileEntity_Locker(String aName, int aTier, String aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, 4, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_Locker(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, 4, aDescription, aTextures);
+ }
+
+ @Override
+ public String[] getDescription() {
+ String[] desc = new String[mDescriptionArray.length + 1];
+ System.arraycopy(mDescriptionArray, 0, desc, 0, mDescriptionArray.length);
+ desc[mDescriptionArray.length] = "Click with Screwdriver to change Style";
+ return desc;
+ }
+
+ @Override
+ public ITexture[][][] getTextureSet(ITexture[] aTextures) {
+ ITexture[][][] rTextures = new ITexture[3][17][];
+ for (byte i = -1; i < 16; i = (byte) (i + 1)) {
+ ITexture[] tmp0 = { MACHINE_CASINGS[this.mTier][(i + 1)] };
+ rTextures[0][(i + 1)] = tmp0;
+ ITexture[] tmp1 = { MACHINE_CASINGS[this.mTier][(i + 1)], OVERLAYS_ENERGY_IN[this.mTier] };
+ rTextures[1][(i + 1)] = tmp1;
+ ITexture[] tmp2 = { MACHINE_CASINGS[this.mTier][(i + 1)], TextureFactory.of(OVERLAY_LOCKER) };
+ rTextures[2][(i + 1)] = tmp2;
+ }
+ return rTextures;
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection aFacing,
+ int colorIndex, boolean aActive, boolean redstoneLevel) {
+ if (side == aFacing) {
+ return new ITexture[] { this.mTextures[2][(colorIndex + 1)][0], this.mTextures[2][(colorIndex + 1)][1],
+ LOCKERS[Math.abs(this.mType % LOCKERS.length)] };
+ }
+ return this.mTextures[0][(colorIndex + 1)];
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Locker(this.mName, this.mTier, this.mDescriptionArray, this.mTextures);
+ }
+
+ @Override
+ public boolean isSimpleMachine() {
+ return false;
+ }
+
+ @Override
+ public boolean isElectric() {
+ return true;
+ }
+
+ @Override
+ public boolean isValidSlot(int aIndex) {
+ return true;
+ }
+
+ @Override
+ public boolean isFacingValid(ForgeDirection facing) {
+ return (facing.flag & (ForgeDirection.UP.flag | ForgeDirection.DOWN.flag)) == 0;
+ }
+
+ @Override
+ public boolean isEnetInput() {
+ return true;
+ }
+
+ @Override
+ public boolean isInputFacing(ForgeDirection side) {
+ return side == getBaseMetaTileEntity().getBackFacing();
+ }
+
+ @Override
+ public boolean isTeleporterCompatible() {
+ return false;
+ }
+
+ @Override
+ public long maxEUStore() {
+ return gregtech.api.enums.GT_Values.V[this.mTier] * maxAmperesIn();
+ }
+
+ @Override
+ public long maxEUInput() {
+ return gregtech.api.enums.GT_Values.V[this.mTier];
+ }
+
+ @Override
+ public long maxAmperesIn() {
+ return this.mInventory.length * 2L;
+ }
+
+ @Override
+ public int rechargerSlotStartIndex() {
+ return 0;
+ }
+
+ @Override
+ public int rechargerSlotCount() {
+ return getBaseMetaTileEntity().isAllowedToWork() ? this.mInventory.length : 0;
+ }
+
+ @Override
+ public boolean isAccessAllowed(EntityPlayer aPlayer) {
+ return true;
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ aNBT.setByte("mType", this.mType);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ this.mType = aNBT.getByte("mType");
+ }
+
+ @Override
+ public void onValueUpdate(byte aValue) {
+ this.mType = aValue;
+ }
+
+ @Override
+ public byte getUpdateData() {
+ return this.mType;
+ }
+
+ @Override
+ public void doSound(byte aIndex, double aX, double aY, double aZ) {
+ if (aIndex == 16) {
+ GT_Utility.doSoundAtClient(SoundResource.RANDOM_CLICK, 1, 1.0F);
+ }
+ }
+
+ @Override
+ public void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ if (side == getBaseMetaTileEntity().getFrontFacing()) {
+ this.mType = ((byte) (this.mType + 1));
+ }
+ }
+
+ @Override
+ public boolean allowCoverOnSide(ForgeDirection side, GT_ItemStack aStack) {
+ return side != getBaseMetaTileEntity().getFrontFacing();
+ }
+
+ @Override
+ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer, ForgeDirection side,
+ float aX, float aY, float aZ) {
+ if ((aBaseMetaTileEntity.isServerSide()) && (side == aBaseMetaTileEntity.getFrontFacing())) {
+ for (int i = 0; i < 4; i++) {
+ ItemStack tSwapStack = this.mInventory[i];
+ this.mInventory[i] = aPlayer.inventory.armorInventory[i];
+ aPlayer.inventory.armorInventory[i] = tSwapStack;
+ }
+ aPlayer.inventoryContainer.detectAndSendChanges();
+ sendSound((byte) 16);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean allowPullStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public boolean allowPutStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return false;
+ }
+
+ @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);
+ for (int i = 0; i < 4; i++) {
+ final ItemStack itemStack = this.mInventory[3 - i];
+
+ if (itemStack != null) {
+ tag.setTag(CHARGE_SLOT_WAILA_TAG + i, itemStack.writeToNBT(new NBTTagCompound()));
+ }
+ }
+ }
+
+ @Override
+ public void getWailaBody(ItemStack itemStack, List<String> currentTip, IWailaDataAccessor accessor,
+ IWailaConfigHandler config) {
+ super.getWailaBody(itemStack, currentTip, accessor, config);
+
+ final NBTTagCompound tag = accessor.getNBTData();
+
+ for (int i = 0; i < 4; i++) {
+ final String index = GT_Utility.formatNumbers(i + 1);
+
+ if (tag.hasKey(CHARGE_SLOT_WAILA_TAG + i)) {
+ final ItemStack slotItem = ItemStack
+ .loadItemStackFromNBT(tag.getCompoundTag(CHARGE_SLOT_WAILA_TAG + i));
+ assert slotItem != null;
+
+ currentTip.add(
+ GT_ModHandler.getElectricItemCharge(slotItem)
+ .map(chargeInfo -> {
+ final float ratio = (float) chargeInfo[0] / (float) chargeInfo[1];
+ final EnumChatFormatting chargeFormat;
+
+ if (ratio == 0L) {
+ chargeFormat = EnumChatFormatting.GRAY;
+ } else if (ratio < 0.25) {
+ chargeFormat = EnumChatFormatting.RED;
+ } else if (ratio < 0.5) {
+ chargeFormat = EnumChatFormatting.GOLD;
+ } else if (ratio < 0.75) {
+ chargeFormat = EnumChatFormatting.YELLOW;
+ } else if (ratio < 1L) {
+ chargeFormat = EnumChatFormatting.GREEN;
+ } else {
+ chargeFormat = EnumChatFormatting.AQUA;
+ }
+
+ return StatCollector.translateToLocalFormatted(
+ "gt.locker.waila_armor_slot_charged",
+ index,
+ slotItem.getDisplayName(),
+ chargeFormat,
+ GT_Utility.formatNumbers(ratio * 100));
+ })
+ .orElseGet(
+ // Lazy initialization
+ () -> StatCollector.translateToLocalFormatted(
+ "gt.locker.waila_armor_slot_generic",
+ index,
+ slotItem.getDisplayName())));
+ } else {
+ currentTip.add(StatCollector.translateToLocalFormatted("gt.locker.waila_armor_slot_none", index));
+ }
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_QuantumChest.java b/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_QuantumChest.java
new file mode 100644
index 0000000000..c830cd4e52
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_QuantumChest.java
@@ -0,0 +1,102 @@
+package gregtech.common.tileentities.storage;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+
+public class GT_MetaTileEntity_QuantumChest extends GT_MetaTileEntity_DigitalChestBase {
+
+ public int mItemCount = 0;
+ public ItemStack mItemStack = null;
+ NBTTagList mInvData = null;
+
+ public GT_MetaTileEntity_QuantumChest(int aID, String aName, String aNameRegional, int aTier) {
+ super(aID, aName, aNameRegional, aTier);
+ }
+
+ public GT_MetaTileEntity_QuantumChest(String aName, int aTier, String aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_QuantumChest(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_QuantumChest(mName, mTier, mDescriptionArray, mTextures);
+ }
+
+ @Override
+ public void setItemNBT(NBTTagCompound aNBT) {
+ mInvData = new NBTTagList();
+ for (int i = 0; i < 3; i++) {
+ if (mInventory[i] != null) {
+ NBTTagCompound tNBT = new NBTTagCompound();
+ tNBT.setByte("Count", (byte) mInventory[i].stackSize);
+ tNBT.setShort("Damage", (short) mInventory[i].getItemDamage());
+ tNBT.setShort("id", (short) Item.getIdFromItem(mInventory[i].getItem()));
+ tNBT.setInteger("IntSlot", i);
+ if (mInventory[i].hasTagCompound()) {
+ tNBT.setTag("tag", mInventory[i].getTagCompound());
+ }
+ mInvData.appendTag(tNBT);
+ }
+ }
+ if (mItemStack != null) aNBT.setTag("mItemStack", getItemStack().writeToNBT(new NBTTagCompound()));
+ aNBT.setTag("Inventory", mInvData);
+ aNBT.setInteger("mItemCount", getItemCount());
+ aNBT.setBoolean("mVoidOverflow", mVoidOverflow);
+
+ super.setItemNBT(aNBT);
+ }
+
+ @Override
+ protected String chestName() {
+ return "Quantum Chest";
+ }
+
+ @Override
+ protected int getItemCount() {
+ return mItemCount;
+ }
+
+ @Override
+ public void setItemCount(int aCount) {
+ mItemCount = aCount;
+ }
+
+ @Override
+ protected ItemStack getItemStack() {
+ return mItemStack;
+ }
+
+ @Override
+ protected void setItemStack(ItemStack s) {
+ mItemStack = s;
+ }
+
+ @Nullable
+ @Override
+ public List<ItemStack> getItemsForHoloGlasses() {
+ List<ItemStack> ret = new ArrayList<>();
+ ret.add(getStackInSlot(0));
+ ret.add(getStackInSlot(1));
+ if (mItemStack != null) {
+ ItemStack copy = mItemStack.copy();
+ copy.stackSize = mItemCount;
+ ret.add(copy);
+ }
+ return ret;
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_QuantumTank.java b/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_QuantumTank.java
new file mode 100644
index 0000000000..4d51d0b634
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_QuantumTank.java
@@ -0,0 +1,55 @@
+package gregtech.common.tileentities.storage;
+
+import net.minecraft.util.EnumChatFormatting;
+
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_QuantumTank extends GT_MetaTileEntity_DigitalTankBase {
+
+ public GT_MetaTileEntity_QuantumTank(int aID, String aName, String aNameRegional, int aTier) {
+ super(aID, aName, aNameRegional, aTier);
+ }
+
+ public GT_MetaTileEntity_QuantumTank(String aName, int aTier, String aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_QuantumTank(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_QuantumTank(mName, mTier, mDescriptionArray, mTextures);
+ }
+
+ @Override
+ public String[] getInfoData() {
+
+ if (mFluid == null) {
+ return new String[] { EnumChatFormatting.BLUE + "Quantum Tank" + EnumChatFormatting.RESET, "Stored Fluid:",
+ EnumChatFormatting.GOLD + "No Fluid" + EnumChatFormatting.RESET,
+ EnumChatFormatting.GREEN + Integer.toString(0)
+ + " L"
+ + EnumChatFormatting.RESET
+ + " "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(getCapacity())
+ + " L"
+ + EnumChatFormatting.RESET };
+ }
+ return new String[] { EnumChatFormatting.BLUE + "Quantum Tank" + EnumChatFormatting.RESET, "Stored Fluid:",
+ EnumChatFormatting.GOLD + mFluid.getLocalizedName() + EnumChatFormatting.RESET,
+ EnumChatFormatting.GREEN + GT_Utility.formatNumbers(mFluid.amount)
+ + " L"
+ + EnumChatFormatting.RESET
+ + " "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(getCapacity())
+ + " L"
+ + EnumChatFormatting.RESET };
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_SuperChest.java b/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_SuperChest.java
new file mode 100644
index 0000000000..271402f0de
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_SuperChest.java
@@ -0,0 +1,30 @@
+package gregtech.common.tileentities.storage;
+
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+
+public class GT_MetaTileEntity_SuperChest extends GT_MetaTileEntity_QuantumChest {
+
+ public GT_MetaTileEntity_SuperChest(int aID, String aName, String aNameRegional, int aTier) {
+ super(aID, aName, aNameRegional, aTier);
+ }
+
+ public GT_MetaTileEntity_SuperChest(String aName, int aTier, String aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_SuperChest(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ }
+
+ @Override
+ protected String chestName() {
+ return "Super Chest";
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_SuperChest(mName, mTier, mDescriptionArray, mTextures);
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_SuperTank.java b/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_SuperTank.java
new file mode 100644
index 0000000000..4f0bdbc237
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_SuperTank.java
@@ -0,0 +1,54 @@
+package gregtech.common.tileentities.storage;
+
+import net.minecraft.util.EnumChatFormatting;
+
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_SuperTank extends GT_MetaTileEntity_DigitalTankBase {
+
+ public GT_MetaTileEntity_SuperTank(int aID, String aName, String aNameRegional, int aTier) {
+ super(aID, aName, aNameRegional, aTier);
+ }
+
+ public GT_MetaTileEntity_SuperTank(String aName, int aTier, String aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_SuperTank(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_SuperTank(mName, mTier, mDescriptionArray, mTextures);
+ }
+
+ @Override
+ public String[] getInfoData() {
+
+ if (mFluid == null) {
+ return new String[] { EnumChatFormatting.BLUE + "Super Tank" + EnumChatFormatting.RESET, "Stored Fluid:",
+ EnumChatFormatting.GOLD + "No Fluid" + EnumChatFormatting.RESET,
+ EnumChatFormatting.GREEN + "0 L"
+ + EnumChatFormatting.RESET
+ + " "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(getCapacity())
+ + " L"
+ + EnumChatFormatting.RESET };
+ }
+ return new String[] { EnumChatFormatting.BLUE + "Super Tank" + EnumChatFormatting.RESET, "Stored Fluid:",
+ EnumChatFormatting.GOLD + mFluid.getLocalizedName() + EnumChatFormatting.RESET,
+ EnumChatFormatting.GREEN + GT_Utility.formatNumbers(mFluid.amount)
+ + " L"
+ + EnumChatFormatting.RESET
+ + " "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(getCapacity())
+ + " L"
+ + EnumChatFormatting.RESET };
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool.java b/src/main/java/gregtech/common/tools/GT_Tool.java
new file mode 100644
index 0000000000..cb637a1bd5
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool.java
@@ -0,0 +1,196 @@
+package gregtech.common.tools;
+
+import java.util.List;
+
+import net.minecraft.block.Block;
+import net.minecraft.enchantment.Enchantment;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.stats.AchievementList;
+import net.minecraft.util.DamageSource;
+import net.minecraft.util.EntityDamageSource;
+import net.minecraft.util.IChatComponent;
+import net.minecraft.world.World;
+import net.minecraftforge.event.world.BlockEvent;
+
+import gregtech.api.damagesources.GT_DamageSources;
+import gregtech.api.enums.SoundResource;
+import gregtech.api.interfaces.IToolStats;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+
+public abstract class GT_Tool implements IToolStats {
+
+ public static final Enchantment[] FORTUNE_ENCHANTMENT = { Enchantment.fortune };
+ public static final Enchantment[] LOOTING_ENCHANTMENT = { Enchantment.looting };
+ public static final Enchantment[] ZERO_ENCHANTMENTS = new Enchantment[0];
+ public static final int[] ZERO_ENCHANTMENT_LEVELS = new int[0];
+
+ @Override
+ public int getToolDamagePerBlockBreak() {
+ return 100;
+ }
+
+ @Override
+ public int getToolDamagePerDropConversion() {
+ return 100;
+ }
+
+ @Override
+ public int getToolDamagePerContainerCraft() {
+ return 800;
+ }
+
+ @Override
+ public int getToolDamagePerEntityAttack() {
+ return 200;
+ }
+
+ @Override
+ public float getSpeedMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public int getHurtResistanceTime(int aOriginalHurtResistance, Entity aEntity) {
+ return aOriginalHurtResistance;
+ }
+
+ @Override
+ public String getMiningSound() {
+ return null;
+ }
+
+ @Override
+ public String getCraftingSound() {
+ return null;
+ }
+
+ @Override
+ public String getEntityHitSound() {
+ return null;
+ }
+
+ @Override
+ public String getBreakingSound() {
+ return SoundResource.RANDOM_BREAK.toString();
+ }
+
+ @Override
+ public int getBaseQuality() {
+ return 0;
+ }
+
+ @Override
+ public boolean canBlock() {
+ return false;
+ }
+
+ @Override
+ public boolean isCrowbar() {
+ return false;
+ }
+
+ @Override
+ public boolean isGrafter() {
+ return false;
+ }
+
+ @Override
+ public boolean isChainsaw() {
+ return false;
+ }
+
+ @Override
+ public boolean isWrench() {
+ return false;
+ }
+
+ @Override
+ public boolean isWeapon() {
+ return false;
+ }
+
+ @Override
+ public boolean isRangedWeapon() {
+ return false;
+ }
+
+ @Override
+ public boolean isMiningTool() {
+ return true;
+ }
+
+ @Override
+ public DamageSource getDamageSource(EntityLivingBase aPlayer, Entity aEntity) {
+ return GT_DamageSources.getCombatDamage(
+ (aPlayer instanceof EntityPlayer) ? "player" : "mob",
+ aPlayer,
+ (aEntity instanceof EntityLivingBase) ? getDeathMessage(aPlayer, (EntityLivingBase) aEntity) : null);
+ }
+
+ public IChatComponent getDeathMessage(EntityLivingBase aPlayer, EntityLivingBase aEntity) {
+ return new EntityDamageSource((aPlayer instanceof EntityPlayer) ? "player" : "mob", aPlayer)
+ .func_151519_b(aEntity);
+ }
+
+ @Override
+ public int convertBlockDrops(List<ItemStack> aDrops, ItemStack aStack, EntityPlayer aPlayer, Block aBlock, int aX,
+ int aY, int aZ, byte aMetaData, int aFortune, boolean aSilkTouch, BlockEvent.HarvestDropsEvent aEvent) {
+ return 0;
+ }
+
+ @Override
+ public ItemStack getBrokenItem(ItemStack aStack) {
+ return null;
+ }
+
+ @Override
+ public Enchantment[] getEnchantments(ItemStack aStack) {
+ return ZERO_ENCHANTMENTS;
+ }
+
+ @Override
+ public int[] getEnchantmentLevels(ItemStack aStack) {
+ return ZERO_ENCHANTMENT_LEVELS;
+ }
+
+ @Override
+ public void onToolCrafted(ItemStack aStack, EntityPlayer aPlayer) {
+ aPlayer.triggerAchievement(AchievementList.openInventory);
+ aPlayer.triggerAchievement(AchievementList.mineWood);
+ aPlayer.triggerAchievement(AchievementList.buildWorkBench);
+ }
+
+ @Override
+ public void onStatsAddedToTool(GT_MetaGenerated_Tool aItem, int aID) {}
+
+ @Override
+ public float getNormalDamageAgainstEntity(float aOriginalDamage, Entity aEntity, ItemStack aStack,
+ EntityPlayer aPlayer) {
+ return aOriginalDamage;
+ }
+
+ @Override
+ public float getMagicDamageAgainstEntity(float aOriginalDamage, Entity aEntity, ItemStack aStack,
+ EntityPlayer aPlayer) {
+ return aOriginalDamage;
+ }
+
+ @Override
+ public float getMiningSpeed(Block aBlock, byte aMetaData, float aDefault, EntityPlayer aPlayer, World worldObj,
+ int aX, int aY, int aZ) {
+ return aDefault;
+ }
+
+ @Override
+ public String getToolTypeName() {
+ return "tool";
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_Axe.java b/src/main/java/gregtech/common/tools/GT_Tool_Axe.java
new file mode 100644
index 0000000000..c54ebac3c9
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_Axe.java
@@ -0,0 +1,175 @@
+package gregtech.common.tools;
+
+import java.util.List;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.material.Material;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IChatComponent;
+import net.minecraft.world.World;
+import net.minecraftforge.event.world.BlockEvent;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.util.GT_ToolHarvestHelper;
+
+public class GT_Tool_Axe extends GT_Tool {
+
+ @Override
+ public int getToolDamagePerBlockBreak() {
+ return 50;
+ }
+
+ @Override
+ public int getToolDamagePerDropConversion() {
+ return 100;
+ }
+
+ @Override
+ public int getToolDamagePerContainerCraft() {
+ return 100;
+ }
+
+ @Override
+ public int getToolDamagePerEntityAttack() {
+ return 200;
+ }
+
+ @Override
+ public int getBaseQuality() {
+ return 0;
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 3.0F;
+ }
+
+ @Override
+ public float getSpeedMultiplier() {
+ return 2.0F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public String getCraftingSound() {
+ return null;
+ }
+
+ @Override
+ public String getEntityHitSound() {
+ return null;
+ }
+
+ @Override
+ public String getMiningSound() {
+ return null;
+ }
+
+ @Override
+ public boolean canBlock() {
+ return false;
+ }
+
+ @Override
+ public boolean isCrowbar() {
+ return false;
+ }
+
+ @Override
+ public boolean isWeapon() {
+ return true;
+ }
+
+ @Override
+ public boolean isMinableBlock(Block aBlock, byte aMetaData) {
+ return GT_ToolHarvestHelper.isAppropriateTool(aBlock, aMetaData, "axe")
+ || GT_ToolHarvestHelper.isAppropriateMaterial(aBlock, Material.wood)
+ || GT_ToolHarvestHelper.isSpecialBlock(aBlock, Blocks.ladder);
+ }
+
+ @Override
+ public int convertBlockDrops(List<ItemStack> aDrops, ItemStack aStack, EntityPlayer aPlayer, Block aBlock, int aX,
+ int aY, int aZ, byte aMetaData, int aFortune, boolean aSilkTouch, BlockEvent.HarvestDropsEvent aEvent) {
+ int rAmount = 0;
+ if ((GregTech_API.sTimber) && (!aPlayer.isSneaking())
+ && (OrePrefixes.log.contains(new ItemStack(aBlock, 1, aMetaData)))) {
+ int tY = aY + 1;
+ for (int tH = aPlayer.worldObj.getHeight(); tY < tH; tY++) {
+ if ((aPlayer.worldObj.getBlock(aX, tY, aZ) != aBlock)
+ || (!aPlayer.worldObj.func_147480_a(aX, tY, aZ, true))) {
+ break;
+ }
+ rAmount++;
+ }
+ }
+ return rAmount;
+ }
+
+ @Override
+ public float getMiningSpeed(Block aBlock, byte aMetaData, float aDefault, EntityPlayer aPlayer, World aWorld,
+ int aX, int aY, int aZ) {
+
+ if (aBlock.isWood(aPlayer.worldObj, aX, aY, aZ)
+ && OrePrefixes.log.contains(new ItemStack(aBlock, 1, aMetaData))) {
+ float rAmount = 1.0F;
+ float tIncrement = 1.0F;
+ if ((GregTech_API.sTimber) && !aPlayer.isSneaking()) {
+ int tY = aY + 1;
+ for (int tH = aPlayer.worldObj.getHeight(); (tY < tH)
+ && (aPlayer.worldObj.getBlock(aX, tY, aZ) == aBlock); tY++) {
+ tIncrement += 0.1F;
+ rAmount += tIncrement;
+ }
+ }
+ return 2.0F * aDefault / rAmount;
+ }
+
+ return (aBlock.getMaterial() == Material.leaves) || (aBlock.getMaterial() == Material.vine)
+ || (aBlock.getMaterial() == Material.plants)
+ || (aBlock.getMaterial() == Material.gourd) ? aDefault / 4.0F : aDefault;
+ }
+
+ @Override
+ public ItemStack getBrokenItem(ItemStack aStack) {
+ return null;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead
+ ? GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mIconSet.mTextures[OrePrefixes.toolHeadAxe.mTextureIndex]
+ : GT_MetaGenerated_Tool.getSecondaryMaterial(aStack).mIconSet.mTextures[OrePrefixes.stick.mTextureIndex];
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa
+ : GT_MetaGenerated_Tool.getSecondaryMaterial(aStack).mRGBa;
+ }
+
+ @Override
+ public void onStatsAddedToTool(GT_MetaGenerated_Tool aItem, int aID) {}
+
+ @Override
+ public IChatComponent getDeathMessage(EntityLivingBase aPlayer, EntityLivingBase aEntity) {
+ return new ChatComponentText(
+ EnumChatFormatting.RED + aEntity.getCommandSenderName()
+ + EnumChatFormatting.WHITE
+ + " has been chopped by "
+ + EnumChatFormatting.GREEN
+ + aPlayer.getCommandSenderName()
+ + EnumChatFormatting.WHITE);
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_BranchCutter.java b/src/main/java/gregtech/common/tools/GT_Tool_BranchCutter.java
new file mode 100644
index 0000000000..a8b83a0221
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_BranchCutter.java
@@ -0,0 +1,101 @@
+package gregtech.common.tools;
+
+import java.util.List;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.material.Material;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraft.init.Items;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IChatComponent;
+import net.minecraftforge.event.world.BlockEvent;
+
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_ToolHarvestHelper;
+import gregtech.api.util.GT_Utility;
+
+public class GT_Tool_BranchCutter extends GT_Tool {
+
+ @Override
+ public float getBaseDamage() {
+ return 2.5F;
+ }
+
+ @Override
+ public float getSpeedMultiplier() {
+ return 0.25F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 0.25F;
+ }
+
+ @Override
+ public boolean isGrafter() {
+ return true;
+ }
+
+ @Override
+ public int convertBlockDrops(List<ItemStack> aDrops, ItemStack aStack, EntityPlayer aPlayer, Block aBlock, int aX,
+ int aY, int aZ, byte aMetaData, int aFortune, boolean aSilkTouch, BlockEvent.HarvestDropsEvent aEvent) {
+ if (aBlock.getMaterial() == Material.leaves) {
+ aEvent.dropChance = Math.min(
+ 1.0F,
+ Math.max(
+ aEvent.dropChance,
+ (aStack.getItem()
+ .getHarvestLevel(aStack, "") + 1) * 0.2F));
+ if (aBlock == Blocks.leaves) {
+ aDrops.clear();
+ if (((aMetaData & 0x3) == 0) && (aPlayer.worldObj.rand.nextInt(9) <= aFortune * 2)) {
+ aDrops.add(new ItemStack(Items.apple, 1, 0));
+ } else {
+ aDrops.add(new ItemStack(Blocks.sapling, 1, aMetaData & 0x3));
+ }
+ } else if (aBlock == Blocks.leaves2) {
+ aDrops.clear();
+ aDrops.add(new ItemStack(Blocks.sapling, 1, (aMetaData & 0x3) + 4));
+ } else if (aBlock == GT_Utility.getBlockFromStack(GT_ModHandler.getIC2Item("rubberLeaves", 1L))) {
+ aDrops.clear();
+ aDrops.add(GT_ModHandler.getIC2Item("rubberSapling", 1L));
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean isMinableBlock(Block aBlock, byte aMetaData) {
+ return GT_ToolHarvestHelper.isAppropriateTool(aBlock, aMetaData, "grafter")
+ || GT_ToolHarvestHelper.isAppropriateMaterial(aBlock, Material.leaves);
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? Textures.ItemIcons.GRAFTER : null;
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa
+ : GT_MetaGenerated_Tool.getSecondaryMaterial(aStack).mRGBa;
+ }
+
+ @Override
+ public IChatComponent getDeathMessage(EntityLivingBase aPlayer, EntityLivingBase aEntity) {
+ return new ChatComponentText(
+ EnumChatFormatting.RED + aEntity.getCommandSenderName()
+ + EnumChatFormatting.WHITE
+ + " has been trimmed by "
+ + EnumChatFormatting.GREEN
+ + aPlayer.getCommandSenderName()
+ + EnumChatFormatting.WHITE);
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_ButcheryKnife.java b/src/main/java/gregtech/common/tools/GT_Tool_ButcheryKnife.java
new file mode 100644
index 0000000000..bdfe66401a
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_ButcheryKnife.java
@@ -0,0 +1,104 @@
+package gregtech.common.tools;
+
+import net.minecraft.block.Block;
+import net.minecraft.enchantment.Enchantment;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IChatComponent;
+
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+
+public class GT_Tool_ButcheryKnife extends GT_Tool {
+
+ @Override
+ public int getToolDamagePerBlockBreak() {
+ return 200;
+ }
+
+ @Override
+ public int getToolDamagePerDropConversion() {
+ return 100;
+ }
+
+ @Override
+ public int getToolDamagePerContainerCraft() {
+ return 100;
+ }
+
+ @Override
+ public int getToolDamagePerEntityAttack() {
+ return 200;
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 3.0F;
+ }
+
+ @Override
+ public int getHurtResistanceTime(int aOriginalHurtResistance, Entity aEntity) {
+ return aOriginalHurtResistance * 2;
+ }
+
+ @Override
+ public float getSpeedMultiplier() {
+ return 0.1F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public boolean isWeapon() {
+ return true;
+ }
+
+ @Override
+ public boolean isMiningTool() {
+ return false;
+ }
+
+ @Override
+ public Enchantment[] getEnchantments(ItemStack aStack) {
+ return LOOTING_ENCHANTMENT;
+ }
+
+ @Override
+ public int[] getEnchantmentLevels(ItemStack aStack) {
+ return new int[] { (2 + GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mToolQuality) / 2 };
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? Textures.ItemIcons.BUTCHERYKNIFE : null;
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa
+ : GT_MetaGenerated_Tool.getSecondaryMaterial(aStack).mRGBa;
+ }
+
+ @Override
+ public IChatComponent getDeathMessage(EntityLivingBase aPlayer, EntityLivingBase aEntity) {
+ return new ChatComponentText(
+ EnumChatFormatting.GREEN + aPlayer.getCommandSenderName()
+ + EnumChatFormatting.WHITE
+ + " has butchered "
+ + EnumChatFormatting.RED
+ + aEntity.getCommandSenderName()
+ + EnumChatFormatting.WHITE);
+ }
+
+ @Override
+ public boolean isMinableBlock(Block aBlock, byte aMetaData) {
+ return false;
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_BuzzSaw.java b/src/main/java/gregtech/common/tools/GT_Tool_BuzzSaw.java
new file mode 100644
index 0000000000..4d7192ce93
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_BuzzSaw.java
@@ -0,0 +1,81 @@
+package gregtech.common.tools;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IChatComponent;
+
+import gregtech.api.enums.SoundResource;
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+
+public class GT_Tool_BuzzSaw extends GT_Tool_Saw {
+
+ @Override
+ public int getToolDamagePerContainerCraft() {
+ return 100;
+ }
+
+ @Override
+ public int getToolDamagePerEntityAttack() {
+ return 300;
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 1.0F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public String getCraftingSound() {
+ return SoundResource.IC2_TOOLS_CHAINSAW_CHAINSAW_USE_ONE.toString();
+ }
+
+ @Override
+ public String getEntityHitSound() {
+ return SoundResource.IC2_TOOLS_CHAINSAW_CHAINSAW_USE_TWO.toString();
+ }
+
+ @Override
+ public String getMiningSound() {
+ return SoundResource.IC2_TOOLS_CHAINSAW_CHAINSAW_USE_ONE.toString();
+ }
+
+ @Override
+ public boolean isMinableBlock(Block aBlock, byte aMetaData) {
+ return false;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return !aIsToolHead
+ ? GT_MetaGenerated_Tool.getPrimaryMaterial(
+ aStack).mIconSet.mTextures[gregtech.api.enums.OrePrefixes.toolHeadBuzzSaw.mTextureIndex]
+ : Textures.ItemIcons.HANDLE_BUZZSAW;
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return !aIsToolHead ? GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa
+ : GT_MetaGenerated_Tool.getSecondaryMaterial(aStack).mRGBa;
+ }
+
+ @Override
+ public IChatComponent getDeathMessage(EntityLivingBase aPlayer, EntityLivingBase aEntity) {
+ return new ChatComponentText(
+ EnumChatFormatting.RED + aEntity.getCommandSenderName()
+ + EnumChatFormatting.WHITE
+ + " got buzzed by "
+ + EnumChatFormatting.GREEN
+ + aPlayer.getCommandSenderName()
+ + EnumChatFormatting.WHITE);
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_Chainsaw_HV.java b/src/main/java/gregtech/common/tools/GT_Tool_Chainsaw_HV.java
new file mode 100644
index 0000000000..38c1d3acb8
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_Chainsaw_HV.java
@@ -0,0 +1,57 @@
+package gregtech.common.tools;
+
+import net.minecraft.item.ItemStack;
+
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+
+public class GT_Tool_Chainsaw_HV extends GT_Tool_Chainsaw_LV {
+
+ @Override
+ public int getToolDamagePerBlockBreak() {
+ return 800;
+ }
+
+ @Override
+ public int getToolDamagePerDropConversion() {
+ return 1600;
+ }
+
+ @Override
+ public int getToolDamagePerContainerCraft() {
+ return 12800;
+ }
+
+ @Override
+ public int getToolDamagePerEntityAttack() {
+ return 3200;
+ }
+
+ @Override
+ public int getBaseQuality() {
+ return 1;
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 4.0F;
+ }
+
+ @Override
+ public float getSpeedMultiplier() {
+ return 4.0F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 4.0F;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead
+ ? gregtech.api.items.GT_MetaGenerated_Tool.getPrimaryMaterial(
+ aStack).mIconSet.mTextures[gregtech.api.enums.OrePrefixes.toolHeadChainsaw.mTextureIndex]
+ : Textures.ItemIcons.POWER_UNIT_HV;
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_Chainsaw_LV.java b/src/main/java/gregtech/common/tools/GT_Tool_Chainsaw_LV.java
new file mode 100644
index 0000000000..142b0c50d2
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_Chainsaw_LV.java
@@ -0,0 +1,185 @@
+package gregtech.common.tools;
+
+import java.util.List;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.material.Material;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IChatComponent;
+import net.minecraft.world.World;
+import net.minecraftforge.common.IShearable;
+import net.minecraftforge.event.world.BlockEvent;
+
+import gregtech.GT_Mod;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.enums.SoundResource;
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+
+public class GT_Tool_Chainsaw_LV extends GT_Tool_Saw {
+
+ @Override
+ public int getToolDamagePerBlockBreak() {
+ return 50;
+ }
+
+ @Override
+ public int getToolDamagePerDropConversion() {
+ return 100;
+ }
+
+ @Override
+ public int getToolDamagePerContainerCraft() {
+ return 800;
+ }
+
+ @Override
+ public int getToolDamagePerEntityAttack() {
+ return 200;
+ }
+
+ @Override
+ public int getBaseQuality() {
+ return 0;
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 3.0F;
+ }
+
+ @Override
+ public float getSpeedMultiplier() {
+ return 2.0F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public String getCraftingSound() {
+ return SoundResource.IC2_TOOLS_CHAINSAW_CHAINSAW_USE_ONE.toString();
+ }
+
+ @Override
+ public String getEntityHitSound() {
+ return SoundResource.IC2_TOOLS_CHAINSAW_CHAINSAW_USE_TWO.toString();
+ }
+
+ @Override
+ public String getMiningSound() {
+ return SoundResource.IC2_TOOLS_CHAINSAW_CHAINSAW_USE_ONE.toString();
+ }
+
+ @Override
+ public boolean canBlock() {
+ return false;
+ }
+
+ @Override
+ public boolean isChainsaw() {
+ return true;
+ }
+
+ @Override
+ public boolean isWeapon() {
+ return true;
+ }
+
+ @Override
+ public void onToolCrafted(ItemStack aStack, EntityPlayer aPlayer) {
+ super.onToolCrafted(aStack, aPlayer);
+ try {
+ GT_Mod.achievements.issueAchievement(aPlayer, "brrrr");
+ GT_Mod.achievements.issueAchievement(aPlayer, "buildChainsaw");
+ } catch (Exception ignored) {}
+ }
+
+ @Override
+ public int convertBlockDrops(List<ItemStack> aDrops, ItemStack aStack, EntityPlayer aPlayer, Block aBlock, int aX,
+ int aY, int aZ, byte aMetaData, int aFortune, boolean aSilkTouch, BlockEvent.HarvestDropsEvent aEvent) {
+ int rAmount = 0;
+ if ((aBlock.getMaterial() == Material.leaves) && ((aBlock instanceof IShearable))) {
+ aPlayer.worldObj.setBlock(aX, aY, aZ, aBlock, aMetaData, 0);
+ if (((IShearable) aBlock).isShearable(aStack, aPlayer.worldObj, aX, aY, aZ)) {
+ ((IShearable) aBlock).onSheared(aStack, aPlayer.worldObj, aX, aY, aZ, aFortune);
+ aDrops.clear();
+ }
+ aPlayer.worldObj.setBlock(aX, aY, aZ, Blocks.air, 0, 0);
+ } else if (((aBlock.getMaterial() == Material.ice) || (aBlock.getMaterial() == Material.packedIce))
+ && (aDrops.isEmpty())) {
+ aDrops.add(new ItemStack(aBlock, 1, aMetaData));
+ aPlayer.worldObj.setBlockToAir(aX, aY, aZ);
+ aEvent.dropChance = 1.0F;
+ return 1;
+ }
+ if ((GregTech_API.sTimber) && (!aPlayer.isSneaking())
+ && (OrePrefixes.log.contains(new ItemStack(aBlock, 1, aMetaData)))) {
+ int tY = aY + 1;
+ for (int tH = aPlayer.worldObj.getHeight(); tY < tH; tY++) {
+ if ((aPlayer.worldObj.getBlock(aX, tY, aZ) != aBlock)
+ || (!aPlayer.worldObj.func_147480_a(aX, tY, aZ, true))) {
+ break;
+ }
+ rAmount++;
+ }
+ }
+ return rAmount;
+ }
+
+ @Override
+ public float getMiningSpeed(Block aBlock, byte aMetaData, float aDefault, EntityPlayer aPlayer, World aWorld,
+ int aX, int aY, int aZ) {
+ if (aBlock.isWood(aPlayer.worldObj, aX, aY, aZ)
+ && OrePrefixes.log.contains(new ItemStack(aBlock, 1, aMetaData))) {
+ float rAmount = 1.0F;
+ float tIncrement = 1.0F;
+ if ((GregTech_API.sTimber) && !aPlayer.isSneaking()) {
+ int tY = aY + 1;
+ for (int tH = aPlayer.worldObj.getHeight(); (tY < tH)
+ && (aPlayer.worldObj.getBlock(aX, tY, aZ) == aBlock); tY++) {
+ tIncrement += 0.1F;
+ rAmount += tIncrement;
+ }
+ }
+ return 2.0F * aDefault / rAmount;
+ }
+ return (aBlock.getMaterial() == Material.leaves) || (aBlock.getMaterial() == Material.vine)
+ || (aBlock.getMaterial() == Material.plants)
+ || (aBlock.getMaterial() == Material.gourd) ? aDefault / 4.0F : aDefault;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead
+ ? GT_MetaGenerated_Tool.getPrimaryMaterial(
+ aStack).mIconSet.mTextures[gregtech.api.enums.OrePrefixes.toolHeadChainsaw.mTextureIndex]
+ : Textures.ItemIcons.POWER_UNIT_LV;
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa
+ : GT_MetaGenerated_Tool.getSecondaryMaterial(aStack).mRGBa;
+ }
+
+ @Override
+ public IChatComponent getDeathMessage(EntityLivingBase aPlayer, EntityLivingBase aEntity) {
+ return new ChatComponentText(
+ EnumChatFormatting.RED + aEntity.getCommandSenderName()
+ + EnumChatFormatting.WHITE
+ + " was massacred by "
+ + EnumChatFormatting.GREEN
+ + aPlayer.getCommandSenderName()
+ + EnumChatFormatting.WHITE);
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_Chainsaw_MV.java b/src/main/java/gregtech/common/tools/GT_Tool_Chainsaw_MV.java
new file mode 100644
index 0000000000..6c88895e48
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_Chainsaw_MV.java
@@ -0,0 +1,57 @@
+package gregtech.common.tools;
+
+import net.minecraft.item.ItemStack;
+
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+
+public class GT_Tool_Chainsaw_MV extends GT_Tool_Chainsaw_LV {
+
+ @Override
+ public int getToolDamagePerBlockBreak() {
+ return 200;
+ }
+
+ @Override
+ public int getToolDamagePerDropConversion() {
+ return 400;
+ }
+
+ @Override
+ public int getToolDamagePerContainerCraft() {
+ return 3200;
+ }
+
+ @Override
+ public int getToolDamagePerEntityAttack() {
+ return 800;
+ }
+
+ @Override
+ public int getBaseQuality() {
+ return 1;
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 3.5F;
+ }
+
+ @Override
+ public float getSpeedMultiplier() {
+ return 3.0F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 2.0F;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead
+ ? gregtech.api.items.GT_MetaGenerated_Tool.getPrimaryMaterial(
+ aStack).mIconSet.mTextures[gregtech.api.enums.OrePrefixes.toolHeadChainsaw.mTextureIndex]
+ : Textures.ItemIcons.POWER_UNIT_MV;
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_Crowbar.java b/src/main/java/gregtech/common/tools/GT_Tool_Crowbar.java
new file mode 100644
index 0000000000..761784284d
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_Crowbar.java
@@ -0,0 +1,140 @@
+package gregtech.common.tools;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.material.Material;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IChatComponent;
+
+import com.google.common.base.Strings;
+
+import gregtech.api.enums.SoundResource;
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.interfaces.IToolStats;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.common.items.GT_MetaGenerated_Tool_01;
+import gregtech.common.items.behaviors.Behaviour_Crowbar;
+
+public class GT_Tool_Crowbar extends GT_Tool {
+
+ @Override
+ public int getToolDamagePerBlockBreak() {
+ return 50;
+ }
+
+ @Override
+ public int getToolDamagePerDropConversion() {
+ return 100;
+ }
+
+ @Override
+ public int getToolDamagePerContainerCraft() {
+ return 100;
+ }
+
+ @Override
+ public int getToolDamagePerEntityAttack() {
+ return 200;
+ }
+
+ @Override
+ public int getBaseQuality() {
+ return 0;
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 2.0F;
+ }
+
+ @Override
+ public float getSpeedMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public String getCraftingSound() {
+ return SoundResource.RANDOM_BREAK.toString();
+ }
+
+ @Override
+ public String getEntityHitSound() {
+ return SoundResource.RANDOM_BREAK.toString();
+ }
+
+ @Override
+ public String getMiningSound() {
+ return SoundResource.RANDOM_BREAK.toString();
+ }
+
+ @Override
+ public boolean canBlock() {
+ return true;
+ }
+
+ @Override
+ public boolean isCrowbar() {
+ return true;
+ }
+
+ @Override
+ public boolean isWeapon() {
+ return true;
+ }
+
+ @Override
+ public boolean isMinableBlock(Block aBlock, byte aMetaData) {
+ if (aBlock.getMaterial() == Material.circuits) {
+ return true;
+ }
+ String tTool = aBlock.getHarvestTool(aMetaData);
+ if (Strings.isNullOrEmpty(tTool)) {
+ for (IToolStats i : GT_MetaGenerated_Tool_01.INSTANCE.mToolStats.values()) {
+ if (i instanceof GT_Tool_Crowbar && i != this && !i.isMinableBlock(aBlock, aMetaData)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return tTool.equals("crowbar");
+ }
+
+ @Override
+ public ItemStack getBrokenItem(ItemStack aStack) {
+ return null;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? Textures.ItemIcons.CROWBAR : null;
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa : null;
+ }
+
+ @Override
+ public void onStatsAddedToTool(GT_MetaGenerated_Tool aItem, int aID) {
+ aItem.addItemBehavior(aID, new Behaviour_Crowbar(1, 1000));
+ }
+
+ @Override
+ public IChatComponent getDeathMessage(EntityLivingBase aPlayer, EntityLivingBase aEntity) {
+ return new ChatComponentText(
+ EnumChatFormatting.RED + aEntity.getCommandSenderName()
+ + EnumChatFormatting.WHITE
+ + " was removed by "
+ + EnumChatFormatting.GREEN
+ + aPlayer.getCommandSenderName()
+ + EnumChatFormatting.WHITE);
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_Drill_HV.java b/src/main/java/gregtech/common/tools/GT_Tool_Drill_HV.java
new file mode 100644
index 0000000000..3731f578db
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_Drill_HV.java
@@ -0,0 +1,68 @@
+package gregtech.common.tools;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+
+import gregtech.GT_Mod;
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+
+public class GT_Tool_Drill_HV extends GT_Tool_Drill_LV {
+
+ @Override
+ public int getToolDamagePerBlockBreak() {
+ return GT_Mod.gregtechproxy.mHardRock ? 400 : 800;
+ }
+
+ @Override
+ public int getToolDamagePerDropConversion() {
+ return 1600;
+ }
+
+ @Override
+ public int getToolDamagePerContainerCraft() {
+ return 12800;
+ }
+
+ @Override
+ public int getToolDamagePerEntityAttack() {
+ return 3200;
+ }
+
+ @Override
+ public int getBaseQuality() {
+ return 1;
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 3.0F;
+ }
+
+ @Override
+ public float getSpeedMultiplier() {
+ return 9.0F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 4.0F;
+ }
+
+ @Override
+ public void onToolCrafted(ItemStack aStack, EntityPlayer aPlayer) {
+ super.onToolCrafted(aStack, aPlayer);
+ try {
+ GT_Mod.achievements.issueAchievement(aPlayer, "highpowerdrill");
+ GT_Mod.achievements.issueAchievement(aPlayer, "buildDDrill");
+ } catch (Exception ignored) {}
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead
+ ? gregtech.api.items.GT_MetaGenerated_Tool.getPrimaryMaterial(
+ aStack).mIconSet.mTextures[gregtech.api.enums.OrePrefixes.toolHeadDrill.mTextureIndex]
+ : Textures.ItemIcons.POWER_UNIT_HV;
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_Drill_LV.java b/src/main/java/gregtech/common/tools/GT_Tool_Drill_LV.java
new file mode 100644
index 0000000000..911374dc15
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_Drill_LV.java
@@ -0,0 +1,152 @@
+package gregtech.common.tools;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.material.Material;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.stats.AchievementList;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IChatComponent;
+
+import gregtech.GT_Mod;
+import gregtech.api.enums.SoundResource;
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.util.GT_ToolHarvestHelper;
+
+public class GT_Tool_Drill_LV extends GT_Tool {
+
+ @Override
+ public int getToolDamagePerBlockBreak() {
+ return GT_Mod.gregtechproxy.mHardRock ? 25 : 50;
+ }
+
+ @Override
+ public int getToolDamagePerDropConversion() {
+ return 100;
+ }
+
+ @Override
+ public int getToolDamagePerContainerCraft() {
+ return 100;
+ }
+
+ @Override
+ public int getToolDamagePerEntityAttack() {
+ return 200;
+ }
+
+ @Override
+ public int getBaseQuality() {
+ return 0;
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 2.0F;
+ }
+
+ @Override
+ public float getSpeedMultiplier() {
+ return 3.0F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public String getCraftingSound() {
+ return SoundResource.IC2_TOOLS_DRILL_DRILL_SOFT.toString();
+ }
+
+ @Override
+ public String getEntityHitSound() {
+ return SoundResource.IC2_TOOLS_DRILL_DRILL_SOFT.toString();
+ }
+
+ @Override
+ public String getBreakingSound() {
+ return SoundResource.IC2_TOOLS_DRILL_DRILL_SOFT.toString();
+ }
+
+ @Override
+ public String getMiningSound() {
+ return SoundResource.IC2_TOOLS_DRILL_DRILL_SOFT.toString();
+ }
+
+ @Override
+ public boolean canBlock() {
+ return false;
+ }
+
+ @Override
+ public boolean isCrowbar() {
+ return false;
+ }
+
+ @Override
+ public boolean isMinableBlock(Block aBlock, byte aMetaData) {
+ return GT_ToolHarvestHelper.isAppropriateTool(aBlock, aMetaData, "pickaxe", "shovel")
+ || GT_ToolHarvestHelper.isAppropriateMaterial(
+ aBlock,
+ Material.rock,
+ Material.iron,
+ Material.anvil,
+ Material.sand,
+ Material.grass,
+ Material.ground,
+ Material.snow,
+ Material.clay,
+ Material.glass);
+ }
+
+ @Override
+ public ItemStack getBrokenItem(ItemStack aStack) {
+ return null;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead
+ ? GT_MetaGenerated_Tool.getPrimaryMaterial(
+ aStack).mIconSet.mTextures[gregtech.api.enums.OrePrefixes.toolHeadDrill.mTextureIndex]
+ : Textures.ItemIcons.POWER_UNIT_LV;
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa
+ : GT_MetaGenerated_Tool.getSecondaryMaterial(aStack).mRGBa;
+ }
+
+ @Override
+ public void onStatsAddedToTool(GT_MetaGenerated_Tool aItem, int aID) {}
+
+ @Override
+ public void onToolCrafted(ItemStack aStack, EntityPlayer aPlayer) {
+ super.onToolCrafted(aStack, aPlayer);
+ aPlayer.triggerAchievement(AchievementList.buildPickaxe);
+ aPlayer.triggerAchievement(AchievementList.buildBetterPickaxe);
+ try {
+ GT_Mod.achievements.issueAchievement(aPlayer, "driltime");
+ GT_Mod.achievements.issueAchievement(aPlayer, "buildDrill");
+ } catch (Exception ignored) {}
+ }
+
+ @Override
+ public IChatComponent getDeathMessage(EntityLivingBase aPlayer, EntityLivingBase aEntity) {
+ return new ChatComponentText(
+ EnumChatFormatting.RED + aEntity.getCommandSenderName()
+ + EnumChatFormatting.WHITE
+ + " got the Drill! (by "
+ + EnumChatFormatting.GREEN
+ + aPlayer.getCommandSenderName()
+ + EnumChatFormatting.WHITE
+ + ")");
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_Drill_MV.java b/src/main/java/gregtech/common/tools/GT_Tool_Drill_MV.java
new file mode 100644
index 0000000000..02e7a08dfc
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_Drill_MV.java
@@ -0,0 +1,58 @@
+package gregtech.common.tools;
+
+import net.minecraft.item.ItemStack;
+
+import gregtech.GT_Mod;
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+
+public class GT_Tool_Drill_MV extends GT_Tool_Drill_LV {
+
+ @Override
+ public int getToolDamagePerBlockBreak() {
+ return GT_Mod.gregtechproxy.mHardRock ? 100 : 200;
+ }
+
+ @Override
+ public int getToolDamagePerDropConversion() {
+ return 400;
+ }
+
+ @Override
+ public int getToolDamagePerContainerCraft() {
+ return 3200;
+ }
+
+ @Override
+ public int getToolDamagePerEntityAttack() {
+ return 800;
+ }
+
+ @Override
+ public int getBaseQuality() {
+ return 1;
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 2.5F;
+ }
+
+ @Override
+ public float getSpeedMultiplier() {
+ return 6.0F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 2.0F;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead
+ ? gregtech.api.items.GT_MetaGenerated_Tool.getPrimaryMaterial(
+ aStack).mIconSet.mTextures[gregtech.api.enums.OrePrefixes.toolHeadDrill.mTextureIndex]
+ : Textures.ItemIcons.POWER_UNIT_MV;
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_File.java b/src/main/java/gregtech/common/tools/GT_Tool_File.java
new file mode 100644
index 0000000000..0a8610a462
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_File.java
@@ -0,0 +1,124 @@
+package gregtech.common.tools;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IChatComponent;
+
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.util.GT_ToolHarvestHelper;
+
+public class GT_Tool_File extends GT_Tool {
+
+ @Override
+ public int getToolDamagePerBlockBreak() {
+ return 50;
+ }
+
+ @Override
+ public int getToolDamagePerDropConversion() {
+ return 100;
+ }
+
+ @Override
+ public int getToolDamagePerContainerCraft() {
+ return 400;
+ }
+
+ @Override
+ public int getToolDamagePerEntityAttack() {
+ return 200;
+ }
+
+ @Override
+ public int getBaseQuality() {
+ return 0;
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 1.5F;
+ }
+
+ @Override
+ public float getSpeedMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public String getCraftingSound() {
+ return null;
+ }
+
+ @Override
+ public String getEntityHitSound() {
+ return null;
+ }
+
+ @Override
+ public String getMiningSound() {
+ return null;
+ }
+
+ @Override
+ public boolean canBlock() {
+ return true;
+ }
+
+ @Override
+ public boolean isCrowbar() {
+ return false;
+ }
+
+ @Override
+ public boolean isMiningTool() {
+ return false;
+ }
+
+ @Override
+ public boolean isMinableBlock(Block aBlock, byte aMetaData) {
+ return GT_ToolHarvestHelper.isAppropriateTool(aBlock, aMetaData, "file");
+ }
+
+ @Override
+ public ItemStack getBrokenItem(ItemStack aStack) {
+ return null;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return !aIsToolHead
+ ? GT_MetaGenerated_Tool.getPrimaryMaterial(
+ aStack).mIconSet.mTextures[gregtech.api.enums.OrePrefixes.toolHeadFile.mTextureIndex]
+ : Textures.ItemIcons.HANDLE_FILE;
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return !aIsToolHead ? GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa
+ : GT_MetaGenerated_Tool.getSecondaryMaterial(aStack).mRGBa;
+ }
+
+ @Override
+ public void onStatsAddedToTool(GT_MetaGenerated_Tool aItem, int aID) {}
+
+ @Override
+ public IChatComponent getDeathMessage(EntityLivingBase aPlayer, EntityLivingBase aEntity) {
+ return new ChatComponentText(
+ EnumChatFormatting.RED + aEntity.getCommandSenderName()
+ + EnumChatFormatting.WHITE
+ + " has been filed D for 'Dead' by "
+ + EnumChatFormatting.GREEN
+ + aPlayer.getCommandSenderName()
+ + EnumChatFormatting.WHITE);
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_HardHammer.java b/src/main/java/gregtech/common/tools/GT_Tool_HardHammer.java
new file mode 100644
index 0000000000..066abd48b8
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_HardHammer.java
@@ -0,0 +1,203 @@
+package gregtech.common.tools;
+
+import static gregtech.GT_Mod.MAX_IC2;
+
+import java.util.Arrays;
+import java.util.List;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.material.Material;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.monster.EntityIronGolem;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IChatComponent;
+import net.minecraftforge.event.world.BlockEvent;
+
+import gregtech.GT_Mod;
+import gregtech.api.enums.SoundResource;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.GT_ToolHarvestHelper;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.items.behaviors.Behaviour_Prospecting;
+
+public class GT_Tool_HardHammer extends GT_Tool {
+
+ public static final List<String> mEffectiveList = Arrays
+ .asList(EntityIronGolem.class.getName(), "EntityTowerGuardian");
+
+ @Override
+ public float getNormalDamageAgainstEntity(float aOriginalDamage, Entity aEntity, ItemStack aStack,
+ EntityPlayer aPlayer) {
+ String tName = aEntity.getClass()
+ .getName();
+ tName = tName.substring(tName.lastIndexOf('.') + 1);
+ return (mEffectiveList.contains(tName)) || (tName.contains("Golem")) ? aOriginalDamage * 2.0F : aOriginalDamage;
+ }
+
+ @Override
+ public int getToolDamagePerBlockBreak() {
+ return 50;
+ }
+
+ @Override
+ public int getToolDamagePerDropConversion() {
+ return 200;
+ }
+
+ @Override
+ public int getToolDamagePerContainerCraft() {
+ return 400;
+ }
+
+ @Override
+ public int getToolDamagePerEntityAttack() {
+ return 200;
+ }
+
+ @Override
+ public int getBaseQuality() {
+ return 0;
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 3.0F;
+ }
+
+ @Override
+ public int getHurtResistanceTime(int aOriginalHurtResistance, Entity aEntity) {
+ return aOriginalHurtResistance * 2;
+ }
+
+ @Override
+ public float getSpeedMultiplier() {
+ return 0.75F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public String getCraftingSound() {
+ return SoundResource.RANDOM_ANVIL_USE.toString();
+ }
+
+ @Override
+ public String getEntityHitSound() {
+ return null;
+ }
+
+ @Override
+ public String getBreakingSound() {
+ return SoundResource.RANDOM_ANVIL_BREAK.toString();
+ }
+
+ @Override
+ public String getMiningSound() {
+ return null;
+ }
+
+ @Override
+ public boolean canBlock() {
+ return true;
+ }
+
+ @Override
+ public boolean isCrowbar() {
+ return false;
+ }
+
+ @Override
+ public boolean isWeapon() {
+ return true;
+ }
+
+ @Override
+ public boolean isMinableBlock(Block aBlock, byte aMetaData) {
+ return GT_ToolHarvestHelper.isAppropriateTool(aBlock, aMetaData, "hammer", "pickaxe")
+ || GT_ToolHarvestHelper
+ .isAppropriateMaterial(aBlock, Material.rock, Material.glass, Material.ice, Material.packedIce)
+ || RecipeMaps.hammerRecipes.containsInput(new ItemStack(aBlock, 1, aMetaData));
+ }
+
+ @Override
+ public int convertBlockDrops(List<ItemStack> aDrops, ItemStack aStack, EntityPlayer aPlayer, Block aBlock, int aX,
+ int aY, int aZ, byte aMetaData, int aFortune, boolean aSilkTouch, BlockEvent.HarvestDropsEvent aEvent) {
+ int rConversions = 0;
+ GT_Recipe tRecipe = RecipeMaps.hammerRecipes
+ .findRecipe(null, true, MAX_IC2, null, new ItemStack(aBlock, 1, aMetaData));
+ if ((tRecipe == null) || (aBlock.hasTileEntity(aMetaData))) {
+ for (ItemStack tDrop : aDrops) {
+ tRecipe = RecipeMaps.hammerRecipes
+ .findRecipe(null, true, MAX_IC2, null, GT_Utility.copyAmount(1, tDrop));
+ if (tRecipe != null) {
+ ItemStack tHammeringOutput = tRecipe.getOutput(0);
+ if (tHammeringOutput != null) {
+ rConversions += tDrop.stackSize;
+ tDrop.stackSize *= tHammeringOutput.stackSize;
+ tHammeringOutput.stackSize = tDrop.stackSize;
+ GT_Utility.setStack(tDrop, tHammeringOutput);
+ }
+ }
+ }
+ } else {
+ aDrops.clear();
+ aDrops.add(tRecipe.getOutput(0));
+ rConversions++;
+ }
+ return rConversions;
+ }
+
+ @Override
+ public ItemStack getBrokenItem(ItemStack aStack) {
+ return null;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead
+ ? GT_MetaGenerated_Tool.getPrimaryMaterial(
+ aStack).mIconSet.mTextures[gregtech.api.enums.OrePrefixes.toolHeadHammer.mTextureIndex]
+ : GT_MetaGenerated_Tool
+ .getSecondaryMaterial(aStack).mIconSet.mTextures[gregtech.api.enums.OrePrefixes.stick.mTextureIndex];
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa
+ : GT_MetaGenerated_Tool.getSecondaryMaterial(aStack).mRGBa;
+ }
+
+ @Override
+ public void onStatsAddedToTool(GT_MetaGenerated_Tool aItem, int aID) {
+ aItem.addItemBehavior(aID, new Behaviour_Prospecting(1, 1000));
+ }
+
+ @Override
+ public IChatComponent getDeathMessage(EntityLivingBase aPlayer, EntityLivingBase aEntity) {
+ return new ChatComponentText(
+ EnumChatFormatting.RED + aEntity.getCommandSenderName()
+ + EnumChatFormatting.WHITE
+ + " was squashed by "
+ + EnumChatFormatting.GREEN
+ + aPlayer.getCommandSenderName()
+ + EnumChatFormatting.WHITE);
+ }
+
+ @Override
+ public void onToolCrafted(ItemStack aStack, EntityPlayer aPlayer) {
+ super.onToolCrafted(aStack, aPlayer);
+ try {
+ GT_Mod.achievements.issueAchievement(aPlayer, "tools");
+ } catch (Exception ignored) {}
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_Hoe.java b/src/main/java/gregtech/common/tools/GT_Tool_Hoe.java
new file mode 100644
index 0000000000..2dc5496176
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_Hoe.java
@@ -0,0 +1,132 @@
+package gregtech.common.tools;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.material.Material;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.stats.AchievementList;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IChatComponent;
+
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.util.GT_ToolHarvestHelper;
+import gregtech.common.items.behaviors.Behaviour_Hoe;
+
+public class GT_Tool_Hoe extends GT_Tool {
+
+ @Override
+ public int getToolDamagePerBlockBreak() {
+ return 50;
+ }
+
+ @Override
+ public int getToolDamagePerDropConversion() {
+ return 100;
+ }
+
+ @Override
+ public int getToolDamagePerContainerCraft() {
+ return 100;
+ }
+
+ @Override
+ public int getToolDamagePerEntityAttack() {
+ return 200;
+ }
+
+ @Override
+ public int getBaseQuality() {
+ return 0;
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 1.75F;
+ }
+
+ @Override
+ public float getSpeedMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public String getCraftingSound() {
+ return null;
+ }
+
+ @Override
+ public String getEntityHitSound() {
+ return null;
+ }
+
+ @Override
+ public String getMiningSound() {
+ return null;
+ }
+
+ @Override
+ public boolean canBlock() {
+ return false;
+ }
+
+ @Override
+ public boolean isCrowbar() {
+ return false;
+ }
+
+ @Override
+ public boolean isMinableBlock(Block aBlock, byte aMetaData) {
+ return GT_ToolHarvestHelper.isAppropriateTool(aBlock, aMetaData, "hoe")
+ || GT_ToolHarvestHelper.isAppropriateMaterial(aBlock, Material.gourd);
+ }
+
+ @Override
+ public ItemStack getBrokenItem(ItemStack aStack) {
+ return null;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead
+ ? GT_MetaGenerated_Tool
+ .getPrimaryMaterial(aStack).mIconSet.mTextures[gregtech.api.enums.OrePrefixes.toolHeadHoe.mTextureIndex]
+ : GT_MetaGenerated_Tool
+ .getSecondaryMaterial(aStack).mIconSet.mTextures[gregtech.api.enums.OrePrefixes.stick.mTextureIndex];
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa
+ : GT_MetaGenerated_Tool.getSecondaryMaterial(aStack).mRGBa;
+ }
+
+ @Override
+ public void onStatsAddedToTool(GT_MetaGenerated_Tool aItem, int aID) {
+ aItem.addItemBehavior(aID, new Behaviour_Hoe(100));
+ }
+
+ @Override
+ public void onToolCrafted(ItemStack aStack, EntityPlayer aPlayer) {
+ super.onToolCrafted(aStack, aPlayer);
+ aPlayer.triggerAchievement(AchievementList.buildHoe);
+ }
+
+ @Override
+ public IChatComponent getDeathMessage(EntityLivingBase aPlayer, EntityLivingBase aEntity) {
+ return new ChatComponentText(
+ EnumChatFormatting.RED + aEntity.getCommandSenderName()
+ + EnumChatFormatting.WHITE
+ + " has been called a stupid Hoe by "
+ + EnumChatFormatting.GREEN
+ + aPlayer.getCommandSenderName()
+ + EnumChatFormatting.WHITE);
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_JackHammer.java b/src/main/java/gregtech/common/tools/GT_Tool_JackHammer.java
new file mode 100644
index 0000000000..2621ff8ef7
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_JackHammer.java
@@ -0,0 +1,128 @@
+package gregtech.common.tools;
+
+import java.util.List;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.material.Material;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IChatComponent;
+import net.minecraftforge.event.world.BlockEvent;
+
+import gregtech.GT_Mod;
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.GT_ToolHarvestHelper;
+import gregtech.api.util.GT_Utility;
+
+public class GT_Tool_JackHammer extends GT_Tool_Drill_LV {
+
+ @Override
+ public int getToolDamagePerBlockBreak() {
+ return GT_Mod.gregtechproxy.mHardRock ? 200 : 400;
+ }
+
+ @Override
+ public int getToolDamagePerDropConversion() {
+ return 400;
+ }
+
+ @Override
+ public int getToolDamagePerContainerCraft() {
+ return 3200;
+ }
+
+ @Override
+ public int getToolDamagePerEntityAttack() {
+ return 800;
+ }
+
+ @Override
+ public int getBaseQuality() {
+ return 1;
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 3.0F;
+ }
+
+ @Override
+ public float getSpeedMultiplier() {
+ return 12.0F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 2.0F;
+ }
+
+ @Override
+ public boolean isMinableBlock(Block aBlock, byte aMetaData) {
+ return GT_ToolHarvestHelper.isAppropriateTool(aBlock, aMetaData, "pickaxe") //
+ || GT_ToolHarvestHelper.isAppropriateMaterial(
+ aBlock, //
+ Material.rock, //
+ Material.glass, //
+ Material.ice, //
+ Material.packedIce //
+ );
+ }
+
+ @Override
+ public int convertBlockDrops(List<ItemStack> aDrops, ItemStack aStack, EntityPlayer aPlayer, Block aBlock, int aX,
+ int aY, int aZ, byte aMetaData, int aFortune, boolean aSilkTouch, BlockEvent.HarvestDropsEvent aEvent) {
+ int rConversions = 0;
+ GT_Recipe tRecipe = RecipeMaps.hammerRecipes
+ .findRecipe(null, true, 2147483647L, null, new ItemStack(aBlock, 1, aMetaData));
+ if ((tRecipe == null) || (aBlock.hasTileEntity(aMetaData))) {
+ for (ItemStack tDrop : aDrops) {
+ tRecipe = RecipeMaps.hammerRecipes
+ .findRecipe(null, true, 2147483647L, null, GT_Utility.copyAmount(1, tDrop));
+ if (tRecipe != null) {
+ ItemStack tHammeringOutput = tRecipe.getOutput(0);
+ if (tHammeringOutput != null) {
+ rConversions += tDrop.stackSize;
+ tDrop.stackSize *= tHammeringOutput.stackSize;
+ tHammeringOutput.stackSize = tDrop.stackSize;
+ GT_Utility.setStack(tDrop, tHammeringOutput);
+ }
+ }
+ }
+ } else {
+ aDrops.clear();
+ aDrops.add(tRecipe.getOutput(0));
+ rConversions++;
+ }
+ return rConversions;
+ }
+
+ @Override
+ public void onToolCrafted(ItemStack aStack, EntityPlayer aPlayer) {
+ super.onToolCrafted(aStack, aPlayer);
+ try {
+ GT_Mod.achievements.issueAchievement(aPlayer, "hammertime");
+ } catch (Exception ignored) {}
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? Textures.ItemIcons.JACKHAMMER : null;
+ }
+
+ @Override
+ public IChatComponent getDeathMessage(EntityLivingBase aPlayer, EntityLivingBase aEntity) {
+ return new ChatComponentText(
+ EnumChatFormatting.RED + aEntity.getCommandSenderName()
+ + EnumChatFormatting.WHITE
+ + " has been jackhammered into pieces by "
+ + EnumChatFormatting.GREEN
+ + aPlayer.getCommandSenderName()
+ + EnumChatFormatting.WHITE);
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_Knife.java b/src/main/java/gregtech/common/tools/GT_Tool_Knife.java
new file mode 100644
index 0000000000..152476fa2d
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_Knife.java
@@ -0,0 +1,76 @@
+package gregtech.common.tools;
+
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IChatComponent;
+
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+
+public class GT_Tool_Knife extends GT_Tool_Sword {
+
+ @Override
+ public int getToolDamagePerBlockBreak() {
+ return 100;
+ }
+
+ @Override
+ public int getToolDamagePerDropConversion() {
+ return 100;
+ }
+
+ @Override
+ public int getToolDamagePerContainerCraft() {
+ return 100;
+ }
+
+ @Override
+ public int getToolDamagePerEntityAttack() {
+ return 600;
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 0F;
+ }
+
+ @Override
+ public int getHurtResistanceTime(int aOriginalHurtResistance, Entity aEntity) {
+ return aOriginalHurtResistance * 3;
+ }
+
+ @Override
+ public float getSpeedMultiplier() {
+ return 0.5F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? Textures.ItemIcons.KNIFE : null;
+ }
+
+ @Override
+ public IChatComponent getDeathMessage(EntityLivingBase aPlayer, EntityLivingBase aEntity) {
+ return new ChatComponentText(
+ "<" + EnumChatFormatting.RED
+ + aEntity.getCommandSenderName()
+ + EnumChatFormatting.WHITE
+ + "> "
+ + EnumChatFormatting.GREEN
+ + aPlayer.getCommandSenderName()
+ + EnumChatFormatting.WHITE
+ + " what are you doing?, "
+ + EnumChatFormatting.GREEN
+ + aPlayer.getCommandSenderName()
+ + EnumChatFormatting.WHITE
+ + "?!? STAHP!!!");
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_Mortar.java b/src/main/java/gregtech/common/tools/GT_Tool_Mortar.java
new file mode 100644
index 0000000000..8e74d3bcc1
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_Mortar.java
@@ -0,0 +1,120 @@
+package gregtech.common.tools;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IChatComponent;
+
+import gregtech.api.enums.Dyes;
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+
+public class GT_Tool_Mortar extends GT_Tool {
+
+ @Override
+ public int getToolDamagePerBlockBreak() {
+ return 50;
+ }
+
+ @Override
+ public int getToolDamagePerDropConversion() {
+ return 100;
+ }
+
+ @Override
+ public int getToolDamagePerContainerCraft() {
+ return 400;
+ }
+
+ @Override
+ public int getToolDamagePerEntityAttack() {
+ return 200;
+ }
+
+ @Override
+ public int getBaseQuality() {
+ return 0;
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 2.0F;
+ }
+
+ @Override
+ public float getSpeedMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public String getCraftingSound() {
+ return null;
+ }
+
+ @Override
+ public String getEntityHitSound() {
+ return null;
+ }
+
+ @Override
+ public String getMiningSound() {
+ return null;
+ }
+
+ @Override
+ public boolean canBlock() {
+ return false;
+ }
+
+ @Override
+ public boolean isCrowbar() {
+ return false;
+ }
+
+ @Override
+ public boolean isMiningTool() {
+ return false;
+ }
+
+ @Override
+ public boolean isMinableBlock(Block aBlock, byte aMetaData) {
+ return false;
+ }
+
+ @Override
+ public ItemStack getBrokenItem(ItemStack aStack) {
+ return null;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? Textures.ItemIcons.MORTAR : null;
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa : Dyes._NULL.mRGBa;
+ }
+
+ @Override
+ public void onStatsAddedToTool(GT_MetaGenerated_Tool aItem, int aID) {}
+
+ @Override
+ public IChatComponent getDeathMessage(EntityLivingBase aPlayer, EntityLivingBase aEntity) {
+ return new ChatComponentText(
+ EnumChatFormatting.RED + aEntity.getCommandSenderName()
+ + EnumChatFormatting.WHITE
+ + " was grounded by "
+ + EnumChatFormatting.GREEN
+ + aPlayer.getCommandSenderName()
+ + EnumChatFormatting.WHITE);
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_Pickaxe.java b/src/main/java/gregtech/common/tools/GT_Tool_Pickaxe.java
new file mode 100644
index 0000000000..e2857e4af1
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_Pickaxe.java
@@ -0,0 +1,139 @@
+package gregtech.common.tools;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.material.Material;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.stats.AchievementList;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IChatComponent;
+
+import gregtech.GT_Mod;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.util.GT_ToolHarvestHelper;
+
+public class GT_Tool_Pickaxe extends GT_Tool {
+
+ @Override
+ public int getToolDamagePerBlockBreak() {
+ return GT_Mod.gregtechproxy.mHardRock ? 25 : 50;
+ }
+
+ @Override
+ public int getToolDamagePerDropConversion() {
+ return 100;
+ }
+
+ @Override
+ public int getToolDamagePerContainerCraft() {
+ return 100;
+ }
+
+ @Override
+ public int getToolDamagePerEntityAttack() {
+ return 200;
+ }
+
+ @Override
+ public int getBaseQuality() {
+ return 0;
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 1.5F;
+ }
+
+ @Override
+ public float getSpeedMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public String getCraftingSound() {
+ return null;
+ }
+
+ @Override
+ public String getEntityHitSound() {
+ return null;
+ }
+
+ @Override
+ public String getMiningSound() {
+ return null;
+ }
+
+ @Override
+ public boolean canBlock() {
+ return false;
+ }
+
+ @Override
+ public boolean isCrowbar() {
+ return false;
+ }
+
+ @Override
+ public boolean isMinableBlock(Block aBlock, byte aMetaData) {
+ return GT_ToolHarvestHelper.isAppropriateTool(aBlock, aMetaData, "pickaxe") //
+ || GT_ToolHarvestHelper.isAppropriateMaterial(
+ aBlock, //
+ Material.rock,
+ Material.iron,
+ Material.anvil,
+ Material.glass);
+ }
+
+ @Override
+ public ItemStack getBrokenItem(ItemStack aStack) {
+ return null;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead
+ ? GT_MetaGenerated_Tool.getPrimaryMaterial(
+ aStack).mIconSet.mTextures[gregtech.api.enums.OrePrefixes.toolHeadPickaxe.mTextureIndex]
+ : GT_MetaGenerated_Tool
+ .getSecondaryMaterial(aStack).mIconSet.mTextures[gregtech.api.enums.OrePrefixes.stick.mTextureIndex];
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa
+ : GT_MetaGenerated_Tool.getSecondaryMaterial(aStack).mRGBa;
+ }
+
+ @Override
+ public void onStatsAddedToTool(GT_MetaGenerated_Tool aItem, int aID) {}
+
+ @Override
+ public void onToolCrafted(ItemStack aStack, EntityPlayer aPlayer) {
+ super.onToolCrafted(aStack, aPlayer);
+ aPlayer.triggerAchievement(AchievementList.buildPickaxe);
+ aPlayer.triggerAchievement(AchievementList.buildBetterPickaxe);
+ try {
+ GT_Mod.achievements.issueAchievement(aPlayer, "flintpick");
+ } catch (Exception ignored) {}
+ }
+
+ @Override
+ public IChatComponent getDeathMessage(EntityLivingBase aPlayer, EntityLivingBase aEntity) {
+ return new ChatComponentText(
+ EnumChatFormatting.RED + aEntity.getCommandSenderName()
+ + EnumChatFormatting.WHITE
+ + " got mined by "
+ + EnumChatFormatting.GREEN
+ + aPlayer.getCommandSenderName()
+ + EnumChatFormatting.WHITE);
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_Plow.java b/src/main/java/gregtech/common/tools/GT_Tool_Plow.java
new file mode 100644
index 0000000000..b6f4be25b5
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_Plow.java
@@ -0,0 +1,110 @@
+package gregtech.common.tools;
+
+import java.util.List;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.material.Material;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.monster.EntitySnowman;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IChatComponent;
+import net.minecraft.world.World;
+import net.minecraftforge.event.world.BlockEvent;
+
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.util.GT_ToolHarvestHelper;
+
+public class GT_Tool_Plow extends GT_Tool {
+
+ private final ThreadLocal<Object> sIsHarvestingRightNow = new ThreadLocal<>();
+
+ @Override
+ public float getNormalDamageAgainstEntity(float aOriginalDamage, Entity aEntity, ItemStack aStack,
+ EntityPlayer aPlayer) {
+ return (aEntity instanceof EntitySnowman) ? aOriginalDamage * 4.0F : aOriginalDamage;
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 1.0F;
+ }
+
+ @Override
+ public boolean isMinableBlock(Block aBlock, byte aMetaData) {
+ return GT_ToolHarvestHelper.isAppropriateTool(aBlock, aMetaData, "plow")
+ || GT_ToolHarvestHelper.isAppropriateMaterial(aBlock, Material.snow, Material.craftedSnow);
+ }
+
+ @Override
+ public float getMiningSpeed(Block aBlock, byte aMetaData, float aDefault, EntityPlayer aPlayer, World worldObj,
+ int aX, int aY, int aZ) {
+ // Speed nerf for using AOE tools to break single block
+ if (aPlayer != null && aPlayer.isSneaking()) {
+ return aDefault / 2;
+ }
+ return super.getMiningSpeed(aBlock, aMetaData, aDefault, aPlayer, worldObj, aX, aY, aZ);
+ }
+
+ @Override
+ public int convertBlockDrops(List<ItemStack> aDrops, ItemStack aStack, EntityPlayer aPlayer, Block aBlock, int aX,
+ int aY, int aZ, byte aMetaData, int aFortune, boolean aSilkTouch, BlockEvent.HarvestDropsEvent aEvent) {
+ int rConversions = 0;
+ if ((this.sIsHarvestingRightNow.get() == null) && ((aPlayer instanceof EntityPlayerMP))) {
+ this.sIsHarvestingRightNow.set(this);
+
+ if (!aPlayer.isSneaking()) {
+ for (int i = -1; i < 2; i++) {
+ for (int j = -1; j < 2; j++) {
+ for (int k = -1; k < 2; k++) {
+ if (((i != 0) || (j != 0) || (k != 0)) && (aStack.getItem()
+ .getDigSpeed(
+ aStack,
+ aPlayer.worldObj.getBlock(aX + i, aY + j, aZ + k),
+ aPlayer.worldObj.getBlockMetadata(aX + i, aY + j, aZ + k))
+ > 0.0F)
+ && (((EntityPlayerMP) aPlayer).theItemInWorldManager
+ .tryHarvestBlock(aX + i, aY + j, aZ + k))) {
+ rConversions++;
+ }
+ }
+ }
+ }
+ }
+
+ this.sIsHarvestingRightNow.set(null);
+ }
+ return rConversions;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead
+ ? GT_MetaGenerated_Tool.getPrimaryMaterial(
+ aStack).mIconSet.mTextures[gregtech.api.enums.OrePrefixes.toolHeadPlow.mTextureIndex]
+ : GT_MetaGenerated_Tool
+ .getSecondaryMaterial(aStack).mIconSet.mTextures[gregtech.api.enums.OrePrefixes.stick.mTextureIndex];
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa
+ : GT_MetaGenerated_Tool.getSecondaryMaterial(aStack).mRGBa;
+ }
+
+ @Override
+ public IChatComponent getDeathMessage(EntityLivingBase aPlayer, EntityLivingBase aEntity) {
+ return new ChatComponentText(
+ EnumChatFormatting.GREEN + aPlayer.getCommandSenderName()
+ + EnumChatFormatting.WHITE
+ + " plew through the yard of "
+ + EnumChatFormatting.RED
+ + aEntity.getCommandSenderName()
+ + EnumChatFormatting.WHITE);
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_Plunger.java b/src/main/java/gregtech/common/tools/GT_Tool_Plunger.java
new file mode 100644
index 0000000000..76c1ccbc24
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_Plunger.java
@@ -0,0 +1,92 @@
+package gregtech.common.tools;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IChatComponent;
+
+import gregtech.api.enums.SoundResource;
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.interfaces.IItemBehaviour;
+import gregtech.api.items.GT_MetaBase_Item;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.util.GT_ToolHarvestHelper;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.items.behaviors.Behaviour_Plunger_Fluid;
+import gregtech.common.items.behaviors.Behaviour_Plunger_Item;
+
+public class GT_Tool_Plunger extends GT_Tool {
+
+ @Override
+ public float getBaseDamage() {
+ return 1.25F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 0.25F;
+ }
+
+ @Override
+ public String getCraftingSound() {
+ return SoundResource.IC2_TOOLS_RUBBER_TRAMPOLINE.toString();
+ }
+
+ @Override
+ public String getEntityHitSound() {
+ return SoundResource.IC2_TOOLS_RUBBER_TRAMPOLINE.toString();
+ }
+
+ @Override
+ public String getMiningSound() {
+ return SoundResource.IC2_TOOLS_RUBBER_TRAMPOLINE.toString();
+ }
+
+ @Override
+ public boolean isMinableBlock(Block aBlock, byte aMetaData) {
+ return GT_ToolHarvestHelper.isAppropriateTool(aBlock, aMetaData, "plunger");
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? Textures.ItemIcons.PLUNGER : null;
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa
+ : GT_MetaGenerated_Tool.getSecondaryMaterial(aStack).mRGBa;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked") // the IItemBehaviour cast cannot be expressed strictly via generics
+ public void onStatsAddedToTool(GT_MetaGenerated_Tool aItem, int aID) {
+ aItem.addItemBehavior(aID, new Behaviour_Plunger_Item(getToolDamagePerDropConversion()));
+ aItem.addItemBehavior(aID, new Behaviour_Plunger_Fluid(getToolDamagePerDropConversion()));
+ try {
+ Object tObject = GT_Utility.callConstructor(
+ "gregtech.common.items.behaviors.Behaviour_Plunger_Essentia",
+ 0,
+ null,
+ false,
+ getToolDamagePerDropConversion());
+ if ((tObject instanceof IItemBehaviour)) {
+ aItem.addItemBehavior(aID, (IItemBehaviour<GT_MetaBase_Item>) tObject);
+ }
+ } catch (Throwable ignored) {}
+ }
+
+ @Override
+ public IChatComponent getDeathMessage(EntityLivingBase aPlayer, EntityLivingBase aEntity) {
+ return new ChatComponentText(
+ EnumChatFormatting.RED + aEntity.getCommandSenderName()
+ + EnumChatFormatting.WHITE
+ + " got stuck trying to escape through a Pipe while fighting "
+ + EnumChatFormatting.GREEN
+ + aPlayer.getCommandSenderName()
+ + EnumChatFormatting.WHITE);
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_RollingPin.java b/src/main/java/gregtech/common/tools/GT_Tool_RollingPin.java
new file mode 100644
index 0000000000..9933c4eb13
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_RollingPin.java
@@ -0,0 +1,70 @@
+package gregtech.common.tools;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IChatComponent;
+
+import gregtech.api.enums.Dyes;
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+
+public class GT_Tool_RollingPin extends GT_Tool {
+
+ @Override
+ public int getToolDamagePerBlockBreak() {
+ return 50;
+ }
+
+ @Override
+ public int getToolDamagePerDropConversion() {
+ return 100;
+ }
+
+ @Override
+ public int getToolDamagePerContainerCraft() {
+ return 100;
+ }
+
+ @Override
+ public int getToolDamagePerEntityAttack() {
+ return 200;
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 2.0F;
+ }
+
+ @Override
+ public boolean isMinableBlock(Block aBlock, byte aMetaData) {
+ return false;
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa : Dyes._NULL.mRGBa;
+ }
+
+ @Override
+ public void onStatsAddedToTool(GT_MetaGenerated_Tool aItem, int aID) {}
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? Textures.ItemIcons.ROLLING_PIN : null;
+ }
+
+ @Override
+ public IChatComponent getDeathMessage(EntityLivingBase aPlayer, EntityLivingBase aEntity) {
+ return new ChatComponentText(
+ EnumChatFormatting.RED + aEntity.getCommandSenderName()
+ + EnumChatFormatting.WHITE
+ + " got flattened by "
+ + EnumChatFormatting.GREEN
+ + aPlayer.getCommandSenderName()
+ + EnumChatFormatting.WHITE);
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_Saw.java b/src/main/java/gregtech/common/tools/GT_Tool_Saw.java
new file mode 100644
index 0000000000..b2c85e2a5e
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_Saw.java
@@ -0,0 +1,149 @@
+package gregtech.common.tools;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.material.Material;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IChatComponent;
+import net.minecraftforge.common.IShearable;
+import net.minecraftforge.event.world.BlockEvent;
+
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.util.GT_ToolHarvestHelper;
+
+public class GT_Tool_Saw extends GT_Tool {
+
+ @Override
+ public int getToolDamagePerBlockBreak() {
+ return 50;
+ }
+
+ @Override
+ public int getToolDamagePerDropConversion() {
+ return 100;
+ }
+
+ @Override
+ public int getToolDamagePerContainerCraft() {
+ return 200;
+ }
+
+ @Override
+ public int getToolDamagePerEntityAttack() {
+ return 200;
+ }
+
+ @Override
+ public int getBaseQuality() {
+ return 0;
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 1.75F;
+ }
+
+ @Override
+ public float getSpeedMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public String getCraftingSound() {
+ return null;
+ }
+
+ @Override
+ public String getEntityHitSound() {
+ return null;
+ }
+
+ @Override
+ public String getMiningSound() {
+ return null;
+ }
+
+ @Override
+ public int convertBlockDrops(List<ItemStack> aDrops, ItemStack aStack, EntityPlayer aPlayer, Block aBlock, int aX,
+ int aY, int aZ, byte aMetaData, int aFortune, boolean aSilkTouch, BlockEvent.HarvestDropsEvent aEvent) {
+ if ((aBlock.getMaterial() == Material.leaves) && ((aBlock instanceof IShearable))) {
+ aPlayer.worldObj.setBlock(aX, aY, aZ, aBlock, aMetaData, 0);
+ if (((IShearable) aBlock).isShearable(aStack, aPlayer.worldObj, aX, aY, aZ)) {
+ ArrayList<ItemStack> tDrops = ((IShearable) aBlock)
+ .onSheared(aStack, aPlayer.worldObj, aX, aY, aZ, aFortune);
+ aDrops.clear();
+ aDrops.addAll(tDrops);
+ aEvent.dropChance = 1.0F;
+ }
+ aPlayer.worldObj.setBlock(aX, aY, aZ, Blocks.air, 0, 0);
+ } else if (((aBlock.getMaterial() == Material.ice) || (aBlock.getMaterial() == Material.packedIce))
+ && (aDrops.isEmpty())) {
+ aDrops.add(new ItemStack(aBlock, 1, aMetaData));
+ aPlayer.worldObj.setBlockToAir(aX, aY, aZ);
+ aEvent.dropChance = 1.0F;
+ return 1;
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean isMinableBlock(Block aBlock, byte aMetaData) {
+ return GT_ToolHarvestHelper.isAppropriateTool(aBlock, aMetaData, "axe", "saw")
+ || GT_ToolHarvestHelper.isAppropriateMaterial(
+ aBlock,
+ Material.leaves,
+ Material.vine,
+ Material.wood,
+ Material.cactus,
+ Material.ice,
+ Material.packedIce)
+ || GT_ToolHarvestHelper.isSpecialBlock(aBlock, Blocks.ladder);
+ }
+
+ @Override
+ public ItemStack getBrokenItem(ItemStack aStack) {
+ return null;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead
+ ? GT_MetaGenerated_Tool
+ .getPrimaryMaterial(aStack).mIconSet.mTextures[gregtech.api.enums.OrePrefixes.toolHeadSaw.mTextureIndex]
+ : Textures.ItemIcons.HANDLE_SAW;
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa
+ : GT_MetaGenerated_Tool.getSecondaryMaterial(aStack).mRGBa;
+ }
+
+ @Override
+ public void onStatsAddedToTool(GT_MetaGenerated_Tool aItem, int aID) {}
+
+ @Override
+ public IChatComponent getDeathMessage(EntityLivingBase aPlayer, EntityLivingBase aEntity) {
+ return new ChatComponentText(
+ EnumChatFormatting.RED + aEntity.getCommandSenderName()
+ + EnumChatFormatting.WHITE
+ + " was getting cut down by "
+ + EnumChatFormatting.GREEN
+ + aPlayer.getCommandSenderName()
+ + EnumChatFormatting.WHITE);
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_Scoop.java b/src/main/java/gregtech/common/tools/GT_Tool_Scoop.java
new file mode 100644
index 0000000000..3181e108bf
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_Scoop.java
@@ -0,0 +1,130 @@
+package gregtech.common.tools;
+
+import static gregtech.api.enums.Mods.Forestry;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.material.Material;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IChatComponent;
+
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.util.GT_ToolHarvestHelper;
+import gregtech.common.items.behaviors.Behaviour_None;
+import gregtech.common.items.behaviors.Behaviour_Scoop;
+
+public class GT_Tool_Scoop extends GT_Tool {
+
+ public static Material sBeeHiveMaterial;
+
+ @Override
+ public int getToolDamagePerBlockBreak() {
+ return 200;
+ }
+
+ @Override
+ public int getToolDamagePerDropConversion() {
+ return 100;
+ }
+
+ @Override
+ public int getToolDamagePerContainerCraft() {
+ return 200;
+ }
+
+ @Override
+ public int getToolDamagePerEntityAttack() {
+ return 200;
+ }
+
+ @Override
+ public int getBaseQuality() {
+ return 0;
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 1.0F;
+ }
+
+ @Override
+ public float getSpeedMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public String getCraftingSound() {
+ return null;
+ }
+
+ @Override
+ public String getEntityHitSound() {
+ return null;
+ }
+
+ @Override
+ public String getMiningSound() {
+ return null;
+ }
+
+ @Override
+ public boolean canBlock() {
+ return false;
+ }
+
+ @Override
+ public boolean isCrowbar() {
+ return false;
+ }
+
+ @Override
+ public boolean isMinableBlock(Block aBlock, byte aMetaData) {
+ return GT_ToolHarvestHelper.isAppropriateTool(aBlock, aMetaData, "scoop")
+ || GT_ToolHarvestHelper.isAppropriateMaterial(aBlock, sBeeHiveMaterial);
+ }
+
+ @Override
+ public ItemStack getBrokenItem(ItemStack aStack) {
+ return null;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? Textures.ItemIcons.SCOOP : null;
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa
+ : GT_MetaGenerated_Tool.getSecondaryMaterial(aStack).mRGBa;
+ }
+
+ @Override
+ public void onStatsAddedToTool(GT_MetaGenerated_Tool aItem, int aID) {
+ if (Forestry.isModLoaded()) {
+ aItem.addItemBehavior(aID, new Behaviour_Scoop(200));
+ } else {
+ aItem.addItemBehavior(aID, new Behaviour_None());
+ }
+ }
+
+ @Override
+ public IChatComponent getDeathMessage(EntityLivingBase aPlayer, EntityLivingBase aEntity) {
+ return new ChatComponentText(
+ EnumChatFormatting.RED + aEntity.getCommandSenderName()
+ + EnumChatFormatting.WHITE
+ + " got scooped up by "
+ + EnumChatFormatting.GREEN
+ + aPlayer.getCommandSenderName()
+ + EnumChatFormatting.WHITE);
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_Screwdriver.java b/src/main/java/gregtech/common/tools/GT_Tool_Screwdriver.java
new file mode 100644
index 0000000000..1d7f4e655d
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_Screwdriver.java
@@ -0,0 +1,160 @@
+package gregtech.common.tools;
+
+import java.util.Arrays;
+import java.util.List;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.material.Material;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.monster.EntityCaveSpider;
+import net.minecraft.entity.monster.EntitySpider;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IChatComponent;
+
+import gregtech.api.enums.SoundResource;
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.util.GT_ToolHarvestHelper;
+import gregtech.common.items.behaviors.Behaviour_Screwdriver;
+
+public class GT_Tool_Screwdriver extends GT_Tool {
+
+ public static final List<String> mEffectiveList = Arrays.asList(
+ EntityCaveSpider.class.getName(),
+ EntitySpider.class.getName(),
+ "EntityTFHedgeSpider",
+ "EntityTFKingSpider",
+ "EntityTFSwarmSpider",
+ "EntityTFTowerBroodling");
+
+ @Override
+ public float getNormalDamageAgainstEntity(float aOriginalDamage, Entity aEntity, ItemStack aStack,
+ EntityPlayer aPlayer) {
+ String tName = aEntity.getClass()
+ .getName();
+ tName = tName.substring(tName.lastIndexOf('.') + 1);
+ return mEffectiveList.contains(tName) ? aOriginalDamage * 2.0F : aOriginalDamage;
+ }
+
+ @Override
+ public int getToolDamagePerBlockBreak() {
+ return 200;
+ }
+
+ @Override
+ public int getToolDamagePerDropConversion() {
+ return 100;
+ }
+
+ @Override
+ public int getToolDamagePerContainerCraft() {
+ return 400;
+ }
+
+ @Override
+ public int getToolDamagePerEntityAttack() {
+ return 200;
+ }
+
+ @Override
+ public int getBaseQuality() {
+ return 0;
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 1.5F;
+ }
+
+ @Override
+ public float getSpeedMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public String getCraftingSound() {
+ return SoundResource.IC2_TOOLS_WRENCH.toString();
+ }
+
+ @Override
+ public String getEntityHitSound() {
+ return null;
+ }
+
+ @Override
+ public String getMiningSound() {
+ return null;
+ }
+
+ @Override
+ public boolean canBlock() {
+ return true;
+ }
+
+ @Override
+ public boolean isCrowbar() {
+ return false;
+ }
+
+ @Override
+ public boolean isMiningTool() {
+ return false;
+ }
+
+ @Override
+ public boolean isScrewdriver() {
+ return true;
+ }
+
+ @Override
+ public boolean isMinableBlock(Block aBlock, byte aMetaData) {
+ return GT_ToolHarvestHelper.isAppropriateTool(aBlock, aMetaData, "screwdriver")
+ || GT_ToolHarvestHelper.isAppropriateMaterial(aBlock, Material.circuits);
+ }
+
+ @Override
+ public ItemStack getBrokenItem(ItemStack aStack) {
+ return null;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return !aIsToolHead
+ ? GT_MetaGenerated_Tool.getPrimaryMaterial(
+ aStack).mIconSet.mTextures[gregtech.api.enums.OrePrefixes.toolHeadScrewdriver.mTextureIndex]
+ : Textures.ItemIcons.HANDLE_SCREWDRIVER;
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return !aIsToolHead ? GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa
+ : GT_MetaGenerated_Tool.getSecondaryMaterial(aStack).mRGBa;
+ }
+
+ @Override
+ public void onStatsAddedToTool(GT_MetaGenerated_Tool aItem, int aID) {
+ aItem.addItemBehavior(aID, new Behaviour_Screwdriver(1, 200));
+ }
+
+ @Override
+ public IChatComponent getDeathMessage(EntityLivingBase aPlayer, EntityLivingBase aEntity) {
+ return new ChatComponentText(
+ EnumChatFormatting.RED + aEntity.getCommandSenderName()
+ + EnumChatFormatting.WHITE
+ + " is screwed! (by "
+ + EnumChatFormatting.GREEN
+ + aPlayer.getCommandSenderName()
+ + EnumChatFormatting.WHITE
+ + ")");
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_Screwdriver_LV.java b/src/main/java/gregtech/common/tools/GT_Tool_Screwdriver_LV.java
new file mode 100644
index 0000000000..e49e020b7b
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_Screwdriver_LV.java
@@ -0,0 +1,34 @@
+package gregtech.common.tools;
+
+import net.minecraft.item.ItemStack;
+
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+
+public class GT_Tool_Screwdriver_LV extends GT_Tool_Screwdriver {
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public int getToolDamagePerContainerCraft() {
+ return 200;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return !aIsToolHead
+ ? GT_MetaGenerated_Tool.getPrimaryMaterial(
+ aStack).mIconSet.mTextures[gregtech.api.enums.OrePrefixes.toolHeadScrewdriver.mTextureIndex]
+ : Textures.ItemIcons.HANDLE_ELECTRIC_SCREWDRIVER;
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return !aIsToolHead ? GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa
+ : GT_MetaGenerated_Tool.getSecondaryMaterial(aStack).mRGBa;
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_Sense.java b/src/main/java/gregtech/common/tools/GT_Tool_Sense.java
new file mode 100644
index 0000000000..013c0f800c
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_Sense.java
@@ -0,0 +1,114 @@
+package gregtech.common.tools;
+
+import java.util.List;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.material.Material;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IChatComponent;
+import net.minecraft.world.World;
+import net.minecraftforge.event.world.BlockEvent;
+
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.util.GT_ToolHarvestHelper;
+import gregtech.common.items.behaviors.Behaviour_Sense;
+
+public class GT_Tool_Sense extends GT_Tool {
+
+ private final ThreadLocal<Object> sIsHarvestingRightNow = new ThreadLocal<>();
+
+ @Override
+ public float getBaseDamage() {
+ return 3.0F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 4.0F;
+ }
+
+ @Override
+ public boolean isMinableBlock(Block aBlock, byte aMetaData) {
+ return GT_ToolHarvestHelper.isAppropriateTool(aBlock, aMetaData, "sense", "scythe")
+ || GT_ToolHarvestHelper.isAppropriateMaterial(aBlock, Material.plants, Material.leaves);
+ }
+
+ @Override
+ public float getMiningSpeed(Block aBlock, byte aMetaData, float aDefault, EntityPlayer aPlayer, World worldObj,
+ int aX, int aY, int aZ) {
+ // Speed nerf for using AOE tools to break single block
+ if (aPlayer != null && aPlayer.isSneaking()) {
+ return aDefault / 2;
+ }
+ return super.getMiningSpeed(aBlock, aMetaData, aDefault, aPlayer, worldObj, aX, aY, aZ);
+ }
+
+ @Override
+ public int convertBlockDrops(List<ItemStack> aDrops, ItemStack aStack, EntityPlayer aPlayer, Block aBlock, int aX,
+ int aY, int aZ, byte aMetaData, int aFortune, boolean aSilkTouch, BlockEvent.HarvestDropsEvent aEvent) {
+ int rConversions = 0;
+ if ((this.sIsHarvestingRightNow.get() == null) && ((aPlayer instanceof EntityPlayerMP))) {
+ this.sIsHarvestingRightNow.set(this);
+
+ if (!aPlayer.isSneaking()) {
+ for (int i = -2; i < 3; i++) {
+ for (int j = -2; j < 3; j++) {
+ for (int k = -2; k < 3; k++) {
+ if (((i != 0) || (j != 0) || (k != 0)) && (aStack.getItem()
+ .getDigSpeed(
+ aStack,
+ aPlayer.worldObj.getBlock(aX + i, aY + j, aZ + k),
+ aPlayer.worldObj.getBlockMetadata(aX + i, aY + j, aZ + k))
+ > 0.0F)
+ && (((EntityPlayerMP) aPlayer).theItemInWorldManager
+ .tryHarvestBlock(aX + i, aY + j, aZ + k))) {
+ rConversions++;
+ }
+ }
+ }
+ }
+ }
+
+ this.sIsHarvestingRightNow.set(null);
+ }
+ return rConversions;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead
+ ? GT_MetaGenerated_Tool.getPrimaryMaterial(
+ aStack).mIconSet.mTextures[gregtech.api.enums.OrePrefixes.toolHeadSense.mTextureIndex]
+ : GT_MetaGenerated_Tool
+ .getSecondaryMaterial(aStack).mIconSet.mTextures[gregtech.api.enums.OrePrefixes.stick.mTextureIndex];
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa
+ : GT_MetaGenerated_Tool.getSecondaryMaterial(aStack).mRGBa;
+ }
+
+ @Override
+ public void onStatsAddedToTool(GT_MetaGenerated_Tool aItem, int aID) {
+ aItem.addItemBehavior(aID, new Behaviour_Sense(getToolDamagePerBlockBreak()));
+ }
+
+ @Override
+ public IChatComponent getDeathMessage(EntityLivingBase aPlayer, EntityLivingBase aEntity) {
+ return new ChatComponentText(
+ EnumChatFormatting.GREEN + aPlayer.getCommandSenderName()
+ + EnumChatFormatting.WHITE
+ + " has taken the Soul of "
+ + EnumChatFormatting.RED
+ + aEntity.getCommandSenderName()
+ + EnumChatFormatting.WHITE);
+ }
+
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_Shovel.java b/src/main/java/gregtech/common/tools/GT_Tool_Shovel.java
new file mode 100644
index 0000000000..886ca126e0
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_Shovel.java
@@ -0,0 +1,127 @@
+package gregtech.common.tools;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.material.Material;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IChatComponent;
+
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.util.GT_ToolHarvestHelper;
+
+public class GT_Tool_Shovel extends GT_Tool {
+
+ @Override
+ public int getToolDamagePerBlockBreak() {
+ return 50;
+ }
+
+ @Override
+ public int getToolDamagePerDropConversion() {
+ return 100;
+ }
+
+ @Override
+ public int getToolDamagePerContainerCraft() {
+ return 100;
+ }
+
+ @Override
+ public int getToolDamagePerEntityAttack() {
+ return 200;
+ }
+
+ @Override
+ public int getBaseQuality() {
+ return 0;
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 1.5F;
+ }
+
+ @Override
+ public float getSpeedMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public String getCraftingSound() {
+ return null;
+ }
+
+ @Override
+ public String getEntityHitSound() {
+ return null;
+ }
+
+ @Override
+ public String getMiningSound() {
+ return null;
+ }
+
+ @Override
+ public boolean canBlock() {
+ return false;
+ }
+
+ @Override
+ public boolean isCrowbar() {
+ return false;
+ }
+
+ @Override
+ public boolean isMinableBlock(Block aBlock, byte aMetaData) {
+ return GT_ToolHarvestHelper.isAppropriateTool(aBlock, aMetaData, "shovel")
+ || GT_ToolHarvestHelper.isAppropriateMaterial(
+ aBlock,
+ Material.sand,
+ Material.grass,
+ Material.ground,
+ Material.snow,
+ Material.clay);
+ }
+
+ @Override
+ public ItemStack getBrokenItem(ItemStack aStack) {
+ return null;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead
+ ? GT_MetaGenerated_Tool.getPrimaryMaterial(
+ aStack).mIconSet.mTextures[gregtech.api.enums.OrePrefixes.toolHeadShovel.mTextureIndex]
+ : GT_MetaGenerated_Tool
+ .getSecondaryMaterial(aStack).mIconSet.mTextures[gregtech.api.enums.OrePrefixes.stick.mTextureIndex];
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa
+ : GT_MetaGenerated_Tool.getSecondaryMaterial(aStack).mRGBa;
+ }
+
+ @Override
+ public void onStatsAddedToTool(GT_MetaGenerated_Tool aItem, int aID) {}
+
+ @Override
+ public IChatComponent getDeathMessage(EntityLivingBase aPlayer, EntityLivingBase aEntity) {
+ return new ChatComponentText(
+ EnumChatFormatting.RED + aEntity.getCommandSenderName()
+ + EnumChatFormatting.WHITE
+ + " got dug up by "
+ + EnumChatFormatting.GREEN
+ + aPlayer.getCommandSenderName()
+ + EnumChatFormatting.WHITE);
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_SoftHammer.java b/src/main/java/gregtech/common/tools/GT_Tool_SoftHammer.java
new file mode 100644
index 0000000000..cc3f5e738b
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_SoftHammer.java
@@ -0,0 +1,139 @@
+package gregtech.common.tools;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IChatComponent;
+
+import gregtech.api.enums.SoundResource;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.util.GT_ToolHarvestHelper;
+import gregtech.common.items.behaviors.Behaviour_SoftHammer;
+
+public class GT_Tool_SoftHammer extends GT_Tool {
+
+ @Override
+ public int getToolDamagePerBlockBreak() {
+ return 50;
+ }
+
+ @Override
+ public int getToolDamagePerDropConversion() {
+ return 100;
+ }
+
+ @Override
+ public int getToolDamagePerContainerCraft() {
+ return 800;
+ }
+
+ @Override
+ public int getToolDamagePerEntityAttack() {
+ return 200;
+ }
+
+ @Override
+ public int getBaseQuality() {
+ return 0;
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 3.0F;
+ }
+
+ @Override
+ public int getHurtResistanceTime(int aOriginalHurtResistance, Entity aEntity) {
+ return aOriginalHurtResistance * 2;
+ }
+
+ @Override
+ public float getSpeedMultiplier() {
+ return 0.1F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 8.0F;
+ }
+
+ @Override
+ public String getCraftingSound() {
+ return SoundResource.IC2_TOOLS_RUBBER_TRAMPOLINE.toString();
+ }
+
+ @Override
+ public String getEntityHitSound() {
+ return SoundResource.IC2_TOOLS_RUBBER_TRAMPOLINE.toString();
+ }
+
+ @Override
+ public String getMiningSound() {
+ return SoundResource.IC2_TOOLS_RUBBER_TRAMPOLINE.toString();
+ }
+
+ @Override
+ public boolean canBlock() {
+ return true;
+ }
+
+ @Override
+ public boolean isCrowbar() {
+ return false;
+ }
+
+ @Override
+ public boolean isMiningTool() {
+ return false;
+ }
+
+ @Override
+ public boolean isWeapon() {
+ return true;
+ }
+
+ @Override
+ public boolean isMinableBlock(Block aBlock, byte aMetaData) {
+ return GT_ToolHarvestHelper.isAppropriateTool(aBlock, aMetaData, "softhammer");
+ }
+
+ @Override
+ public ItemStack getBrokenItem(ItemStack aStack) {
+ return null;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead
+ ? GT_MetaGenerated_Tool.getPrimaryMaterial(
+ aStack).mIconSet.mTextures[gregtech.api.enums.OrePrefixes.toolHeadMallet.mTextureIndex]
+ : GT_MetaGenerated_Tool.getSecondaryMaterial(
+ aStack).mIconSet.mTextures[gregtech.api.enums.OrePrefixes.handleMallet.mTextureIndex];
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa
+ : GT_MetaGenerated_Tool.getSecondaryMaterial(aStack).mRGBa;
+ }
+
+ @Override
+ public void onStatsAddedToTool(GT_MetaGenerated_Tool aItem, int aID) {
+ aItem.addItemBehavior(aID, new Behaviour_SoftHammer(100));
+ }
+
+ @Override
+ public IChatComponent getDeathMessage(EntityLivingBase aPlayer, EntityLivingBase aEntity) {
+ return new ChatComponentText(
+ EnumChatFormatting.RED + aEntity.getCommandSenderName()
+ + EnumChatFormatting.WHITE
+ + " was hammered to death by "
+ + EnumChatFormatting.GREEN
+ + aPlayer.getCommandSenderName()
+ + EnumChatFormatting.WHITE);
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_Soldering_Iron.java b/src/main/java/gregtech/common/tools/GT_Tool_Soldering_Iron.java
new file mode 100644
index 0000000000..9b5ef3a638
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_Soldering_Iron.java
@@ -0,0 +1,153 @@
+package gregtech.common.tools;
+
+import java.util.Arrays;
+import java.util.List;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.material.Material;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.monster.EntityCaveSpider;
+import net.minecraft.entity.monster.EntitySpider;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IChatComponent;
+
+import gregtech.api.enums.SoundResource;
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.util.GT_ToolHarvestHelper;
+import gregtech.common.items.behaviors.Behaviour_Screwdriver;
+
+public class GT_Tool_Soldering_Iron extends GT_Tool {
+
+ public static final List<String> mEffectiveList = Arrays.asList(
+ EntityCaveSpider.class.getName(),
+ EntitySpider.class.getName(),
+ "EntityTFHedgeSpider",
+ "EntityTFKingSpider",
+ "EntityTFSwarmSpider",
+ "EntityTFTowerBroodling");
+
+ @Override
+ public float getNormalDamageAgainstEntity(float aOriginalDamage, Entity aEntity, ItemStack aStack,
+ EntityPlayer aPlayer) {
+ String tName = aEntity.getClass()
+ .getName();
+ tName = tName.substring(tName.lastIndexOf('.') + 1);
+ return mEffectiveList.contains(tName) ? aOriginalDamage * 2.0F : aOriginalDamage;
+ }
+
+ @Override
+ public int getToolDamagePerBlockBreak() {
+ return 1000;
+ }
+
+ @Override
+ public int getToolDamagePerDropConversion() {
+ return 500;
+ }
+
+ @Override
+ public int getToolDamagePerContainerCraft() {
+ return 1000;
+ }
+
+ @Override
+ public int getToolDamagePerEntityAttack() {
+ return 500;
+ }
+
+ @Override
+ public int getBaseQuality() {
+ return 0;
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 1.5F;
+ }
+
+ @Override
+ public float getSpeedMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public String getCraftingSound() {
+ return SoundResource.IC2_TOOLS_WRENCH.toString();
+ }
+
+ @Override
+ public String getEntityHitSound() {
+ return null;
+ }
+
+ @Override
+ public String getMiningSound() {
+ return null;
+ }
+
+ @Override
+ public boolean canBlock() {
+ return true;
+ }
+
+ @Override
+ public boolean isCrowbar() {
+ return false;
+ }
+
+ @Override
+ public boolean isMiningTool() {
+ return false;
+ }
+
+ @Override
+ public boolean isMinableBlock(Block aBlock, byte aMetaData) {
+ return GT_ToolHarvestHelper.isAppropriateTool(aBlock, aMetaData, "soldering_iron")
+ || GT_ToolHarvestHelper.isAppropriateMaterial(aBlock, Material.circuits);
+ }
+
+ @Override
+ public ItemStack getBrokenItem(ItemStack aStack) {
+ return null;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return !aIsToolHead ? GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mIconSet.mTextures[49]
+ : Textures.ItemIcons.HANDLE_SOLDERING;
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return !aIsToolHead ? GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa
+ : GT_MetaGenerated_Tool.getSecondaryMaterial(aStack).mRGBa;
+ }
+
+ @Override
+ public void onStatsAddedToTool(GT_MetaGenerated_Tool aItem, int aID) {
+ aItem.addItemBehavior(aID, new Behaviour_Screwdriver(1, 200));
+ }
+
+ @Override
+ public IChatComponent getDeathMessage(EntityLivingBase aPlayer, EntityLivingBase aEntity) {
+ return new ChatComponentText(
+ EnumChatFormatting.RED + aEntity.getCommandSenderName()
+ + EnumChatFormatting.WHITE
+ + " got soldert! (by "
+ + EnumChatFormatting.GREEN
+ + aPlayer.getCommandSenderName()
+ + EnumChatFormatting.WHITE
+ + ")");
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_Sword.java b/src/main/java/gregtech/common/tools/GT_Tool_Sword.java
new file mode 100644
index 0000000000..7bfaaee797
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_Sword.java
@@ -0,0 +1,128 @@
+package gregtech.common.tools;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.material.Material;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.stats.AchievementList;
+
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.util.GT_ToolHarvestHelper;
+
+public class GT_Tool_Sword extends GT_Tool {
+
+ @Override
+ public int getToolDamagePerBlockBreak() {
+ return 200;
+ }
+
+ @Override
+ public int getToolDamagePerDropConversion() {
+ return 100;
+ }
+
+ @Override
+ public int getToolDamagePerContainerCraft() {
+ return 100;
+ }
+
+ @Override
+ public int getToolDamagePerEntityAttack() {
+ return 100;
+ }
+
+ @Override
+ public int getBaseQuality() {
+ return 0;
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 4.0F;
+ }
+
+ @Override
+ public float getSpeedMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public String getCraftingSound() {
+ return null;
+ }
+
+ @Override
+ public String getEntityHitSound() {
+ return null;
+ }
+
+ @Override
+ public String getMiningSound() {
+ return null;
+ }
+
+ @Override
+ public boolean canBlock() {
+ return true;
+ }
+
+ @Override
+ public boolean isCrowbar() {
+ return false;
+ }
+
+ @Override
+ public boolean isWeapon() {
+ return true;
+ }
+
+ @Override
+ public boolean isMinableBlock(Block aBlock, byte aMetaData) {
+ return GT_ToolHarvestHelper.isAppropriateTool(aBlock, aMetaData, "sword")
+ || GT_ToolHarvestHelper.isAppropriateMaterial(
+ aBlock,
+ Material.leaves,
+ Material.gourd,
+ Material.vine,
+ Material.web,
+ Material.cloth,
+ Material.carpet,
+ Material.plants,
+ Material.cactus,
+ Material.cake,
+ Material.tnt,
+ Material.sponge);
+ }
+
+ @Override
+ public ItemStack getBrokenItem(ItemStack aStack) {
+ return null;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return !aIsToolHead
+ ? GT_MetaGenerated_Tool.getPrimaryMaterial(
+ aStack).mIconSet.mTextures[gregtech.api.enums.OrePrefixes.toolHeadSword.mTextureIndex]
+ : Textures.ItemIcons.HANDLE_SWORD;
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return !aIsToolHead ? GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa
+ : GT_MetaGenerated_Tool.getSecondaryMaterial(aStack).mRGBa;
+ }
+
+ @Override
+ public void onToolCrafted(ItemStack aStack, EntityPlayer aPlayer) {
+ super.onToolCrafted(aStack, aPlayer);
+ aPlayer.triggerAchievement(AchievementList.buildSword);
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_Turbine.java b/src/main/java/gregtech/common/tools/GT_Tool_Turbine.java
new file mode 100644
index 0000000000..daaf2c4438
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_Turbine.java
@@ -0,0 +1,58 @@
+package gregtech.common.tools;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IChatComponent;
+
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+
+public abstract class GT_Tool_Turbine extends GT_Tool {
+
+ @Override
+ public abstract float getBaseDamage();
+
+ @Override
+ public boolean isMinableBlock(Block aBlock, byte aMetaData) {
+ return false;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? getTurbineIcon() : null;
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa : null;
+ }
+
+ @Override
+ public IChatComponent getDeathMessage(EntityLivingBase aPlayer, EntityLivingBase aEntity) {
+ return new ChatComponentText(
+ EnumChatFormatting.GREEN + aPlayer.getCommandSenderName()
+ + EnumChatFormatting.WHITE
+ + " put "
+ + EnumChatFormatting.RED
+ + aEntity.getCommandSenderName()
+ + "s"
+ + EnumChatFormatting.WHITE
+ + " head into a turbine");
+ }
+
+ public abstract IIconContainer getTurbineIcon();
+
+ @Override
+ public abstract float getSpeedMultiplier();
+
+ @Override
+ public abstract float getMaxDurabilityMultiplier();
+
+ @Override
+ public ItemStack getBrokenItem(ItemStack aStack) {
+ return null;
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_Turbine_Huge.java b/src/main/java/gregtech/common/tools/GT_Tool_Turbine_Huge.java
new file mode 100644
index 0000000000..46b0de72d9
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_Turbine_Huge.java
@@ -0,0 +1,27 @@
+package gregtech.common.tools;
+
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+
+public class GT_Tool_Turbine_Huge extends GT_Tool_Turbine {
+
+ @Override
+ public float getSpeedMultiplier() {
+ return 4.0F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 4.0F;
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 7.5F;
+ }
+
+ @Override
+ public IIconContainer getTurbineIcon() {
+ return Textures.ItemIcons.TURBINE_HUGE;
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_Turbine_Large.java b/src/main/java/gregtech/common/tools/GT_Tool_Turbine_Large.java
new file mode 100644
index 0000000000..7e8307f6b0
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_Turbine_Large.java
@@ -0,0 +1,27 @@
+package gregtech.common.tools;
+
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+
+public class GT_Tool_Turbine_Large extends GT_Tool_Turbine {
+
+ @Override
+ public float getSpeedMultiplier() {
+ return 3.0F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 3.0F;
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 5.0F;
+ }
+
+ @Override
+ public IIconContainer getTurbineIcon() {
+ return Textures.ItemIcons.TURBINE_LARGE;
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_Turbine_Normal.java b/src/main/java/gregtech/common/tools/GT_Tool_Turbine_Normal.java
new file mode 100644
index 0000000000..ac2fc29a89
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_Turbine_Normal.java
@@ -0,0 +1,27 @@
+package gregtech.common.tools;
+
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+
+public class GT_Tool_Turbine_Normal extends GT_Tool_Turbine {
+
+ @Override
+ public float getSpeedMultiplier() {
+ return 2.0F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 2.0F;
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 2.5F;
+ }
+
+ @Override
+ public IIconContainer getTurbineIcon() {
+ return Textures.ItemIcons.TURBINE;
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_Turbine_Small.java b/src/main/java/gregtech/common/tools/GT_Tool_Turbine_Small.java
new file mode 100644
index 0000000000..fab527386e
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_Turbine_Small.java
@@ -0,0 +1,27 @@
+package gregtech.common.tools;
+
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+
+public class GT_Tool_Turbine_Small extends GT_Tool_Turbine {
+
+ @Override
+ public float getSpeedMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 0.0F;
+ }
+
+ @Override
+ public IIconContainer getTurbineIcon() {
+ return Textures.ItemIcons.TURBINE_SMALL;
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_UniversalSpade.java b/src/main/java/gregtech/common/tools/GT_Tool_UniversalSpade.java
new file mode 100644
index 0000000000..184d506872
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_UniversalSpade.java
@@ -0,0 +1,160 @@
+package gregtech.common.tools;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.material.Material;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.stats.AchievementList;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IChatComponent;
+
+import gregtech.GT_Mod;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.util.GT_ToolHarvestHelper;
+import gregtech.common.items.behaviors.Behaviour_Crowbar;
+
+public class GT_Tool_UniversalSpade extends GT_Tool {
+
+ @Override
+ public int getToolDamagePerBlockBreak() {
+ return 50;
+ }
+
+ @Override
+ public int getToolDamagePerDropConversion() {
+ return 100;
+ }
+
+ @Override
+ public int getToolDamagePerContainerCraft() {
+ return 400;
+ }
+
+ @Override
+ public int getToolDamagePerEntityAttack() {
+ return 100;
+ }
+
+ @Override
+ public int getBaseQuality() {
+ return 0;
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 3.0F;
+ }
+
+ @Override
+ public float getSpeedMultiplier() {
+ return 0.75F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public String getCraftingSound() {
+ return null;
+ }
+
+ @Override
+ public String getEntityHitSound() {
+ return null;
+ }
+
+ @Override
+ public String getMiningSound() {
+ return null;
+ }
+
+ @Override
+ public boolean canBlock() {
+ return true;
+ }
+
+ @Override
+ public boolean isCrowbar() {
+ return true;
+ }
+
+ @Override
+ public boolean isWeapon() {
+ return true;
+ }
+
+ @Override
+ public boolean isMinableBlock(Block aBlock, byte aMetaData) {
+ return GT_ToolHarvestHelper.isAppropriateTool(aBlock, aMetaData, "shovel", "axe", "saw", "sword", "crowbar")
+ || GT_ToolHarvestHelper.isAppropriateMaterial(
+ aBlock,
+ Material.sand,
+ Material.grass,
+ Material.ground,
+ Material.snow,
+ Material.clay,
+ Material.leaves,
+ Material.vine,
+ Material.wood,
+ Material.cactus,
+ Material.circuits,
+ Material.gourd,
+ Material.web,
+ Material.cloth,
+ Material.carpet,
+ Material.plants,
+ Material.cake,
+ Material.tnt,
+ Material.sponge);
+ }
+
+ @Override
+ public ItemStack getBrokenItem(ItemStack aStack) {
+ return null;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead
+ ? GT_MetaGenerated_Tool.getPrimaryMaterial(
+ aStack).mIconSet.mTextures[gregtech.api.enums.OrePrefixes.toolHeadUniversalSpade.mTextureIndex]
+ : GT_MetaGenerated_Tool
+ .getSecondaryMaterial(aStack).mIconSet.mTextures[gregtech.api.enums.OrePrefixes.stick.mTextureIndex];
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa
+ : GT_MetaGenerated_Tool.getSecondaryMaterial(aStack).mRGBa;
+ }
+
+ @Override
+ public void onStatsAddedToTool(GT_MetaGenerated_Tool aItem, int aID) {
+ aItem.addItemBehavior(aID, new Behaviour_Crowbar(2, 2000));
+ }
+
+ @Override
+ public void onToolCrafted(ItemStack aStack, EntityPlayer aPlayer) {
+ super.onToolCrafted(aStack, aPlayer);
+ aPlayer.triggerAchievement(AchievementList.buildSword);
+ try {
+ GT_Mod.achievements.issueAchievement(aPlayer, "unitool");
+ } catch (Exception ignored) {}
+ }
+
+ @Override
+ public IChatComponent getDeathMessage(EntityLivingBase aPlayer, EntityLivingBase aEntity) {
+ return new ChatComponentText(
+ EnumChatFormatting.RED + aEntity.getCommandSenderName()
+ + EnumChatFormatting.WHITE
+ + " has been digged by "
+ + EnumChatFormatting.GREEN
+ + aPlayer.getCommandSenderName()
+ + EnumChatFormatting.WHITE);
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_WireCutter.java b/src/main/java/gregtech/common/tools/GT_Tool_WireCutter.java
new file mode 100644
index 0000000000..54b76e6d81
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_WireCutter.java
@@ -0,0 +1,117 @@
+package gregtech.common.tools;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IChatComponent;
+
+import gregtech.api.enums.SoundResource;
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.util.GT_ToolHarvestHelper;
+
+public class GT_Tool_WireCutter extends GT_Tool {
+
+ @Override
+ public int getToolDamagePerBlockBreak() {
+ return 100;
+ }
+
+ @Override
+ public int getToolDamagePerDropConversion() {
+ return 100;
+ }
+
+ @Override
+ public int getToolDamagePerContainerCraft() {
+ return 400;
+ }
+
+ @Override
+ public int getToolDamagePerEntityAttack() {
+ return 200;
+ }
+
+ @Override
+ public int getBaseQuality() {
+ return 0;
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 1.25F;
+ }
+
+ @Override
+ public float getSpeedMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public String getCraftingSound() {
+ return SoundResource.IC2_TOOLS_INSULATION_CUTTERS.toString();
+ }
+
+ @Override
+ public String getEntityHitSound() {
+ return null;
+ }
+
+ @Override
+ public String getMiningSound() {
+ return SoundResource.IC2_TOOLS_INSULATION_CUTTERS.toString();
+ }
+
+ @Override
+ public boolean canBlock() {
+ return false;
+ }
+
+ @Override
+ public boolean isCrowbar() {
+ return false;
+ }
+
+ @Override
+ public boolean isMinableBlock(Block aBlock, byte aMetaData) {
+ return GT_ToolHarvestHelper.isAppropriateTool(aBlock, aMetaData, "cutter");
+ }
+
+ @Override
+ public ItemStack getBrokenItem(ItemStack aStack) {
+ return null;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? Textures.ItemIcons.WIRE_CUTTER : null;
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa
+ : GT_MetaGenerated_Tool.getSecondaryMaterial(aStack).mRGBa;
+ }
+
+ @Override
+ public void onStatsAddedToTool(GT_MetaGenerated_Tool aItem, int aID) {}
+
+ @Override
+ public IChatComponent getDeathMessage(EntityLivingBase aPlayer, EntityLivingBase aEntity) {
+ return new ChatComponentText(
+ EnumChatFormatting.GREEN + aPlayer.getCommandSenderName()
+ + EnumChatFormatting.WHITE
+ + " has cut the Cable for the Life Support Machine of "
+ + EnumChatFormatting.RED
+ + aEntity.getCommandSenderName()
+ + EnumChatFormatting.WHITE);
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_Wrench.java b/src/main/java/gregtech/common/tools/GT_Tool_Wrench.java
new file mode 100644
index 0000000000..4dad749997
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_Wrench.java
@@ -0,0 +1,272 @@
+package gregtech.common.tools;
+
+import static gregtech.api.items.GT_MetaGenerated_Tool.getPrimaryMaterial;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.material.Material;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.monster.EntityIronGolem;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.ItemStack;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IChatComponent;
+import net.minecraft.world.World;
+import net.minecraftforge.event.world.BlockEvent;
+
+import appeng.api.parts.IPartHost;
+import appeng.block.AEBaseTileBlock;
+import appeng.parts.PartPlacement;
+import appeng.util.Platform;
+import gregtech.api.enums.SoundResource;
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.util.GT_ToolHarvestHelper;
+import gregtech.common.items.behaviors.Behaviour_Switch_Mode;
+import gregtech.common.items.behaviors.Behaviour_Wrench;
+import ic2.api.tile.IWrenchable;
+
+public class GT_Tool_Wrench extends GT_Tool {
+
+ public static final List<String> mEffectiveList = Arrays
+ .asList(EntityIronGolem.class.getName(), "EntityTowerGuardian");
+
+ @Override
+ public float getNormalDamageAgainstEntity(float aOriginalDamage, Entity aEntity, ItemStack aStack,
+ EntityPlayer aPlayer) {
+ String tName = aEntity.getClass()
+ .getName();
+ tName = tName.substring(tName.lastIndexOf('.') + 1);
+ return (mEffectiveList.contains(tName)) || (tName.contains("Golem")) ? aOriginalDamage * 2.0F : aOriginalDamage;
+ }
+
+ @Override
+ public int getToolDamagePerBlockBreak() {
+ return 50;
+ }
+
+ @Override
+ public int getToolDamagePerDropConversion() {
+ return 100;
+ }
+
+ @Override
+ public int getToolDamagePerContainerCraft() {
+ return 800;
+ }
+
+ @Override
+ public int getToolDamagePerEntityAttack() {
+ return 200;
+ }
+
+ @Override
+ public int getBaseQuality() {
+ return 0;
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 3.0F;
+ }
+
+ @Override
+ public int getHurtResistanceTime(int aOriginalHurtResistance, Entity aEntity) {
+ return aOriginalHurtResistance * 2;
+ }
+
+ @Override
+ public float getSpeedMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public String getCraftingSound() {
+ return SoundResource.IC2_TOOLS_WRENCH.toString();
+ }
+
+ @Override
+ public String getEntityHitSound() {
+ return null;
+ }
+
+ @Override
+ public String getMiningSound() {
+ return SoundResource.IC2_TOOLS_WRENCH.toString();
+ }
+
+ @Override
+ public boolean canBlock() {
+ return false;
+ }
+
+ @Override
+ public boolean isCrowbar() {
+ return false;
+ }
+
+ @Override
+ public boolean isWrench() {
+ return true;
+ }
+
+ @Override
+ public boolean isMinableBlock(Block block, byte aMetaData) {
+ return GT_ToolHarvestHelper.isAppropriateTool(block, aMetaData, "wrench")
+ || GT_ToolHarvestHelper.isAppropriateMaterial(block, Material.piston)
+ || block instanceof AEBaseTileBlock
+ || GT_ToolHarvestHelper.isSpecialBlock(block, Blocks.crafting_table, Blocks.bookshelf)
+ || Behaviour_Wrench.isVanillaRotatable(block)
+ || GT_ToolHarvestHelper.isIC2Wrenchable(block);
+ }
+
+ @Override
+ public ItemStack getBrokenItem(ItemStack aStack) {
+ return null;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? Textures.ItemIcons.WRENCH : null;
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? getPrimaryMaterial(aStack).mRGBa : null;
+ }
+
+ @Override
+ public void onStatsAddedToTool(GT_MetaGenerated_Tool aItem, int aID) {
+ aItem.addItemBehavior(aID, new Behaviour_Switch_Mode());
+ aItem.addItemBehavior(aID, new Behaviour_Wrench(100));
+ }
+
+ @Override
+ public IChatComponent getDeathMessage(EntityLivingBase aPlayer, EntityLivingBase aEntity) {
+ return new ChatComponentText(
+ EnumChatFormatting.GREEN + aPlayer.getCommandSenderName()
+ + EnumChatFormatting.WHITE
+ + " threw a Monkey Wrench into the Plans of "
+ + EnumChatFormatting.RED
+ + aEntity.getCommandSenderName()
+ + EnumChatFormatting.WHITE);
+ }
+
+ /**
+ * <p>
+ * holding drop from {@link IWrenchable#getWrenchDrop(EntityPlayer)}
+ * </p>
+ * Since no tile available during
+ * {@link #convertBlockDrops(List, ItemStack, EntityPlayer, Block, int, int, int, byte, int, boolean, BlockEvent.HarvestDropsEvent)},
+ * this is filled during
+ * {@link #onBreakBlock(EntityPlayer, int, int, int, Block, byte, TileEntity, BlockEvent.BreakEvent)}
+ */
+ private ItemStack wrenchableDrop = null;
+ /**
+ * <p>
+ * drop rate from {@link IWrenchable#getWrenchDropRate()}
+ * </p>
+ * see {@link #wrenchableDrop}
+ */
+ private float wrenchableDropRate = 0.0f;
+
+ /**
+ * <p>
+ * prevent recursion from
+ * {@link AEBaseTileBlock#onBlockActivated(World, int, int, int, EntityPlayer, int, float, float, float)}
+ * </p>
+ */
+ private boolean LastEventFromThis = false;
+
+ @Override
+ public void onBreakBlock(@Nonnull EntityPlayer player, int x, int y, int z, @Nonnull Block block, byte metadata,
+ TileEntity tile, @Nonnull BlockEvent.BreakEvent event) {
+ if (tile instanceof IWrenchable wrenchable) {
+ if (!wrenchable.wrenchCanRemove(player)) {
+ event.setCanceled(true);
+ return;
+ }
+ wrenchableDrop = wrenchable.getWrenchDrop(player);
+ wrenchableDropRate = wrenchable.getWrenchDropRate();
+ }
+ if (block instanceof AEBaseTileBlock aeBaseTileBlock) {
+ if (LastEventFromThis) {
+ return;
+ }
+ final boolean sneak = player.isSneaking();
+ try {
+ LastEventFromThis = true;
+ player.setSneaking(true);
+ final int sideHit = Platform.rayTrace(player, true, false).sideHit;
+ if (tile instanceof IPartHost) {
+ if (sneak && PartPlacement.place(
+ player.getHeldItem(),
+ x,
+ y,
+ z,
+ sideHit,
+ player,
+ player.worldObj,
+ PartPlacement.PlaceType.INTERACT_FIRST_PASS,
+ 0)) {
+ event.setCanceled(true);
+ }
+ return;
+ }
+ if (aeBaseTileBlock.onBlockActivated(event.world, x, y, z, player, sideHit, x, y, z)) {
+ event.setCanceled(true);
+ }
+ } finally {
+ LastEventFromThis = false;
+ player.setSneaking(sneak);
+ }
+ }
+ }
+
+ @Override
+ public int convertBlockDrops(List<ItemStack> drops, ItemStack Stack, EntityPlayer player, Block block, int x, int y,
+ int z, byte metaData, int fortune, boolean silkTouch, BlockEvent.HarvestDropsEvent event) {
+ ItemStack drop = null;
+ int modified = 0;
+ if (wrenchableDrop != null) {
+ drop = wrenchableDrop;
+ wrenchableDrop = null;
+ modified = wrenchableDropRate == 1.0f ? 3 : 10;
+ wrenchableDropRate = 0.0f;
+ } else if (block == Blocks.bookshelf || block == Blocks.ender_chest) {
+ drop = new ItemStack(block);
+ modified = 1;
+ }
+
+ if (drop != null) {
+ event.dropChance = 1.0f;
+ drops.clear();
+ drops.add(drop);
+ }
+ return modified;
+ }
+
+ @Override
+ public byte getMaxMode() {
+ return 2;
+ }
+
+ @Override
+ public String getToolTypeName() {
+ return "wrench";
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_Wrench_HV.java b/src/main/java/gregtech/common/tools/GT_Tool_Wrench_HV.java
new file mode 100644
index 0000000000..7a7c725f8f
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_Wrench_HV.java
@@ -0,0 +1,69 @@
+package gregtech.common.tools;
+
+import net.minecraft.item.ItemStack;
+
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+
+public class GT_Tool_Wrench_HV extends GT_Tool_Wrench_LV {
+
+ @Override
+ public int getToolDamagePerBlockBreak() {
+ return 800;
+ }
+
+ @Override
+ public int getToolDamagePerDropConversion() {
+ return 1600;
+ }
+
+ @Override
+ public int getToolDamagePerContainerCraft() {
+ return 12800;
+ }
+
+ @Override
+ public int getToolDamagePerEntityAttack() {
+ return 3200;
+ }
+
+ @Override
+ public int getBaseQuality() {
+ return 1;
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 2.0F;
+ }
+
+ @Override
+ public float getSpeedMultiplier() {
+ return 4.0F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 4.0F;
+ }
+
+ @Override
+ public boolean canBlock() {
+ return false;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead
+ ? GT_MetaGenerated_Tool.getPrimaryMaterial(
+ aStack).mIconSet.mTextures[gregtech.api.enums.OrePrefixes.toolHeadWrench.mTextureIndex]
+ : Textures.ItemIcons.POWER_UNIT_HV;
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa
+ : GT_MetaGenerated_Tool.getSecondaryMaterial(aStack).mRGBa;
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_Wrench_LV.java b/src/main/java/gregtech/common/tools/GT_Tool_Wrench_LV.java
new file mode 100644
index 0000000000..5f82a7d5b1
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_Wrench_LV.java
@@ -0,0 +1,77 @@
+package gregtech.common.tools;
+
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+
+public class GT_Tool_Wrench_LV extends GT_Tool_Wrench {
+
+ @Override
+ public float getNormalDamageAgainstEntity(float aOriginalDamage, Entity aEntity, ItemStack aStack,
+ EntityPlayer aPlayer) {
+ return aOriginalDamage;
+ }
+
+ @Override
+ public int getToolDamagePerBlockBreak() {
+ return 50;
+ }
+
+ @Override
+ public int getToolDamagePerDropConversion() {
+ return 100;
+ }
+
+ @Override
+ public int getToolDamagePerContainerCraft() {
+ return 800;
+ }
+
+ @Override
+ public int getToolDamagePerEntityAttack() {
+ return 200;
+ }
+
+ @Override
+ public int getBaseQuality() {
+ return 0;
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 1.0F;
+ }
+
+ @Override
+ public float getSpeedMultiplier() {
+ return 2.0F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 1.0F;
+ }
+
+ @Override
+ public boolean canBlock() {
+ return false;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead
+ ? GT_MetaGenerated_Tool.getPrimaryMaterial(
+ aStack).mIconSet.mTextures[gregtech.api.enums.OrePrefixes.toolHeadWrench.mTextureIndex]
+ : Textures.ItemIcons.POWER_UNIT_LV;
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa
+ : GT_MetaGenerated_Tool.getSecondaryMaterial(aStack).mRGBa;
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/GT_Tool_Wrench_MV.java b/src/main/java/gregtech/common/tools/GT_Tool_Wrench_MV.java
new file mode 100644
index 0000000000..cc5b649647
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/GT_Tool_Wrench_MV.java
@@ -0,0 +1,69 @@
+package gregtech.common.tools;
+
+import net.minecraft.item.ItemStack;
+
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+
+public class GT_Tool_Wrench_MV extends GT_Tool_Wrench_LV {
+
+ @Override
+ public int getToolDamagePerBlockBreak() {
+ return 200;
+ }
+
+ @Override
+ public int getToolDamagePerDropConversion() {
+ return 400;
+ }
+
+ @Override
+ public int getToolDamagePerContainerCraft() {
+ return 3200;
+ }
+
+ @Override
+ public int getToolDamagePerEntityAttack() {
+ return 800;
+ }
+
+ @Override
+ public int getBaseQuality() {
+ return 1;
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 1.5F;
+ }
+
+ @Override
+ public float getSpeedMultiplier() {
+ return 3.0F;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 2.0F;
+ }
+
+ @Override
+ public boolean canBlock() {
+ return false;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead
+ ? GT_MetaGenerated_Tool.getPrimaryMaterial(
+ aStack).mIconSet.mTextures[gregtech.api.enums.OrePrefixes.toolHeadWrench.mTextureIndex]
+ : Textures.ItemIcons.POWER_UNIT_MV;
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa
+ : GT_MetaGenerated_Tool.getSecondaryMaterial(aStack).mRGBa;
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/pocket/GT_Tool_Pocket_BranchCutter.java b/src/main/java/gregtech/common/tools/pocket/GT_Tool_Pocket_BranchCutter.java
new file mode 100644
index 0000000000..b831306df9
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/pocket/GT_Tool_Pocket_BranchCutter.java
@@ -0,0 +1,39 @@
+package gregtech.common.tools.pocket;
+
+import net.minecraft.item.ItemStack;
+
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.common.items.behaviors.Behaviour_Switch_Metadata;
+import gregtech.common.tools.GT_Tool_BranchCutter;
+
+public class GT_Tool_Pocket_BranchCutter extends GT_Tool_BranchCutter {
+
+ public final int mSwitchIndex;
+
+ public GT_Tool_Pocket_BranchCutter(int aSwitchIndex) {
+ mSwitchIndex = aSwitchIndex;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 4.0F;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? Textures.ItemIcons.POCKET_MULTITOOL_BRANCHCUTTER : Textures.ItemIcons.VOID;
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa;
+ }
+
+ @Override
+ public void onStatsAddedToTool(GT_MetaGenerated_Tool aItem, int aID) {
+ super.onStatsAddedToTool(aItem, aID);
+ aItem.addItemBehavior(aID, new Behaviour_Switch_Metadata(mSwitchIndex, true, true));
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/pocket/GT_Tool_Pocket_File.java b/src/main/java/gregtech/common/tools/pocket/GT_Tool_Pocket_File.java
new file mode 100644
index 0000000000..84372b1d98
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/pocket/GT_Tool_Pocket_File.java
@@ -0,0 +1,39 @@
+package gregtech.common.tools.pocket;
+
+import net.minecraft.item.ItemStack;
+
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.common.items.behaviors.Behaviour_Switch_Metadata;
+import gregtech.common.tools.GT_Tool_File;
+
+public class GT_Tool_Pocket_File extends GT_Tool_File {
+
+ public final int mSwitchIndex;
+
+ public GT_Tool_Pocket_File(int aSwitchIndex) {
+ mSwitchIndex = aSwitchIndex;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 4.0F;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? Textures.ItemIcons.POCKET_MULTITOOL_FILE : Textures.ItemIcons.VOID;
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa;
+ }
+
+ @Override
+ public void onStatsAddedToTool(GT_MetaGenerated_Tool aItem, int aID) {
+ super.onStatsAddedToTool(aItem, aID);
+ aItem.addItemBehavior(aID, new Behaviour_Switch_Metadata(mSwitchIndex, true, true));
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/pocket/GT_Tool_Pocket_Knife.java b/src/main/java/gregtech/common/tools/pocket/GT_Tool_Pocket_Knife.java
new file mode 100644
index 0000000000..2b43984c51
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/pocket/GT_Tool_Pocket_Knife.java
@@ -0,0 +1,39 @@
+package gregtech.common.tools.pocket;
+
+import net.minecraft.item.ItemStack;
+
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.common.items.behaviors.Behaviour_Switch_Metadata;
+import gregtech.common.tools.GT_Tool_Knife;
+
+public class GT_Tool_Pocket_Knife extends GT_Tool_Knife {
+
+ public final int mSwitchIndex;
+
+ public GT_Tool_Pocket_Knife(int aSwitchIndex) {
+ mSwitchIndex = aSwitchIndex;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 4.0F;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? Textures.ItemIcons.POCKET_MULTITOOL_KNIFE : Textures.ItemIcons.VOID;
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa;
+ }
+
+ @Override
+ public void onStatsAddedToTool(GT_MetaGenerated_Tool aItem, int aID) {
+ super.onStatsAddedToTool(aItem, aID);
+ aItem.addItemBehavior(aID, new Behaviour_Switch_Metadata(mSwitchIndex, true, true));
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/pocket/GT_Tool_Pocket_Multitool.java b/src/main/java/gregtech/common/tools/pocket/GT_Tool_Pocket_Multitool.java
new file mode 100644
index 0000000000..16ab9229c6
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/pocket/GT_Tool_Pocket_Multitool.java
@@ -0,0 +1,50 @@
+package gregtech.common.tools.pocket;
+
+import net.minecraft.block.Block;
+import net.minecraft.item.ItemStack;
+
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.common.items.behaviors.Behaviour_Switch_Metadata;
+import gregtech.common.tools.GT_Tool;
+
+public class GT_Tool_Pocket_Multitool extends GT_Tool {
+
+ public final int mSwitchIndex;
+
+ public GT_Tool_Pocket_Multitool(int aSwitchIndex) {
+ mSwitchIndex = aSwitchIndex;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 4.0F;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? Textures.ItemIcons.POCKET_MULTITOOL_CLOSED : Textures.ItemIcons.VOID;
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa;
+ }
+
+ @Override
+ public void onStatsAddedToTool(GT_MetaGenerated_Tool aItem, int aID) {
+ super.onStatsAddedToTool(aItem, aID);
+ aItem.addItemBehavior(aID, new Behaviour_Switch_Metadata(mSwitchIndex, true, true));
+ }
+
+ @Override
+ public float getBaseDamage() {
+ return 0;
+ }
+
+ @Override
+ public boolean isMinableBlock(Block aBlock, byte aMetaData) {
+ return false;
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/pocket/GT_Tool_Pocket_Saw.java b/src/main/java/gregtech/common/tools/pocket/GT_Tool_Pocket_Saw.java
new file mode 100644
index 0000000000..579f809f2a
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/pocket/GT_Tool_Pocket_Saw.java
@@ -0,0 +1,39 @@
+package gregtech.common.tools.pocket;
+
+import net.minecraft.item.ItemStack;
+
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.common.items.behaviors.Behaviour_Switch_Metadata;
+import gregtech.common.tools.GT_Tool_Saw;
+
+public class GT_Tool_Pocket_Saw extends GT_Tool_Saw {
+
+ public final int mSwitchIndex;
+
+ public GT_Tool_Pocket_Saw(int aSwitchIndex) {
+ mSwitchIndex = aSwitchIndex;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 4.0F;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? Textures.ItemIcons.POCKET_MULTITOOL_SAW : Textures.ItemIcons.VOID;
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa;
+ }
+
+ @Override
+ public void onStatsAddedToTool(GT_MetaGenerated_Tool aItem, int aID) {
+ super.onStatsAddedToTool(aItem, aID);
+ aItem.addItemBehavior(aID, new Behaviour_Switch_Metadata(mSwitchIndex, true, true));
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/pocket/GT_Tool_Pocket_Screwdriver.java b/src/main/java/gregtech/common/tools/pocket/GT_Tool_Pocket_Screwdriver.java
new file mode 100644
index 0000000000..ce04ba2d15
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/pocket/GT_Tool_Pocket_Screwdriver.java
@@ -0,0 +1,39 @@
+package gregtech.common.tools.pocket;
+
+import net.minecraft.item.ItemStack;
+
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.common.items.behaviors.Behaviour_Switch_Metadata;
+import gregtech.common.tools.GT_Tool_Screwdriver;
+
+public class GT_Tool_Pocket_Screwdriver extends GT_Tool_Screwdriver {
+
+ public final int mSwitchIndex;
+
+ public GT_Tool_Pocket_Screwdriver(int aSwitchIndex) {
+ mSwitchIndex = aSwitchIndex;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 4.0F;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? Textures.ItemIcons.POCKET_MULTITOOL_SCREWDRIVER : Textures.ItemIcons.VOID;
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa;
+ }
+
+ @Override
+ public void onStatsAddedToTool(GT_MetaGenerated_Tool aItem, int aID) {
+ super.onStatsAddedToTool(aItem, aID);
+ aItem.addItemBehavior(aID, new Behaviour_Switch_Metadata(mSwitchIndex, true, true));
+ }
+}
diff --git a/src/main/java/gregtech/common/tools/pocket/GT_Tool_Pocket_WireCutter.java b/src/main/java/gregtech/common/tools/pocket/GT_Tool_Pocket_WireCutter.java
new file mode 100644
index 0000000000..6907ff6735
--- /dev/null
+++ b/src/main/java/gregtech/common/tools/pocket/GT_Tool_Pocket_WireCutter.java
@@ -0,0 +1,39 @@
+package gregtech.common.tools.pocket;
+
+import net.minecraft.item.ItemStack;
+
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.common.items.behaviors.Behaviour_Switch_Metadata;
+import gregtech.common.tools.GT_Tool_WireCutter;
+
+public class GT_Tool_Pocket_WireCutter extends GT_Tool_WireCutter {
+
+ public final int mSwitchIndex;
+
+ public GT_Tool_Pocket_WireCutter(int aSwitchIndex) {
+ mSwitchIndex = aSwitchIndex;
+ }
+
+ @Override
+ public float getMaxDurabilityMultiplier() {
+ return 4.0F;
+ }
+
+ @Override
+ public IIconContainer getIcon(boolean aIsToolHead, ItemStack aStack) {
+ return aIsToolHead ? Textures.ItemIcons.POCKET_MULTITOOL_WIRECUTTER : Textures.ItemIcons.VOID;
+ }
+
+ @Override
+ public short[] getRGBa(boolean aIsToolHead, ItemStack aStack) {
+ return GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mRGBa;
+ }
+
+ @Override
+ public void onStatsAddedToTool(GT_MetaGenerated_Tool aItem, int aID) {
+ super.onStatsAddedToTool(aItem, aID);
+ aItem.addItemBehavior(aID, new Behaviour_Switch_Metadata(mSwitchIndex, true, true));
+ }
+}