aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/gregtech/api
diff options
context:
space:
mode:
authorBlueWeabo <ilia.iliev2005@gmail.com>2024-01-06 00:41:00 +0200
committerGitHub <noreply@github.com>2024-01-05 23:41:00 +0100
commit02bedd5c0a96a654c6692edd1b7f2765fd9c46b4 (patch)
tree57dd675f658dda3caba629f15d4708247e702f88 /src/main/java/gregtech/api
parentfc63cee4c0284635c601889ce49a892cf73082ff (diff)
downloadGT5-Unofficial-02bedd5c0a96a654c6692edd1b7f2765fd9c46b4.tar.gz
GT5-Unofficial-02bedd5c0a96a654c6692edd1b7f2765fd9c46b4.tar.bz2
GT5-Unofficial-02bedd5c0a96a654c6692edd1b7f2765fd9c46b4.zip
Merge MuTEMaster into Master (#2431)
* Fix MuTE structure check and power intake (#1975) * Fixed casing lists being cleared for every checked structure piece * Fixed power being taken from any side BUT the right one * ACP Structure - Rebased (#1978) * Added 2nd structure tier to ACR and make complex parallels depend on it * Added tier 3 to 8 structure pieces to ACR * Added disclaimer * Renamed ACR to ACP because MV CR already is named ACR * Add autopush functionality to MuTE (#1976) - fix conflict * Working auto push * Revert wildcard import * Addresssed reviews * Fix reference issue * Minor MuTE fixes - Rebased (#1983) * Fixed ACP recipe map * Fixed controller side being used instead of part side when accessing tanks * Fix Structure not forming (#1984) * fix cables not connecting * fix structure and don't store controller * Add missing tooltips (#1981) * Add missing tooltips * Address blue's change * Distillation MuTE (#1989) * Started work on DT MuTE * Renamed methods so they also make sense when used horizontally * MuTE Upgrade Casings - Rebased (#1988) - fix conflict * Added cleanroom upgrade casing * Added inventory and tank upgrades * Added tooltips to mute casings * Added power upgrades * Set player UUID when placing MuTE * MuTE fixes (#1991) * Fixed pipes not connectable to MuTE casings * Fixed not all things being renamed to ACP * Fix running in obf * fix for real yo * Add a Generic Processing Logic and extract methods - Rebased (#1992) * add a generic processing logic * calculate tier in another method * calculate power logic in another method * Add Layered Coke Foundry (#1995) * Add the Foundry class and call it * Foundry name correction * Buildable stackable structure * Fixed min stacks and added motor casings * checkMachine override for custom checking * Working checkMachine for all stacks, and recipes * Fix getOutputFluids * Change recipe processing to GenericProcessingLogic * Change inventoryName to protected for override * Override checkRecipe for multis that consume EU * Rename class and add inner walls to multi * Structure update and other fixes * Fix processing logic being static * MuTE inventory upgrade logic (#2082) * Catch potential NPE * Don't load name when it doesn't exist * Potentially cause weird non-replicatable issue where registry ends up with different key * Use proper block removal method * Validate index before using it * Don't open controller GUI from inventory upgrade * semi-working concept * sync the ID of the inventory upgrade to correctly remove it later * remove unneeded boolean --------- Co-authored-by: BlueWeabo <76872108+BlueWeabo@users.noreply.github.com> * fixed layeredCokeBattery checkMachine to prevent 'already in building state' (#2099) * MuTE casing structure element (#2105) - fix conflict * Added class containing MuTE relevant structure elements * Migrate MuTE to new structure element * Formatting fix * Use int array instead of int hashmap, since its expected these arrays will never get long enough to be faster as hashmap * Delete old code * Cache MuTEs for non-instance specific actions (#2109) * Introduce map of cached TEs, which are used to perform actions that don't require a specific instance of the TE. This prevents constant creation of new TEs * Remove static modifier from map of cached TEs * First Modular Upgrade Casings Implementation (#2142) * Base support for Heater MUCs - Define Heater upgrade casings; - Create the 5 tiers of Heaters; - Add method to increase and decrease count. * Refactor the cache of MUCs in structure - Change the way that each MUC is counted: since there will be several types, the integer that counted heaters is now a hashmap that divides all MUCs based on their type and tier, to be counted separately from each other. * Add Insulator MUC - Add second MUC type (insulator) to test alongside heaters on the Layered Coke Battery. * Fix MUC count reset * Refactor MUC implementation into subclass - Move the new methods and hashmap away from the base classes, and onto a s specific one that won't be used by unrelated multiblocks. * Remove empty lines * Refactor MUC implementations into subclasses * Requested fixes in StackableModularController * Change hashmap keys to an enum * Hashmap getter for load order purposes - Added a getter that generates the default value for the hashmap if it is null, due to problems with load order; * Apply spotless * NotNull annotations * More Additions to MUCs and the LCB (#2215) * Fix old LCB multi name in some locations * Refactor mucMap and override checkRecipe - Refactor mucMap to an array of primitive integers instead of the wrapper type, for ease of use with other methods such as stream; - Override checkRecipe for custom recipe behavior on MUC multis, to be implemented in a future commit; * First implementation of bonuses and MUC requirements - Change EU/t and recipe duration of this multi based on the count of different MUCs in the multi; - Fail the structure check based on the count of each of the allowed MUCs. * Parallel count implementation - Calculate parallels based on the count of base MUCs, the cheapest option amongst the possibilities, in this case heaters; - Added more abstract methods to require specific values from the multi classes. * Fix parallel count and processing - Fixed the handling of parallels by pointing to the corrent maxParallel variable in ProcessingLogic. * Test of parallels with additional amp input * Structure fix for the intended LCB - Changed MUC placements to match what I intended at the beginning, to better test the multi. * One more comment * Remove checkRecipe override * Refactor Item and Fluid to be in separate logic classes (#2178) - fix conflict * basics of inventory logic * mostly working item logic * working nbt saving/loading * fluid handler * FluidSlotHandler WIP * fluid handler mostly working * remove fluid handler from gt5u * prepare for conversion * use correct imports * spotless * more controller logic * spotless * final refactor. migration next * spotless * add more methods to logic classes * convert almost everything to use new Logic * spotless * make mute casing mode an int * allow pump cover to work with FluidInventoryLogic * pumps work * spotless * make item inventory logic work with every item input thing * rework Fluid Inventory Logic to work with all fluid inputs * spotless * address annotation reviews * finish off todos * missed to dos * cleanup Coke oven will get a new GUI when i get to it * address review * prevent npes from ControllerXXXLogic * null checks * remove accidentally added methods * fix missed return * fixes after rebase - fix conflict * Laser Engraver Multi. (#2223) - fix conflict * saving............. * clean up * savin * Small fixes + Adding back stuff, Crashes you and spams logs. * fix stack overflow * Fixes * Fixes --------- Co-authored-by: BlueWeabo <76872108+BlueWeabo@users.noreply.github.com> * Add TickableTask (#2216) * Add autopush functionality to MuTE (#1976) * Working auto push * Revert wildcard import * Addresssed reviews * Fix reference issue * MuTE Upgrade Casings (#1988) * Added cleanroom upgrade casing * Added inventory and tank upgrades * Added tooltips to mute casings * Added power upgrades * Set player UUID when placing MuTE * Add a Generic Processing Logic and extract methods (#1992) * add a generic processing logic * calculate tier in another method * calculate power logic in another method * MuTE inventory upgrade logic (#2082) * Catch potential NPE * Don't load name when it doesn't exist * Potentially cause weird non-replicatable issue where registry ends up with different key * Use proper block removal method * Validate index before using it * Don't open controller GUI from inventory upgrade * semi-working concept * sync the ID of the inventory upgrade to correctly remove it later * remove unneeded boolean --------- Co-authored-by: BlueWeabo <76872108+BlueWeabo@users.noreply.github.com> * MuTE casing structure element (#2105) * Added class containing MuTE relevant structure elements * Migrate MuTE to new structure element * Formatting fix * Use int array instead of int hashmap, since its expected these arrays will never get long enough to be faster as hashmap * Delete old code * Refactor Item and Fluid to be in separate logic classes (#2178) * basics of inventory logic * mostly working item logic * working nbt saving/loading * fluid handler * FluidSlotHandler WIP * fluid handler mostly working * remove fluid handler from gt5u * prepare for conversion * use correct imports * spotless * more controller logic * spotless * final refactor. migration next * spotless * add more methods to logic classes * convert almost everything to use new Logic * spotless * make mute casing mode an int * allow pump cover to work with FluidInventoryLogic * pumps work * spotless * make item inventory logic work with every item input thing * rework Fluid Inventory Logic to work with all fluid inputs * spotless * address annotation reviews * finish off todos * missed to dos * cleanup Coke oven will get a new GUI when i get to it * address review * prevent npes from ControllerXXXLogic * null checks * Base work * PollutionTask * move package * Fix generics * Internal -> OverrideOnly * rebase fix * Ducttape addPollution --------- Co-authored-by: Maxim <maxim235@gmx.de> Co-authored-by: BlueWeabo <ilia.iliev2005@gmail.com> Co-authored-by: BlueWeabo <76872108+BlueWeabo@users.noreply.github.com> * Rework a bit of ProcessingLogic to fit MuTEs (#2283) - fix conflicts * Add a way to enable or disable the crafting buffer on GPL multiblocks (#2218) * add a way to enable or disable the crafting buffer on GPL multiblocks * don't register the hatch either * fix Refractory Capsule (#2219) * Fix PAs overclocking ulv recipes too much (#2220) * fix PAs overclocking ulv recipes too much * make sure we save the returned value * Fix Digital Tank capacity for Fluid Storage Monitor (#2217) * Fix Digital Tank capacity for Fluid Storage Monitor * Annotations * Blacklist AE2FC drop and packet, and Chisel stones from Recycler (#2222) * Fix recycler blacklist being sensitive to NBT * Blacklist AE2FC drop and packet, and Chisel stones * fix class loader issue * Add detailed logging for ME hatches (#2224) * Fix overclock calculator calculating eu/t use for ulv recipe wrong on certain parallel (#2225) * fix overclock calculator calculating eu/t use for ulv recipe wrong on certain parallel * make formula into its own method * Fix drilling rigs, plants and concrete backfiller to fail with multiple energy hatches (#2227) * max-1-energy-hatch-in-drilling-rigs.-plants-and-concrete-backfiller * spotlessApply (#2228) Co-authored-by: GitHub GTNH Actions <> * revert --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * clear stale crafting input bus list (#2233) * add ability to remove item data and use it for clay (#2229) * Update buildscript (#2232) * Fix server crash with RecipeFilter (#2231) * Fix server crash with RecipeFilter * Make client send filtered machines to server * Use mUniqueIdentifier * Fix a NPE w/ injecting into super/quantum chests (#2234) When simulating an injection, if the stackSize > chest's capacity, it causes a NPE when the internal chest is empty. Also fixes a potential bug when void overflow is set; the chest should return null in such a scenario regardless of simulation/modulation. * Fix lag caused by getRecipeMap for PA (#2236) * Experimental fix to prevent infinite loop in Grid destruction (#2235) Co-authored-by: Firenoo <49818773+firenoo@users.noreply.github.com> * Fix ME Output Bus and Crafting Input Bus overflow when save/load (#2238) * Remove fire display from singleblock generator (#2240) * Fix some output slots allowing insertion (#2230) * fix overlay zfighting by disable depth test (#2226) * Crafting input - Optimize isEmpty check to reduce lag (#2239) * Optimize isEmpty check * rearrage * remove broken hsla recipe (#2241) * Correct PCB Factory Energy Hatch description (#2237) * Correct PCB Factory Energy Hatch description Changes the PCB factory description (the one seen when holding shift) which currently says "Energy Hatches: 1+" I believe this is incorrect and that the correct description is 1-2 energy hatches or 1 TT energy hatch. I believe the PCB factory uses this, which checks for 1-2 or 1 TT: public boolean checkExoticAndNormalEnergyHatches() { if (mExoticEnergyHatches.isEmpty() && mEnergyHatches.isEmpty()) { return false; } if (!mExoticEnergyHatches.isEmpty()) { if (!mEnergyHatches.isEmpty()) { return false; } if (mExoticEnergyHatches.size() != 1) { return false; } } return mEnergyHatches.size() <= 2; } * gradlew spotlessApply * Correct file name on resource pack guide (#2242) * Fix GT_RecipeConstants.Fuel (#2243) * Update text (#2246) * Fix startup tier for fusion NEI (#2249) * Update the conditionals buttons and tooltips on covers to reflect their actual effects (#2244) * Update redstone buttons and tooltips to better reflect actual use * Spotless Apply * Update GT_Cover_FluidRegulator.java * Update GT_Cover_FluidRegulator.java * Typo fix, Icon Improved and interactive blocking ui - Fixed a typo in the world machine - Fixed double button situation for conveyor belts. - There was never any issue, the testing methodology gave me invalid results. - Conveyor behaviour is in line with all the other covers affected by this PR/Branch. - Updated icon for the machine state to be a miniature machine controller cover. - Made the block/allow input section more interactive in order to better reflect the actual effect of these buttons. - In import mode, it actually blocks the machine from outputting from that side. * typos I can't write to save myself sometimes * Better text alignment - Better text alignment * fix typos I swear I can't write to save myself. --------- Co-authored-by: Martin Robertz <dream-master@gmx.net> * Fix Orichalcum and Shadowiron smelting (#2251) * fix orichalcum and shadowiron smelting * add Alduorite and Chrysotile * Fix tier display for Fusion NEI header (#2250) * fix ulv recipes being broken again when under 1 tick calculation is taken (#2254) * change way to fix zfighting (#2253) * Crafting input hatches QoLs (#2200) * Fixes + Detect Inventory Slot Changes * support rename + check for updates * add back onChangeListener + fix npe * ICustomNameObject TileEntity * Fix NPEs * Use IInterfaceTerminalSupport * fix * register * dep * spotless * General Crafting Input Hatch QoL fixes (#2212) * feat: refactor naming && include circuit and catalyst in default name * feat: add 4 more slot to solve my ocd * fix: formatting * feat: migrate from 4x8 to 4x9 * spotlessApply (#2213) Co-authored-by: GitHub GTNH Actions <> * QoLs * 9 manual items * spotless * feat: open master GUI when used, without holding a data-stick (#2221) * fix destpos * optimize empty check * Fix error when fluidInventory.size() == 0 If the fluidInventory size is 0, there is no element to get. Add a check for it. * name in waila + fix int overflow * unnecssary super * update deps --------- Co-authored-by: Fox_white <39846845+foxwhite25@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Firenoo <49818773+firenoo@users.noreply.github.com> Co-authored-by: Martin Robertz <dream-master@gmx.net> * Use real stack limit (#2256) * Fix incorrect data stick behaviors for hatches (#2257) * Fix pcb factory not applying its roughness multiplier when it doesn't OC (#2258) * fix PCB Factory not applying its roughness multiplier when it doesn't do any overclocks * spotless * Remove duplicate obsidian long rod (#2259) * disable gt obsidian long rod * cleaner code * Add hazmat to ThaumicBoots (#2260) * Add hazmat to ThaumicBoots does what it says * fixed * fix item names (#2263) * Fix renaming recipe check might ignore NBT equality (#2261) * Fix GPL ignoring if the recipe is allowed to be cached (#2262) * Added bricked blast furnace recipe progress to waila. (#2265) * Added bricked blast furnace recipe progress to waila. * fixed formatting issues. * Fix cutter recipes not being added (#2271) * add processing task * clean up item logic host * temporary fix for GT_StructrureMuTE * use j9+ feature on pollution task * prepare complex parallel logic for transition * feature to ProcessingLogicHost * fix up multiblock bases * add processing logic for each multi to prepare for transition * spotless * removed debug text from wailaBody of GT_MetaTileEntity_Hatch_CraftingInput_ME (#2272) * Proper recipe selection for output overflow in LCR and other multiblocks (#2247) * Implement Stream<FindRecipeResult> findRecipesWithResult for GT_RecipeMap * Change ProcessingLogic.process to actually use new findRecipesWithResult * Change ProcessingLogic.process to start finding something only for OUTPUT_FULL result * Refactor ProcessingLogic.process to make logic more readable * Replace while with for loop, remove NOT_FOUND return in end of findRecipesWithResult * Apply spotless * Make findRecipe use findRecipes, add annotation to GT_Recipe and FindRecipeResult for processRecipe and make method protected, replace wildcard imports * Remake isRecipeWithOutputFullFound * Add @Nonnull to methods * Apply spotless * Remove Stream version of findRecipeWithResult, replace with predicate one. Add GT_Predicated_Recipe_Map class for utilizing this method. Changes some existent recipe maps to inherit from base class. * Remove GT_Predicated_Recipe_Map, add Predicate directly to GT_Recipe_Map#findRecipeWithResult. Add AdvancedRecipeValidatorPredicate and FindRecipeWithAdvancedValidatorResult to allow store validation calculations for further use and proper errors displaying. * Fix InsufficientVoltage errors * Changes according to review comments. Integrate FindRecipeWithAdvancedValidatorResult to FindRecipeResult, rename AdvancedRecipeValidatorPredicate, encapsulate AdvancedRecipeValidatorPredicate fields, fixes some typos, etc * Moves InsufficientVoltage check to GT_ParallelHelper. Removes FindRecipeResult#State#INSUFFICIENT_VOLTAGE * Return an old findRecipeWithResult * Renames things, call old methods for singleblocks * Renames things, makes FindRecipeResult ctor private * Apply spotless * Move RecipeValidator, fix comments typos * update deps * fix up complex processing logic * add a getter for voiding mode * fix getAccessibleSlotsFromSide being wrong sometimes * allow for subtraction of a specific item * use long for amount * add a setter for machine host * initial work on finding recipes and input consumption * Deprecate PA by removing its controller recipe (#2273) * Restore PA controller recipe (#2276) * Restore PA controller recipe * Remove duplicated recipe * Add optional description to input hatch constructors (#2278) * mini fix (#2204) * [chore] Bump fallback version to 44 (#2274) * find recipe in theory working * add some helper methods to inventory logics * update deps * use collect not toList * fix loading crash * fix complex processing logic using wrong find recipe * fix up everything and get recipe finding working * annotate and clean up methods * spotless * save things to nbt * input separation for mutes and fully working processing * apply mute mode on processing logic * clean up overrides --------- Co-authored-by: chochem <40274384+chochem@users.noreply.github.com> Co-authored-by: miozune <miozune@gmail.com> Co-authored-by: Pxx500 <81298696+Pxx500@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Glease <4586901+Glease@users.noreply.github.com> Co-authored-by: firenoo <49818773+firenoo@users.noreply.github.com> Co-authored-by: Martin Robertz <dream-master@gmx.net> Co-authored-by: Harry <harryyunull@gmail.com> Co-authored-by: Eraldoe <Eraldoe@users.noreply.github.com> Co-authored-by: Jakub <53441451+kuba6000@users.noreply.github.com> Co-authored-by: Connor-Colenso <52056774+Connor-Colenso@users.noreply.github.com> Co-authored-by: Guillaume Mercier <C0bra5@users.noreply.github.com> Co-authored-by: Fox_white <39846845+foxwhite25@users.noreply.github.com> Co-authored-by: Alastors <78517796+Alastors@users.noreply.github.com> Co-authored-by: Kyium <43573052+Kyium@users.noreply.github.com> Co-authored-by: SKProCH <29896317+SKProCH@users.noreply.github.com> Co-authored-by: Sampsa <69092953+S4mpsa@users.noreply.github.com> Co-authored-by: Jaiden Baker <jaidencolebaker@gmail.com> * address minecraft's reviews from #2283 * Refactor MuTE processing logic (#2301) -fix conflicts * Fix void protection for mutes (#2298) - fix conflicts * initial variables * implement working void protection on items and fluids * Adds a Simple PowerOutput task and cleans up some of the code. (#2303) * create a power output task which can be used for dynamos * refactor the controllers and clean up * add some documentation to power logic * make a wireless network manager class instead of using an interface * clean up and add documentation. * setAmperage to setMaxAmperage * fix comment * remove IGlobalWirelessEnergy usage * getAmperage -> getMaxAmperage * add todo for future * Cleanup MuTEMaster code (#2282) * exit early * spotless * better side checking * make if blocks mutually exclusive * more exit early * convert nested ternary operators into if blocks * remove dead code * collapse nested if blocks * add todo to break verylong condition into much smaller ones * spotless apply * collapsing nested if blocks and more exit early * spotless apply * extract try/catch block to its own utility method * break down this unreadable condition * boolean magic (1/5) * boolean magic (2/5) Also corrected some logic on the player null check, we want it to be non null * boolean magic (3/5) * boolean magic (4/5) * boolean magic (5/5) * remove todo * Fix logic --------- Co-authored-by: Jason Mitchell <jason@puzzle.io> Co-authored-by: BlueWeabo <76872108+BlueWeabo@users.noreply.github.com> * Clean up a lil bit and fix some issues with MuTEs (#2316) * clean up fixes * actual fix and remove useless if * Rework MuTEGUI structure (#2429) - fix conflicts` Merged to rebase MuTEMaster and fix any non-compile errors and game not launching in there * some docs on a few methods * innitial GUI class * try to implement guis * almost working - fix comflict * add UIBuildContext to getGUI method * make it compile * sketch gui - fix conflict * compile and spotless * add config option to enabling MuTEs * Spotless apply for branch feature/MuTEMaster for #2431 (#2432) spotlessApply Co-authored-by: GitHub GTNH Actions <> * address reviews on broken processing logic * spotless * fix doc and review --------- Co-authored-by: Maxim <maxim235@gmx.de> Co-authored-by: RIONDY 'POPlol333' Adam <76914762+POPlol333@users.noreply.github.com> Co-authored-by: Jason Mitchell <mitchej@gmail.com> Co-authored-by: Daniel Mendes <70096037+Steelux8@users.noreply.github.com> Co-authored-by: kstvr32 <109012629+kstvr32@users.noreply.github.com> Co-authored-by: TheEpicGamer274 <102255081+TheEpicGamer274@users.noreply.github.com> Co-authored-by: miozune <miozune@gmail.com> Co-authored-by: chochem <40274384+chochem@users.noreply.github.com> Co-authored-by: Pxx500 <81298696+Pxx500@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Glease <4586901+Glease@users.noreply.github.com> Co-authored-by: firenoo <49818773+firenoo@users.noreply.github.com> Co-authored-by: Martin Robertz <dream-master@gmx.net> Co-authored-by: Harry <harryyunull@gmail.com> Co-authored-by: Eraldoe <Eraldoe@users.noreply.github.com> Co-authored-by: Jakub <53441451+kuba6000@users.noreply.github.com> Co-authored-by: Connor-Colenso <52056774+Connor-Colenso@users.noreply.github.com> Co-authored-by: Guillaume Mercier <C0bra5@users.noreply.github.com> Co-authored-by: Fox_white <39846845+foxwhite25@users.noreply.github.com> Co-authored-by: Alastors <78517796+Alastors@users.noreply.github.com> Co-authored-by: Kyium <43573052+Kyium@users.noreply.github.com> Co-authored-by: SKProCH <29896317+SKProCH@users.noreply.github.com> Co-authored-by: Sampsa <69092953+S4mpsa@users.noreply.github.com> Co-authored-by: Jaiden Baker <jaidencolebaker@gmail.com> Co-authored-by: boubou19 <miisterunknown@gmail.com> Co-authored-by: Jason Mitchell <jason@puzzle.io>
Diffstat (limited to 'src/main/java/gregtech/api')
-rw-r--r--src/main/java/gregtech/api/GregTech_API.java5
-rw-r--r--src/main/java/gregtech/api/enums/GT_Values.java12
-rw-r--r--src/main/java/gregtech/api/enums/InventoryType.java7
-rw-r--r--src/main/java/gregtech/api/gui/GUIHost.java56
-rw-r--r--src/main/java/gregtech/api/gui/GUIProvider.java38
-rw-r--r--src/main/java/gregtech/api/interfaces/IGlobalWirelessEnergy.java92
-rw-r--r--src/main/java/gregtech/api/interfaces/tileentity/IEnergyConnected.java104
-rw-r--r--src/main/java/gregtech/api/interfaces/tileentity/IMachineProgress.java10
-rw-r--r--src/main/java/gregtech/api/logic/AbstractProcessingLogic.java346
-rw-r--r--src/main/java/gregtech/api/logic/ComplexParallelProcessingLogic.java219
-rw-r--r--src/main/java/gregtech/api/logic/ControllerFluidLogic.java152
-rw-r--r--src/main/java/gregtech/api/logic/ControllerItemLogic.java148
-rw-r--r--src/main/java/gregtech/api/logic/FluidInventoryLogic.java269
-rw-r--r--src/main/java/gregtech/api/logic/ItemInventoryLogic.java314
-rw-r--r--src/main/java/gregtech/api/logic/MuTEProcessingLogic.java256
-rw-r--r--src/main/java/gregtech/api/logic/NullPowerLogic.java5
-rw-r--r--src/main/java/gregtech/api/logic/PollutionLogic.java17
-rw-r--r--src/main/java/gregtech/api/logic/PowerLogic.java129
-rw-r--r--src/main/java/gregtech/api/logic/ProcessingLogic.java323
-rw-r--r--src/main/java/gregtech/api/logic/interfaces/FluidInventoryLogicHost.java95
-rw-r--r--src/main/java/gregtech/api/logic/interfaces/ItemInventoryLogicHost.java172
-rw-r--r--src/main/java/gregtech/api/logic/interfaces/PollutionLogicHost.java8
-rw-r--r--src/main/java/gregtech/api/logic/interfaces/PowerLogicHost.java48
-rw-r--r--src/main/java/gregtech/api/logic/interfaces/ProcessingLogicHost.java80
-rw-r--r--src/main/java/gregtech/api/metatileentity/BaseTileEntity.java32
-rw-r--r--src/main/java/gregtech/api/metatileentity/CommonMetaTileEntity.java23
-rw-r--r--src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Cable.java2
-rw-r--r--src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Wireless_Dynamo.java5
-rw-r--r--src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Wireless_Hatch.java5
-rw-r--r--src/main/java/gregtech/api/multitileentity/MultiTileEntityBlock.java70
-rw-r--r--src/main/java/gregtech/api/multitileentity/MultiTileEntityClassContainer.java18
-rw-r--r--src/main/java/gregtech/api/multitileentity/MultiTileEntityItemInternal.java168
-rw-r--r--src/main/java/gregtech/api/multitileentity/MultiTileEntityRegistry.java12
-rw-r--r--src/main/java/gregtech/api/multitileentity/base/MultiTileEntity.java182
-rw-r--r--src/main/java/gregtech/api/multitileentity/base/TickableMultiTileEntity.java81
-rw-r--r--src/main/java/gregtech/api/multitileentity/enums/GT_MultiTileCasing.java23
-rw-r--r--src/main/java/gregtech/api/multitileentity/enums/GT_MultiTileUpgradeCasing.java71
-rw-r--r--src/main/java/gregtech/api/multitileentity/enums/MultiTileCasingPurpose.java13
-rw-r--r--src/main/java/gregtech/api/multitileentity/interfaces/IMultiBlockController.java45
-rw-r--r--src/main/java/gregtech/api/multitileentity/interfaces/IMultiBlockPart.java11
-rw-r--r--src/main/java/gregtech/api/multitileentity/interfaces/IMultiTileEntity.java19
-rw-r--r--src/main/java/gregtech/api/multitileentity/interfaces/UpgradableModularMuTE.java10
-rw-r--r--src/main/java/gregtech/api/multitileentity/interfaces/UpgradableMuTE.java12
-rw-r--r--src/main/java/gregtech/api/multitileentity/machine/MultiTileBasicMachine.java821
-rw-r--r--src/main/java/gregtech/api/multitileentity/multiblock/base/ComplexParallelController.java198
-rw-r--r--src/main/java/gregtech/api/multitileentity/multiblock/base/Controller.java2013
-rw-r--r--src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockPart.java688
-rw-r--r--src/main/java/gregtech/api/multitileentity/multiblock/base/PowerController.java92
-rw-r--r--src/main/java/gregtech/api/multitileentity/multiblock/base/StackableController.java43
-rw-r--r--src/main/java/gregtech/api/multitileentity/multiblock/base/StackableModularController.java77
-rw-r--r--src/main/java/gregtech/api/multitileentity/multiblock/base/WallShareablePart.java32
-rw-r--r--src/main/java/gregtech/api/multitileentity/multiblock/casing/UpgradeCasing.java10
-rw-r--r--src/main/java/gregtech/api/net/GT_Packet_MultiTileEntity.java96
-rw-r--r--src/main/java/gregtech/api/objects/GT_ItemStack.java4
-rw-r--r--src/main/java/gregtech/api/recipe/check/CheckRecipeResult.java7
-rw-r--r--src/main/java/gregtech/api/recipe/check/CheckRecipeResultRegistry.java16
-rw-r--r--src/main/java/gregtech/api/recipe/check/ResultInsufficientHeat.java20
-rw-r--r--src/main/java/gregtech/api/recipe/check/ResultInsufficientMachineTier.java17
-rw-r--r--src/main/java/gregtech/api/recipe/check/ResultInsufficientPower.java20
-rw-r--r--src/main/java/gregtech/api/recipe/check/ResultInsufficientStartupPower.java17
-rw-r--r--src/main/java/gregtech/api/recipe/check/SimpleCheckRecipeResult.java12
-rw-r--r--src/main/java/gregtech/api/task/TaskHost.java18
-rw-r--r--src/main/java/gregtech/api/task/TickableTask.java48
-rw-r--r--src/main/java/gregtech/api/task/tasks/PollutionTask.java45
-rw-r--r--src/main/java/gregtech/api/task/tasks/PowerOutputTask.java32
-rw-r--r--src/main/java/gregtech/api/task/tasks/ProcessingTask.java51
-rw-r--r--src/main/java/gregtech/api/util/GT_OverclockCalculator.java25
-rw-r--r--src/main/java/gregtech/api/util/GT_ParallelHelper.java77
-rw-r--r--src/main/java/gregtech/api/util/GT_Recipe.java77
-rw-r--r--src/main/java/gregtech/api/util/GT_StructureUtilityMuTE.java271
-rw-r--r--src/main/java/gregtech/api/util/VoidProtectionHelper.java124
-rw-r--r--src/main/java/gregtech/api/util/item/ItemHolder.java79
-rw-r--r--src/main/java/gregtech/api/util/recipe/RecipeInputRequirements.java77
73 files changed, 5002 insertions, 3812 deletions
diff --git a/src/main/java/gregtech/api/GregTech_API.java b/src/main/java/gregtech/api/GregTech_API.java
index c5e27aebca..1f936f3119 100644
--- a/src/main/java/gregtech/api/GregTech_API.java
+++ b/src/main/java/gregtech/api/GregTech_API.java
@@ -71,6 +71,7 @@ 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.api.util.item.ItemHolder;
import gregtech.api.world.GT_Worldgen;
import gregtech.common.GT_DummyWorld;
import gregtech.common.items.GT_IntegratedCircuit_Item;
@@ -107,8 +108,8 @@ public class GregTech_API {
/**
* Fixes the HashMap Mappings for ItemStacks once the Server started
*/
- public static final Collection<Map<? extends GT_ItemStack, ?>> sItemStackMappings = new ArrayList<>();
- public static final Collection<SetMultimap<? extends GT_ItemStack, ?>> itemStackMultiMaps = new ArrayList<>();
+ public static final Collection<Map<? extends ItemHolder, ?>> sItemStackMappings = new ArrayList<>();
+ public static final Collection<SetMultimap<? extends ItemHolder, ?>> itemStackMultiMaps = new ArrayList<>();
/**
* The MetaTileEntity-ID-List-Length
diff --git a/src/main/java/gregtech/api/enums/GT_Values.java b/src/main/java/gregtech/api/enums/GT_Values.java
index 98d9e5a176..418bf2d14c 100644
--- a/src/main/java/gregtech/api/enums/GT_Values.java
+++ b/src/main/java/gregtech/api/enums/GT_Values.java
@@ -289,7 +289,7 @@ public class GT_Values {
public static final String COLOR = "gt.color", // Integer
COVERS = "gt.covers", // String
CUSTOM_NAME = "name", // String
- DISPAY = "gt.display", // String
+ DISPLAY = "gt.display", // String
TIER = "gt.tier", // Number
FACING = "gt.facing", // Byte
LOCK_UPGRADE = "gt.locked", // Boolean
@@ -322,6 +322,7 @@ public class GT_Values {
BURN_TIME_LEFT = "gt.burn.time.left", // Number
TOTAL_BURN_TIME = "gt.total.burn.time", // Number
ALLOWED_WORK = "gt.allowed.work", // Boolean
+ TASKS = "gt.tasks", // Compound
// MultiBlock
STRUCTURE_OK = "gt.structure.ok", ROTATION = "gt.eRotation", FLIP = "gt.eFlip", TARGET = "gt.target", // Boolean
@@ -337,13 +338,14 @@ public class GT_Values {
UPGRADE_INVENTORIES_INPUT = "gt.invlist.upg.in", // NBT List
UPGRADE_INVENTORIES_OUTPUT = "gt.invlist.upg.out", // NBT List
UPGRADE_TANK_CAPACITY = "gt.tank.cap.upg", // Long
+ UPGRADE_TANK_COUNT = "gt.tank.ct.upg", // Int
UPGRADE_TANK_CAPACITY_MULTIPLIER = "gt.tank.cap.mult.upg", // Long
UPGRADE_TANK_UUID = "gt.tankuuid.upg", // String
UPGRADE_TANK_NAME = "gt.tankname.upg", // String
UPGRADE_TANKS_INPUT = "gt.tanklist.upg.in", // NBT List
UPGRADE_TANKS_OUTPUT = "gt.tanklist.upg.out", // NBT List
- UPGRADE_TANKS_COUNT = "gt.tankcount.upg", // Int
UPGRADE_TANKS_PREFIX = "gt.tank.upg", // NBT Tag
+ UPGRADE_AMPERAGE = "gt.amp.upg", // Long
SEPARATE_INPUTS = "gt.separate.inputs", // Boolean
VOIDING_MODE = "gt.voiding.mode", // String
BATCH_MODE = "gt.batch.mode", // Boolean
@@ -490,6 +492,11 @@ public class GT_Values {
*/
public static boolean debugWorldData = false;
/**
+ * Parameter if multi tile entities (MuTEs) should be enabled in the pack. Turned off by default until
+ * implementation is done.
+ */
+ public static boolean enableMultiTileEntities = false;
+ /**
* Number of ticks between sending sound packets to clients for electric machines. Default is 1.5 seconds. Trying to
* mitigate lag and FPS drops.
*/
@@ -606,6 +613,7 @@ public class GT_Values {
+ "minecraft7771";
public static final String AuthorQuerns = "Author: " + EnumChatFormatting.RED + "Querns";
+ public static final String AuthorTheEpicGamer274 = "Author: " + "TheEpicGamer274";
// 7.5F comes from GT_Tool_Turbine_Large#getBaseDamage() given huge turbines are the most efficient now.
public static double getMaxPlasmaTurbineEfficiencyFromMaterial(Materials material) {
diff --git a/src/main/java/gregtech/api/enums/InventoryType.java b/src/main/java/gregtech/api/enums/InventoryType.java
new file mode 100644
index 0000000000..f8e3c47741
--- /dev/null
+++ b/src/main/java/gregtech/api/enums/InventoryType.java
@@ -0,0 +1,7 @@
+package gregtech.api.enums;
+
+public enum InventoryType {
+ Input,
+ Output,
+ Both;
+}
diff --git a/src/main/java/gregtech/api/gui/GUIHost.java b/src/main/java/gregtech/api/gui/GUIHost.java
new file mode 100644
index 0000000000..bbb94317c4
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/GUIHost.java
@@ -0,0 +1,56 @@
+package gregtech.api.gui;
+
+import java.util.Objects;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.item.ItemStack;
+
+import com.gtnewhorizons.modularui.api.screen.ITileWithModularUI;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+
+public interface GUIHost extends ITileWithModularUI {
+
+ @Nonnull
+ @Override
+ default ModularWindow createWindow(UIBuildContext uiContext) {
+ Objects.requireNonNull(uiContext);
+ GUIProvider<?> gui = getGUI(uiContext);
+ return gui.openGUI(uiContext);
+ }
+
+ /**
+ * Width of the GUI when its being displayed
+ */
+ default int getWidth() {
+ return 170;
+ }
+
+ default int getHeight() {
+ return 192;
+ }
+
+ @Nonnull
+ GUIProvider<?> getGUI(@Nonnull UIBuildContext uiContext);
+
+ ItemStack getAsItem();
+
+ String getMachineName();
+
+ default boolean hasItemInput() {
+ return true;
+ }
+
+ default boolean hasItemOutput() {
+ return true;
+ }
+
+ default boolean hasFluidInput() {
+ return true;
+ }
+
+ default boolean hasFluidOutput() {
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/GUIProvider.java b/src/main/java/gregtech/api/gui/GUIProvider.java
new file mode 100644
index 0000000000..6fec4aa52a
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/GUIProvider.java
@@ -0,0 +1,38 @@
+package gregtech.api.gui;
+
+import java.util.Objects;
+
+import javax.annotation.Nonnull;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow.Builder;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+
+public abstract class GUIProvider<T extends GUIHost> {
+
+ @Nonnull
+ protected final T host;
+
+ public GUIProvider(@Nonnull T host) {
+ this.host = host;
+ }
+
+ @Nonnull
+ public ModularWindow openGUI(@Nonnull UIBuildContext uiContext) {
+ Builder builder = Objects.requireNonNull(ModularWindow.builder(host.getWidth(), host.getHeight()));
+ if (shouldBindPlayerInventory()) {
+ builder.bindPlayerInventory(uiContext.getPlayer());
+ }
+ attachSynchHandlers(builder, uiContext);
+ addWidgets(builder, uiContext);
+ return Objects.requireNonNull(builder.build());
+ }
+
+ protected abstract void attachSynchHandlers(@Nonnull Builder builder, @Nonnull UIBuildContext uiContext);
+
+ protected abstract void addWidgets(@Nonnull Builder builder, @Nonnull UIBuildContext uiContext);
+
+ protected boolean shouldBindPlayerInventory() {
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/api/interfaces/IGlobalWirelessEnergy.java b/src/main/java/gregtech/api/interfaces/IGlobalWirelessEnergy.java
index be4db5412a..47c03743a5 100644
--- a/src/main/java/gregtech/api/interfaces/IGlobalWirelessEnergy.java
+++ b/src/main/java/gregtech/api/interfaces/IGlobalWirelessEnergy.java
@@ -1,25 +1,25 @@
package gregtech.api.interfaces;
-import static gregtech.common.misc.GlobalVariableStorage.GlobalEnergy;
-import static gregtech.common.misc.GlobalVariableStorage.GlobalEnergyName;
-import static gregtech.common.misc.GlobalVariableStorage.GlobalEnergyTeam;
-
import java.math.BigInteger;
import java.util.UUID;
import net.minecraft.entity.player.EntityPlayer;
import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
-import gregtech.common.misc.GlobalEnergyWorldSavedData;
+import gregtech.common.misc.WirelessNetworkManager;
// If you are adding very late-game content feel free to tap into this interface.
// The eventual goal is to bypass laser/dynamo stuff and have energy deposited directly from ultra-endgame
// multi-blocks directly into the users network.
+/**
+ * Use WirelessNetworkManager instead
+ */
+@Deprecated
public interface IGlobalWirelessEnergy {
// User 0 will join user 1 by calling this function. They will share the same energy network.
default void joinUserNetwork(String user_uuid_0, String user_uuid_1) {
- GlobalEnergyTeam.put(user_uuid_0, user_uuid_1);
+ WirelessNetworkManager.joinUserNetwork(user_uuid_0, user_uuid_1);
}
// Adds a user to the energy map if they do not already exist. Otherwise, do nothing. Will also check if the user
@@ -27,35 +27,18 @@ public interface IGlobalWirelessEnergy {
// tick of a machine being placed only.
default void strongCheckOrAddUser(EntityPlayer user) {
- strongCheckOrAddUser(
+ WirelessNetworkManager.strongCheckOrAddUser(
user.getUniqueID()
.toString(),
user.getDisplayName());
}
default void strongCheckOrAddUser(UUID user_uuid, String user_name) {
- strongCheckOrAddUser(user_uuid.toString(), user_name);
+ WirelessNetworkManager.strongCheckOrAddUser(user_uuid.toString(), user_name);
}
default void strongCheckOrAddUser(String user_uuid, String user_name) {
-
- // Check if the user has a team. Add them if not.
- GlobalEnergyTeam.putIfAbsent(user_uuid, user_uuid);
-
- // Check if the user is in the global energy map.
- GlobalEnergy.putIfAbsent(user_uuid, BigInteger.ZERO);
-
- // If the username linked to the users fixed uuid is not equal to their current name then remove it.
- // This indicates that their username has changed.
- if (!(GlobalEnergyName.getOrDefault(user_uuid, "")
- .equals(user_name))) {
- String old_name = GlobalEnergyName.get(user_uuid);
- GlobalEnergyName.remove(old_name);
- }
-
- // Add UUID -> Name, Name -> UUID.
- GlobalEnergyName.put(user_name, user_uuid);
- GlobalEnergyName.put(user_uuid, user_name);
+ WirelessNetworkManager.strongCheckOrAddUser(user_uuid, user_name);
}
// ------------------------------------------------------------------------------------
@@ -64,30 +47,7 @@ public interface IGlobalWirelessEnergy {
// 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.
default boolean addEUToGlobalEnergyMap(String userUUID, 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.
- String teamUUID = GlobalEnergyTeam.getOrDefault(userUUID, userUUID);
-
- // 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;
+ return WirelessNetworkManager.addEUToGlobalEnergyMap(userUUID, EU);
}
default boolean addEUToGlobalEnergyMap(UUID user_uuid, BigInteger EU) {
@@ -113,28 +73,20 @@ public interface IGlobalWirelessEnergy {
// ------------------------------------------------------------------------------------
default BigInteger getUserEU(String user_uuid) {
- return GlobalEnergy.getOrDefault(GlobalEnergyTeam.getOrDefault(user_uuid, user_uuid), BigInteger.ZERO);
+ return WirelessNetworkManager.getUserEU(user_uuid);
}
// This overwrites the EU in the network. Only use this if you are absolutely sure you know what you are doing.
default void setUserEU(String 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(GlobalEnergyTeam.get(user_uuid), EU);
+ WirelessNetworkManager.setUserEU(user_uuid, EU);
}
default String GetUsernameFromUUID(String uuid) {
- return GlobalEnergyName.getOrDefault(GlobalEnergyTeam.getOrDefault(uuid, ""), "");
+ return WirelessNetworkManager.getUsernameFromUUID(uuid);
}
default String getUUIDFromUsername(String username) {
- return GlobalEnergyTeam.getOrDefault(GlobalEnergyName.getOrDefault(username, ""), "");
+ return WirelessNetworkManager.getUUIDFromUsername(username);
}
/**
@@ -143,24 +95,14 @@ public interface IGlobalWirelessEnergy {
* @return
*/
default String getRawUUIDFromUsername(String username) {
- return GlobalEnergyName.getOrDefault(username, "");
+ return WirelessNetworkManager.getRawUUIDFromUsername(username);
}
static void clearGlobalEnergyInformationMaps() {
- // Do not use this unless you are 100% certain you know what you are doing.
- GlobalEnergy.clear();
- GlobalEnergyName.clear();
- GlobalEnergyTeam.clear();
+ WirelessNetworkManager.clearGlobalEnergyInformationMaps();
}
default String processInitialSettings(final IGregTechTileEntity machine) {
-
- // UUID and username of the owner.
- final String UUID = machine.getOwnerUuid()
- .toString();
- final String name = machine.getOwnerName();
-
- strongCheckOrAddUser(UUID, name);
- return UUID;
+ return WirelessNetworkManager.processInitialSettings(machine);
}
}
diff --git a/src/main/java/gregtech/api/interfaces/tileentity/IEnergyConnected.java b/src/main/java/gregtech/api/interfaces/tileentity/IEnergyConnected.java
index f866092d38..91a9759e47 100644
--- a/src/main/java/gregtech/api/interfaces/tileentity/IEnergyConnected.java
+++ b/src/main/java/gregtech/api/interfaces/tileentity/IEnergyConnected.java
@@ -1,5 +1,9 @@
package gregtech.api.interfaces.tileentity;
+import java.util.Objects;
+
+import javax.annotation.Nonnull;
+
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.util.ForgeDirection;
@@ -53,24 +57,25 @@ public interface IEnergyConnected extends IColoredTileEntity {
*/
final class Util {
+ // TODO: Deduplicate code by rewokring the Enet system using the GTCEu one as inspiration - BlueWeabo
/**
* Emits Energy to the E-net. Also compatible with adjacent IC2 TileEntities.
*
* @return the used Amperage.
*/
- public static long emitEnergyToNetwork(long aVoltage, long aAmperage, IEnergyConnected aEmitter) {
- long rUsedAmperes = 0;
- if (!(aEmitter instanceof IHasWorldObjectAndCoords emitterTile)) {
+ public static long emitEnergyToNetwork(long voltage, long amperage, IEnergyConnected emitter) {
+ long usedAmperes = 0;
+ if (!(emitter instanceof IHasWorldObjectAndCoords emitterTile)) {
return 0;
}
for (final ForgeDirection side : ForgeDirection.VALID_DIRECTIONS) {
- if (rUsedAmperes > aAmperage) break;
- if (!aEmitter.outputsEnergyTo(side)) {
+ if (usedAmperes > amperage) break;
+ if (!emitter.outputsEnergyTo(side)) {
continue;
}
- final ForgeDirection oppositeSide = side.getOpposite();
+ final ForgeDirection oppositeSide = Objects.requireNonNull(side.getOpposite());
final TileEntity tTileEntity = emitterTile.getTileEntityAtSide(side);
if (tTileEntity instanceof PowerLogicHost host) {
@@ -79,28 +84,95 @@ public interface IEnergyConnected extends IColoredTileEntity {
continue;
}
- rUsedAmperes += logic.injectEnergy(aVoltage, aAmperage - rUsedAmperes);
+ usedAmperes += logic.injectEnergy(voltage, amperage - usedAmperes);
} else if (tTileEntity instanceof IEnergyConnected energyConnected) {
- if (aEmitter.getColorization() >= 0) {
+ if (emitter.getColorization() >= 0) {
final byte tColor = energyConnected.getColorization();
- if (tColor >= 0 && tColor != aEmitter.getColorization()) continue;
+ if (tColor >= 0 && tColor != emitter.getColorization()) continue;
}
- rUsedAmperes += energyConnected.injectEnergyUnits(oppositeSide, aVoltage, aAmperage - rUsedAmperes);
+ usedAmperes += energyConnected.injectEnergyUnits(oppositeSide, voltage, amperage - usedAmperes);
} else if (tTileEntity instanceof IEnergySink sink) {
- if (sink.acceptsEnergyFrom((TileEntity) aEmitter, oppositeSide)) {
- while (aAmperage > rUsedAmperes && sink.getDemandedEnergy() > 0
- && sink.injectEnergy(oppositeSide, aVoltage, aVoltage) < aVoltage) rUsedAmperes++;
+ if (sink.acceptsEnergyFrom((TileEntity) emitter, oppositeSide)) {
+ while (amperage > usedAmperes && sink.getDemandedEnergy() > 0
+ && sink.injectEnergy(oppositeSide, voltage, voltage) < voltage) usedAmperes++;
}
} else if (GregTech_API.mOutputRF && tTileEntity instanceof IEnergyReceiver receiver) {
- final int rfOut = GT_Utility.safeInt(aVoltage * GregTech_API.mEUtoRF / 100);
+ final int rfOut = GT_Utility.safeInt(voltage * GregTech_API.mEUtoRF / 100);
if (receiver.receiveEnergy(oppositeSide, rfOut, true) == rfOut) {
receiver.receiveEnergy(oppositeSide, rfOut, false);
- rUsedAmperes++;
+ usedAmperes++;
+ }
+ }
+ }
+ return usedAmperes;
+ }
+
+ /**
+ * Same as {@link #emitEnergyToNetwork(long, long, IEnergyConnected)}, but instead we remove the energy directly from the logic itself.
+ * @param emitter The host, which is trying to emit energy in the network
+ * @param outputSide side from where energy is being outputted to. If its {@link ForgeDirection#UNKNOWN} then it doesn't emit energy to the network
+ */
+ public static void emitEnergyToNetwork(@Nonnull final PowerLogicHost emitter, @Nonnull final ForgeDirection outputSide) {
+ if (outputSide == ForgeDirection.UNKNOWN) return;
+ final PowerLogic emitterLogic = emitter.getPowerLogic();
+ long usedAmperes = 0;
+ long voltage = emitterLogic.getVoltage();
+ long amperage = emitterLogic.getMaxAmperage();
+ if (!(emitter instanceof final IHasWorldObjectAndCoords emitterTile)) {
+ return;
+ }
+ // We need to make sure we can actually output energy on this side. This is more of a safety check.
+ if (emitter.getPowerLogic(outputSide) == null) {
+ return;
+ }
+
+ final ForgeDirection oppositeSide = Objects.requireNonNull(outputSide.getOpposite());
+ final TileEntity tileEntity = emitterTile.getTileEntityAtSide(outputSide);
+ if (tileEntity instanceof PowerLogicHost host) {
+
+ final PowerLogic logic = host.getPowerLogic(oppositeSide);
+ if (logic == null || logic.isEnergyReceiver()) {
+ return;
+ }
+
+ usedAmperes += logic.injectEnergy(voltage, amperage);
+ emitterLogic.removeEnergyUnsafe(usedAmperes * voltage);
+ return;
+ }
+
+ if (tileEntity instanceof IEnergyConnected energyConnected) {
+ if (emitter instanceof IColoredTileEntity coloredEmitter && coloredEmitter.getColorization() >= 0) {
+ final byte tColor = energyConnected.getColorization();
+ if (tColor >= 0 && tColor != coloredEmitter.getColorization()) {
+ return;
}
}
+ usedAmperes += energyConnected.injectEnergyUnits(oppositeSide, voltage, amperage - usedAmperes);
+ emitterLogic.removeEnergyUnsafe(usedAmperes * voltage);
+ return;
+ }
+
+ if (tileEntity instanceof IEnergySink sink) {
+ if (sink.acceptsEnergyFrom((TileEntity) emitter, oppositeSide)) {
+ while (amperage > usedAmperes && sink.getDemandedEnergy() > 0
+ && sink.injectEnergy(oppositeSide, voltage, voltage) < voltage) {
+ usedAmperes++;
+ }
+ emitterLogic.removeEnergyUnsafe(usedAmperes * voltage);
+ return;
+ }
+ }
+
+ if (GregTech_API.mOutputRF && tileEntity instanceof IEnergyReceiver receiver) {
+ final int rfOut = GT_Utility.safeInt(voltage * GregTech_API.mEUtoRF / 100);
+ if (receiver.receiveEnergy(oppositeSide, rfOut, true) == rfOut) {
+ receiver.receiveEnergy(oppositeSide, rfOut, false);
+ usedAmperes++;
+ emitterLogic.removeEnergyUnsafe(usedAmperes * voltage);
+ return;
+ }
}
- return rUsedAmperes;
}
}
}
diff --git a/src/main/java/gregtech/api/interfaces/tileentity/IMachineProgress.java b/src/main/java/gregtech/api/interfaces/tileentity/IMachineProgress.java
index bcd213b4ff..517f4a0cd3 100644
--- a/src/main/java/gregtech/api/interfaces/tileentity/IMachineProgress.java
+++ b/src/main/java/gregtech/api/interfaces/tileentity/IMachineProgress.java
@@ -16,7 +16,7 @@ public interface IMachineProgress extends IHasWorldObjectAndCoords {
int getMaxProgress();
/**
- * increases the Progress of the Machine
+ * Manually increases the Progress of the Machine by vent cover.
*/
boolean increaseProgress(int aProgressAmountInTicks);
@@ -46,6 +46,14 @@ public interface IMachineProgress extends IHasWorldObjectAndCoords {
*/
boolean isAllowedToWork();
+ default void setAllowedToWork(Boolean allowedToWork) {
+ if (allowedToWork) {
+ enableWorking();
+ } else {
+ disableWorking();
+ }
+ }
+
/**
* used to control Machines via Redstone Signal Strength by special Covers In case of 0 the Machine is very likely
* doing nothing, or is just not being controlled at all.
diff --git a/src/main/java/gregtech/api/logic/AbstractProcessingLogic.java b/src/main/java/gregtech/api/logic/AbstractProcessingLogic.java
new file mode 100644
index 0000000000..ae78bbacc2
--- /dev/null
+++ b/src/main/java/gregtech/api/logic/AbstractProcessingLogic.java
@@ -0,0 +1,346 @@
+package gregtech.api.logic;
+
+import java.util.function.Supplier;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.fluids.FluidStack;
+
+import gregtech.api.interfaces.tileentity.IVoidable;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.util.GT_OverclockCalculator;
+import gregtech.api.util.GT_ParallelHelper;
+import gregtech.api.util.GT_Recipe;
+
+/**
+ * Logic class to calculate result of recipe check from inputs.
+ */
+@SuppressWarnings({ "unused", "UnusedReturnValue" })
+public abstract class AbstractProcessingLogic<P extends AbstractProcessingLogic<P>> {
+
+ protected IVoidable machine;
+ protected Supplier<RecipeMap<?>> recipeMapSupplier;
+ protected GT_Recipe lastRecipe;
+ protected RecipeMap<?> lastRecipeMap;
+ protected ItemStack[] outputItems;
+ protected FluidStack[] outputFluids;
+ protected long calculatedEut;
+ protected int duration;
+ protected long availableVoltage;
+ protected long availableAmperage;
+ protected int overClockTimeReduction = 1;
+ protected int overClockPowerIncrease = 2;
+ protected boolean protectItems;
+ protected boolean protectFluids;
+ protected int maxParallel = 1;
+ protected Supplier<Integer> maxParallelSupplier;
+ protected int calculatedParallels = 0;
+ protected int batchSize = 1;
+ protected float euModifier = 1.0f;
+ protected float speedBoost = 1.0f;
+ protected boolean amperageOC = true;
+ protected boolean isCleanroom;
+
+ // #region Setters
+
+ /**
+ * Overwrites item output result of the calculation.
+ */
+ public P setOutputItems(ItemStack... itemOutputs) {
+ this.outputItems = itemOutputs;
+ return getThis();
+ }
+
+ /**
+ * Overwrites fluid output result of the calculation.
+ */
+ public P setOutputFluids(FluidStack... fluidOutputs) {
+ this.outputFluids = fluidOutputs;
+ return getThis();
+ }
+
+ public P setIsCleanroom(boolean isCleanroom) {
+ this.isCleanroom = isCleanroom;
+ return getThis();
+ }
+
+ /**
+ * Sets max amount of parallel.
+ */
+ public P setMaxParallel(int maxParallel) {
+ this.maxParallel = maxParallel;
+ return getThis();
+ }
+
+ /**
+ * Sets method to get max amount of parallel.
+ */
+ public P setMaxParallelSupplier(Supplier<Integer> supplier) {
+ this.maxParallelSupplier = supplier;
+ return getThis();
+ }
+
+ /**
+ * Sets batch size for batch mode.
+ */
+ public P setBatchSize(int size) {
+ this.batchSize = size;
+ return getThis();
+ }
+
+ public P setRecipeMap(RecipeMap<?> recipeMap) {
+ return setRecipeMapSupplier(() -> recipeMap);
+ }
+
+ public P setRecipeMapSupplier(Supplier<RecipeMap<?>> supplier) {
+ this.recipeMapSupplier = supplier;
+ return getThis();
+ }
+
+ public P setEuModifier(float modifier) {
+ this.euModifier = modifier;
+ return getThis();
+ }
+
+ public P setSpeedBonus(float speedModifier) {
+ this.speedBoost = speedModifier;
+ return getThis();
+ }
+
+ /**
+ * Sets machine used for void protection logic.
+ */
+ public P setMachine(IVoidable machine) {
+ this.machine = machine;
+ return getThis();
+ }
+
+ /**
+ * Overwrites duration result of the calculation.
+ */
+ public P setDuration(int duration) {
+ this.duration = duration;
+ return getThis();
+ }
+
+ /**
+ * Overwrites EU/t result of the calculation.
+ */
+ public P setCalculatedEut(long calculatedEut) {
+ this.calculatedEut = calculatedEut;
+ return getThis();
+ }
+
+ /**
+ * Sets voltage of the machine. It doesn't need to be actual voltage (excluding amperage) of the machine;
+ * For example, most of the multiblock machines set maximum possible input power (including amperage) as voltage
+ * and 1 as amperage. That way recipemap search will be executed with overclocked voltage.
+ */
+ public P setAvailableVoltage(long voltage) {
+ availableVoltage = voltage;
+ return getThis();
+ }
+
+ /**
+ * Sets amperage of the machine. This amperage doesn't involve in EU/t when searching recipemap.
+ * Useful for preventing tier skip but still considering amperage for parallel.
+ */
+ public P setAvailableAmperage(long amperage) {
+ availableAmperage = amperage;
+ return getThis();
+ }
+
+ public P setVoidProtection(boolean protectItems, boolean protectFluids) {
+ this.protectItems = protectItems;
+ this.protectFluids = protectFluids;
+ return getThis();
+ }
+
+ /**
+ * Sets custom overclock ratio. 2/4 by default.
+ * Parameters represent number of bit shift, so 1 -> 2x, 2 -> 4x.
+ */
+ public P setOverclock(int timeReduction, int powerIncrease) {
+ this.overClockTimeReduction = timeReduction;
+ this.overClockPowerIncrease = powerIncrease;
+ return getThis();
+ }
+
+ /**
+ * Sets overclock ratio to 4/4.
+ */
+ public P enablePerfectOverclock() {
+ return this.setOverclock(2, 2);
+ }
+
+ /**
+ * Sets whether the multi should use amperage to OC or not
+ */
+ public P setAmperageOC(boolean amperageOC) {
+ this.amperageOC = amperageOC;
+ return getThis();
+ }
+
+ /**
+ * Clears calculated results (and provided machine inputs) to prepare for the next machine operation.
+ */
+ public P clear() {
+ this.calculatedEut = 0;
+ this.duration = 0;
+ this.calculatedParallels = 0;
+ return getThis();
+ }
+
+ // #endregion
+
+ // #region Logic
+
+ /**
+ * Executes the recipe check: Find recipe from recipemap, Calculate parallel, overclock and outputs.
+ */
+ @Nonnull
+ public abstract CheckRecipeResult process();
+
+ /**
+ * Refreshes recipemap to use. Remember to call this before {@link #process} to make sure correct recipemap is used.
+ *
+ * @return Recipemap to use now
+ */
+ protected RecipeMap<?> preProcess() {
+ RecipeMap<?> recipeMap;
+ if (recipeMapSupplier == null) {
+ recipeMap = null;
+ } else {
+ recipeMap = recipeMapSupplier.get();
+ }
+ if (lastRecipeMap != recipeMap) {
+ lastRecipe = null;
+ lastRecipeMap = recipeMap;
+ }
+
+ if (maxParallelSupplier != null) {
+ maxParallel = maxParallelSupplier.get();
+ }
+
+ return recipeMap;
+ }
+
+ /**
+ * Check has been succeeded, so it applies the recipe and calculated parameters.
+ * At this point, inputs have been already consumed.
+ */
+ @Nonnull
+ protected CheckRecipeResult applyRecipe(@Nonnull GT_Recipe recipe, @Nonnull GT_ParallelHelper helper,
+ @Nonnull GT_OverclockCalculator calculator, @Nonnull CheckRecipeResult result) {
+ if (recipe.mCanBeBuffered) {
+ lastRecipe = recipe;
+ } else {
+ lastRecipe = null;
+ }
+ calculatedParallels = helper.getCurrentParallel();
+
+ if (calculator.getConsumption() == Long.MAX_VALUE) {
+ return CheckRecipeResultRegistry.POWER_OVERFLOW;
+ }
+ if (calculator.getDuration() == Integer.MAX_VALUE) {
+ return CheckRecipeResultRegistry.DURATION_OVERFLOW;
+ }
+
+ calculatedEut = calculator.getConsumption();
+
+ double finalDuration = calculateDuration(recipe, helper, calculator);
+ if (finalDuration >= Integer.MAX_VALUE) {
+ return CheckRecipeResultRegistry.DURATION_OVERFLOW;
+ }
+ duration = (int) finalDuration;
+
+ CheckRecipeResult hookResult = onRecipeStart(recipe);
+ if (!hookResult.wasSuccessful()) {
+ return hookResult;
+ }
+
+ outputItems = helper.getItemOutputs();
+ outputFluids = helper.getFluidOutputs();
+
+ return result;
+ }
+
+ /**
+ * Override to tweak final duration that will be set as a result of this logic class.
+ */
+ protected double calculateDuration(@Nonnull GT_Recipe recipe, @Nonnull GT_ParallelHelper helper,
+ @Nonnull GT_OverclockCalculator calculator) {
+ return calculator.getDuration() * helper.getDurationMultiplierDouble();
+ }
+
+ /**
+ * Override to do additional check for found recipe if needed.
+ */
+ @Nonnull
+ protected CheckRecipeResult validateRecipe(@Nonnull GT_Recipe recipe) {
+ return CheckRecipeResultRegistry.SUCCESSFUL;
+ }
+
+ /**
+ * Override to perform additional logic when recipe starts.
+ *
+ * This is called when the recipe processing logic has finished all
+ * checks, consumed all inputs, but has not yet set the outputs to
+ * be produced. Returning a result other than SUCCESSFUL will void
+ * all inputs!
+ */
+ @Nonnull
+ protected CheckRecipeResult onRecipeStart(@Nonnull GT_Recipe recipe) {
+ return CheckRecipeResultRegistry.SUCCESSFUL;
+ }
+
+ /**
+ * Override to tweak overclock logic if needed.
+ */
+ @Nonnull
+ protected GT_OverclockCalculator createOverclockCalculator(@Nonnull GT_Recipe recipe) {
+ return new GT_OverclockCalculator().setRecipeEUt(recipe.mEUt)
+ .setAmperage(availableAmperage)
+ .setEUt(availableVoltage)
+ .setDuration(recipe.mDuration)
+ .setSpeedBoost(speedBoost)
+ .setEUtDiscount(euModifier)
+ .setAmperageOC(amperageOC)
+ .setDurationDecreasePerOC(overClockTimeReduction)
+ .setEUtIncreasePerOC(overClockPowerIncrease);
+ }
+ // #endregion
+
+ // #region Getters
+
+ public ItemStack[] getOutputItems() {
+ return outputItems;
+ }
+
+ public FluidStack[] getOutputFluids() {
+ return outputFluids;
+ }
+
+ public int getDuration() {
+ return duration;
+ }
+
+ public long getCalculatedEut() {
+ return calculatedEut;
+ }
+
+ public int getCurrentParallels() {
+ return calculatedParallels;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Nonnull
+ public P getThis() {
+ return (P) this;
+ }
+
+ // #endregion
+}
diff --git a/src/main/java/gregtech/api/logic/ComplexParallelProcessingLogic.java b/src/main/java/gregtech/api/logic/ComplexParallelProcessingLogic.java
index 3c7974db9e..72a74ebd04 100644
--- a/src/main/java/gregtech/api/logic/ComplexParallelProcessingLogic.java
+++ b/src/main/java/gregtech/api/logic/ComplexParallelProcessingLogic.java
@@ -5,180 +5,117 @@ import java.util.stream.LongStream;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fluids.FluidStack;
-import gregtech.api.multitileentity.multiblock.base.Controller;
-import gregtech.api.recipe.RecipeMap;
-import gregtech.api.util.GT_OverclockCalculator;
-import gregtech.api.util.GT_ParallelHelper;
-import gregtech.api.util.GT_Recipe;
+public class ComplexParallelProcessingLogic<P extends ComplexParallelProcessingLogic<P>>
+ extends MuTEProcessingLogic<P> {
-public class ComplexParallelProcessingLogic {
+ protected int maxComplexParallels;
+ protected ItemStack[][] outputItems;
+ protected FluidStack[][] outputFluids;
+ protected long[] calculatedEutValues;
+ protected int[] durations;
+ protected int[] progresses;
- protected Controller<?> tileEntity;
- protected RecipeMap<?> recipeMap;
- protected boolean hasPerfectOverclock;
- protected final int maxComplexParallels;
- protected final ItemStack[][] outputItems;
- protected final ItemStack[][] inputItems;
- protected final FluidStack[][] inputFluids;
- protected final FluidStack[][] outputFluids;
- protected final long[] availableEut;
- protected final long[] eut;
- protected final long[] durations;
- protected final boolean[] isItemVoidProtected;
- protected final boolean[] isFluidVoidProtected;
-
- public ComplexParallelProcessingLogic(int maxComplexParallels) {
- this(null, maxComplexParallels);
- }
-
- public ComplexParallelProcessingLogic(RecipeMap<?> recipeMap, int maxComplexParallels) {
+ public P setMaxComplexParallel(int maxComplexParallels) {
this.maxComplexParallels = maxComplexParallels;
- this.recipeMap = recipeMap;
- inputItems = new ItemStack[maxComplexParallels][];
- outputItems = new ItemStack[maxComplexParallels][];
- inputFluids = new FluidStack[maxComplexParallels][];
- outputFluids = new FluidStack[maxComplexParallels][];
- eut = new long[maxComplexParallels];
- availableEut = new long[maxComplexParallels];
- durations = new long[maxComplexParallels];
- isItemVoidProtected = new boolean[maxComplexParallels];
- isFluidVoidProtected = new boolean[maxComplexParallels];
- }
-
- public ComplexParallelProcessingLogic setRecipeMap(RecipeMap<?> recipeMap) {
- this.recipeMap = recipeMap;
- return this;
+ reinitializeProcessingArrays();
+ return getThis();
}
- public ComplexParallelProcessingLogic setInputItems(int index, ItemStack... itemInputs) {
+ public ItemStack[] getOutputItems(int index) {
if (index >= 0 && index < maxComplexParallels) {
- inputItems[index] = itemInputs;
+ return outputItems[index];
}
- return this;
+ return null;
}
- public ComplexParallelProcessingLogic setInputFluids(int index, FluidStack... inputFluids) {
+ public FluidStack[] getOutputFluids(int index) {
if (index >= 0 && index < maxComplexParallels) {
- this.inputFluids[index] = inputFluids;
+ return outputFluids[index];
}
- return this;
+ return null;
}
- public ComplexParallelProcessingLogic setTileEntity(Controller<?> tileEntity) {
- this.tileEntity = tileEntity;
- return this;
+ @Override
+ public boolean canWork() {
+ for (int i = 0; i < maxComplexParallels; i++) {
+ if (progresses[i] >= durations[i]) {
+ return machineHost.isAllowedToWork();
+ }
+ }
+ return false;
}
- public ComplexParallelProcessingLogic setEut(int index, long eut) {
- if (index >= 0 && index < maxComplexParallels) {
- availableEut[index] = eut;
- }
- return this;
+ @Override
+ public long getCalculatedEut() {
+ return LongStream.of(this.calculatedEutValues)
+ .sum();
}
- public ComplexParallelProcessingLogic setVoidProtection(int index, boolean protectItem, boolean protectFluid) {
- if (index >= 0 && index < maxComplexParallels) {
- isItemVoidProtected[index] = protectItem;
- isFluidVoidProtected[index] = protectFluid;
- }
- return this;
+ public int getDuration(int index) {
+ return durations[index];
}
- public ComplexParallelProcessingLogic setPerfectOverclock(boolean shouldOverclockPerfectly) {
- this.hasPerfectOverclock = shouldOverclockPerfectly;
- return this;
+ public int getProgress(int index) {
+ return progresses[index];
}
- public ComplexParallelProcessingLogic clear() {
+ @Override
+ public void progress() {
for (int i = 0; i < maxComplexParallels; i++) {
- outputItems[i] = null;
- outputFluids[i] = null;
- durations[i] = 0;
- eut[i] = 0;
+ if (progresses[i] == durations[i]) {
+ progresses[i] = 0;
+ durations[i] = 0;
+ output(i);
+ continue;
+ }
+ progresses[i] = progresses[i] + 1;
}
- return this;
}
- public ComplexParallelProcessingLogic clear(int index) {
- if (index >= 0 && index < maxComplexParallels) {
- inputItems[index] = null;
- inputFluids[index] = null;
- outputItems[index] = null;
- outputFluids[index] = null;
- durations[index] = 0;
- availableEut[index] = 0;
- eut[index] = 0;
+ @Override
+ public void startCheck() {
+ for (int i = 0; i < maxComplexParallels; i++) {
+ if (durations[i] > 0) continue;
+ recipeResult = process();
+ calculatedEutValues[i] = calculatedEut;
+ durations[i] = duration;
+ progresses[i] = 0;
+ outputItems[i] = getOutputItems();
+ outputFluids[i] = getOutputFluids();
}
- return this;
}
- public boolean process(int index) {
- if (recipeMap == null) {
- return false;
- }
- GT_Recipe recipe = recipeMap
- .findRecipe(tileEntity, false, false, availableEut[index], inputFluids[index], inputItems[index]);
- if (recipe == null) {
- return false;
- }
-
- GT_ParallelHelper helper = new GT_ParallelHelper().setRecipe(recipe)
- .setItemInputs(inputItems[index])
- .setFluidInputs(inputFluids[index])
- .setAvailableEUt(availableEut[index])
- .setMachine(tileEntity, isItemVoidProtected[index], isFluidVoidProtected[index])
- .setConsumption(true)
- .setOutputCalculation(true);
-
- helper.build();
-
- if (helper.getCurrentParallel() <= 0) {
- return false;
- }
-
- GT_OverclockCalculator calculator = new GT_OverclockCalculator().setRecipeEUt(recipe.mEUt)
- .setDuration(recipe.mDuration)
- .setEUt(availableEut[index]);
+ protected void output(int index) {
+ setOutputItems(getOutputItems(index));
+ setOutputFluids(getOutputFluids(index));
+ output();
+ }
- if (hasPerfectOverclock) {
- calculator.enablePerfectOC();
+ protected void reinitializeProcessingArrays() {
+ ItemStack[][] oldOutputItems = outputItems;
+ FluidStack[][] oldOutputFluids = outputFluids;
+ long[] oldCalculatedEutValues = calculatedEutValues;
+ int[] oldDurations = durations;
+ int[] oldProgresses = progresses;
+ outputItems = new ItemStack[maxComplexParallels][];
+ outputFluids = new FluidStack[maxComplexParallels][];
+ calculatedEutValues = new long[maxComplexParallels];
+ durations = new int[maxComplexParallels];
+ progresses = new int[maxComplexParallels];
+ for (int i = 0; i < oldOutputItems.length; i++) {
+ outputItems[i] = oldOutputItems[i];
}
-
- if (calculator.getConsumption() == Long.MAX_VALUE - 1 || calculator.getDuration() == Integer.MAX_VALUE - 1) {
- return false;
+ for (int i = 0; i < oldOutputFluids.length; i++) {
+ outputFluids[i] = oldOutputFluids[i];
}
-
- durations[index] = calculator.getDuration();
- eut[index] = calculator.getConsumption();
- outputItems[index] = helper.getItemOutputs();
- outputFluids[index] = helper.getFluidOutputs();
-
- return true;
- }
-
- public long getDuration(int index) {
- if (index >= 0 && index < maxComplexParallels) {
- return durations[index];
+ for (int i = 0; i < oldCalculatedEutValues.length; i++) {
+ calculatedEutValues[i] = oldCalculatedEutValues[i];
}
- return 0;
- }
-
- public long getTotalEU() {
- return LongStream.of(eut)
- .sum();
- }
-
- public ItemStack[] getOutputItems(int index) {
- if (index >= 0 && index < maxComplexParallels) {
- return outputItems[index];
+ for (int i = 0; i < oldDurations[i]; i++) {
+ durations[i] = oldDurations[i];
}
- return null;
- }
-
- public FluidStack[] getOutputFluids(int index) {
- if (index >= 0 && index < maxComplexParallels) {
- return outputFluids[index];
+ for (int i = 0; i < oldProgresses.length; i++) {
+ progresses[i] = oldProgresses[i];
}
- return null;
}
}
diff --git a/src/main/java/gregtech/api/logic/ControllerFluidLogic.java b/src/main/java/gregtech/api/logic/ControllerFluidLogic.java
new file mode 100644
index 0000000000..211c1c2982
--- /dev/null
+++ b/src/main/java/gregtech/api/logic/ControllerFluidLogic.java
@@ -0,0 +1,152 @@
+package gregtech.api.logic;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.Set;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraftforge.common.util.Constants;
+
+import org.apache.commons.lang3.tuple.Pair;
+
+/**
+ * Controller logic for Fluid inventories
+ *
+ * @author BlueWeabo
+ */
+public class ControllerFluidLogic {
+
+ private final Map<UUID, FluidInventoryLogic> inventories = new HashMap<>();
+ private final Set<Pair<UUID, FluidInventoryLogic>> unallocatedInventories = new HashSet<>();
+
+ public void addInventory(@Nonnull UUID id, @Nonnull FluidInventoryLogic inventory) {
+ Pair<UUID, FluidInventoryLogic> found = checkIfInventoryExistsAsUnallocated(inventory);
+ if (inventory.isUpgradeInventory() && found != null) {
+ unallocatedInventories.remove(found);
+ inventories.put(id, found.getRight());
+ return;
+ }
+ inventories.put(id, inventory);
+ }
+
+ @Nonnull
+ public UUID addInventory(@Nonnull FluidInventoryLogic inventory) {
+ Pair<UUID, FluidInventoryLogic> found = checkIfInventoryExistsAsUnallocated(inventory);
+ if (inventory.isUpgradeInventory() && found != null) {
+ unallocatedInventories.remove(found);
+ inventories.put(found.getLeft(), found.getRight());
+ return Objects.requireNonNull(found.getLeft());
+ }
+ UUID generatedUUID = Objects.requireNonNull(UUID.randomUUID());
+ inventories.put(generatedUUID, inventory);
+ return generatedUUID;
+ }
+
+ @Nullable
+ private Pair<UUID, FluidInventoryLogic> checkIfInventoryExistsAsUnallocated(
+ @Nonnull FluidInventoryLogic inventory) {
+ if (unallocatedInventories.size() == 0) {
+ return null;
+ }
+ return unallocatedInventories.stream()
+ .filter(
+ unallocated -> unallocated.getRight()
+ .getTier() == inventory.getTier())
+ .findFirst()
+ .get();
+ }
+
+ /**
+ * Removes the inventory with said id and gives it back to be processed if needed.
+ */
+ @Nonnull
+ public FluidInventoryLogic removeInventory(@Nonnull UUID id) {
+ return Objects.requireNonNull(inventories.remove(id));
+ }
+
+ @Nonnull
+ public FluidInventoryLogic getAllInventoryLogics() {
+ return new FluidInventoryLogic(
+ inventories.values()
+ .stream()
+ .map(inv -> inv.getInventory())
+ .collect(Collectors.toList()));
+ }
+
+ @Nonnull
+ public FluidInventoryLogic getInventoryLogic(@Nullable UUID id) {
+ if (id == null) return getAllInventoryLogics();
+ return Objects.requireNonNull(inventories.getOrDefault(id, getAllInventoryLogics()));
+ }
+
+ @Nonnull
+ public Set<Entry<UUID, FluidInventoryLogic>> getAllInventoryLogicsAsEntrySet() {
+ return Objects.requireNonNull(inventories.entrySet());
+ }
+
+ @Nonnull
+ public String getInventoryDisplayName(@Nullable UUID id) {
+ if (id == null) return "";
+ FluidInventoryLogic logic = inventories.get(id);
+ if (logic == null) return "";
+ String displayName = logic.getDisplayName();
+ if (displayName == null) return Objects.requireNonNull(id.toString());
+ return displayName;
+ }
+
+ public void setInventoryDisplayName(@Nullable UUID id, @Nullable String displayName) {
+ if (id == null) return;
+ FluidInventoryLogic logic = inventories.get(id);
+ if (logic == null) return;
+ logic.setDisplayName(displayName);
+ }
+
+ @Nonnull
+ public NBTTagCompound saveToNBT() {
+ NBTTagCompound nbt = new NBTTagCompound();
+ NBTTagList inventoriesNBT = new NBTTagList();
+ inventories.forEach((uuid, inventory) -> {
+ NBTTagCompound inventoryNBT = new NBTTagCompound();
+ inventoryNBT.setTag("inventory", inventory.saveToNBT());
+ inventoryNBT.setString("uuid", uuid.toString());
+ inventoryNBT.setInteger(
+ "invSize",
+ inventory.getInventory()
+ .getTanks());
+ inventoryNBT.setLong(
+ "tankCapacity",
+ inventory.getInventory()
+ .getTankCapacity(0));
+ inventoriesNBT.appendTag(inventoryNBT);
+ });
+ nbt.setTag("inventories", inventoriesNBT);
+ return nbt;
+ }
+
+ public void loadFromNBT(@Nonnull NBTTagCompound nbt) {
+ NBTTagList inventoriesNBT = nbt.getTagList("inventories", Constants.NBT.TAG_COMPOUND);
+ if (inventoriesNBT == null) return;
+ for (int i = 0; i < inventoriesNBT.tagCount(); i++) {
+ NBTTagCompound inventoryNBT = inventoriesNBT.getCompoundTagAt(i);
+ UUID uuid = UUID.fromString(inventoryNBT.getString("uuid"));
+ FluidInventoryLogic inventory = new FluidInventoryLogic(
+ inventoryNBT.getInteger("invSize"),
+ inventoryNBT.getLong("tankCapacity"));
+ inventory.loadFromNBT(inventoryNBT.getCompoundTag("inventory"));
+ if (inventory.isUpgradeInventory()) {
+ unallocatedInventories.add(Pair.of(uuid, inventory));
+ } else {
+ inventories.put(uuid, inventory);
+ }
+ }
+ }
+}
diff --git a/src/main/java/gregtech/api/logic/ControllerItemLogic.java b/src/main/java/gregtech/api/logic/ControllerItemLogic.java
new file mode 100644
index 0000000000..2863c2f49c
--- /dev/null
+++ b/src/main/java/gregtech/api/logic/ControllerItemLogic.java
@@ -0,0 +1,148 @@
+package gregtech.api.logic;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.Set;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraftforge.common.util.Constants;
+
+import org.apache.commons.lang3.tuple.Pair;
+
+/**
+ * Logic of the Item logic for the controller. This is controlling all of the inventories.
+ *
+ * @author BlueWeabo
+ */
+public class ControllerItemLogic {
+
+ private final Map<UUID, ItemInventoryLogic> inventories = new HashMap<>();
+ private final Set<Pair<UUID, ItemInventoryLogic>> unallocatedInventories = new HashSet<>();
+
+ public void addInventory(@Nonnull UUID id, @Nonnull ItemInventoryLogic inventory) {
+ Pair<UUID, ItemInventoryLogic> found = checkIfInventoryExistsAsUnallocated(inventory);
+ if (inventory.isUpgradeInventory() && found != null) {
+ unallocatedInventories.remove(found);
+ inventories.put(id, found.getRight());
+ return;
+ }
+ inventories.put(id, inventory);
+ }
+
+ @Nonnull
+ public UUID addInventory(@Nonnull ItemInventoryLogic inventory) {
+ Pair<UUID, ItemInventoryLogic> found = checkIfInventoryExistsAsUnallocated(inventory);
+ if (inventory.isUpgradeInventory() && found != null) {
+ unallocatedInventories.remove(found);
+ inventories.put(found.getLeft(), found.getRight());
+ return Objects.requireNonNull(found.getLeft());
+ }
+ UUID generatedUUID = Objects.requireNonNull(UUID.randomUUID());
+ inventories.put(generatedUUID, inventory);
+ return generatedUUID;
+ }
+
+ @Nullable
+ private Pair<UUID, ItemInventoryLogic> checkIfInventoryExistsAsUnallocated(@Nonnull ItemInventoryLogic inventory) {
+ if (unallocatedInventories.size() == 0) {
+ return null;
+ }
+ return unallocatedInventories.stream()
+ .filter(
+ unallocated -> unallocated.getRight()
+ .getTier() == inventory.getTier()
+ && unallocated.getRight()
+ .getSlots() == inventory.getSlots())
+ .findFirst()
+ .get();
+ }
+
+ /**
+ * Removes the inventory with said id and gives it back to be processed if needed.
+ */
+ @Nonnull
+ public ItemInventoryLogic removeInventory(@Nonnull UUID id) {
+ return Objects.requireNonNull(inventories.remove(id));
+ }
+
+ @Nonnull
+ public ItemInventoryLogic getAllInventoryLogics() {
+ return new ItemInventoryLogic(
+ inventories.values()
+ .stream()
+ .map(inv -> inv.getInventory())
+ .collect(Collectors.toList()));
+ }
+
+ @Nonnull
+ public ItemInventoryLogic getInventoryLogic(@Nullable UUID id) {
+ if (id == null) return getAllInventoryLogics();
+ return Objects.requireNonNull(inventories.getOrDefault(id, getAllInventoryLogics()));
+ }
+
+ @Nonnull
+ public Set<Entry<UUID, ItemInventoryLogic>> getAllInventoryLogicsAsEntrySet() {
+ return Objects.requireNonNull(inventories.entrySet());
+ }
+
+ @Nullable
+ public String getInventoryDisplayName(@Nullable UUID id) {
+ if (id == null) return "";
+ ItemInventoryLogic logic = inventories.get(id);
+ if (logic == null) return "";
+ String displayName = logic.getDisplayName();
+ if (displayName == null) return Objects.requireNonNull(id.toString());
+ return displayName;
+ }
+
+ public void setInventoryDisplayName(@Nullable UUID id, @Nullable String displayName) {
+ if (id == null) return;
+ ItemInventoryLogic logic = inventories.get(id);
+ if (logic == null) return;
+ logic.setDisplayName(displayName);
+ }
+
+ @Nonnull
+ public NBTTagCompound saveToNBT() {
+ NBTTagCompound nbt = new NBTTagCompound();
+ NBTTagList inventoriesNBT = new NBTTagList();
+ inventories.forEach((uuid, inventory) -> {
+ NBTTagCompound inventoryNBT = new NBTTagCompound();
+ inventoryNBT.setTag("inventory", inventory.saveToNBT());
+ inventoryNBT.setString("uuid", uuid.toString());
+ inventoryNBT.setInteger(
+ "invSize",
+ inventory.getInventory()
+ .getSlots());
+ inventoriesNBT.appendTag(inventoryNBT);
+ });
+ nbt.setTag("inventories", inventoriesNBT);
+ return nbt;
+ }
+
+ public void loadFromNBT(@Nonnull NBTTagCompound nbt) {
+ NBTTagList inventoriesNBT = nbt.getTagList("inventories", Constants.NBT.TAG_COMPOUND);
+ if (inventoriesNBT == null) return;
+ for (int i = 0; i < inventoriesNBT.tagCount(); i++) {
+ NBTTagCompound inventoryNBT = inventoriesNBT.getCompoundTagAt(i);
+ UUID uuid = UUID.fromString(inventoryNBT.getString("uuid"));
+ ItemInventoryLogic inventory = new ItemInventoryLogic(inventoryNBT.getInteger("invSize"));
+ NBTTagCompound internalInventoryNBT = inventoryNBT.getCompoundTag("inventory");
+ if (internalInventoryNBT != null) inventory.loadFromNBT(internalInventoryNBT);
+ if (inventory.isUpgradeInventory()) {
+ unallocatedInventories.add(Pair.of(uuid, inventory));
+ } else {
+ inventories.put(uuid, inventory);
+ }
+ }
+ }
+}
diff --git a/src/main/java/gregtech/api/logic/FluidInventoryLogic.java b/src/main/java/gregtech/api/logic/FluidInventoryLogic.java
new file mode 100644
index 0000000000..88c0c954ec
--- /dev/null
+++ b/src/main/java/gregtech/api/logic/FluidInventoryLogic.java
@@ -0,0 +1,269 @@
+package gregtech.api.logic;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraftforge.common.util.Constants;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidStack;
+
+import com.gtnewhorizons.modularui.api.fluids.FluidTanksHandler;
+import com.gtnewhorizons.modularui.api.fluids.IFluidTankLong;
+import com.gtnewhorizons.modularui.api.fluids.IFluidTanksHandler;
+import com.gtnewhorizons.modularui.api.fluids.ListFluidHandler;
+import com.gtnewhorizons.modularui.api.math.Size;
+import com.gtnewhorizons.modularui.api.widget.Widget;
+import com.gtnewhorizons.modularui.common.widget.FluidSlotWidget;
+import com.gtnewhorizons.modularui.common.widget.Scrollable;
+
+/**
+ * Generic Fluid logic for MuTEs.
+ *
+ * @author BlueWeabo
+ */
+public class FluidInventoryLogic {
+
+ private static final int DEFAULT_COLUMNS_PER_ROW = 4;
+ private static final int POSITION_INTERVAL = 18;
+ private static final Size SIZE = new Size(18, 18);
+
+ protected String displayName = "";
+ @Nonnull
+ protected final IFluidTanksHandler inventory;
+ protected final Map<Fluid, IFluidTankLong> fluidToTankMap;
+ protected int tier = 0;
+ protected boolean isUpgradeInventory = false;
+
+ public FluidInventoryLogic(int numberOfSlots, long capacityOfEachTank) {
+ this(new FluidTanksHandler(numberOfSlots, capacityOfEachTank), 0, false);
+ }
+
+ public FluidInventoryLogic(int numberOfSlots, long capacityOfEachTank, int tier) {
+ this(new FluidTanksHandler(numberOfSlots, capacityOfEachTank), tier, false);
+ }
+
+ public FluidInventoryLogic(int numberOfSlots, long capacityOfEachTank, int tier, boolean isUpgradeInventory) {
+ this(new FluidTanksHandler(numberOfSlots, capacityOfEachTank), tier, isUpgradeInventory);
+ }
+
+ public FluidInventoryLogic(@Nonnull IFluidTanksHandler inventory, int tier, boolean isUpgradeInventory) {
+ this.inventory = inventory;
+ fluidToTankMap = new HashMap<>(inventory.getTanks());
+ this.tier = tier;
+ this.isUpgradeInventory = isUpgradeInventory;
+ }
+
+ public FluidInventoryLogic(Collection<IFluidTanksHandler> inventories) {
+ this(new ListFluidHandler(inventories), -1, false);
+ }
+
+ @Nullable
+ public String getDisplayName() {
+ return displayName;
+ }
+
+ public int getTier() {
+ return tier;
+ }
+
+ public boolean isUpgradeInventory() {
+ return isUpgradeInventory;
+ }
+
+ public void setDisplayName(@Nullable String displayName) {
+ this.displayName = displayName;
+ }
+
+ /**
+ *
+ * @return The Fluid Inventory Logic as an NBTTagList to be saved in another nbt as how one wants.
+ */
+ @Nonnull
+ public NBTTagCompound saveToNBT() {
+ final NBTTagCompound nbt = new NBTTagCompound();
+ final NBTTagList tList = new NBTTagList();
+ for (int tankNumber = 0; tankNumber < inventory.getTanks(); tankNumber++) {
+ final IFluidTankLong tank = inventory.getFluidTank(tankNumber);
+ if (tank == null) continue;
+
+ final NBTTagCompound tag = new NBTTagCompound();
+ tag.setByte("s", (byte) tankNumber);
+ tank.saveToNBT(tag);
+ tList.appendTag(tag);
+ }
+ nbt.setTag("inventory", tList);
+ nbt.setInteger("tier", tier);
+ if (displayName != null) {
+ nbt.setString("displayName", displayName);
+ }
+ nbt.setBoolean("isUpgradeInventory", isUpgradeInventory);
+ return nbt;
+ }
+
+ /**
+ * Loads the Item Inventory Logic from an NBTTagList.
+ */
+ public void loadFromNBT(@Nonnull NBTTagCompound nbt) {
+ NBTTagList nbtList = nbt.getTagList("inventory", Constants.NBT.TAG_COMPOUND);
+ for (int i = 0; i < nbtList.tagCount(); i++) {
+ final NBTTagCompound tankNBT = nbtList.getCompoundTagAt(i);
+ final int tank = tankNBT.getShort("s");
+ if (tank >= 0 && tank < inventory.getTanks()) inventory.getFluidTank(tank)
+ .loadFromNBT(tankNBT);
+ if (inventory.getFluidInTank(tank) != null) {
+ fluidToTankMap.put(inventory.getFluidInTank(tank), inventory.getFluidTank(tank));
+ }
+ }
+ tier = nbt.getInteger("tier");
+ if (nbt.hasKey("displayName")) {
+ displayName = nbt.getString("displayName");
+ }
+ isUpgradeInventory = nbt.getBoolean("isUpgradeInventory");
+ }
+
+ @Nonnull
+ public IFluidTanksHandler getInventory() {
+ return inventory;
+ }
+
+ @Nonnull
+ public FluidStack[] getStoredFluids() {
+ final FluidStack[] fluids = inventory.getFluids()
+ .stream()
+ .filter(fluid -> fluid != null)
+ .collect(Collectors.toList())
+ .toArray(new FluidStack[0]);
+ if (fluids == null) {
+ return new FluidStack[0];
+ }
+ return fluids;
+ }
+
+ public boolean isFluidValid(@Nullable Fluid fluid) {
+ return fluid != null;
+ }
+
+ /**
+ * @param fluid What we are trying to input
+ * @param amount amount of fluid we are trying to put
+ * @return amount of fluid filled into the tank
+ */
+ public long fill(@Nullable Fluid fluid, long amount, boolean simulate) {
+ if (!isFluidValid(fluid)) return 0;
+ IFluidTankLong tank = fluidToTankMap.get(fluid);
+ if (tank != null) {
+ return tank.fill(fluid, amount, !simulate);
+ }
+ int tankNumber = 0;
+ tank = inventory.getFluidTank(tankNumber++);
+ while (tank.getStoredFluid() != fluid && tank.getStoredFluid() != null) {
+ tank = inventory.getFluidTank(tankNumber++);
+ }
+ fluidToTankMap.put(fluid, tank);
+ return tank.fill(fluid, amount, !simulate);
+ }
+
+ @Nullable
+ public FluidStack fill(@Nullable FluidStack fluid) {
+ if (fluid == null) return null;
+ for (int i = 0; i < inventory.getTanks(); i++) {
+ fill(fluid.getFluid(), fluid.amount, false);
+ }
+ return fluid;
+ }
+
+ /**
+ * Try and drain the first fluid found for that amount. Used by GT_Cover_Pump
+ *
+ * @param amount Fluid to drain from the tank
+ * @return A fluidstack with the possible amount drained
+ */
+ @Nullable
+ public FluidStack drain(long amount, boolean simulate) {
+ for (int i = 0; i < inventory.getTanks(); i++) {
+ Fluid fluid = inventory.getFluidInTank(i);
+ FluidStack drained = drain(fluid, amount, simulate);
+ if (drained != null) return drained;
+ }
+
+ return null;
+ }
+
+ @Nullable
+ public FluidStack drain(Fluid fluid, long amount, boolean simulate) {
+ if (!isFluidValid(fluid)) return null;
+ IFluidTankLong tank = fluidToTankMap.get(fluid);
+ if (tank != null) {
+ return tank.drain(amount, !simulate);
+ }
+ int tankNumber = 0;
+ tank = inventory.getFluidTank(tankNumber++);
+ while (tank.getStoredFluid() != fluid) {
+ tank = inventory.getFluidTank(tankNumber++);
+ }
+ fluidToTankMap.put(fluid, tank);
+ return tank.drain(amount, !simulate);
+ }
+
+ public void update() {
+ for (int i = 0; i < inventory.getTanks(); i++) {
+ IFluidTankLong tank = inventory.getFluidTank(i);
+ if (tank.getFluidAmountLong() > 0) continue;
+ tank.setFluid(null, 0);
+ }
+ }
+
+ public long calculateAmountOfTimesFluidCanBeTaken(Fluid fluid, long amountToTake) {
+ if (!isFluidValid(fluid)) return 0;
+ IFluidTankLong tank = fluidToTankMap.get(fluid);
+ if (tank == null) return 0;
+ return tank.getFluidAmountLong() / amountToTake;
+ }
+
+ @Nonnull
+ public Map<Fluid, Long> getMapOfStoredFluids() {
+ Map<Fluid, Long> map = new HashMap<>();
+ for (int i = 0; i < inventory.getTanks(); i++) {
+ IFluidTankLong tank = inventory.getFluidTank(i);
+ if (tank == null) continue;
+ Fluid fluid = tank.getStoredFluid();
+ if (fluid == null) continue;
+ map.put(fluid, map.getOrDefault(fluid, 0L) + tank.getFluidAmountLong());
+ }
+ return map;
+ }
+
+ /**
+ * Return a scrollable widget with only the inventory.
+ */
+ @Nonnull
+ public Widget getGuiPart() {
+ return getGUIPart(DEFAULT_COLUMNS_PER_ROW);
+ }
+
+ /**
+ * Return a scrollable widget with only the inventory.
+ */
+ @Nonnull
+ public Widget getGUIPart(int columnsPerRow) {
+ final Scrollable scrollable = new Scrollable();
+ scrollable.setVerticalScroll();
+ for (int rows = 0; rows * 4 < inventory.getTanks(); rows++) {
+ final int columnsToMake = Math.min(inventory.getTanks() - rows * 4, 4);
+ for (int column = 0; column < columnsToMake; column++) {
+ final FluidSlotWidget fluidSlot = new FluidSlotWidget(inventory, rows * 4 + column);
+ scrollable.widget(
+ fluidSlot.setPos(column * POSITION_INTERVAL, rows * POSITION_INTERVAL)
+ .setSize(SIZE));
+ }
+ }
+ return scrollable;
+ }
+}
diff --git a/src/main/java/gregtech/api/logic/ItemInventoryLogic.java b/src/main/java/gregtech/api/logic/ItemInventoryLogic.java
new file mode 100644
index 0000000000..69005216b8
--- /dev/null
+++ b/src/main/java/gregtech/api/logic/ItemInventoryLogic.java
@@ -0,0 +1,314 @@
+package gregtech.api.logic;
+
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraftforge.common.util.Constants;
+
+import com.gtnewhorizons.modularui.api.forge.IItemHandlerModifiable;
+import com.gtnewhorizons.modularui.api.forge.ItemStackHandler;
+import com.gtnewhorizons.modularui.api.forge.ListItemHandler;
+import com.gtnewhorizons.modularui.api.math.Size;
+import com.gtnewhorizons.modularui.api.widget.Widget;
+import com.gtnewhorizons.modularui.common.widget.Scrollable;
+import com.gtnewhorizons.modularui.common.widget.SlotWidget;
+
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.item.ItemHolder;
+
+/**
+ * Generic Item logic for MuTEs.
+ *
+ * @author BlueWeabo
+ */
+public class ItemInventoryLogic {
+
+ private static final int DEFAULT_COLUMNS_PER_ROW = 4;
+ private static final int POSITION_INTERVAL = 18;
+ private static final Size SIZE = new Size(18, 18);
+
+ protected String displayName;
+ @Nonnull
+ protected final IItemHandlerModifiable inventory;
+ protected UUID connectedFluidInventory;
+ protected int tier;
+ protected boolean isUpgradeInventory;
+ protected Map<ItemHolder, Long> cachedItemMap;
+ protected boolean inRecipeCheck;
+
+ public ItemInventoryLogic(int numberOfSlots) {
+ this(numberOfSlots, 0);
+ }
+
+ public ItemInventoryLogic(int numberOfSlots, int tier) {
+ this(new ItemStackHandler(numberOfSlots), tier, false);
+ }
+
+ public ItemInventoryLogic(int numberOfSlots, int tier, boolean isUpgradeInventory) {
+ this(new ItemStackHandler(numberOfSlots), tier, isUpgradeInventory);
+ }
+
+ public ItemInventoryLogic(@Nonnull IItemHandlerModifiable inventory, int tier, boolean isUpgradeInventory) {
+ this.inventory = inventory;
+ this.tier = tier;
+ this.isUpgradeInventory = isUpgradeInventory;
+ }
+
+ public ItemInventoryLogic(Collection<IItemHandlerModifiable> inventories) {
+ this(new ListItemHandler(inventories), -1, false);
+ }
+
+ @Nullable
+ public String getDisplayName() {
+ return displayName;
+ }
+
+ public int getTier() {
+ return tier;
+ }
+
+ public boolean isUpgradeInventory() {
+ return isUpgradeInventory;
+ }
+
+ public int getSlots() {
+ return getInventory().getSlots();
+ }
+
+ public void setDisplayName(@Nullable String displayName) {
+ this.displayName = displayName;
+ }
+
+ @Nullable
+ public UUID getConnectedFluidInventoryID() {
+ return connectedFluidInventory;
+ }
+
+ public void setConnectedFluidInventoryID(@Nullable UUID connectedFluidTank) {
+ this.connectedFluidInventory = connectedFluidTank;
+ }
+
+ /**
+ *
+ * @return The Item Inventory Logic as an NBTTagCompound to be saved in another nbt as how one wants.
+ */
+ @Nonnull
+ public NBTTagCompound saveToNBT() {
+ final NBTTagCompound nbt = new NBTTagCompound();
+ final NBTTagList tList = new NBTTagList();
+ for (int slot = 0; slot < inventory.getSlots(); slot++) {
+ final ItemStack tStack = inventory.getStackInSlot(slot);
+ if (tStack == null) continue;
+
+ final NBTTagCompound tag = new NBTTagCompound();
+ tag.setByte("s", (byte) slot);
+ tStack.writeToNBT(tag);
+ tList.appendTag(tag);
+ }
+ nbt.setTag("inventory", tList);
+ nbt.setInteger("tier", tier);
+ if (displayName != null) {
+ nbt.setString("displayName", displayName);
+ }
+ nbt.setBoolean("isUpgradeInventory", isUpgradeInventory);
+ if (connectedFluidInventory != null) {
+ nbt.setString("connectedFluidInventory", connectedFluidInventory.toString());
+ }
+ return nbt;
+ }
+
+ /**
+ * Loads the Item Inventory Logic from an NBTTagCompound.
+ */
+ public void loadFromNBT(@Nonnull NBTTagCompound nbt) {
+ tier = nbt.getInteger("tier");
+ if (nbt.hasKey("displayName")) {
+ displayName = nbt.getString("displayName");
+ }
+
+ isUpgradeInventory = nbt.getBoolean("isUpgradeInventory");
+ if (nbt.hasKey("connectedFluidInventory")) {
+ connectedFluidInventory = UUID.fromString(nbt.getString("connectedFluidInventory"));
+ }
+
+ NBTTagList nbtList = nbt.getTagList("inventory", Constants.NBT.TAG_COMPOUND);
+ if (nbtList == null) return;
+
+ for (int i = 0; i < nbtList.tagCount(); i++) {
+ final NBTTagCompound tNBT = nbtList.getCompoundTagAt(i);
+ final int tSlot = tNBT.getShort("s");
+ if (tSlot >= 0 && tSlot < inventory.getSlots()) {
+ inventory.setStackInSlot(tSlot, GT_Utility.loadItem(tNBT));
+ }
+ }
+ }
+
+ @Nonnull
+ public IItemHandlerModifiable getInventory() {
+ return inventory;
+ }
+
+ @Nonnull
+ public ItemStack[] getStoredItems() {
+ final ItemStack[] items = inventory.getStacks()
+ .stream()
+ .filter(item -> item != null)
+ .collect(Collectors.toList())
+ .toArray(new ItemStack[0]);
+ if (items == null) {
+ return new ItemStack[0];
+ }
+ return items;
+ }
+
+ public boolean isStackValid(ItemStack item) {
+ return true;
+ }
+
+ @Nullable
+ public ItemStack insertItem(ItemStack item) {
+ if (!isStackValid(item)) return item;
+ for (int i = 0; i < inventory.getSlots() && item != null && item.stackSize > 0; i++) {
+ item = inventory.insertItem(i, item, false);
+ }
+ return item;
+ }
+
+ @Nullable
+ public ItemStack extractItem(int slot, int amount) {
+ return inventory.extractItem(slot, amount, false);
+ }
+
+ public boolean subtractItemAmount(@Nonnull ItemHolder item, long amount, boolean simulate) {
+ Map<ItemHolder, Long> itemMap = getMapOfStoredItems();
+ if (!itemMap.containsKey(item)) {
+ return false;
+ }
+
+ if (itemMap.get(item) < amount) {
+ return false;
+ }
+
+ if (simulate) {
+ return true;
+ }
+
+ itemMap.put(item, itemMap.get(item) - amount);
+ return true;
+ }
+
+ @Nullable
+ public ItemStack getItemInSlot(int slot) {
+ return inventory.getStackInSlot(slot);
+ }
+
+ public void sort() {
+ Map<ItemHolder, Long> itemMap = getMapOfStoredItems();
+ List<ItemHolder> sortedItems = itemMap.keySet()
+ .stream()
+ .sorted(
+ Comparator.comparing(
+ a -> a.getItem()
+ .getUnlocalizedName() + a.getMeta()))
+ .collect(Collectors.toList());
+ putInItemsFromMap(itemMap, sortedItems);
+ }
+
+ public void update(boolean shouldSort) {
+ if (shouldSort) {
+ sort();
+ }
+
+ for (int i = 0; i < inventory.getSlots(); i++) {
+ ItemStack item = inventory.getStackInSlot(i);
+ if (item == null) continue;
+ if (item.stackSize > 0) continue;
+ inventory.setStackInSlot(i, null);
+ }
+ }
+
+ /**
+ * Return a scrollable widget with only the inventory.
+ */
+ @Nonnull
+ public Widget getGuiPart() {
+ return getGUIPart(DEFAULT_COLUMNS_PER_ROW);
+ }
+
+ /**
+ * Return a scrollable widget with only the inventory.
+ */
+ @Nonnull
+ public Widget getGUIPart(int columnsPerRow) {
+ final Scrollable scrollable = new Scrollable();
+ scrollable.setVerticalScroll();
+ for (int rows = 0; rows * columnsPerRow < Math.min(inventory.getSlots(), 128); rows++) {
+ final int columnsToMake = Math
+ .min(Math.min(inventory.getSlots(), 128) - rows * columnsPerRow, columnsPerRow);
+ for (int column = 0; column < columnsToMake; column++) {
+ scrollable.widget(
+ new SlotWidget(inventory, rows * columnsPerRow + column)
+ .setPos(column * POSITION_INTERVAL, rows * POSITION_INTERVAL)
+ .setSize(SIZE));
+ }
+ }
+ return scrollable;
+ }
+
+ public void startRecipeCheck() {
+ cachedItemMap = getMapOfStoredItems();
+ inRecipeCheck = true;
+ }
+
+ public void stopRecipeCheck() {
+ inRecipeCheck = false;
+ putInItemsFromMap(cachedItemMap, null);
+ cachedItemMap = null;
+ }
+
+ @Nonnull
+ public Map<ItemHolder, Long> getMapOfStoredItems() {
+ if (inRecipeCheck) return cachedItemMap;
+ Map<ItemHolder, Long> items = new HashMap<>();
+ for (int i = 0; i < inventory.getSlots(); i++) {
+ ItemStack item = extractItem(i, Integer.MAX_VALUE);
+ if (item == null) continue;
+ ItemHolder itemHolder = new ItemHolder(item);
+ items.put(itemHolder, items.getOrDefault(itemHolder, 0L) + item.stackSize);
+ }
+ return items;
+ }
+
+ protected void putInItemsFromMap(@Nonnull Map<ItemHolder, Long> itemMap, @Nullable List<ItemHolder> sortedList) {
+ for (ItemHolder itemHolder : (sortedList == null ? itemMap.keySet() : sortedList)) {
+ long itemAmount = itemMap.get(itemHolder);
+ ItemStack item = new ItemStack(itemHolder.getItem(), 0, itemHolder.getMeta());
+ item.setTagCompound(itemHolder.getNBT());
+ while (itemAmount > 0) {
+ item.stackSize = (int) Math.min(item.getMaxStackSize(), itemAmount);
+ itemAmount -= item.stackSize;
+ insertItem(item);
+ }
+ }
+ }
+
+ public long calculateAmountOfTimesItemCanBeTaken(ItemHolder item, long amount) {
+ return getMapOfStoredItems().getOrDefault(item, 0L) / amount;
+ }
+
+ public Set<ItemHolder> getSetOfStoredItems() {
+ return getMapOfStoredItems().keySet();
+ }
+}
diff --git a/src/main/java/gregtech/api/logic/MuTEProcessingLogic.java b/src/main/java/gregtech/api/logic/MuTEProcessingLogic.java
new file mode 100644
index 0000000000..da53c8875d
--- /dev/null
+++ b/src/main/java/gregtech/api/logic/MuTEProcessingLogic.java
@@ -0,0 +1,256 @@
+package gregtech.api.logic;
+
+import static net.minecraftforge.common.util.Constants.NBT.TAG_COMPOUND;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.UUID;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraftforge.fluids.FluidStack;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.widget.Widget;
+import com.gtnewhorizons.modularui.common.widget.Scrollable;
+
+import gregtech.api.enums.InventoryType;
+import gregtech.api.logic.interfaces.ProcessingLogicHost;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.util.GT_OverclockCalculator;
+import gregtech.api.util.GT_ParallelHelper;
+import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.GT_Utility;
+
+/**
+ * Processing logic class, dedicated for MultiTileEntities.
+ */
+public class MuTEProcessingLogic<P extends MuTEProcessingLogic<P>> extends AbstractProcessingLogic<P> {
+
+ protected boolean hasWork;
+ protected int progress;
+ protected ProcessingLogicHost<P> machineHost;
+ @Nonnull
+ protected CheckRecipeResult recipeResult = CheckRecipeResultRegistry.NONE;
+ @Nullable
+ protected UUID itemOutputID;
+ @Nullable
+ protected UUID fluidOutputID;
+
+ public P setMachineHost(@Nonnull ProcessingLogicHost<P> machineHost) {
+ this.machineHost = machineHost;
+ return getThis();
+ }
+
+ // #region Logic
+
+ @Nonnull
+ @Override
+ public CheckRecipeResult process() {
+ RecipeMap<?> recipeMap = preProcess();
+
+ ItemInventoryLogic itemInput = null;
+ FluidInventoryLogic fluidInput = null;
+ if (machineHost.isInputSeparated()) {
+ for (Map.Entry<UUID, ItemInventoryLogic> itemEntry : machineHost
+ .getAllItemInventoryLogics(InventoryType.Input)) {
+ itemOutputID = Objects.requireNonNull(itemEntry.getKey());
+ itemInput = Objects.requireNonNull(itemEntry.getValue());
+ fluidInput = Objects.requireNonNull(
+ machineHost.getFluidLogic(InventoryType.Input, itemInput.getConnectedFluidInventoryID()));
+ fluidOutputID = itemInput.getConnectedFluidInventoryID();
+ }
+ } else {
+ itemInput = Objects.requireNonNull(machineHost.getItemLogic(InventoryType.Input, null));
+ fluidInput = Objects.requireNonNull(machineHost.getFluidLogic(InventoryType.Input, null));
+ }
+
+ CheckRecipeResult recipeValidatorResult = null;
+ if (recipeValidatorResult != null) {
+ return recipeValidatorResult;
+ }
+
+ return processRecipe(null, Objects.requireNonNull(itemInput), Objects.requireNonNull(fluidInput));
+ }
+
+ @Nonnull
+ protected CheckRecipeResult processRecipe(@Nonnull List<GT_Recipe> recipes, @Nonnull ItemInventoryLogic itemInput,
+ @Nonnull FluidInventoryLogic fluidInput) {
+ CheckRecipeResult result = CheckRecipeResultRegistry.INTERNAL_ERROR;
+ for (GT_Recipe recipe : recipes) {
+ Objects.requireNonNull(recipe);
+ GT_ParallelHelper helper = createParallelHelper(recipe, itemInput, fluidInput);
+ GT_OverclockCalculator calculator = createOverclockCalculator(recipe);
+ helper.setCalculator(calculator);
+ helper.build();
+ result = helper.getResult();
+ if (result.wasSuccessful()) {
+ return applyRecipe(recipe, helper, calculator, result);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Override if you don't work with regular gt recipe maps
+ */
+ @Nonnull
+ protected Object findRecipe(@Nullable RecipeMap<?> map, @Nonnull ItemInventoryLogic itemInput,
+ @Nonnull FluidInventoryLogic fluidInput) {
+ if (map == null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Nonnull
+ protected GT_ParallelHelper createParallelHelper(@Nonnull GT_Recipe recipe, @Nonnull ItemInventoryLogic itemInput,
+ @Nonnull FluidInventoryLogic fluidInput) {
+ return new GT_ParallelHelper().setRecipe(recipe)
+ .setItemInputInventory(itemInput)
+ .setFluidInputInventory(fluidInput)
+ .setAvailableEUt(availableVoltage * availableAmperage)
+ .setMaxParallel(maxParallel)
+ .setEUtModifier(euModifier)
+ .enableBatchMode(batchSize)
+ .setConsumption(true)
+ .setOutputCalculation(true)
+ .setMuTEMode(true);
+ }
+
+ // #endregion
+
+ // #region Getters
+
+ @Nonnull
+ public CheckRecipeResult getResult() {
+ return recipeResult;
+ }
+
+ public int getProgress() {
+ return progress;
+ }
+
+ // #endregion
+
+ // #region Other
+
+ public void startCheck() {
+ recipeResult = process();
+ }
+
+ public void progress() {
+ if (!hasWork) return;
+ if (progress == duration) {
+ progress = 0;
+ duration = 0;
+ calculatedEut = 0;
+ output();
+ return;
+ }
+ progress++;
+ }
+
+ protected void output() {
+ ItemInventoryLogic itemOutput = machineHost.getItemLogic(InventoryType.Output, itemOutputID);
+ FluidInventoryLogic fluidOutput = machineHost.getFluidLogic(InventoryType.Output, fluidOutputID);
+ if (itemOutput == null || fluidOutput == null) return;
+ for (ItemStack item : outputItems) {
+ if (item == null) continue;
+ itemOutput.insertItem(item);
+ }
+ for (FluidStack fluid : outputFluids) {
+ if (fluid == null) continue;
+ fluidOutput.fill(fluid.getFluid(), fluid.amount, false);
+ }
+ outputItems = new ItemStack[0];
+ outputFluids = new FluidStack[0];
+ }
+
+ public boolean canWork() {
+ return !hasWork && machineHost.isAllowedToWork();
+ }
+
+ /**
+ * By how much to increase the progress?
+ *
+ * @param progressAmount in ticks
+ */
+ public void increaseProgress(int progressAmount) {
+ progress += progressAmount;
+ }
+
+ public NBTTagCompound saveToNBT() {
+ NBTTagCompound logicNBT = new NBTTagCompound();
+ logicNBT.setLong("eutConsumption", calculatedEut);
+ logicNBT.setInteger("duration", duration);
+ logicNBT.setInteger("progress", progress);
+ logicNBT.setBoolean("hasWork", hasWork);
+ if (outputItems != null) {
+ NBTTagList itemOutputsNBT = new NBTTagList();
+ for (ItemStack item : outputItems) {
+ itemOutputsNBT.appendTag(GT_Utility.saveItem(item));
+ }
+ logicNBT.setTag("itemOutputs", itemOutputsNBT);
+ }
+ if (outputFluids != null) {
+ NBTTagList fluidOutputsNBT = new NBTTagList();
+ for (FluidStack fluid : outputFluids) {
+ fluidOutputsNBT.appendTag(fluid.writeToNBT(new NBTTagCompound()));
+ }
+ logicNBT.setTag("fluidOutputs", fluidOutputsNBT);
+ }
+ if (itemOutputID != null) {
+ logicNBT.setString("itemOutputID", itemOutputID.toString());
+ }
+ if (fluidOutputID != null) {
+ logicNBT.setString("fluidOutputID", fluidOutputID.toString());
+ }
+ return logicNBT;
+ }
+
+ public void loadFromNBT(@Nonnull NBTTagCompound logicNBT) {
+ calculatedEut = logicNBT.getLong("eutConsumption");
+ duration = logicNBT.getInteger("duration");
+ progress = logicNBT.getInteger("progress");
+ hasWork = logicNBT.getBoolean("hasWork");
+ if (logicNBT.hasKey("itemOutputs")) {
+ NBTTagList itemOutputsNBT = logicNBT.getTagList("itemOutputs", TAG_COMPOUND);
+ outputItems = new ItemStack[itemOutputsNBT.tagCount()];
+ for (int i = 0; i < itemOutputsNBT.tagCount(); i++) {
+ outputItems[i] = GT_Utility.loadItem(itemOutputsNBT.getCompoundTagAt(i));
+ }
+ }
+ if (logicNBT.hasKey("fluidOutputs")) {
+ NBTTagList fluidOutputsNBT = logicNBT.getTagList("fluidOutputs", TAG_COMPOUND);
+ outputFluids = new FluidStack[fluidOutputsNBT.tagCount()];
+ for (int i = 0; i < fluidOutputsNBT.tagCount(); i++) {
+ outputFluids[i] = FluidStack.loadFluidStackFromNBT(fluidOutputsNBT.getCompoundTagAt(i));
+ }
+ }
+ if (logicNBT.hasKey("itemOutputID")) {
+ itemOutputID = UUID.fromString(logicNBT.getString("itemOutputID"));
+ }
+ if (logicNBT.hasKey("fluidOutputID")) {
+ fluidOutputID = UUID.fromString(logicNBT.getString("fluidOutputID"));
+ }
+ }
+
+ /**
+ * Returns a gui part, which will be displayed in a separate tab on the machine's gui.
+ */
+ @Nonnull
+ public Widget getGUIPart(ModularWindow.Builder builder) {
+ return new Scrollable();
+ }
+
+ // #endregion
+}
diff --git a/src/main/java/gregtech/api/logic/NullPowerLogic.java b/src/main/java/gregtech/api/logic/NullPowerLogic.java
new file mode 100644
index 0000000000..0017f0e647
--- /dev/null
+++ b/src/main/java/gregtech/api/logic/NullPowerLogic.java
@@ -0,0 +1,5 @@
+package gregtech.api.logic;
+
+public class NullPowerLogic extends PowerLogic {
+
+}
diff --git a/src/main/java/gregtech/api/logic/PollutionLogic.java b/src/main/java/gregtech/api/logic/PollutionLogic.java
deleted file mode 100644
index 8e1172e105..0000000000
--- a/src/main/java/gregtech/api/logic/PollutionLogic.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package gregtech.api.logic;
-
-public class PollutionLogic {
-
- private int pollutionAmount;
-
- public PollutionLogic() {}
-
- public PollutionLogic setPollutionAmount(int pollutionAmount) {
- this.pollutionAmount = pollutionAmount;
- return this;
- }
-
- public int getPollutionAmount() {
- return pollutionAmount;
- }
-}
diff --git a/src/main/java/gregtech/api/logic/PowerLogic.java b/src/main/java/gregtech/api/logic/PowerLogic.java
index ac12ef8917..ad19987a76 100644
--- a/src/main/java/gregtech/api/logic/PowerLogic.java
+++ b/src/main/java/gregtech/api/logic/PowerLogic.java
@@ -1,54 +1,97 @@
package gregtech.api.logic;
+import static gregtech.common.misc.WirelessNetworkManager.addEUToGlobalEnergyMap;
+
+import java.util.UUID;
+
+import javax.annotation.Nonnull;
+
import net.minecraft.nbt.NBTTagCompound;
import gregtech.api.enums.GT_Values.NBT;
+/**
+ * Power logic for machines. This is used to store all the important variables for a machine to have energy and use it
+ * in any way.
+ *
+ * @author BlueWeabo, Maxim
+ */
public class PowerLogic {
- public static int NONE = 0;
- public static int RECEIVER = 1;
- public static int EMITTER = 2;
- public static int BOTH = RECEIVER | EMITTER;
+ public static final int NONE = 0;
+ public static final int RECEIVER = 1;
+ public static final int EMITTER = 2;
+ public static final int BOTH = RECEIVER | EMITTER;
+ private static float wirelessChargeFactor = 0.5F;
private long storedEnergy = 0;
private long energyCapacity = 0;
private long voltage = 0;
private long amperage = 0;
private int type = 0;
private boolean canUseLaser = false;
+ private boolean canUseWireless = false;
+ private UUID owner;
public PowerLogic() {}
+ /**
+ * Sets the max voltage the logic can accept
+ */
+ @Nonnull
public PowerLogic setMaxVoltage(long voltage) {
this.voltage = voltage;
return this;
}
+ /**
+ * Sets the maximum amount of energy the machine can store inside of it
+ */
+ @Nonnull
public PowerLogic setEnergyCapacity(long energyCapacity) {
this.energyCapacity = energyCapacity;
return this;
}
- public PowerLogic setAmperage(long amperage) {
+ /**
+ * Sets the maximum amount of amps a machine can receive from an emitter
+ */
+ @Nonnull
+ public PowerLogic setMaxAmperage(long amperage) {
this.amperage = amperage;
return this;
}
+ /**
+ * Sets the type of power logic this is. Whether it will receive EU or emit it to others, or do both
+ */
+ @Nonnull
public PowerLogic setType(int type) {
this.type = type;
return this;
}
- public PowerLogic disableLaser() {
- canUseLaser = false;
+ /**
+ * If this power logic can use lasers to be used for it
+ */
+ @Nonnull
+ public PowerLogic setCanUseLaser(boolean canUse) {
+ canUseLaser = canUse;
return this;
}
- public PowerLogic enableLaser() {
- canUseLaser = true;
+ /**
+ * If the power logic should use wireless EU first before using its internal buffer
+ */
+ @Nonnull
+ public PowerLogic setCanUseWireless(boolean canUse, UUID owner) {
+ canUseWireless = canUse;
+ this.owner = owner;
return this;
}
+ /**
+ * Adding energy directly to the buffer, but only if it has the capacity.
+ */
public boolean addEnergyUnsafe(long totalEUAdded) {
if (storedEnergy + totalEUAdded >= energyCapacity) {
return false;
@@ -58,6 +101,9 @@ public class PowerLogic {
return true;
}
+ /**
+ * Adding energy to the buffer if the voltage given isn't higher than the voltage of the logic
+ */
public boolean addEnergy(long voltage, long amperage) {
if (voltage > this.voltage) {
return false;
@@ -66,11 +112,23 @@ public class PowerLogic {
return addEnergyUnsafe(voltage * amperage);
}
+ /**
+ * Same as {@link #addEnergy(long, long)}, but only 1 amp of it
+ */
public boolean addEnergy(long voltage) {
return addEnergy(voltage, 1);
}
+ /**
+ * Injecting energy in the multiblock ampere per ampere until full or until we have added the maximum possible
+ * amperes for this tick
+ *
+ * @param voltage At what voltage are the amps?
+ * @param availableAmperage How much amperage do we have available
+ * @return Amount of amperes used
+ */
public long injectEnergy(long voltage, long availableAmperage) {
+ if (canUseWireless) return 0;
long usedAmperes = 0;
while (addEnergy(voltage, 1) && usedAmperes < amperage) {
usedAmperes++;
@@ -79,7 +137,17 @@ public class PowerLogic {
return usedAmperes;
}
+ /**
+ * Remove energy from the logic only if it has enough to be removed.
+ */
public boolean removeEnergyUnsafe(long totalEURemoved) {
+ if (canUseWireless) {
+ if (storedEnergy < energyCapacity * wirelessChargeFactor) {
+ if (addEUToGlobalEnergyMap(owner, -(energyCapacity - storedEnergy))) {
+ storedEnergy = energyCapacity;
+ }
+ }
+ }
if (storedEnergy - totalEURemoved < 0) {
return false;
}
@@ -88,6 +156,9 @@ public class PowerLogic {
return true;
}
+ /**
+ * Remove the given voltage for the amount of amperage if the removed isn't higher than the logic's voltage
+ */
public boolean removeEnergy(long voltage, long amperage) {
if (voltage > this.voltage) {
return false;
@@ -96,31 +167,61 @@ public class PowerLogic {
return removeEnergyUnsafe(voltage * amperage);
}
+ /**
+ * Same as {@link #removeEnergy(long, long)}, but with only 1 amperage
+ */
public boolean removeEnergy(long voltage) {
return removeEnergy(voltage, 1);
}
+ /**
+ * @return The maximum energy that can be stored.
+ */
public long getCapacity() {
return energyCapacity;
}
+ /**
+ * @return The maximum voltage that is available
+ */
public long getVoltage() {
return voltage;
}
+ /**
+ * @return The current energy stored
+ */
public long getStoredEnergy() {
return storedEnergy;
}
+ /**
+ * @return The current maximum Amperage
+ */
+ public long getMaxAmperage() {
+ return amperage;
+ }
+
+ /**
+ * Is the logic a receiver to receive energy
+ */
public boolean isEnergyReceiver() {
return (type & RECEIVER) > 0;
}
+ /**
+ * Is the logic a emitter to emit energy
+ */
public boolean isEnergyEmitter() {
return (type & EMITTER) > 0;
}
- public void writeToNBT(NBTTagCompound nbt) {
+ /**
+ * Saves the power logic to its own nbt tag before saving it to the given one.
+ *
+ * @param nbt Tag where you want to save the power logic tag to.
+ */
+ public void saveToNBT(NBTTagCompound nbt) {
NBTTagCompound powerLogic = new NBTTagCompound();
powerLogic.setLong(NBT.POWER_LOGIC_ENERGY_CAPACITY, energyCapacity);
powerLogic.setLong(NBT.POWER_LOGIC_STORED_ENERGY, storedEnergy);
@@ -130,6 +231,11 @@ public class PowerLogic {
nbt.setTag(NBT.POWER_LOGIC, powerLogic);
}
+ /**
+ * Loads the power logic from its own nbt after getting it from the given one
+ *
+ * @param nbt Tag where the power logic tag was saved to
+ */
public void loadFromNBT(NBTTagCompound nbt) {
NBTTagCompound powerLogic = nbt.getCompoundTag(NBT.POWER_LOGIC);
energyCapacity = powerLogic.getLong(NBT.POWER_LOGIC_ENERGY_CAPACITY);
@@ -139,6 +245,9 @@ public class PowerLogic {
type = powerLogic.getInteger(NBT.POWER_LOGIC_TYPE);
}
+ /**
+ * Can we use lasers for inputting EU
+ */
public boolean canUseLaser() {
return canUseLaser;
}
diff --git a/src/main/java/gregtech/api/logic/ProcessingLogic.java b/src/main/java/gregtech/api/logic/ProcessingLogic.java
index 6b9f2d454f..4d203ed80f 100644
--- a/src/main/java/gregtech/api/logic/ProcessingLogic.java
+++ b/src/main/java/gregtech/api/logic/ProcessingLogic.java
@@ -1,7 +1,6 @@
package gregtech.api.logic;
import java.util.List;
-import java.util.function.Supplier;
import java.util.stream.Stream;
import javax.annotation.Nonnull;
@@ -10,10 +9,7 @@ import javax.annotation.Nullable;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fluids.FluidStack;
-import org.jetbrains.annotations.NotNull;
-
import gregtech.api.interfaces.tileentity.IRecipeLockable;
-import gregtech.api.interfaces.tileentity.IVoidable;
import gregtech.api.recipe.RecipeMap;
import gregtech.api.recipe.check.CheckRecipeResult;
import gregtech.api.recipe.check.CheckRecipeResultRegistry;
@@ -26,90 +22,45 @@ import gregtech.api.util.GT_Recipe;
* Logic class to calculate result of recipe check from inputs, based on recipemap.
*/
@SuppressWarnings({ "unused", "UnusedReturnValue" })
-public class ProcessingLogic {
+public class ProcessingLogic extends AbstractProcessingLogic<ProcessingLogic> {
- protected IVoidable machine;
protected IRecipeLockable recipeLockableMachine;
- protected Supplier<RecipeMap<?>> recipeMapSupplier;
- protected GT_Recipe lastRecipe;
- protected RecipeMap<?> lastRecipeMap;
protected ItemStack specialSlotItem;
protected ItemStack[] inputItems;
- protected ItemStack[] outputItems;
- protected ItemStack[] currentOutputItems;
protected FluidStack[] inputFluids;
- protected FluidStack[] outputFluids;
- protected FluidStack[] currentOutputFluids;
- protected long calculatedEut;
- protected int duration;
- protected long availableVoltage;
- protected long availableAmperage;
- protected int overClockTimeReduction = 1;
- protected int overClockPowerIncrease = 2;
- protected boolean protectItems;
- protected boolean protectFluids;
protected boolean isRecipeLocked;
- protected int maxParallel = 1;
- protected int calculatedParallels = 0;
- protected Supplier<Integer> maxParallelSupplier;
- protected int batchSize = 1;
- protected float euModifier = 1.0f;
- protected float speedBoost = 1.0f;
- protected boolean amperageOC = true;
public ProcessingLogic() {}
- // region Setters
+ // #region Setters
+ @Nonnull
public ProcessingLogic setInputItems(ItemStack... itemInputs) {
this.inputItems = itemInputs;
- return this;
+ return getThis();
}
+ @Nonnull
public ProcessingLogic setInputItems(List<ItemStack> itemOutputs) {
this.inputItems = itemOutputs.toArray(new ItemStack[0]);
- return this;
+ return getThis();
}
+ @Nonnull
public ProcessingLogic setInputFluids(FluidStack... fluidInputs) {
this.inputFluids = fluidInputs;
- return this;
+ return getThis();
}
+ @Nonnull
public ProcessingLogic setInputFluids(List<FluidStack> fluidInputs) {
this.inputFluids = fluidInputs.toArray(new FluidStack[0]);
- return this;
+ return getThis();
}
public ProcessingLogic setSpecialSlotItem(ItemStack specialSlotItem) {
this.specialSlotItem = specialSlotItem;
- return this;
- }
-
- /**
- * Overwrites item output result of the calculation.
- */
- public ProcessingLogic setOutputItems(ItemStack... itemOutputs) {
- this.outputItems = itemOutputs;
- return this;
- }
-
- /**
- * Overwrites fluid output result of the calculation.
- */
- public ProcessingLogic setOutputFluids(FluidStack... fluidOutputs) {
- this.outputFluids = fluidOutputs;
- return this;
- }
-
- public ProcessingLogic setCurrentOutputItems(ItemStack... currentOutputItems) {
- this.currentOutputItems = currentOutputItems;
- return this;
- }
-
- public ProcessingLogic setCurrentOutputFluids(FluidStack... currentOutputFluids) {
- this.currentOutputFluids = currentOutputFluids;
- return this;
+ return getThis();
}
/**
@@ -118,129 +69,13 @@ public class ProcessingLogic {
public ProcessingLogic setRecipeLocking(IRecipeLockable recipeLockableMachine, boolean isRecipeLocked) {
this.recipeLockableMachine = recipeLockableMachine;
this.isRecipeLocked = isRecipeLocked;
- return this;
- }
-
- /**
- * Sets max amount of parallel.
- */
- public ProcessingLogic setMaxParallel(int maxParallel) {
- this.maxParallel = maxParallel;
- return this;
- }
-
- /**
- * Sets method to get max amount of parallel.
- */
- public ProcessingLogic setMaxParallelSupplier(Supplier<Integer> supplier) {
- this.maxParallelSupplier = supplier;
- return this;
- }
-
- /**
- * Sets batch size for batch mode.
- */
- public ProcessingLogic setBatchSize(int size) {
- this.batchSize = size;
- return this;
- }
-
- public ProcessingLogic setRecipeMap(RecipeMap<?> recipeMap) {
- return setRecipeMapSupplier(() -> recipeMap);
- }
-
- public ProcessingLogic setRecipeMapSupplier(Supplier<RecipeMap<?>> supplier) {
- this.recipeMapSupplier = supplier;
- return this;
- }
-
- public ProcessingLogic setEuModifier(float modifier) {
- this.euModifier = modifier;
- return this;
- }
-
- public ProcessingLogic setSpeedBonus(float speedModifier) {
- this.speedBoost = speedModifier;
- return this;
- }
-
- /**
- * Sets machine used for void protection logic.
- */
- public ProcessingLogic setMachine(IVoidable machine) {
- this.machine = machine;
- return this;
- }
-
- /**
- * Overwrites duration result of the calculation.
- */
- public ProcessingLogic setDuration(int duration) {
- this.duration = duration;
- return this;
- }
-
- /**
- * Overwrites EU/t result of the calculation.
- */
- public ProcessingLogic setCalculatedEut(long calculatedEut) {
- this.calculatedEut = calculatedEut;
- return this;
- }
-
- /**
- * Sets voltage of the machine. It doesn't need to be actual voltage (excluding amperage) of the machine;
- * For example, most of the multiblock machines set maximum possible input power (including amperage) as voltage
- * and 1 as amperage. That way recipemap search will be executed with overclocked voltage.
- */
- public ProcessingLogic setAvailableVoltage(long voltage) {
- availableVoltage = voltage;
- return this;
- }
-
- /**
- * Sets amperage of the machine. This amperage doesn't involve in EU/t when searching recipemap.
- * Useful for preventing tier skip but still considering amperage for parallel.
- */
- public ProcessingLogic setAvailableAmperage(long amperage) {
- availableAmperage = amperage;
- return this;
- }
-
- public ProcessingLogic setVoidProtection(boolean protectItems, boolean protectFluids) {
- this.protectItems = protectItems;
- this.protectFluids = protectFluids;
- return this;
- }
-
- /**
- * Sets custom overclock ratio. 2/4 by default.
- * Parameters represent number of bit shift, so 1 -> 2x, 2 -> 4x.
- */
- public ProcessingLogic setOverclock(int timeReduction, int powerIncrease) {
- this.overClockTimeReduction = timeReduction;
- this.overClockPowerIncrease = powerIncrease;
- return this;
- }
-
- /**
- * Sets overclock ratio to 4/4.
- */
- public ProcessingLogic enablePerfectOverclock() {
- return this.setOverclock(2, 2);
- }
-
- /**
- * Sets wether the multi should use amperage to OC or not
- */
- public ProcessingLogic setAmperageOC(boolean amperageOC) {
- this.amperageOC = amperageOC;
- return this;
+ return getThis();
}
/**
* Clears calculated results and provided machine inputs to prepare for the next machine operation.
*/
+
public ProcessingLogic clear() {
this.inputItems = null;
this.inputFluids = null;
@@ -250,32 +85,19 @@ public class ProcessingLogic {
this.calculatedEut = 0;
this.duration = 0;
this.calculatedParallels = 0;
- return this;
+ return getThis();
}
- // endregion
+ // #endregion
- // region Logic
+ // #region Logic
/**
* Executes the recipe check: Find recipe from recipemap, Calculate parallel, overclock and outputs.
*/
@Nonnull
public CheckRecipeResult process() {
- RecipeMap<?> recipeMap;
- if (recipeMapSupplier == null) {
- recipeMap = null;
- } else {
- recipeMap = recipeMapSupplier.get();
- }
- if (lastRecipeMap != recipeMap) {
- lastRecipe = null;
- lastRecipeMap = recipeMap;
- }
-
- if (maxParallelSupplier != null) {
- maxParallel = maxParallelSupplier.get();
- }
+ RecipeMap<?> recipeMap = preProcess();
if (inputItems == null) {
inputItems = new ItemStack[0];
@@ -297,7 +119,6 @@ public class ProcessingLogic {
recipeLockableMachine.getSingleRecipeCheck()
.getRecipe()).checkRecipeResult;
}
-
Stream<GT_Recipe> matchedRecipes = findRecipeMatches(recipeMap);
Iterable<GT_Recipe> recipeIterable = matchedRecipes::iterator;
CheckRecipeResult checkRecipeResult = CheckRecipeResultRegistry.NO_RECIPE;
@@ -342,53 +163,6 @@ public class ProcessingLogic {
}
/**
- * Check has been succeeded, so it applies the recipe and calculated parameters.
- * At this point, inputs have been already consumed.
- */
- private CheckRecipeResult applyRecipe(@NotNull GT_Recipe recipe, GT_ParallelHelper helper,
- GT_OverclockCalculator calculator, CheckRecipeResult result) {
- if (recipe.mCanBeBuffered) {
- lastRecipe = recipe;
- } else {
- lastRecipe = null;
- }
- calculatedParallels = helper.getCurrentParallel();
-
- if (calculator.getConsumption() == Long.MAX_VALUE) {
- return CheckRecipeResultRegistry.POWER_OVERFLOW;
- }
- if (calculator.getDuration() == Integer.MAX_VALUE) {
- return CheckRecipeResultRegistry.DURATION_OVERFLOW;
- }
-
- calculatedEut = calculator.getConsumption();
-
- double finalDuration = calculateDuration(recipe, helper, calculator);
- if (finalDuration >= Integer.MAX_VALUE) {
- return CheckRecipeResultRegistry.DURATION_OVERFLOW;
- }
- duration = (int) finalDuration;
-
- CheckRecipeResult hookResult = onRecipeStart(recipe);
- if (!hookResult.wasSuccessful()) {
- return hookResult;
- }
-
- outputItems = helper.getItemOutputs();
- outputFluids = helper.getFluidOutputs();
-
- return result;
- }
-
- /**
- * Override to tweak final duration that will be set as a result of this logic class.
- */
- protected double calculateDuration(@Nonnull GT_Recipe recipe, @Nonnull GT_ParallelHelper helper,
- @Nonnull GT_OverclockCalculator calculator) {
- return calculator.getDuration() * helper.getDurationMultiplierDouble();
- }
-
- /**
* Finds a list of matched recipes. At this point no additional check to the matched recipe has been done.
* <p>
* Override {@link #validateRecipe} to have custom check.
@@ -409,14 +183,6 @@ public class ProcessingLogic {
}
/**
- * Override to do additional check for found recipe if needed.
- */
- @Nonnull
- protected CheckRecipeResult validateRecipe(@Nonnull GT_Recipe recipe) {
- return CheckRecipeResultRegistry.SUCCESSFUL;
- }
-
- /**
* Override to tweak parallel logic if needed.
*/
@Nonnull
@@ -434,60 +200,7 @@ public class ProcessingLogic {
.setOutputCalculation(true);
}
- /**
- * Override to tweak overclock logic if needed.
- */
- @Nonnull
- protected GT_OverclockCalculator createOverclockCalculator(@Nonnull GT_Recipe recipe) {
- return new GT_OverclockCalculator().setRecipeEUt(recipe.mEUt)
- .setAmperage(availableAmperage)
- .setEUt(availableVoltage)
- .setDuration(recipe.mDuration)
- .setSpeedBoost(speedBoost)
- .setEUtDiscount(euModifier)
- .setAmperageOC(amperageOC)
- .setDurationDecreasePerOC(overClockTimeReduction)
- .setEUtIncreasePerOC(overClockPowerIncrease);
- }
-
- /**
- * Override to perform additional logic when recipe starts.
- *
- * This is called when the recipe processing logic has finished all
- * checks, consumed all inputs, but has not yet set the outputs to
- * be produced. Returning a result other than SUCCESSFUL will void
- * all inputs!
- */
- @Nonnull
- protected CheckRecipeResult onRecipeStart(@Nonnull GT_Recipe recipe) {
- return CheckRecipeResultRegistry.SUCCESSFUL;
- }
-
- // endregion
-
- // region Getters
-
- public ItemStack[] getOutputItems() {
- return outputItems;
- }
-
- public FluidStack[] getOutputFluids() {
- return outputFluids;
- }
-
- public int getDuration() {
- return duration;
- }
-
- public long getCalculatedEut() {
- return calculatedEut;
- }
-
- public int getCurrentParallels() {
- return calculatedParallels;
- }
-
- // endregion
+ // #endregion
/**
* Represents the status of check recipe calculation. {@link #successfullyConsumedInputs} does not necessarily mean
diff --git a/src/main/java/gregtech/api/logic/interfaces/FluidInventoryLogicHost.java b/src/main/java/gregtech/api/logic/interfaces/FluidInventoryLogicHost.java
new file mode 100644
index 0000000000..c12333a4c6
--- /dev/null
+++ b/src/main/java/gregtech/api/logic/interfaces/FluidInventoryLogicHost.java
@@ -0,0 +1,95 @@
+package gregtech.api.logic.interfaces;
+
+import static com.google.common.primitives.Ints.saturatedCast;
+
+import java.util.HashSet;
+import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.Set;
+import java.util.UUID;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+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 gregtech.api.enums.InventoryType;
+import gregtech.api.logic.FluidInventoryLogic;
+
+public interface FluidInventoryLogicHost extends IFluidHandler {
+
+ /**
+ * To be used for single blocks or when directly interacting with the controller
+ *
+ * @param side The side from where fluids are being inputted or extracted from
+ * @param type The type of inventory being accessed. For inputting its Input, For outputting its Output.
+ * @return The Fluid Logic responsible for said type. Can return null if the side is invalid
+ */
+ @Nullable
+ FluidInventoryLogic getFluidLogic(@Nonnull ForgeDirection side, @Nonnull InventoryType type);
+
+ /**
+ * Only to be used by MultiBlockPart for accessing the Controller Inventory
+ *
+ * @param type Type of inventory, is it Input or Output
+ * @param id ID of the locked inventory. A null id is all inventories of said controller of said type
+ * @return The Fluid Logic responsible for everything that should be done with said inventory
+ */
+ @Nonnull
+ default FluidInventoryLogic getFluidLogic(@Nonnull InventoryType type, @Nullable UUID id) {
+ return Objects.requireNonNull(getFluidLogic(ForgeDirection.UNKNOWN, type));
+ }
+
+ /**
+ * Returns an empty set if the type is {@link InventoryType#Both} or when the machine isn't a controller.
+ */
+ @Nonnull
+ default Set<Entry<UUID, FluidInventoryLogic>> getAllFluidInventoryLogics(@Nonnull InventoryType type) {
+ return new HashSet<>();
+ }
+
+ @Override
+ default boolean canDrain(@Nonnull ForgeDirection from, Fluid fluid) {
+ FluidInventoryLogic logic = getFluidLogic(from, InventoryType.Output);
+ return logic != null;
+ }
+
+ @Override
+ default boolean canFill(@Nonnull ForgeDirection from, Fluid fluid) {
+ FluidInventoryLogic logic = getFluidLogic(from, InventoryType.Input);
+ return logic != null;
+ }
+
+ @Override
+ @Nullable
+ default FluidStack drain(@Nonnull ForgeDirection from, @Nonnull FluidStack resource, boolean doDrain) {
+ FluidInventoryLogic logic = getFluidLogic(from, InventoryType.Output);
+ if (logic == null) return null;
+ return logic.drain(resource.getFluid(), resource.amount, !doDrain);
+ }
+
+ @Override
+ @Nullable
+ default FluidStack drain(@Nonnull ForgeDirection from, int maxDrain, boolean doDrain) {
+ FluidInventoryLogic logic = getFluidLogic(from, InventoryType.Output);
+ if (logic == null) return null;
+ return logic.drain(maxDrain, !doDrain);
+ }
+
+ @Override
+ default int fill(@Nonnull ForgeDirection from, @Nonnull FluidStack resource, boolean doFill) {
+ FluidInventoryLogic logic = getFluidLogic(from, InventoryType.Input);
+ if (logic == null) return 0;
+ return saturatedCast(logic.fill(resource.getFluid(), resource.amount, !doFill));
+ }
+
+ @Override
+ @Nullable
+ default FluidTankInfo[] getTankInfo(@Nonnull ForgeDirection from) {
+ return null;
+ }
+}
diff --git a/src/main/java/gregtech/api/logic/interfaces/ItemInventoryLogicHost.java b/src/main/java/gregtech/api/logic/interfaces/ItemInventoryLogicHost.java
new file mode 100644
index 0000000000..a65f3c50f1
--- /dev/null
+++ b/src/main/java/gregtech/api/logic/interfaces/ItemInventoryLogicHost.java
@@ -0,0 +1,172 @@
+package gregtech.api.logic.interfaces;
+
+import java.util.HashSet;
+import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.Set;
+import java.util.UUID;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.inventory.ISidedInventory;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.enums.InventoryType;
+import gregtech.api.logic.ItemInventoryLogic;
+
+public interface ItemInventoryLogicHost extends ISidedInventory {
+
+ /**
+ * To be used for single blocks or when directly interacting with the controller
+ *
+ * @param side The side from where items are being inputted or extracted from
+ * @param type The type of inventory being accessed. For inputting its Input, For outputting its Output.
+ * @return The Item Logic responsible for said type. Will return null if the side is not valid
+ */
+ @Nullable
+ ItemInventoryLogic getItemLogic(@Nonnull ForgeDirection side, @Nonnull InventoryType type);
+
+ /**
+ * Only to be used by MultiBlockPart for accessing the Controller Inventory
+ *
+ * @param type Type of inventory, is it Input or Output
+ * @param id ID of the locked inventory. A null id is all inventories of said controller of said type
+ * @return The Item Logic responsible for everything that should be done with said inventory
+ */
+ @Nonnull
+ default ItemInventoryLogic getItemLogic(@Nonnull InventoryType type, @Nullable UUID id) {
+ return Objects.requireNonNull(getItemLogic(ForgeDirection.UNKNOWN, type));
+ }
+
+ /**
+ * Only to be used for MultiBlockPart
+ *
+ * @return
+ */
+ @Nullable
+ default InventoryType getItemInventoryType() {
+ return null;
+ }
+
+ /**
+ * Returns an empty set if the type is {@link InventoryType#Both} or this is used when the machine isn't a
+ * controller
+ */
+ @Nonnull
+ default Set<Entry<UUID, ItemInventoryLogic>> getAllItemInventoryLogics(@Nonnull InventoryType type) {
+ return new HashSet<>();
+ }
+
+ @Override
+ @Nullable
+ default ItemStack decrStackSize(int slot, int count) {
+ InventoryType type = getItemInventoryType();
+ if (type == InventoryType.Both) return null;
+ ItemInventoryLogic logic = getItemLogic(ForgeDirection.UNKNOWN, type == null ? InventoryType.Output : type);
+ if (logic == null) return null;
+ return logic.extractItem(slot, count);
+ }
+
+ @Override
+ default int getSizeInventory() {
+ InventoryType type = getItemInventoryType();
+ if (type == InventoryType.Both) return 0;
+ ItemInventoryLogic logic = getItemLogic(ForgeDirection.UNKNOWN, type == null ? InventoryType.Output : type);
+ if (logic == null) return 0;
+ return logic.getSlots();
+ }
+
+ @Override
+ @Nullable
+ default ItemStack getStackInSlot(int slot) {
+ InventoryType type = getItemInventoryType();
+ if (type == InventoryType.Both) return null;
+ ItemInventoryLogic logic = getItemLogic(ForgeDirection.UNKNOWN, type == null ? InventoryType.Output : type);
+ if (logic == null) return null;
+ return logic.getInventory()
+ .getStackInSlot(slot);
+ }
+
+ @Override
+ default boolean isItemValidForSlot(int slot, @Nullable ItemStack stack) {
+ InventoryType type = getItemInventoryType();
+ if (type == InventoryType.Both) return false;
+ ItemInventoryLogic logic = getItemLogic(ForgeDirection.UNKNOWN, type == null ? InventoryType.Output : type);
+ if (logic == null) return false;
+ return logic.getInventory()
+ .isItemValid(slot, stack);
+ }
+
+ @Override
+ default void setInventorySlotContents(int slot, @Nullable ItemStack stack) {
+ InventoryType type = getItemInventoryType();
+ if (type == InventoryType.Both) return;
+ ItemInventoryLogic logic = getItemLogic(ForgeDirection.UNKNOWN, type == null ? InventoryType.Output : type);
+ if (logic == null) return;
+ logic.getInventory()
+ .setStackInSlot(slot, stack);
+ }
+
+ @Override
+ default boolean canExtractItem(int ignoredSlot, ItemStack ignoredItem, int side) {
+ InventoryType type = getItemInventoryType();
+ if (type == null) return false;
+ return getItemLogic(ForgeDirection.getOrientation(side), type) != null;
+ }
+
+ @Override
+ default boolean canInsertItem(int ignoredSlot, ItemStack ignoredItem, int side) {
+ InventoryType type = getItemInventoryType();
+ if (type == null) return false;
+ return getItemInventoryType() != InventoryType.Output
+ && getItemLogic(ForgeDirection.getOrientation(side), type) != null;
+ }
+
+ @Override
+ default int[] getAccessibleSlotsFromSide(int side) {
+ InventoryType type = getItemInventoryType();
+ if (type == null) return new int[0];
+ ItemInventoryLogic logic = getItemLogic(ForgeDirection.UNKNOWN, type == null ? InventoryType.Output : type);
+ if (logic == null) return new int[0];
+ int[] indexes = new int[logic.getSlots()];
+ for (int i = 0; i < logic.getSlots(); i++) {
+ indexes[i] = i;
+ }
+ return indexes;
+ }
+
+ @Override
+ default void closeInventory() {}
+
+ @Override
+ default String getInventoryName() {
+ return "";
+ }
+
+ @Override
+ default int getInventoryStackLimit() {
+ return 64;
+ }
+
+ @Override
+ default ItemStack getStackInSlotOnClosing(int index) {
+ return null;
+ }
+
+ @Override
+ default boolean hasCustomInventoryName() {
+ return false;
+ }
+
+ @Override
+ default boolean isUseableByPlayer(@Nonnull EntityPlayer player) {
+ return false;
+ }
+
+ @Override
+ default void openInventory() {}
+
+}
diff --git a/src/main/java/gregtech/api/logic/interfaces/PollutionLogicHost.java b/src/main/java/gregtech/api/logic/interfaces/PollutionLogicHost.java
deleted file mode 100644
index 657efbb74d..0000000000
--- a/src/main/java/gregtech/api/logic/interfaces/PollutionLogicHost.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package gregtech.api.logic.interfaces;
-
-import gregtech.api.logic.PollutionLogic;
-
-public interface PollutionLogicHost {
-
- PollutionLogic getPollutionLogic();
-}
diff --git a/src/main/java/gregtech/api/logic/interfaces/PowerLogicHost.java b/src/main/java/gregtech/api/logic/interfaces/PowerLogicHost.java
index 8604c160fb..4903d7fa23 100644
--- a/src/main/java/gregtech/api/logic/interfaces/PowerLogicHost.java
+++ b/src/main/java/gregtech/api/logic/interfaces/PowerLogicHost.java
@@ -1,18 +1,60 @@
package gregtech.api.logic.interfaces;
+import java.util.Objects;
+
+import javax.annotation.Nonnull;
+
import net.minecraftforge.common.util.ForgeDirection;
+import gregtech.api.interfaces.tileentity.IEnergyConnected;
import gregtech.api.logic.PowerLogic;
+/**
+ * Power logic class for one to use to enable a machine to use energy
+ */
public interface PowerLogicHost {
- PowerLogic getPowerLogic(ForgeDirection side);
+ /**
+ *
+ * @param side Side being access to try and get the power logic from
+ * @return Can return NullPowerLogic if the side doesn't allow the return of the logic. That power logic is unusable
+ */
+ @Nonnull
+ PowerLogic getPowerLogic(@Nonnull ForgeDirection side);
+
+ /**
+ * Gives the power logic ignoring the side.
+ */
+ @Nonnull
+ default PowerLogic getPowerLogic() {
+ return Objects.requireNonNull(getPowerLogic(ForgeDirection.UNKNOWN));
+ }
+ /**
+ * Shortcut to the method of {@link PowerLogic#isEnergyReceiver()}
+ */
default boolean isEnergyReceiver() {
- return false;
+ return getPowerLogic().isEnergyReceiver();
}
+ /**
+ * Shortcut to the method of {@link PowerLogic#isEnergyEmitter()}
+ */
default boolean isEnergyEmitter() {
- return false;
+ return getPowerLogic().isEnergyEmitter();
}
+
+ /**
+ * Method for emitting energy to other blocks and machines. Override when it needs to be changed.
+ */
+ default void emitEnergyFromLogic() {
+ IEnergyConnected.Util.emitEnergyToNetwork(this, getPowerOutputSide());
+ }
+
+ /**
+ * From where does the machine output energy from?
+ * When the output side is {@link ForgeDirection#UNKNOWN} then it won't output energy
+ */
+ @Nonnull
+ ForgeDirection getPowerOutputSide();
}
diff --git a/src/main/java/gregtech/api/logic/interfaces/ProcessingLogicHost.java b/src/main/java/gregtech/api/logic/interfaces/ProcessingLogicHost.java
index 55418208b0..b8291c9843 100644
--- a/src/main/java/gregtech/api/logic/interfaces/ProcessingLogicHost.java
+++ b/src/main/java/gregtech/api/logic/interfaces/ProcessingLogicHost.java
@@ -1,8 +1,82 @@
package gregtech.api.logic.interfaces;
-import gregtech.api.logic.ProcessingLogic;
+import javax.annotation.Nonnull;
-public interface ProcessingLogicHost {
+import gregtech.api.enums.VoidingMode;
+import gregtech.api.interfaces.tileentity.IMachineProgress;
+import gregtech.api.interfaces.tileentity.IVoidable;
+import gregtech.api.logic.MuTEProcessingLogic;
- ProcessingLogic getProcessingLogic();
+public interface ProcessingLogicHost<P extends MuTEProcessingLogic<P>>
+ extends IVoidable, ItemInventoryLogicHost, FluidInventoryLogicHost, IMachineProgress {
+
+ /**
+ * Get the processing logic for the current machine
+ */
+ @Nonnull
+ P getProcessingLogic();
+
+ boolean isInputSeparated();
+
+ void setInputSeparation(Boolean inputSeparation);
+
+ default boolean supportsInputSeparation() {
+ return true;
+ }
+
+ default boolean getDefaultInputSeparationMode() {
+ return false;
+ }
+
+ boolean isRecipeLockingEnabled();
+
+ void setRecipeLocking(Boolean recipeLocked);
+
+ default boolean supportsSingleRecipeLocking() {
+ return true;
+ }
+
+ default boolean getDefaultRecipeLockingMode() {
+ return false;
+ }
+
+ default boolean supportsBatchMode() {
+ return true;
+ }
+
+ void setBatchMode(Boolean batchMode);
+
+ boolean isBatchModeEnabled();
+
+ default boolean getDefaultBatchMode() {
+ return false;
+ }
+
+ /**
+ * Get what the machine can void or not
+ */
+ @Nonnull
+ VoidingMode getVoidMode();
+
+ /**
+ * Called when the processing logic should be updated by {@link #needsUpdate()}
+ */
+ default void updateProcessingLogic(@Nonnull P processingLogic) {}
+
+ /**
+ * Called before the recipe check, but after any other updates
+ */
+ default void setProcessingLogicPower(@Nonnull P processingLogic) {}
+
+ /**
+ * DO NOT CALL YOURSELF!!!
+ *
+ * If you want to make the processing logic be updated call {@link #setProcessingUpdate(boolean)}
+ */
+ boolean needsUpdate();
+
+ /**
+ * To be called when one needs to updated the processing logic. That can be when parallel changes, ect.
+ */
+ void setProcessingUpdate(boolean update);
}
diff --git a/src/main/java/gregtech/api/metatileentity/BaseTileEntity.java b/src/main/java/gregtech/api/metatileentity/BaseTileEntity.java
index 774c13e91b..d8b0086f0f 100644
--- a/src/main/java/gregtech/api/metatileentity/BaseTileEntity.java
+++ b/src/main/java/gregtech/api/metatileentity/BaseTileEntity.java
@@ -51,6 +51,8 @@ import com.gtnewhorizons.modularui.common.widget.SlotGroup;
import com.gtnewhorizons.modularui.common.widget.SlotWidget;
import com.gtnewhorizons.modularui.common.widget.TextWidget;
+import cpw.mods.fml.common.FMLCommonHandler;
+import cpw.mods.fml.relauncher.Side;
import gregtech.GT_Mod;
import gregtech.api.enums.Dyes;
import gregtech.api.enums.GT_Values;
@@ -175,13 +177,18 @@ public abstract class BaseTileEntity extends TileEntity implements IHasWorldObje
@Override
public final boolean isServerSide() {
if (worldObj == null) {
- return false;
+ return FMLCommonHandler.instance()
+ .getEffectiveSide() == Side.SERVER;
}
return !worldObj.isRemote;
}
@Override
public final boolean isClientSide() {
+ if (worldObj == null) {
+ return FMLCommonHandler.instance()
+ .getEffectiveSide() == Side.CLIENT;
+ }
return worldObj.isRemote;
}
@@ -609,29 +616,6 @@ public abstract class BaseTileEntity extends TileEntity implements IHasWorldObje
return false;
}
- @Override
- public ModularWindow createWindow(UIBuildContext buildContext) {
- if (!useModularUI()) return null;
-
- buildContext.setValidator(getValidator());
- final ModularWindow.Builder builder = ModularWindow.builder(getGUIWidth(), getGUIHeight());
- builder.setBackground(getGUITextureSet().getMainBackground());
- builder.setGuiTint(getGUIColorization());
- if (doesBindPlayerInventory()) {
- bindPlayerInventoryUI(builder, buildContext);
- }
- addUIWidgets(builder, buildContext);
- addTitleToUI(builder);
- addCoverTabs(builder, buildContext);
- final IConfigurationCircuitSupport csc = getConfigurationCircuitSupport();
- if (csc != null && csc.allowSelectCircuit()) {
- addConfigurationCircuitSlot(builder);
- } else {
- addGregTechLogo(builder);
- }
- return builder.build();
- }
-
/*
* IC2 Energy Compat
*/
diff --git a/src/main/java/gregtech/api/metatileentity/CommonMetaTileEntity.java b/src/main/java/gregtech/api/metatileentity/CommonMetaTileEntity.java
index acb3e75235..5a2e88b242 100644
--- a/src/main/java/gregtech/api/metatileentity/CommonMetaTileEntity.java
+++ b/src/main/java/gregtech/api/metatileentity/CommonMetaTileEntity.java
@@ -314,4 +314,27 @@ public abstract class CommonMetaTileEntity extends CoverableTileEntity
public ItemStack getMachineCraftingIcon() {
return getMetaTileEntity() != null ? getMetaTileEntity().getMachineCraftingIcon() : null;
}
+
+ @Override
+ public ModularWindow createWindow(UIBuildContext buildContext) {
+ if (!useModularUI()) return null;
+
+ buildContext.setValidator(getValidator());
+ final ModularWindow.Builder builder = ModularWindow.builder(getGUIWidth(), getGUIHeight());
+ builder.setBackground(getGUITextureSet().getMainBackground());
+ builder.setGuiTint(getGUIColorization());
+ if (doesBindPlayerInventory()) {
+ bindPlayerInventoryUI(builder, buildContext);
+ }
+ addUIWidgets(builder, buildContext);
+ addTitleToUI(builder);
+ addCoverTabs(builder, buildContext);
+ final IConfigurationCircuitSupport csc = getConfigurationCircuitSupport();
+ if (csc != null && csc.allowSelectCircuit()) {
+ addConfigurationCircuitSlot(builder);
+ } else {
+ addGregTechLogo(builder);
+ }
+ return builder.build();
+ }
}
diff --git a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Cable.java b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Cable.java
index db4ead0932..d2e37bf2f3 100644
--- a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Cable.java
+++ b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Cable.java
@@ -360,7 +360,7 @@ public class GT_MetaPipeEntity_Cable extends MetaPipeEntity implements IMetaTile
final ForgeDirection oppositeSide = side.getOpposite();
// GT Machine handling
- if ((tileEntity instanceof PowerLogicHost powerLogic && powerLogic.getPowerLogic(side) != null)
+ if ((tileEntity instanceof PowerLogicHost powerLogic && powerLogic.getPowerLogic(oppositeSide) != null)
|| ((tileEntity instanceof IEnergyConnected energyConnected)
&& (energyConnected.inputEnergyFrom(oppositeSide, false)
|| energyConnected.outputsEnergyTo(oppositeSide, false))))
diff --git a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Wireless_Dynamo.java b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Wireless_Dynamo.java
index 821c02d10f..4b73210afd 100644
--- a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Wireless_Dynamo.java
+++ b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Wireless_Dynamo.java
@@ -2,6 +2,8 @@ package gregtech.api.metatileentity.implementations;
import static gregtech.api.enums.GT_Values.AuthorColen;
import static gregtech.api.enums.GT_Values.V;
+import static gregtech.common.misc.WirelessNetworkManager.addEUToGlobalEnergyMap;
+import static gregtech.common.misc.WirelessNetworkManager.strongCheckOrAddUser;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
@@ -9,14 +11,13 @@ import net.minecraft.util.EnumChatFormatting;
import net.minecraftforge.common.util.ForgeDirection;
import gregtech.api.enums.Textures;
-import gregtech.api.interfaces.IGlobalWirelessEnergy;
import gregtech.api.interfaces.ITexture;
import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
import gregtech.api.interfaces.tileentity.IWirelessEnergyHatchInformation;
import gregtech.api.metatileentity.MetaTileEntity;
public class GT_MetaTileEntity_Wireless_Dynamo extends GT_MetaTileEntity_Hatch_Dynamo
- implements IGlobalWirelessEnergy, IWirelessEnergyHatchInformation {
+ implements IWirelessEnergyHatchInformation {
private String owner_uuid;
private String owner_name;
diff --git a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Wireless_Hatch.java b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Wireless_Hatch.java
index 66a84dfa99..251a9dfcec 100644
--- a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Wireless_Hatch.java
+++ b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Wireless_Hatch.java
@@ -2,6 +2,8 @@ package gregtech.api.metatileentity.implementations;
import static gregtech.api.enums.GT_Values.AuthorColen;
import static gregtech.api.enums.GT_Values.V;
+import static gregtech.common.misc.WirelessNetworkManager.addEUToGlobalEnergyMap;
+import static gregtech.common.misc.WirelessNetworkManager.strongCheckOrAddUser;
import static java.lang.Long.min;
import java.math.BigInteger;
@@ -12,14 +14,13 @@ import net.minecraft.util.EnumChatFormatting;
import net.minecraftforge.common.util.ForgeDirection;
import gregtech.api.enums.Textures;
-import gregtech.api.interfaces.IGlobalWirelessEnergy;
import gregtech.api.interfaces.ITexture;
import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
import gregtech.api.interfaces.tileentity.IWirelessEnergyHatchInformation;
import gregtech.api.metatileentity.MetaTileEntity;
public class GT_MetaTileEntity_Wireless_Hatch extends GT_MetaTileEntity_Hatch_Energy
- implements IGlobalWirelessEnergy, IWirelessEnergyHatchInformation {
+ implements IWirelessEnergyHatchInformation {
private final BigInteger eu_transferred_per_operation = BigInteger
.valueOf(2 * V[mTier] * ticks_between_energy_addition);
diff --git a/src/main/java/gregtech/api/multitileentity/MultiTileEntityBlock.java b/src/main/java/gregtech/api/multitileentity/MultiTileEntityBlock.java
index a30d523b55..5ea1069193 100644
--- a/src/main/java/gregtech/api/multitileentity/MultiTileEntityBlock.java
+++ b/src/main/java/gregtech/api/multitileentity/MultiTileEntityBlock.java
@@ -189,8 +189,8 @@ public class MultiTileEntityBlock extends Block implements IDebugableBlock, ITil
@Override
public ArrayList<String> getDebugInfo(EntityPlayer aPlayer, int aX, int aY, int aZ, int aLogLevel) {
final TileEntity aTileEntity = aPlayer.worldObj.getTileEntity(aX, aY, aZ);
- if (aTileEntity instanceof IDebugableTileEntity) {
- return ((IDebugableTileEntity) aTileEntity).getDebugInfo(aPlayer, aLogLevel);
+ if (aTileEntity instanceof IDebugableTileEntity mte) {
+ return mte.getDebugInfo(aPlayer, aLogLevel);
}
return new ArrayList<>();
}
@@ -291,7 +291,7 @@ public class MultiTileEntityBlock extends Block implements IDebugableBlock, ITil
final TileEntity aTileEntity = aWorld.getTileEntity(aX, aY, aZ);
if (!LOCK) {
LOCK = true;
- if (aTileEntity instanceof BaseTileEntity) ((BaseTileEntity) aTileEntity).onAdjacentBlockChange(aX, aY, aZ);
+ if (aTileEntity instanceof BaseTileEntity bte) bte.onAdjacentBlockChange(aX, aY, aZ);
LOCK = false;
}
if (aTileEntity instanceof IMTE_OnNeighborBlockChange change) change.onNeighborBlockChange(aWorld, aBlock);
@@ -368,21 +368,25 @@ public class MultiTileEntityBlock extends Block implements IDebugableBlock, ITil
final int aFortune = EnchantmentHelper.getFortuneModifier(aPlayer);
float aChance = 1.0F;
final TileEntity aTileEntity = getTileEntity(aWorld, aX, aY, aZ, true);
- if (aTileEntity instanceof IMultiTileEntity) {
- final ArrayList<ItemStack> tList = ((IMultiTileEntity) aTileEntity).getDrops(aFortune, aSilkTouch);
- aChance = ForgeEventFactory
- .fireBlockHarvesting(tList, aWorld, this, aX, aY, aZ, aMeta, aFortune, aChance, aSilkTouch, aPlayer);
- for (final ItemStack tStack : tList)
- if (XSTR.XSTR_INSTANCE.nextFloat() <= aChance) dropBlockAsItem(aWorld, aX, aY, aZ, tStack);
+
+ if (!(aTileEntity instanceof IMultiTileEntity mte)) {
+ return;
}
+
+ final ArrayList<ItemStack> tList = mte.getDrops(aFortune, aSilkTouch);
+ aChance = ForgeEventFactory
+ .fireBlockHarvesting(tList, aWorld, this, aX, aY, aZ, aMeta, aFortune, aChance, aSilkTouch, aPlayer);
+ for (final ItemStack tStack : tList)
+ if (XSTR.XSTR_INSTANCE.nextFloat() <= aChance) dropBlockAsItem(aWorld, aX, aY, aZ, tStack);
+
}
@Override
public final boolean shouldSideBeRendered(IBlockAccess aWorld, int aX, int aY, int aZ, int ordinalSide) {
final TileEntity aTileEntity = aWorld
.getTileEntity(aX - OFFX[ordinalSide], aY - OFFY[ordinalSide], aZ - OFFZ[ordinalSide]);
- return aTileEntity instanceof IMultiTileEntity
- ? ((IMultiTileEntity) aTileEntity).shouldSideBeRendered(ForgeDirection.getOrientation(ordinalSide))
+ return aTileEntity instanceof IMultiTileEntity mte
+ ? mte.shouldSideBeRendered(ForgeDirection.getOrientation(ordinalSide))
: super.shouldSideBeRendered(aWorld, aX, aY, aZ, ordinalSide);
}
@@ -473,12 +477,17 @@ public class MultiTileEntityBlock extends Block implements IDebugableBlock, ITil
@Override
public final int getComparatorInputOverride(World aWorld, int aX, int aY, int aZ, int ordinalSide) {
final TileEntity aTileEntity = aWorld.getTileEntity(aX, aY, aZ);
- return aTileEntity instanceof IMTE_GetComparatorInputOverride override
- ? override.getComparatorInputOverride(ForgeDirection.getOrientation(ordinalSide))
- : aTileEntity instanceof IMTE_IsProvidingWeakPower power ? power.isProvidingWeakPower(
+ if (aTileEntity instanceof IMTE_GetComparatorInputOverride override) {
+ return override.getComparatorInputOverride(ForgeDirection.getOrientation(ordinalSide));
+ }
+
+ if (aTileEntity instanceof IMTE_IsProvidingWeakPower power) {
+ return power.isProvidingWeakPower(
ForgeDirection.getOrientation(ordinalSide)
- .getOpposite())
- : super.getComparatorInputOverride(aWorld, aX, aY, aZ, ordinalSide);
+ .getOpposite());
+ }
+
+ return super.getComparatorInputOverride(aWorld, aX, aY, aZ, ordinalSide);
}
@Override
@@ -523,7 +532,7 @@ public class MultiTileEntityBlock extends Block implements IDebugableBlock, ITil
public final ArrayList<ItemStack> getDrops(World aWorld, int aX, int aY, int aZ, int aUnusableMetaData,
int aFortune) {
final TileEntity aTileEntity = getTileEntity(aWorld, aX, aY, aZ, true);
- if (aTileEntity instanceof IMultiTileEntity) return ((IMultiTileEntity) aTileEntity).getDrops(aFortune, false);
+ if (aTileEntity instanceof IMultiTileEntity mte) return mte.getDrops(aFortune, false);
return new ArrayList<>();
}
@@ -536,8 +545,8 @@ public class MultiTileEntityBlock extends Block implements IDebugableBlock, ITil
public final float getExplosionResistance(Entity aExploder, World aWorld, int aX, int aY, int aZ,
double aExplosionX, double aExplosionY, double aExplosionZ) {
final TileEntity aTileEntity = aWorld.getTileEntity(aX, aY, aZ);
- return aTileEntity instanceof IMultiTileEntity
- ? ((IMultiTileEntity) aTileEntity).getExplosionResistance(aExploder, aExplosionX, aExplosionY, aExplosionZ)
+ return aTileEntity instanceof IMultiTileEntity mte
+ ? mte.getExplosionResistance(aExploder, aExplosionX, aExplosionY, aExplosionZ)
: 1.0F;
}
@@ -546,14 +555,14 @@ public class MultiTileEntityBlock extends Block implements IDebugableBlock, ITil
if (aWorld.isRemote) return;
final TileEntity aTileEntity = getTileEntity(aWorld, aX, aY, aZ, true);
if (aTileEntity != null) LAST_BROKEN_TILEENTITY.set(aTileEntity);
- if (aTileEntity instanceof IMultiTileEntity) {
+ if (aTileEntity instanceof IMultiTileEntity mte) {
GT_Log.exp.printf(
"Explosion at : %d | %d | %d DIMID: %s due to near explosion!%n",
aX,
aY,
aZ,
aWorld.provider.dimensionId);
- ((IMultiTileEntity) aTileEntity).onExploded(aExplosion);
+ mte.onExploded(aExplosion);
} else aWorld.setBlockToAir(aX, aY, aZ);
}
@@ -587,13 +596,13 @@ public class MultiTileEntityBlock extends Block implements IDebugableBlock, ITil
public final ItemStack getPickBlock(MovingObjectPosition aTarget, World aWorld, int aX, int aY, int aZ,
EntityPlayer aPlayer) {
final TileEntity aTileEntity = aWorld.getTileEntity(aX, aY, aZ);
- return aTileEntity instanceof IMultiTileEntity ? ((IMultiTileEntity) aTileEntity).getPickBlock(aTarget) : null;
+ return aTileEntity instanceof IMultiTileEntity mte ? mte.getPickBlock(aTarget) : null;
}
@Override
public final ItemStack getPickBlock(MovingObjectPosition aTarget, World aWorld, int aX, int aY, int aZ) {
final TileEntity aTileEntity = aWorld.getTileEntity(aX, aY, aZ);
- return aTileEntity instanceof IMultiTileEntity ? ((IMultiTileEntity) aTileEntity).getPickBlock(aTarget) : null;
+ return aTileEntity instanceof IMultiTileEntity mte ? mte.getPickBlock(aTarget) : null;
}
public final IMultiTileEntity receiveMultiTileEntityData(IBlockAccess aWorld, int aX, short aY, int aZ, short aRID,
@@ -601,9 +610,8 @@ public class MultiTileEntityBlock extends Block implements IDebugableBlock, ITil
if (!(aWorld instanceof World)) return null;
TileEntity aTileEntity = aWorld.getTileEntity(aX, aY, aZ);
- if (!(aTileEntity instanceof IMultiTileEntity)
- || ((IMultiTileEntity) aTileEntity).getMultiTileEntityRegistryID() != aRID
- || ((IMultiTileEntity) aTileEntity).getMultiTileEntityID() != aID) {
+ if (!(aTileEntity instanceof IMultiTileEntity mte) || mte.getMultiTileEntityRegistryID() != aRID
+ || mte.getMultiTileEntityID() != aID) {
final MultiTileEntityRegistry tRegistry = MultiTileEntityRegistry.getRegistry(aRID);
if (tRegistry == null) return null;
@@ -612,7 +620,7 @@ public class MultiTileEntityBlock extends Block implements IDebugableBlock, ITil
setTileEntity((World) aWorld, aX, aY, aZ, aTileEntity, false);
}
- return ((IMultiTileEntity) aTileEntity);
+ return (IMultiTileEntity) aTileEntity;
}
public void receiveCoverData(IMultiTileEntity mte, int aCover0, int aCover1, int aCover2, int aCover3, int aCover4,
@@ -629,14 +637,6 @@ public class MultiTileEntityBlock extends Block implements IDebugableBlock, ITil
mte.issueBlockUpdate();
}
}
- //
- // te.receiveClientEvent(GregTechTileClientEvents.CHANGE_COMMON_DATA, aTextureData);
- //
- // te.receiveClientEvent(GregTechTileClientEvents.CHANGE_CUSTOM_DATA, aUpdateData & 0x7F);
- // te.receiveClientEvent(GregTechTileClientEvents.CHANGE_CUSTOM_DATA, aTexturePage | 0x80);
- //
- // te.receiveClientEvent(GregTechTileClientEvents.CHANGE_COLOR, aColorData);
- // te.receiveClientEvent(GregTechTileClientEvents.CHANGE_REDSTONE_OUTPUT, aRedstoneData);
@Override
public final TileEntity createTileEntity(World aWorld, int aMeta) {
diff --git a/src/main/java/gregtech/api/multitileentity/MultiTileEntityClassContainer.java b/src/main/java/gregtech/api/multitileentity/MultiTileEntityClassContainer.java
index 3eae75f934..4ce4c3c886 100644
--- a/src/main/java/gregtech/api/multitileentity/MultiTileEntityClassContainer.java
+++ b/src/main/java/gregtech/api/multitileentity/MultiTileEntityClassContainer.java
@@ -13,6 +13,7 @@ import gregtech.api.multitileentity.multiblock.casing.FunctionalCasing;
import gregtech.api.multitileentity.multiblock.casing.UpgradeCasing;
import gregtech.api.util.GT_Util;
import gregtech.common.tileentities.casings.upgrade.Inventory;
+import gregtech.common.tileentities.casings.upgrade.Tank;
public class MultiTileEntityClassContainer {
@@ -144,6 +145,23 @@ public class MultiTileEntityClassContainer {
return this;
}
+ public MultiTileEntityClassContainer upgradeTankCount(int count) {
+ verifyDescendentOf(Tank.class);
+
+ mParameters.setInteger(NBT.UPGRADE_TANK_COUNT, count);
+ return this;
+ }
+
+ public MultiTileEntityClassContainer upgradeTankCapacity(Long aCapacity) {
+ mParameters.setLong(NBT.UPGRADE_TANK_CAPACITY, aCapacity);
+ return this;
+ }
+
+ public MultiTileEntityClassContainer upgradeAmperage(long amperage) {
+ mParameters.setLong(NBT.UPGRADE_AMPERAGE, amperage);
+ return this;
+ }
+
@SuppressWarnings("unused")
public MultiTileEntityClassContainer setNBT(String key, Object val) {
return setNBT(new Tuple(key, val));
diff --git a/src/main/java/gregtech/api/multitileentity/MultiTileEntityItemInternal.java b/src/main/java/gregtech/api/multitileentity/MultiTileEntityItemInternal.java
index 07a9124df4..cc10485f84 100644
--- a/src/main/java/gregtech/api/multitileentity/MultiTileEntityItemInternal.java
+++ b/src/main/java/gregtech/api/multitileentity/MultiTileEntityItemInternal.java
@@ -51,14 +51,14 @@ public class MultiTileEntityItemInternal extends ItemBlock implements IFluidCont
@SuppressWarnings("unchecked")
public void addInformation(ItemStack aStack, EntityPlayer aPlayer, List<String> aList, boolean aF3_H) {
final MultiTileEntityContainer tTileEntityContainer = mBlock.mMultiTileEntityRegistry
- .getNewTileEntityContainer(aStack);
+ .getCachedTileEntityContainer(aStack);
if (tTileEntityContainer == null) {
aList.add("INVALID ITEM!");
return;
}
- if (tTileEntityContainer.mTileEntity instanceof IMTE_AddToolTips) {
+ if (tTileEntityContainer.mTileEntity instanceof IMTE_AddToolTips mte) {
try {
- ((IMTE_AddToolTips) tTileEntityContainer.mTileEntity).addToolTips(aList, aStack, aF3_H);
+ mte.addToolTips(aList, aStack, aF3_H);
} catch (Throwable e) {
GT_FML_LOGGER.error("addInformation", e);
}
@@ -73,11 +73,9 @@ public class MultiTileEntityItemInternal extends ItemBlock implements IFluidCont
@SuppressWarnings("unchecked")
public void getSubItems(Item aItem, CreativeTabs aTab, List<ItemStack> aList) {
for (MultiTileEntityClassContainer tClass : mBlock.mMultiTileEntityRegistry.mRegistrations) {
- if (!tClass.mHidden) {
- if (((IMultiTileEntity) tClass.mCanonicalTileEntity)
- .getSubItems(mBlock, aItem, aTab, aList, tClass.mID)) {
- aList.add(mBlock.mMultiTileEntityRegistry.getItem(tClass.mID));
- }
+ if (!tClass.mHidden && ((IMultiTileEntity) tClass.mCanonicalTileEntity)
+ .getSubItems(mBlock, aItem, aTab, aList, tClass.mID)) {
+ aList.add(mBlock.mMultiTileEntityRegistry.getItem(tClass.mID));
}
}
}
@@ -85,10 +83,15 @@ public class MultiTileEntityItemInternal extends ItemBlock implements IFluidCont
@Override
public boolean onItemUse(ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX, int aY, int aZ,
int ordinalSide, float aHitX, float aHitY, float aHitZ) {
+
if (aY < 0 || aY > aWorld.getHeight()) return false;
+
+ if (aPlayer == null) return false;
+
try {
ForgeDirection side = ForgeDirection.getOrientation(ordinalSide);
final Block tClickedBlock = aWorld.getBlock(aX, aY, aZ);
+
if (tClickedBlock instanceof BlockSnow && (aWorld.getBlockMetadata(aX, aY, aZ) & 7) < 1) {
ordinalSide = SIDE_TOP;
side = ForgeDirection.UP;
@@ -102,79 +105,86 @@ public class MultiTileEntityItemInternal extends ItemBlock implements IFluidCont
final Block tReplacedBlock = aWorld.getBlock(aX, aY, aZ);
if (!tReplacedBlock.isReplaceable(aWorld, aX, aY, aZ)
- || !mBlock.canReplace(aWorld, aX, aY, aZ, ordinalSide, aStack)) return false;
- if (aStack.stackSize == 0 || (aPlayer != null && !aPlayer.canPlayerEdit(aX, aY, aZ, ordinalSide, aStack)))
+ || !mBlock.canReplace(aWorld, aX, aY, aZ, ordinalSide, aStack)) {
return false;
+ }
+
+ if (aStack.stackSize == 0 || (!aPlayer.canPlayerEdit(aX, aY, aZ, ordinalSide, aStack))) {
+ return false;
+ }
final MultiTileEntityContainer aMTEContainer = mBlock.mMultiTileEntityRegistry
.getNewTileEntityContainer(aWorld, aX, aY, aZ, aStack);
- if (aMTEContainer != null
- && (aPlayer == null || aPlayer.isSneaking()
- || !(aMTEContainer.mTileEntity instanceof IMTE_OnlyPlaceableWhenSneaking mteSNeaking)
- || !mteSNeaking.onlyPlaceableWhenSneaking())
- && (aWorld.checkNoEntityCollision(AxisAlignedBB.getBoundingBox(aX, aY, aZ, aX + 1, aY + 1, aZ + 1))
- || (aMTEContainer.mTileEntity instanceof IMTE_IgnoreEntityCollisionWhenPlacing mteIgnoreCollision
- && mteIgnoreCollision.ignoreEntityCollisionWhenPlacing(
- aStack,
- aPlayer,
- aWorld,
- aX,
- aY,
- aZ,
- side,
- aHitX,
- aHitY,
- aHitZ)))
- && (!(aMTEContainer.mTileEntity instanceof IMTE_CanPlace mteCanPlace)
- || mteCanPlace.canPlace(aStack, aPlayer, aWorld, aX, aY, aZ, side, aHitX, aHitY, aHitZ))
- && aWorld.setBlock(aX, aY, aZ, aMTEContainer.mBlock, 15 - aMTEContainer.mBlockMetaData, 2)) {
- aMTEContainer.setMultiTile(aWorld, aX, aY, aZ);
-
- try {
- if (((IMultiTileEntity) aMTEContainer.mTileEntity)
- .onPlaced(aStack, aPlayer, aWorld, aX, aY, aZ, side, aHitX, aHitY, aHitZ)) {
- aWorld.playSoundEffect(
- aX + 0.5,
- aY + 0.5,
- aZ + 0.5,
- aMTEContainer.mBlock.stepSound.func_150496_b(),
- (aMTEContainer.mBlock.stepSound.getVolume() + 1) / 2,
- aMTEContainer.mBlock.stepSound.getPitch() * 0.8F);
- }
- } catch (Throwable e) {
- GT_FML_LOGGER.error("onPlaced", e);
- }
- try {
- if (aMTEContainer.mTileEntity instanceof IMTE_HasMultiBlockMachineRelevantData mteData
- && (mteData.hasMultiBlockMachineRelevantData())) {
- GregTech_API.causeMachineUpdate(aWorld, aX, aY, aZ);
- }
- } catch (Throwable e) {
- GT_FML_LOGGER.error("causeMachineUpdate", e);
- }
- try {
- if (!aWorld.isRemote) {
- aWorld.notifyBlockChange(aX, aY, aZ, tReplacedBlock);
- aWorld.func_147453_f /* updateNeighborsAboutBlockChange */(aX, aY, aZ, aMTEContainer.mBlock);
- }
- } catch (Throwable e) {
- GT_FML_LOGGER.error("notifyBlockChange", e);
+ if (aMTEContainer == null) return false;
+
+ if (!aPlayer.isSneaking() && aMTEContainer.mTileEntity instanceof IMTE_OnlyPlaceableWhenSneaking mteSNeaking
+ && mteSNeaking.onlyPlaceableWhenSneaking()) {
+ return false;
+ }
+
+ if ((!(aMTEContainer.mTileEntity instanceof IMTE_IgnoreEntityCollisionWhenPlacing mteIgnoreCollision)
+ || !mteIgnoreCollision
+ .ignoreEntityCollisionWhenPlacing(aStack, aPlayer, aWorld, aX, aY, aZ, side, aHitX, aHitY, aHitZ))
+ && !aWorld.checkNoEntityCollision(AxisAlignedBB.getBoundingBox(aX, aY, aZ, aX + 1, aY + 1, aZ + 1))) {
+ return false;
+ }
+
+ if (aMTEContainer.mTileEntity instanceof IMTE_CanPlace mteCanPlace
+ && !mteCanPlace.canPlace(aStack, aPlayer, aWorld, aX, aY, aZ, side, aHitX, aHitY, aHitZ)) {
+ return false;
+ }
+
+ if (!aWorld.setBlock(aX, aY, aZ, aMTEContainer.mBlock, 15 - aMTEContainer.mBlockMetaData, 2)) {
+ return false;
+ }
+
+ aMTEContainer.setMultiTile(aWorld, aX, aY, aZ);
+
+ try {
+ if (((IMultiTileEntity) aMTEContainer.mTileEntity)
+ .onPlaced(aStack, aPlayer, aWorld, aX, aY, aZ, side, aHitX, aHitY, aHitZ)) {
+ aWorld.playSoundEffect(
+ aX + 0.5,
+ aY + 0.5,
+ aZ + 0.5,
+ aMTEContainer.mBlock.stepSound.func_150496_b(),
+ (aMTEContainer.mBlock.stepSound.getVolume() + 1) / 2,
+ aMTEContainer.mBlock.stepSound.getPitch() * 0.8F);
}
- try {
- ((IMultiTileEntity) aMTEContainer.mTileEntity).onTileEntityPlaced();
- } catch (Throwable e) {
- GT_FML_LOGGER.error("onTileEntityPlaced", e);
+ } catch (Throwable e) {
+ GT_FML_LOGGER.error("onPlaced", e);
+ }
+ try {
+ if (aMTEContainer.mTileEntity instanceof IMTE_HasMultiBlockMachineRelevantData mteData
+ && (mteData.hasMultiBlockMachineRelevantData())) {
+ GregTech_API.causeMachineUpdate(aWorld, aX, aY, aZ);
}
- try {
- aWorld.func_147451_t /* updateAllLightTypes */(aX, aY, aZ);
- } catch (Throwable e) {
- GT_FML_LOGGER.error("updateAllLightTypes", e);
+ } catch (Throwable e) {
+ GT_FML_LOGGER.error("causeMachineUpdate", e);
+ }
+ try {
+ if (!aWorld.isRemote) {
+ aWorld.notifyBlockChange(aX, aY, aZ, tReplacedBlock);
+ aWorld.func_147453_f /* updateNeighborsAboutBlockChange */(aX, aY, aZ, aMTEContainer.mBlock);
}
-
- aStack.stackSize--;
- return true;
+ } catch (Throwable e) {
+ GT_FML_LOGGER.error("notifyBlockChange", e);
+ }
+ try {
+ ((IMultiTileEntity) aMTEContainer.mTileEntity).onTileEntityPlaced();
+ } catch (Throwable e) {
+ GT_FML_LOGGER.error("onTileEntityPlaced", e);
}
+ try {
+ aWorld.func_147451_t /* updateAllLightTypes */(aX, aY, aZ);
+ } catch (Throwable e) {
+ GT_FML_LOGGER.error("updateAllLightTypes", e);
+ }
+
+ aStack.stackSize--;
+ return true;
+
} catch (Throwable e) {
GT_FML_LOGGER.error("onItemUse", e);
}
@@ -186,7 +196,7 @@ public class MultiTileEntityItemInternal extends ItemBlock implements IFluidCont
final MultiTileEntityClassContainer tContainer = mBlock.mMultiTileEntityRegistry.getClassContainer(aStack);
if (tContainer == null) return;
final MultiTileEntityContainer tTileEntityContainer = mBlock.mMultiTileEntityRegistry
- .getNewTileEntityContainer(aStack);
+ .getCachedTileEntityContainer(aStack);
if (tTileEntityContainer != null && tTileEntityContainer.mTileEntity instanceof IItemUpdatable itemUpdatable) {
itemUpdatable.updateItemStack(aStack);
}
@@ -197,7 +207,7 @@ public class MultiTileEntityItemInternal extends ItemBlock implements IFluidCont
final MultiTileEntityClassContainer tContainer = mBlock.mMultiTileEntityRegistry.getClassContainer(aStack);
if (tContainer == null) return;
final MultiTileEntityContainer tTileEntityContainer = mBlock.mMultiTileEntityRegistry
- .getNewTileEntityContainer(aStack);
+ .getCachedTileEntityContainer(aStack);
if (tTileEntityContainer != null && tTileEntityContainer.mTileEntity instanceof IItemUpdatable itemUpdatable) {
itemUpdatable.updateItemStack(aStack, aWorld, aX, aY, aZ);
}
@@ -208,7 +218,7 @@ public class MultiTileEntityItemInternal extends ItemBlock implements IFluidCont
final MultiTileEntityClassContainer tContainer = mBlock.mMultiTileEntityRegistry.getClassContainer(aStack);
if (tContainer == null) return 1;
final MultiTileEntityContainer tTileEntityContainer = mBlock.mMultiTileEntityRegistry
- .getNewTileEntityContainer(aStack);
+ .getCachedTileEntityContainer(aStack);
if (tTileEntityContainer != null
&& tTileEntityContainer.mTileEntity instanceof IMTE_GetMaxStackSize maxStackSize) {
return maxStackSize.getMaxStackSize(aStack, tContainer.mStackSize);
@@ -224,7 +234,7 @@ public class MultiTileEntityItemInternal extends ItemBlock implements IFluidCont
@Override
public FluidStack getFluid(ItemStack aStack) {
final MultiTileEntityContainer tTileEntityContainer = mBlock.mMultiTileEntityRegistry
- .getNewTileEntityContainer(aStack);
+ .getCachedTileEntityContainer(aStack);
if (tTileEntityContainer != null
&& tTileEntityContainer.mTileEntity instanceof IFluidContainerItem fluidContainerItem) {
final FluidStack rFluid = fluidContainerItem.getFluid(aStack);
@@ -237,7 +247,7 @@ public class MultiTileEntityItemInternal extends ItemBlock implements IFluidCont
@Override
public int getCapacity(ItemStack aStack) {
final MultiTileEntityContainer tTileEntityContainer = mBlock.mMultiTileEntityRegistry
- .getNewTileEntityContainer(aStack);
+ .getCachedTileEntityContainer(aStack);
if (tTileEntityContainer != null
&& tTileEntityContainer.mTileEntity instanceof IFluidContainerItem fluidContainerItem) {
final int rCapacity = fluidContainerItem.getCapacity(aStack);
@@ -250,7 +260,7 @@ public class MultiTileEntityItemInternal extends ItemBlock implements IFluidCont
@Override
public int fill(ItemStack aStack, FluidStack aFluid, boolean aDoFill) {
final MultiTileEntityContainer tTileEntityContainer = mBlock.mMultiTileEntityRegistry
- .getNewTileEntityContainer(aStack);
+ .getCachedTileEntityContainer(aStack);
if (tTileEntityContainer != null
&& tTileEntityContainer.mTileEntity instanceof IFluidContainerItem fluidContainerItem) {
final int tFilled = fluidContainerItem.fill(aStack, aFluid, aDoFill);
@@ -263,7 +273,7 @@ public class MultiTileEntityItemInternal extends ItemBlock implements IFluidCont
@Override
public FluidStack drain(ItemStack aStack, int aMaxDrain, boolean aDoDrain) {
final MultiTileEntityContainer tTileEntityContainer = mBlock.mMultiTileEntityRegistry
- .getNewTileEntityContainer(aStack);
+ .getCachedTileEntityContainer(aStack);
if (tTileEntityContainer != null
&& tTileEntityContainer.mTileEntity instanceof IFluidContainerItem fluidContainerItem) {
final FluidStack rFluid = fluidContainerItem.drain(aStack, aMaxDrain, aDoDrain);
diff --git a/src/main/java/gregtech/api/multitileentity/MultiTileEntityRegistry.java b/src/main/java/gregtech/api/multitileentity/MultiTileEntityRegistry.java
index 45117773fe..a5e30fb76c 100644
--- a/src/main/java/gregtech/api/multitileentity/MultiTileEntityRegistry.java
+++ b/src/main/java/gregtech/api/multitileentity/MultiTileEntityRegistry.java
@@ -38,6 +38,7 @@ public class MultiTileEntityRegistry {
// TODO: NBT sensitive or not? Starting with not for now
private static final ItemStackMap<MultiTileEntityRegistry> REGISTRIES = new ItemStackMap<>(false);
private static final HashSet<Class<?>> sRegisteredTileEntities = new HashSet<>();
+ private final HashMap<Integer, MultiTileEntityContainer> cachedTileEntityContainers = new HashMap<>();
public HashMap<Short, CreativeTab> mCreativeTabs = new HashMap<>();
public Map<Short, MultiTileEntityClassContainer> mRegistry = new HashMap<>();
@@ -80,7 +81,7 @@ public class MultiTileEntityRegistry {
mBlock = aBlock;
GT_FML_LOGGER.info(aNameInternal + " " + Block.getIdFromBlock(aBlock) + "This is the answer");
mBlock.mMultiTileEntityRegistry = this;
- REGISTRIES.put(new ItemStack(Item.getItemFromBlock(aBlock), 1, GT_Values.W), this);
+ REGISTRIES.put(new ItemStack(Item.getItemById(Block.getIdFromBlock(aBlock)), 1, GT_Values.W), this);
NAMED_REGISTRIES.put(mNameInternal, this);
}
@@ -267,6 +268,15 @@ public class MultiTileEntityRegistry {
return tContainer == null ? null : tContainer.mTileEntity;
}
+ public MultiTileEntityContainer getCachedTileEntityContainer(ItemStack stack) {
+ MultiTileEntityContainer container = cachedTileEntityContainers.get(Items.feather.getDamage(stack));
+ if (container == null) {
+ container = getNewTileEntityContainer(stack);
+ cachedTileEntityContainers.put(Items.feather.getDamage(stack), container);
+ }
+ return container;
+ }
+
public MultiTileEntityContainer getNewTileEntityContainer(ItemStack aStack) {
return getNewTileEntityContainer(null, 0, 0, 0, Items.feather.getDamage(aStack), aStack.getTagCompound());
}
diff --git a/src/main/java/gregtech/api/multitileentity/base/MultiTileEntity.java b/src/main/java/gregtech/api/multitileentity/base/MultiTileEntity.java
index 4b2a5aca67..3d98663e6d 100644
--- a/src/main/java/gregtech/api/multitileentity/base/MultiTileEntity.java
+++ b/src/main/java/gregtech/api/multitileentity/base/MultiTileEntity.java
@@ -8,6 +8,8 @@ import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
+import javax.annotation.Nonnull;
+
import net.minecraft.block.Block;
import net.minecraft.client.Minecraft;
import net.minecraft.creativetab.CreativeTabs;
@@ -16,6 +18,7 @@ import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.init.Items;
import net.minecraft.item.Item;
+import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.Packet;
@@ -28,9 +31,6 @@ import net.minecraft.world.Explosion;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.fluids.Fluid;
-import net.minecraftforge.fluids.FluidStack;
-import net.minecraftforge.fluids.FluidTankInfo;
-import net.minecraftforge.fluids.IFluidTank;
import com.gtnewhorizons.modularui.common.internal.network.NetworkUtils;
@@ -90,6 +90,7 @@ public abstract class MultiTileEntity extends CoverableTileEntity
protected boolean needsUpdate = false;
protected boolean hasInventoryChanged = false;
protected boolean isPainted = false;
+ @Nonnull
protected ForgeDirection facing = ForgeDirection.WEST; // Default to WEST, so it renders facing Left in the
// inventory
protected byte color;
@@ -203,12 +204,6 @@ public abstract class MultiTileEntity extends CoverableTileEntity
}
@Override
- public ITexture[] getTexture(Block ignoredBlock, ForgeDirection ignoredSide) {
- // We are not going to be using this
- return null;
- }
-
- @Override
public void readFromNBT(NBTTagCompound nbt) {
// Check if it is a World/Chunk-Loading Process calling readFromNBT
if (mteID == GT_Values.W || mteRegistry == GT_Values.W) {
@@ -231,7 +226,7 @@ public abstract class MultiTileEntity extends CoverableTileEntity
if (nbt.hasKey("y")) yCoord = nbt.getInteger("y");
if (nbt.hasKey("z")) zCoord = nbt.getInteger("z");
// read the custom Name.
- if (nbt.hasKey(NBT.DISPAY)) customName = nbt.getCompoundTag(NBT.DISPAY)
+ if (nbt.hasKey(NBT.DISPLAY)) customName = nbt.getCompoundTag(NBT.DISPLAY)
.getString(NBT.CUSTOM_NAME);
// And now everything else.
@@ -249,6 +244,7 @@ public abstract class MultiTileEntity extends CoverableTileEntity
if (nbt.hasKey(NBT.FACING)) facing = ForgeDirection.getOrientation(nbt.getInteger(NBT.FACING));
readCoverNBT(nbt);
+ readTasksNBT(nbt);
readMultiTileNBT(nbt);
if (NetworkUtils.isDedicatedClient()) {
@@ -272,6 +268,8 @@ public abstract class MultiTileEntity extends CoverableTileEntity
/* Do Nothing */
}
+ protected void readTasksNBT(NBTTagCompound nbt) {}
+
@Override
public final void writeToNBT(NBTTagCompound aNBT) {
super.writeToNBT(aNBT);
@@ -281,11 +279,11 @@ public abstract class MultiTileEntity extends CoverableTileEntity
// write the Custom Name
if (GT_Utility.isStringValid(customName)) {
final NBTTagCompound displayNBT;
- if (aNBT.hasKey(NBT.DISPAY)) {
- displayNBT = aNBT.getCompoundTag(NBT.DISPAY);
+ if (aNBT.hasKey(NBT.DISPLAY)) {
+ displayNBT = aNBT.getCompoundTag(NBT.DISPLAY);
} else {
displayNBT = new NBTTagCompound();
- aNBT.setTag(NBT.DISPAY, displayNBT);
+ aNBT.setTag(NBT.DISPLAY, displayNBT);
}
displayNBT.setString(NBT.CUSTOM_NAME, customName);
}
@@ -298,6 +296,7 @@ public abstract class MultiTileEntity extends CoverableTileEntity
aNBT.setInteger(NBT.FACING, facing.ordinal());
writeCoverNBT(aNBT, false);
+ writeTasksNBT(aNBT);
writeMultiTileNBT(aNBT);
} catch (Throwable e) {
GT_FML_LOGGER.error("writeToNBT", e);
@@ -308,10 +307,13 @@ public abstract class MultiTileEntity extends CoverableTileEntity
/* Do Nothing */
}
+ protected void writeTasksNBT(NBTTagCompound aNBT) {}
+
@Override
public NBTTagCompound writeItemNBT(NBTTagCompound aNBT) {
writeCoverNBT(aNBT, true);
if (shouldSaveNBTToItemStack()) {
+ writeTasksNBT(aNBT);
writeMultiTileNBT(aNBT);
}
return aNBT;
@@ -711,6 +713,8 @@ public abstract class MultiTileEntity extends CoverableTileEntity
public boolean onPlaced(ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX, int aY, int aZ,
ForgeDirection side, float aHitX, float aHitY, float aHitZ) {
facing = getSideForPlayerPlacing(aPlayer, facing, getValidFacings());
+ setOwnerUuid(aPlayer.getUniqueID());
+ setOwnerName(aPlayer.getDisplayName());
onFacingChange();
return true;
}
@@ -749,8 +753,7 @@ public abstract class MultiTileEntity extends CoverableTileEntity
}
if (!getCoverInfoAtSide(side).isGUIClickable()) return false;
- }
- if (isServerSide()) {
+ } else { // server side
if (!privateAccess() || aPlayer.getDisplayName()
.equalsIgnoreCase(getOwnerName())) {
final ItemStack tCurrentItem = aPlayer.inventory.getCurrentItem();
@@ -836,6 +839,11 @@ public abstract class MultiTileEntity extends CoverableTileEntity
if (!getCoverInfoAtSide(side).isGUIClickable()) return false;
+ if (aPlayer.getHeldItem() != null && aPlayer.getHeldItem()
+ .getItem() instanceof ItemBlock) {
+ return false;
+ }
+
return openModularUi(aPlayer, side);
}
}
@@ -1060,7 +1068,7 @@ public abstract class MultiTileEntity extends CoverableTileEntity
}
@Override
- public boolean receiveClientEvent(int aEventID, int aValue) {
+ public boolean receiveClientData(int aEventID, int aValue) {
super.receiveClientEvent(aEventID, aValue);
if (isClientSide()) {
issueTextureUpdate();
@@ -1127,11 +1135,6 @@ public abstract class MultiTileEntity extends CoverableTileEntity
}
@Override
- public boolean hasCustomInventoryName() {
- return false;
- }
-
- @Override
public ArrayList<String> getDebugInfo(EntityPlayer aPlayer, int aLogLevel) {
final ArrayList<String> tList = new ArrayList<>();
if (aLogLevel > 2) {
@@ -1155,82 +1158,6 @@ public abstract class MultiTileEntity extends CoverableTileEntity
}
/**
- * Fluid - A Default implementation of the Fluid Tank behaviour, so that every TileEntity can use this to simplify
- * its Code.
- */
- protected IFluidTank getFluidTankFillable(ForgeDirection side, FluidStack aFluidToFill) {
- return null;
- }
-
- protected IFluidTank getFluidTankDrainable(ForgeDirection side, FluidStack aFluidToDrain) {
- return null;
- }
-
- protected IFluidTank[] getFluidTanks(ForgeDirection side) {
- return GT_Values.emptyFluidTank;
- }
-
- public boolean isLiquidInput(ForgeDirection side) {
- return true;
- }
-
- public boolean isLiquidOutput(ForgeDirection side) {
- return true;
- }
-
- @Override
- public int fill(ForgeDirection aDirection, FluidStack aFluid, boolean aDoFill) {
- if (aFluid == null || aFluid.amount <= 0) return 0;
- final IFluidTank tTank = getFluidTankFillable(aDirection, aFluid);
- return (tTank == null) ? 0 : tTank.fill(aFluid, aDoFill);
- }
-
- @Override
- public FluidStack drain(ForgeDirection aDirection, FluidStack aFluid, boolean aDoDrain) {
- if (aFluid == null || aFluid.amount <= 0) return null;
- final IFluidTank tTank = getFluidTankDrainable(aDirection, aFluid);
- if (tTank == null || tTank.getFluid() == null
- || tTank.getFluidAmount() == 0
- || !tTank.getFluid()
- .isFluidEqual(aFluid))
- return null;
- return tTank.drain(aFluid.amount, aDoDrain);
- }
-
- @Override
- public FluidStack drain(ForgeDirection aDirection, int aAmountToDrain, boolean aDoDrain) {
- if (aAmountToDrain <= 0) return null;
- final IFluidTank tTank = getFluidTankDrainable(aDirection, null);
- if (tTank == null || tTank.getFluid() == null || tTank.getFluidAmount() == 0) return null;
- return tTank.drain(aAmountToDrain, aDoDrain);
- }
-
- @Override
- public boolean canFill(ForgeDirection aDirection, Fluid aFluid) {
- if (aFluid == null) return false;
- final IFluidTank tTank = getFluidTankFillable(aDirection, new FluidStack(aFluid, 0));
- return tTank != null && (tTank.getFluid() == null || tTank.getFluid()
- .getFluid() == aFluid);
- }
-
- @Override
- public boolean canDrain(ForgeDirection aDirection, Fluid aFluid) {
- if (aFluid == null) return false;
- final IFluidTank tTank = getFluidTankDrainable(aDirection, new FluidStack(aFluid, 0));
- return tTank != null && (tTank.getFluid() != null && tTank.getFluid()
- .getFluid() == aFluid);
- }
-
- @Override
- public FluidTankInfo[] getTankInfo(ForgeDirection aDirection) {
- final IFluidTank[] tTanks = getFluidTanks(aDirection);
- if (tTanks == null || tTanks.length <= 0) return GT_Values.emptyFluidTankInfo;
- final FluidTankInfo[] rInfo = new FluidTankInfo[tTanks.length];
- for (int i = 0; i < tTanks.length; i++) rInfo[i] = new FluidTankInfo(tTanks[i]);
- return rInfo;
- }
-
- /**
* Energy - Do nothing by Default
*/
@Override
@@ -1321,17 +1248,6 @@ public abstract class MultiTileEntity extends CoverableTileEntity
/**
* Inventory - Do nothing by default
*/
- @Override
- public void openInventory() {
- System.out.println("Open Inventory");
- /* Do nothing */
- }
-
- @Override
- public void closeInventory() {
- System.out.println("Close Inventory");
- /* Do nothing */
- }
@Override
public boolean hasInventoryBeenModified() {
@@ -1354,56 +1270,6 @@ public abstract class MultiTileEntity extends CoverableTileEntity
}
@Override
- public int[] getAccessibleSlotsFromSide(int ordinalSide) {
- return GT_Values.emptyIntArray;
- }
-
- @Override
- public boolean canInsertItem(int aSlot, ItemStack aStack, int ordinalSide) {
- return false;
- }
-
- @Override
- public boolean canExtractItem(int aSlot, ItemStack aStack, int ordinalSide) {
- return false;
- }
-
- @Override
- public int getSizeInventory() {
- return 0;
- }
-
- @Override
- public ItemStack getStackInSlot(int aSlot) {
- return null;
- }
-
- @Override
- public ItemStack decrStackSize(int aSlot, int aDecrement) {
- return null;
- }
-
- @Override
- public ItemStack getStackInSlotOnClosing(int aSlot) {
- return null;
- }
-
- @Override
- public void setInventorySlotContents(int aSlot, ItemStack aStack) {
- /* Do nothing */
- }
-
- @Override
- public int getInventoryStackLimit() {
- return 0;
- }
-
- @Override
- public boolean isItemValidForSlot(int aSlot, ItemStack aStack) {
- return false;
- }
-
- @Override
public void markInventoryBeenModified() {
hasInventoryChanged = true;
}
diff --git a/src/main/java/gregtech/api/multitileentity/base/TickableMultiTileEntity.java b/src/main/java/gregtech/api/multitileentity/base/TickableMultiTileEntity.java
index d61f32813f..9dcfce6d43 100644
--- a/src/main/java/gregtech/api/multitileentity/base/TickableMultiTileEntity.java
+++ b/src/main/java/gregtech/api/multitileentity/base/TickableMultiTileEntity.java
@@ -2,16 +2,26 @@ package gregtech.api.multitileentity.base;
import static gregtech.GT_Mod.GT_FML_LOGGER;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayerMP;
+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.multitileentity.interfaces.IMultiTileEntity.IMTE_OnNeighborBlockChange;
+import gregtech.api.task.TaskHost;
+import gregtech.api.task.TickableTask;
import gregtech.api.util.GT_Log;
import gregtech.api.util.GT_Util;
-public abstract class TickableMultiTileEntity extends MultiTileEntity implements IMTE_OnNeighborBlockChange {
+public abstract class TickableMultiTileEntity extends MultiTileEntity implements TaskHost, IMTE_OnNeighborBlockChange {
/** Variable for seeing if the Tick Function is called right now. */
public boolean isRunningTick = false;
@@ -22,11 +32,26 @@ public abstract class TickableMultiTileEntity extends MultiTileEntity implements
/** Variable for updating Data to the Client */
private boolean sendClientData = false;
+ private final Map<String, TickableTask<?>> tasks = new HashMap<>();
+
public TickableMultiTileEntity() {
super(true);
}
@Override
+ public final void registerTask(@Nonnull TickableTask<?> task) {
+ if (tasks.containsKey(task.getName())) {
+ throw new IllegalStateException(String.format("Task with name %s is already registered", task.getName()));
+ }
+ tasks.put(task.getName(), task);
+ }
+
+ @Nullable
+ public TickableTask<?> getTask(@Nonnull String name) {
+ return tasks.get(name);
+ }
+
+ @Override
public final void updateEntity() {
isRunningTick = true;
final boolean isServerSide = isServerSide();
@@ -46,6 +71,9 @@ public abstract class TickableMultiTileEntity extends MultiTileEntity implements
needsUpdate = false;
}
onTick(timer, isServerSide);
+ for (TickableTask<?> task : tasks.values()) {
+ task.update(timer, isServerSide);
+ }
if (isServerSide && timer > 2 && sendClientData) {
sendClientData(null);
}
@@ -73,7 +101,9 @@ public abstract class TickableMultiTileEntity extends MultiTileEntity implements
}
}
- /** The very first Tick happening to this TileEntity */
+ /**
+ * The very first Tick happening to this TileEntity.
+ */
public void onFirstTick(boolean isServerSide) {
if (isServerSide) {
checkDropCover();
@@ -82,19 +112,48 @@ public abstract class TickableMultiTileEntity extends MultiTileEntity implements
}
}
- /** The first part of the Tick. */
- public void onPreTick(long aTick, boolean isServerSide) {}
+ /**
+ * The first part of the Tick, before block update.
+ */
+ public void onPreTick(long tick, boolean isServerSide) {}
- /** The regular Tick. */
- public void onTick(long tick, boolean isServerSide) {
+ /**
+ * The regular Tick. After block update, before sending data to client.
+ */
+ public void onTick(long tick, boolean isServerSide) {}
- }
+ /**
+ * The absolute last part of the Tick, after sending data to client.
+ */
+ public void onPostTick(long tick, boolean isServerSide) {}
- /** The absolute last part of the Tick. */
- public void onPostTick(long aTick, boolean isServerSide) {}
+ /**
+ * Gets called when there is an Exception/Error happening during one of the Tick methods.
+ */
+ public void onTickFailed(long tick, boolean isServerSide) {}
- /** Gets called when there is an Exception happening during one of the Tick Functions. */
- public void onTickFailed(long aTimer, boolean isServerSide) {}
+ @Override
+ protected final void readTasksNBT(NBTTagCompound nbt) {
+ if (nbt.hasKey(GT_Values.NBT.TASKS)) {
+ NBTTagCompound tasksTag = nbt.getCompoundTag(GT_Values.NBT.TASKS);
+ for (TickableTask<?> task : tasks.values()) {
+ if (tasksTag.hasKey(task.getName())) {
+ task.readFromNBT(tasksTag.getCompoundTag(task.getName()));
+ }
+ }
+ }
+ }
+
+ @Override
+ protected final void writeTasksNBT(NBTTagCompound aNBT) {
+ NBTTagCompound tasksTag = new NBTTagCompound();
+ for (TickableTask<?> task : tasks.values()) {
+ NBTTagCompound tag = new NBTTagCompound();
+ task.writeToNBT(tag);
+ tasksTag.setTag(task.getName(), tag);
+ }
+ aNBT.setTag(GT_Values.NBT.TASKS, tasksTag);
+ }
@Override
public void onNeighborBlockChange(World aWorld, Block aBlock) {
diff --git a/src/main/java/gregtech/api/multitileentity/enums/GT_MultiTileCasing.java b/src/main/java/gregtech/api/multitileentity/enums/GT_MultiTileCasing.java
index baa235ccf1..73bd55738a 100644
--- a/src/main/java/gregtech/api/multitileentity/enums/GT_MultiTileCasing.java
+++ b/src/main/java/gregtech/api/multitileentity/enums/GT_MultiTileCasing.java
@@ -1,20 +1,43 @@
package gregtech.api.multitileentity.enums;
+import static gregtech.api.util.GT_StructureUtilityMuTE.createMuTEStructureCasing;
+import static gregtech.loaders.preload.GT_Loader_MultiTileEntities.CASING_REGISTRY_NAME;
+
import gregtech.api.enums.GT_Values;
+import gregtech.api.util.GT_StructureUtilityMuTE;
public enum GT_MultiTileCasing {
CokeOven(0),
Chemical(1),
+ Distillation(2),
+ Macerator(18000),
+ LaserEngraver(4),
+ Mirror(5),
+ BlackLaserEngraverCasing(6),
+ LaserEngraverUpgrade1(7),
+ LaserEngraverUpgrade2(8),
+ LaserEngraverUpgrade3(9),
+ LaserEngraverUpgrade4(10),
NONE(GT_Values.W);
private final int meta;
+ private final GT_StructureUtilityMuTE.MuTEStructureCasing casing;
GT_MultiTileCasing(int meta) {
this.meta = meta;
+ casing = createMuTEStructureCasing(CASING_REGISTRY_NAME, meta);
}
public int getId() {
return meta;
}
+
+ public short getRegistryId() {
+ return (short) casing.getRegistryId();
+ }
+
+ public GT_StructureUtilityMuTE.MuTEStructureCasing getCasing() {
+ return casing;
+ }
}
diff --git a/src/main/java/gregtech/api/multitileentity/enums/GT_MultiTileUpgradeCasing.java b/src/main/java/gregtech/api/multitileentity/enums/GT_MultiTileUpgradeCasing.java
new file mode 100644
index 0000000000..296bae546d
--- /dev/null
+++ b/src/main/java/gregtech/api/multitileentity/enums/GT_MultiTileUpgradeCasing.java
@@ -0,0 +1,71 @@
+package gregtech.api.multitileentity.enums;
+
+import gregtech.api.enums.GT_Values;
+
+public enum GT_MultiTileUpgradeCasing {
+
+ ULV_Inventory(0),
+ LV_Inventory(1),
+ MV_Inventory(2),
+ HV_Inventory(3),
+ EV_Inventory(4),
+ IV_Inventory(5),
+ LuV_Inventory(6),
+ ZPM_Inventory(7),
+ UV_Inventory(8),
+ UHV_Inventory(9),
+ UEV_Inventory(10),
+ UIV_Inventory(11),
+ UXV_Inventory(12),
+ UMV_Inventory(13),
+ MAX_Inventory(14),
+ ULV_Tank(15),
+ LV_Tank(16),
+ MV_Tank(17),
+ HV_Tank(18),
+ EV_Tank(19),
+ IV_Tank(20),
+ LuV_Tank(21),
+ ZPM_Tank(22),
+ UV_Tank(23),
+ UHV_Tank(24),
+ UEV_Tank(25),
+ UIV_Tank(26),
+ UXV_Tank(27),
+ UMV_Tank(28),
+ MAX_Tank(29),
+ Amp_4(30),
+ Amp_16(31),
+ Amp_64(32),
+ Amp_256(33),
+ Amp_1_024(34),
+ Amp_4_096(35),
+ Amp_16_384(36),
+ Amp_65_536(37),
+ Amp_262_144(38),
+ Amp_1_048_576(39),
+ Laser(40),
+ Wireless(41),
+ Cleanroom(42),
+ Heater_Prototype(100),
+ Heater_IndustrialGrade(101),
+ Heater_NextGen(102),
+ Heater_Omnipotent(103),
+ Heater_OmegaType(104),
+ Insulator_Prototype(105),
+ Insulator_IndustrialGrade(106),
+ Insulator_NextGen(107),
+ Insulator_Omnipotent(108),
+ Insulator_OmegaType(109),
+ NONE(GT_Values.W);
+
+ private final int meta;
+
+ GT_MultiTileUpgradeCasing(int meta) {
+ this.meta = meta;
+ }
+
+ public int getId() {
+ return meta;
+ }
+}
diff --git a/src/main/java/gregtech/api/multitileentity/enums/MultiTileCasingPurpose.java b/src/main/java/gregtech/api/multitileentity/enums/MultiTileCasingPurpose.java
new file mode 100644
index 0000000000..2733da33cf
--- /dev/null
+++ b/src/main/java/gregtech/api/multitileentity/enums/MultiTileCasingPurpose.java
@@ -0,0 +1,13 @@
+package gregtech.api.multitileentity.enums;
+
+/**
+ * Purposes with which a casing can registered itself in the MuTE controller to be ticked.
+ * Can be used for example to auto output recipe outputs from output casings.
+ *
+ * @author minecraft7771
+ */
+public enum MultiTileCasingPurpose {
+ ItemOutput,
+ FluidOutput,
+ EnergyOutput,
+}
diff --git a/src/main/java/gregtech/api/multitileentity/interfaces/IMultiBlockController.java b/src/main/java/gregtech/api/multitileentity/interfaces/IMultiBlockController.java
index 8535c50790..58af918c50 100644
--- a/src/main/java/gregtech/api/multitileentity/interfaces/IMultiBlockController.java
+++ b/src/main/java/gregtech/api/multitileentity/interfaces/IMultiBlockController.java
@@ -1,16 +1,24 @@
package gregtech.api.multitileentity.interfaces;
+import java.util.UUID;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
import net.minecraft.util.ChunkCoordinates;
import net.minecraftforge.common.util.ForgeDirection;
-import net.minecraftforge.fluids.Fluid;
-import net.minecraftforge.fluids.FluidStack;
-import com.gtnewhorizons.modularui.api.screen.ModularWindow;
-import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import gregtech.api.enums.InventoryType;
+import gregtech.api.gui.GUIHost;
+import gregtech.api.logic.FluidInventoryLogic;
+import gregtech.api.logic.ItemInventoryLogic;
+import gregtech.api.logic.interfaces.FluidInventoryLogicHost;
+import gregtech.api.logic.interfaces.ItemInventoryLogicHost;
+import gregtech.api.logic.interfaces.PowerLogicHost;
+import gregtech.api.multitileentity.enums.MultiTileCasingPurpose;
-import gregtech.api.logic.PowerLogic;
-
-public interface IMultiBlockController extends IMultiTileEntity, IMultiBlockFluidHandler, IMultiBlockInventory {
+public interface IMultiBlockController
+ extends IMultiTileEntity, FluidInventoryLogicHost, ItemInventoryLogicHost, UpgradableMuTE, PowerLogicHost, GUIHost {
boolean checkStructure(boolean aForceReset);
@@ -20,25 +28,24 @@ public interface IMultiBlockController extends IMultiTileEntity, IMultiBlockFlui
@Override
ChunkCoordinates getCoords();
- FluidStack getDrainableFluid(ForgeDirection side);
-
- FluidStack getDrainableFluid(ForgeDirection side, Fluid fluid);
+ void registerCoveredPartOnSide(final ForgeDirection side, IMultiBlockPart part);
- boolean isLiquidInput(ForgeDirection side);
+ void unregisterCoveredPartOnSide(final ForgeDirection side, IMultiBlockPart part);
- boolean isLiquidOutput(ForgeDirection side);
+ void registerCaseWithPurpose(MultiTileCasingPurpose purpose, IMultiBlockPart part);
- void registerCoveredPartOnSide(final ForgeDirection side, IMultiBlockPart part);
+ void unregisterCaseWithPurpose(MultiTileCasingPurpose purpose, IMultiBlockPart part);
- void unregisterCoveredPartOnSide(final ForgeDirection side, IMultiBlockPart part);
+ UUID registerItemInventory(int slots, int tier, @Nonnull InventoryType type, boolean isUpgradeInventory);
- void registerInventory(String aName, String aID, int aInventorySize, int aType);
+ ItemInventoryLogic unregisterItemInventory(@Nonnull UUID id, @Nonnull InventoryType type);
- void unregisterInventory(String aName, String aID, int aType);
+ void changeItemInventoryDisplayName(@Nonnull UUID id, @Nullable String displayName, @Nonnull InventoryType type);
- void changeInventoryName(String aName, String aID, int aType);
+ UUID registerFluidInventory(int tanks, long capacity, int tier, @Nonnull InventoryType type,
+ boolean isUpgradeInventory);
- PowerLogic getPowerLogic(IMultiBlockPart part, ForgeDirection side);
+ FluidInventoryLogic unregisterFluidInventory(@Nonnull UUID id, @Nonnull InventoryType type);
- ModularWindow createWindowGUI(UIBuildContext buildContext);
+ void changeFluidInventoryDisplayName(@Nonnull UUID id, @Nullable String displayName, @Nonnull InventoryType type);
}
diff --git a/src/main/java/gregtech/api/multitileentity/interfaces/IMultiBlockPart.java b/src/main/java/gregtech/api/multitileentity/interfaces/IMultiBlockPart.java
index 017954f554..59d838fdeb 100644
--- a/src/main/java/gregtech/api/multitileentity/interfaces/IMultiBlockPart.java
+++ b/src/main/java/gregtech/api/multitileentity/interfaces/IMultiBlockPart.java
@@ -1,9 +1,14 @@
package gregtech.api.multitileentity.interfaces;
+import java.util.UUID;
+
import net.minecraft.util.ChunkCoordinates;
import net.minecraftforge.common.util.ForgeDirection;
-public interface IMultiBlockPart extends IMultiTileEntity {
+import gregtech.api.logic.interfaces.FluidInventoryLogicHost;
+import gregtech.api.logic.interfaces.ItemInventoryLogicHost;
+
+public interface IMultiBlockPart extends IMultiTileEntity, ItemInventoryLogicHost, FluidInventoryLogicHost {
ChunkCoordinates getTargetPos();
@@ -13,5 +18,9 @@ public interface IMultiBlockPart extends IMultiTileEntity {
int getLockedInventoryIndex();
+ UUID getLockedInventory();
+
boolean tickCoverAtSide(ForgeDirection side, long aTickTimer);
+
+ boolean shouldTick(long tickTimer);
}
diff --git a/src/main/java/gregtech/api/multitileentity/interfaces/IMultiTileEntity.java b/src/main/java/gregtech/api/multitileentity/interfaces/IMultiTileEntity.java
index 7925ebd5b9..91803690fc 100644
--- a/src/main/java/gregtech/api/multitileentity/interfaces/IMultiTileEntity.java
+++ b/src/main/java/gregtech/api/multitileentity/interfaces/IMultiTileEntity.java
@@ -17,18 +17,11 @@ import net.minecraft.util.MovingObjectPosition;
import net.minecraft.world.Explosion;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
-import net.minecraftforge.fluids.IFluidHandler;
import cpw.mods.fml.common.Optional;
import gregtech.api.enums.Mods;
-import gregtech.api.interfaces.tileentity.IBasicEnergyContainer;
-import gregtech.api.interfaces.tileentity.IColoredTileEntity;
import gregtech.api.interfaces.tileentity.ICoverable;
import gregtech.api.interfaces.tileentity.IDebugableTileEntity;
-import gregtech.api.interfaces.tileentity.IEnergyConnected;
-import gregtech.api.interfaces.tileentity.IHasInventory;
-import gregtech.api.interfaces.tileentity.IHasWorldObjectAndCoords;
-import gregtech.api.interfaces.tileentity.ITexturedTileEntity;
import gregtech.api.interfaces.tileentity.ITurnable;
import gregtech.api.multitileentity.MultiTileEntityBlockInternal;
import gregtech.api.multitileentity.MultiTileEntityItemInternal;
@@ -37,9 +30,7 @@ import gregtech.api.multitileentity.MultiTileEntityRegistry;
/*
* Heavily inspired by GT6
*/
-public interface IMultiTileEntity
- extends IHasWorldObjectAndCoords, ICoverable, ITurnable, IHasInventory, IEnergyConnected, IBasicEnergyContainer,
- IFluidHandler, ITexturedTileEntity, IDebugableTileEntity, IColoredTileEntity {
+public interface IMultiTileEntity extends ICoverable, ITurnable, IDebugableTileEntity {
/**
* Those two IDs HAVE to be saved inside the NBT of the TileEntity itself. They get set by the Registry itself, when
@@ -88,7 +79,7 @@ public interface IMultiTileEntity
void sendClientData(EntityPlayerMP aPlayer);
- boolean receiveClientEvent(int aEventID, int aValue);
+ boolean receiveClientData(int aEventID, int aValue);
void setShouldRefresh(boolean aShouldRefresh);
@@ -291,12 +282,12 @@ public interface IMultiTileEntity
interface IMTE_HasModes extends IMultiTileEntity {
- byte getMode();
+ int getMode();
- void setMode(byte aMode);
+ void setMode(int mode);
int getAllowedModes();
- void setAllowedModes(int aAllowedModes);
+ void setAllowedModes(int allowedModes);
}
}
diff --git a/src/main/java/gregtech/api/multitileentity/interfaces/UpgradableModularMuTE.java b/src/main/java/gregtech/api/multitileentity/interfaces/UpgradableModularMuTE.java
new file mode 100644
index 0000000000..3b4c3cb6f3
--- /dev/null
+++ b/src/main/java/gregtech/api/multitileentity/interfaces/UpgradableModularMuTE.java
@@ -0,0 +1,10 @@
+package gregtech.api.multitileentity.interfaces;
+
+import gregtech.api.util.GT_StructureUtilityMuTE.UpgradeCasings;
+
+public interface UpgradableModularMuTE extends UpgradableMuTE {
+
+ void increaseMucCount(UpgradeCasings casingType, int tier);
+
+ void resetMucCount();
+}
diff --git a/src/main/java/gregtech/api/multitileentity/interfaces/UpgradableMuTE.java b/src/main/java/gregtech/api/multitileentity/interfaces/UpgradableMuTE.java
new file mode 100644
index 0000000000..c18852c95e
--- /dev/null
+++ b/src/main/java/gregtech/api/multitileentity/interfaces/UpgradableMuTE.java
@@ -0,0 +1,12 @@
+package gregtech.api.multitileentity.interfaces;
+
+public interface UpgradableMuTE {
+
+ void setCleanroom(boolean isCleanroom);
+
+ void setWirelessSupport(boolean canUse);
+
+ void setLaserSupport(boolean canUse);
+
+ void setMaxAmperage(long amperage);
+}
diff --git a/src/main/java/gregtech/api/multitileentity/machine/MultiTileBasicMachine.java b/src/main/java/gregtech/api/multitileentity/machine/MultiTileBasicMachine.java
index 0b6d4f587d..19c052b96a 100644
--- a/src/main/java/gregtech/api/multitileentity/machine/MultiTileBasicMachine.java
+++ b/src/main/java/gregtech/api/multitileentity/machine/MultiTileBasicMachine.java
@@ -1,18 +1,19 @@
package gregtech.api.multitileentity.machine;
-import static com.google.common.primitives.Ints.saturatedCast;
-import static gregtech.api.enums.GT_Values.B;
-import static gregtech.api.enums.GT_Values.VN;
+import static gregtech.api.enums.GT_Values.*;
+import static gregtech.api.enums.TickTime.MINUTE;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.Objects;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
-import net.minecraft.nbt.NBTTagList;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityFurnace;
import net.minecraft.util.EnumChatFormatting;
@@ -20,26 +21,32 @@ import net.minecraft.util.ResourceLocation;
import net.minecraft.util.StatCollector;
import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.fluids.FluidStack;
-import net.minecraftforge.fluids.IFluidTank;
+
+import org.jetbrains.annotations.ApiStatus.OverrideOnly;
import com.gtnewhorizons.modularui.api.forge.IItemHandlerModifiable;
import com.gtnewhorizons.modularui.api.forge.ItemStackHandler;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import gregtech.api.enums.GT_Values;
import gregtech.api.enums.GT_Values.NBT;
+import gregtech.api.enums.InventoryType;
import gregtech.api.enums.Mods;
import gregtech.api.enums.SoundResource;
import gregtech.api.enums.Textures;
import gregtech.api.enums.Textures.BlockIcons.CustomIcon;
import gregtech.api.enums.TickTime;
-import gregtech.api.fluid.FluidTankGT;
+import gregtech.api.enums.VoidingMode;
+import gregtech.api.gui.GUIHost;
+import gregtech.api.gui.GUIProvider;
import gregtech.api.interfaces.ITexture;
-import gregtech.api.logic.PollutionLogic;
+import gregtech.api.logic.FluidInventoryLogic;
+import gregtech.api.logic.ItemInventoryLogic;
+import gregtech.api.logic.MuTEProcessingLogic;
+import gregtech.api.logic.NullPowerLogic;
import gregtech.api.logic.PowerLogic;
-import gregtech.api.logic.ProcessingLogic;
-import gregtech.api.logic.interfaces.PollutionLogicHost;
import gregtech.api.logic.interfaces.PowerLogicHost;
import gregtech.api.logic.interfaces.ProcessingLogicHost;
import gregtech.api.metatileentity.GregTechTileClientEvents;
@@ -47,13 +54,14 @@ import gregtech.api.multitileentity.MultiTileEntityRegistry;
import gregtech.api.multitileentity.base.TickableMultiTileEntity;
import gregtech.api.multitileentity.interfaces.IMultiTileMachine;
import gregtech.api.net.GT_Packet_MultiTileEntity;
-import gregtech.api.recipe.check.CheckRecipeResult;
import gregtech.api.render.TextureFactory;
+import gregtech.api.task.tasks.ProcessingTask;
import gregtech.api.util.GT_Utility;
import gregtech.client.GT_SoundLoop;
-import gregtech.common.GT_Pollution;
+import gregtech.common.gui.MachineGUIProvider;
-public abstract class MultiTileBasicMachine extends TickableMultiTileEntity implements IMultiTileMachine {
+public abstract class MultiTileBasicMachine<P extends MuTEProcessingLogic<P>> extends TickableMultiTileEntity
+ implements IMultiTileMachine, ProcessingLogicHost<P>, PowerLogicHost, GUIHost {
protected static final int ACTIVE = B[0];
protected static final int TICKS_BETWEEN_RECIPE_CHECKS = 5 * TickTime.SECOND;
@@ -70,22 +78,10 @@ public abstract class MultiTileBasicMachine extends TickableMultiTileEntity impl
protected int maxParallel = 1;
protected boolean active = false;
- protected long storedEnergy = 0;
- protected long voltage = 0;
- protected long amperage = 2;
- protected long eut = 0;
protected int tier = 0;
- protected long maxProgressTime = 0;
- protected long progressTime = 0;
protected long burnTime = 0;
protected long totalBurnTime = 0;
- protected FluidTankGT[] inputTanks = GT_Values.emptyFluidTankGT;
- protected FluidTankGT[] outputTanks = GT_Values.emptyFluidTankGT;
- protected FluidStack[] fluidsToOutput = GT_Values.emptyFluidStack;
- protected ItemStack[] itemsToOutput = GT_Values.emptyItemStackArray;
- protected IItemHandlerModifiable inputInventory = EMPTY_INVENTORY;
- protected IItemHandlerModifiable outputInventory = EMPTY_INVENTORY;
protected boolean outputInventoryChanged = false;
protected boolean powerShutDown = false;
protected boolean wasEnabled = false;
@@ -93,13 +89,30 @@ public abstract class MultiTileBasicMachine extends TickableMultiTileEntity impl
protected boolean isElectric = true;
protected boolean isSteam = false;
protected boolean acceptsFuel = false;
- protected boolean isWireless = false;
+
protected byte soundEvent = 0;
protected int soundEventValue = 0;
+ protected ItemInventoryLogic itemInput;
+ protected ItemInventoryLogic itemOutput;
+ protected FluidInventoryLogic fluidInput;
+ protected FluidInventoryLogic fluidOutput;
+
+ protected P processingLogic;
+ @Nonnull
+ protected VoidingMode voidingMode = VoidingMode.VOID_NONE;
+ protected boolean processingUpdate = false;
+ @Nonnull
+ protected PowerLogic power = createPowerLogic();
+ @Nonnull
+ protected GUIProvider<?> guiProvider = createGUIProvider();
@SideOnly(Side.CLIENT)
protected GT_SoundLoop activitySoundLoop;
+ public MultiTileBasicMachine() {
+ new ProcessingTask<>(this);
+ }
+
@Override
public String getTileEntityName() {
return "gt.multitileentity.machine.basic";
@@ -116,80 +129,34 @@ public abstract class MultiTileBasicMachine extends TickableMultiTileEntity impl
nbt.setBoolean(NBT.ACTIVE, active);
}
- if (inputInventory != null && inputInventory.getSlots() > 0) {
- writeInventory(nbt, inputInventory, NBT.INV_INPUT_LIST);
- }
-
- if (outputInventory != null && outputInventory.getSlots() > 0) {
- writeInventory(nbt, outputInventory, NBT.INV_OUTPUT_LIST);
- }
+ saveItemLogic(nbt);
+ saveFluidLogic(nbt);
- for (int i = 0; i < inputTanks.length; i++) {
- inputTanks[i].writeToNBT(nbt, NBT.TANK_IN + i);
- }
-
- for (int i = 0; i < outputTanks.length; i++) {
- outputTanks[i].writeToNBT(nbt, NBT.TANK_OUT + i);
- }
-
- if (fluidsToOutput != null && fluidsToOutput.length > 0) {
- writeFluids(nbt, fluidsToOutput, NBT.FLUID_OUT);
- }
-
- if (itemsToOutput != null) {
- saveItemsToOutput(nbt);
+ if (processingLogic != null) {
+ NBTTagCompound processingLogicNBT = processingLogic.saveToNBT();
+ nbt.setTag("processingLogic", processingLogicNBT);
}
nbt.setInteger(NBT.TIER, tier);
- nbt.setLong(NBT.EUT_CONSUMPTION, eut);
nbt.setLong(NBT.BURN_TIME_LEFT, burnTime);
nbt.setLong(NBT.TOTAL_BURN_TIME, totalBurnTime);
nbt.setBoolean(NBT.ALLOWED_WORK, canWork);
nbt.setBoolean(NBT.ACTIVE, active);
+ power.saveToNBT(nbt);
}
- protected void writeFluids(NBTTagCompound nbt, FluidStack[] fluids, String fluidListTag) {
- if (fluids != null && fluids.length > 0) {
- final NBTTagList tList = new NBTTagList();
- for (final FluidStack tFluid : fluids) {
- if (tFluid != null) {
- final NBTTagCompound tag = new NBTTagCompound();
- tFluid.writeToNBT(tag);
- tList.appendTag(tag);
- }
- }
- nbt.setTag(fluidListTag, tList);
- }
- }
-
- protected void writeInventory(NBTTagCompound nbt, IItemHandlerModifiable inv, String invListTag) {
- if (inv != null && inv.getSlots() > 0) {
- final NBTTagList tList = new NBTTagList();
- for (int slot = 0; slot < inv.getSlots(); slot++) {
- final ItemStack tStack = inv.getStackInSlot(slot);
- if (tStack != null) {
- final NBTTagCompound tag = new NBTTagCompound();
- tag.setByte("s", (byte) slot);
- tStack.writeToNBT(tag);
- tList.appendTag(tag);
- }
- }
- nbt.setTag(invListTag, tList);
- }
+ protected void saveItemLogic(NBTTagCompound nbt) {
+ NBTTagCompound nbtListInput = itemInput.saveToNBT();
+ nbt.setTag(NBT.INV_INPUT_LIST, nbtListInput);
+ NBTTagCompound nbtListOutput = itemOutput.saveToNBT();
+ nbt.setTag(NBT.INV_OUTPUT_LIST, nbtListOutput);
}
- protected void saveItemsToOutput(NBTTagCompound aNBT) {
- final NBTTagList nbtList = new NBTTagList();
- for (int slot = 0; slot < itemsToOutput.length; slot++) {
- final ItemStack itemStack = itemsToOutput[slot];
- if (itemStack != null) {
- final NBTTagCompound tag = new NBTTagCompound();
- tag.setByte("s", (byte) slot);
- itemStack.writeToNBT(tag);
- nbtList.appendTag(tag);
- }
- }
- aNBT.setTag(NBT.ITEM_OUT, nbtList);
+ protected void saveFluidLogic(NBTTagCompound nbt) {
+ NBTTagCompound fluidInputNBT = fluidInput.saveToNBT();
+ nbt.setTag(NBT.TANK_IN, fluidInputNBT);
+ NBTTagCompound fluidOutputNBT = fluidOutput.saveToNBT();
+ nbt.setTag(NBT.TANK_OUT, fluidOutputNBT);
}
@Override
@@ -203,63 +170,48 @@ public abstract class MultiTileBasicMachine extends TickableMultiTileEntity impl
active = nbt.getBoolean(NBT.ACTIVE);
}
- /* Inventories */
- inputInventory = new ItemStackHandler(Math.max(nbt.getInteger(NBT.INV_INPUT_SIZE), 0));
- outputInventory = new ItemStackHandler(Math.max(nbt.getInteger(NBT.INV_OUTPUT_SIZE), 0));
- loadInventory(nbt, inputInventory, NBT.INV_INPUT_LIST);
- loadInventory(nbt, outputInventory, NBT.INV_OUTPUT_LIST);
-
- /* Tanks */
- long capacity = 1000;
- if (nbt.hasKey(NBT.TANK_CAPACITY)) {
- capacity = saturatedCast(nbt.getLong(NBT.TANK_CAPACITY));
- }
-
- inputTanks = new FluidTankGT[getFluidInputCount()];
- outputTanks = new FluidTankGT[getFluidOutputCount()];
- fluidsToOutput = new FluidStack[getFluidOutputCount()];
-
- // TODO: See if we need the adjustable map here `.setCapacity(mRecipes, mParallel * 2L)` in place of the
- // `setCapacityMultiplier`
- for (int i = 0; i < inputTanks.length; i++) {
- inputTanks[i] = new FluidTankGT(capacity).setCapacityMultiplier(maxParallel * 2L)
- .readFromNBT(nbt, NBT.TANK_IN + i);
- }
- for (int i = 0; i < outputTanks.length; i++) {
- outputTanks[i] = new FluidTankGT(capacity).setCapacityMultiplier(maxParallel * 2L)
- .readFromNBT(nbt, NBT.TANK_OUT + i);
- }
+ loadItemLogic(nbt);
+ loadFluidLogic(nbt);
- for (int i = 0; i < fluidsToOutput.length; i++) {
- fluidsToOutput[i] = FluidStack.loadFluidStackFromNBT(nbt.getCompoundTag(NBT.FLUID_OUT + "." + i));
+ if (nbt.hasKey("processingLogic")) {
+ P processingLogic = getProcessingLogic();
+ processingLogic.loadFromNBT(Objects.requireNonNull(nbt.getCompoundTag("processingLogic")));
}
- loadItemsToOutput(nbt);
-
tier = nbt.getInteger(NBT.TIER);
- eut = nbt.getLong(NBT.EUT_CONSUMPTION);
burnTime = nbt.getLong(NBT.BURN_TIME_LEFT);
totalBurnTime = nbt.getLong(NBT.TOTAL_BURN_TIME);
canWork = nbt.getBoolean(NBT.ALLOWED_WORK);
active = nbt.getBoolean(NBT.ACTIVE);
+ power.loadFromNBT(nbt);
}
- protected void loadInventory(NBTTagCompound aNBT, IItemHandlerModifiable inv, String invListTag) {
- final NBTTagList tList = aNBT.getTagList(invListTag, 10);
- for (int i = 0; i < tList.tagCount(); i++) {
- final NBTTagCompound tNBT = tList.getCompoundTagAt(i);
- final int tSlot = tNBT.getShort("s");
- if (tSlot >= 0 && tSlot < inv.getSlots()) inv.setStackInSlot(tSlot, GT_Utility.loadItem(tNBT));
+ protected void loadItemLogic(NBTTagCompound nbt) {
+ itemInput = new ItemInventoryLogic(nbt.getInteger(NBT.INV_OUTPUT_SIZE), tier);
+ itemOutput = new ItemInventoryLogic(nbt.getInteger(NBT.INV_OUTPUT_SIZE), tier);
+ if (nbt.hasKey(NBT.INV_INPUT_LIST)) {
+ itemInput.loadFromNBT(nbt.getCompoundTag(NBT.INV_INPUT_LIST));
+ }
+ if (nbt.hasKey(NBT.INV_OUTPUT_LIST)) {
+ itemOutput.loadFromNBT(nbt.getCompoundTag(NBT.INV_OUTPUT_LIST));
}
}
- protected void loadItemsToOutput(NBTTagCompound aNBT) {
- final NBTTagList tList = aNBT.getTagList(NBT.ITEM_OUT, 10);
- itemsToOutput = new ItemStack[tList.tagCount()];
- for (int i = 0; i < tList.tagCount(); i++) {
- final NBTTagCompound tNBT = tList.getCompoundTagAt(i);
- final int tSlot = tNBT.getByte("s");
- if (tSlot >= 0 && tSlot < itemsToOutput.length) itemsToOutput[tSlot] = GT_Utility.loadItem(tNBT);
+ protected void loadFluidLogic(NBTTagCompound nbt) {
+ fluidInput = new FluidInventoryLogic(16, 10000, tier);
+ fluidOutput = new FluidInventoryLogic(16, 10000, tier);
+ fluidInput.loadFromNBT(nbt.getCompoundTag(NBT.TANK_IN));
+ fluidOutput.loadFromNBT(nbt.getCompoundTag(NBT.TANK_OUT));
+ }
+
+ public boolean checkTexture(String modID, String resourcePath) {
+ try {
+ Minecraft.getMinecraft()
+ .getResourceManager()
+ .getResource(new ResourceLocation(modID, resourcePath));
+ return true;
+ } catch (IOException ignored) {
+ return false;
}
}
@@ -268,17 +220,10 @@ public abstract class MultiTileBasicMachine extends TickableMultiTileEntity impl
super.loadTextures(folder);
for (StatusTextures textureName : StatusTextures.TEXTURES) {
ITexture texture = null;
- try {
- Minecraft.getMinecraft()
- .getResourceManager()
- .getResource(
- new ResourceLocation(
- Mods.GregTech.ID,
- "textures/blocks/multitileentity/" + folder + "/" + textureName.getName() + ".png"));
- } catch (IOException ignored) {
+ String texturePath = "textures/blocks/multitileentity/" + folder + "/" + textureName.getName() + ".png";
+ if (!checkTexture(Mods.GregTech.ID, texturePath)) {
texture = TextureFactory.of(Textures.BlockIcons.VOID);
- }
- if (texture == null) {
+ } else {
if (textureName.hasGlow()) {
texture = TextureFactory.builder()
.addIcon(new CustomIcon("multitileentity/" + folder + "/" + textureName.getName()))
@@ -357,79 +302,6 @@ public abstract class MultiTileBasicMachine extends TickableMultiTileEntity impl
@Override
public void setLightValue(byte aLightValue) {}
- @Override
- public String getInventoryName() {
- final String name = getCustomName();
- if (name != null) return name;
- final MultiTileEntityRegistry tRegistry = MultiTileEntityRegistry.getRegistry(getMultiTileEntityRegistryID());
- return tRegistry == null ? getClass().getName() : tRegistry.getLocal(getMultiTileEntityID());
- }
-
- @Override
- public boolean isUseableByPlayer(EntityPlayer aPlayer) {
- return playerOwnsThis(aPlayer, false) && mTickTimer > 40
- && getTileEntityOffset(0, 0, 0) == this
- && aPlayer.getDistanceSq(xCoord + 0.5, yCoord + 0.5, zCoord + 0.5) < 64
- && allowInteraction(aPlayer);
- }
-
- @Override
- public boolean isLiquidInput(ForgeDirection side) {
- return side != facing;
- }
-
- @Override
- public boolean isLiquidOutput(ForgeDirection side) {
- return side != facing;
- }
-
- @Override
- protected IFluidTank[] getFluidTanks(ForgeDirection side) {
- final boolean fluidInput = isLiquidInput(side);
- final boolean fluidOutput = isLiquidOutput(side);
-
- if (fluidInput && fluidOutput) {
- final IFluidTank[] rTanks = new IFluidTank[inputTanks.length + outputTanks.length];
- System.arraycopy(inputTanks, 0, rTanks, 0, inputTanks.length);
- System.arraycopy(outputTanks, 0, rTanks, inputTanks.length, outputTanks.length);
- return rTanks;
- } else if (fluidInput) {
- return inputTanks;
- } else if (fluidOutput) {
- return outputTanks;
- }
- return GT_Values.emptyFluidTank;
- }
-
- @Override
- public IFluidTank getFluidTankFillable(ForgeDirection side, FluidStack aFluidToFill) {
- return getFluidTankFillable(facing, side, aFluidToFill);
- }
-
- public IFluidTank getFluidTankFillable(ForgeDirection sideSource, ForgeDirection sideDestination,
- FluidStack fluidToFill) {
- if (sideSource.compareTo(sideDestination) != 0) return null;
- for (FluidTankGT tankGT : inputTanks) if (tankGT.contains(fluidToFill)) return tankGT;
- // if (!mRecipes.containsInput(aFluidToFill, this, slot(mRecipes.mInputItemsCount +
- // mRecipes.mOutputItemsCount))) return null;
- for (FluidTankGT fluidTankGT : inputTanks) if (fluidTankGT.isEmpty()) return fluidTankGT;
- return null;
- }
-
- @Override
- protected IFluidTank getFluidTankDrainable(ForgeDirection side, FluidStack aFluidToDrain) {
- return getFluidTankDrainable(facing, side, aFluidToDrain);
- }
-
- protected IFluidTank getFluidTankDrainable(ForgeDirection sideSource, ForgeDirection sideDestination,
- FluidStack fluidToDrain) {
- if (sideSource.compareTo(sideDestination) != 0) return null;
- for (FluidTankGT fluidTankGT : outputTanks)
- if (fluidToDrain == null ? fluidTankGT.has() : fluidTankGT.contains(fluidToDrain)) return fluidTankGT;
-
- return null;
- }
-
/*
* Inventory
*/
@@ -453,16 +325,6 @@ public abstract class MultiTileBasicMachine extends TickableMultiTileEntity impl
hasInventoryChanged = true;
}
- @Override
- public boolean isItemValidForSlot(int aSlot, ItemStack aStack) {
- return true;
- }
-
- @Override
- public int getInventoryStackLimit() {
- return 64;
- }
-
// #region Machine
@Override
@@ -480,28 +342,26 @@ public abstract class MultiTileBasicMachine extends TickableMultiTileEntity impl
* @param tick The current tick of the machine
*/
protected void runMachine(long tick) {
- if (acceptsFuel() && isActive()) {
- if (!consumeFuel()) {
- stopMachine(true);
- return;
- }
+ if (acceptsFuel() && isActive() && !consumeFuel()) {
+ stopMachine(true);
+ return;
}
if (hasThingsToDo()) {
markDirty();
runningTick(tick);
- } else {
- if (tick % TICKS_BETWEEN_RECIPE_CHECKS == 0 || hasWorkJustBeenEnabled() || hasInventoryBeenModified()) {
- if (isAllowedToWork()) {
- wasEnabled = false;
- if (checkRecipe()) {
- setActive(true);
- setSound(GregTechTileClientEvents.START_SOUND_LOOP, PROCESS_START_SOUND_INDEX);
- updateSlots();
- markDirty();
- issueClientUpdate();
- }
- }
+ return;
+ }
+
+ if (tick % TICKS_BETWEEN_RECIPE_CHECKS == 0 || hasWorkJustBeenEnabled()
+ || hasInventoryBeenModified() && isAllowedToWork()) {
+ wasEnabled = false;
+ if (checkRecipe()) {
+ setActive(true);
+ setSound(GregTechTileClientEvents.START_SOUND_LOOP, PROCESS_START_SOUND_INDEX);
+ updateSlots();
+ markDirty();
+ issueClientUpdate();
}
}
}
@@ -512,81 +372,25 @@ public abstract class MultiTileBasicMachine extends TickableMultiTileEntity impl
* @param tick The current tick of the machine
*/
protected void runningTick(long tick) {
- if (this instanceof PowerLogicHost) {
- consumeEnergy();
- }
-
- if (maxProgressTime > 0 && ++progressTime >= maxProgressTime) {
- progressTime = 0;
- maxProgressTime = 0;
- outputItems();
- outputFluids();
- if (isAllowedToWork()) {
- if (!checkRecipe()) {
- setActive(false);
- issueClientUpdate();
- }
- }
- updateSlots();
- }
-
- if (this instanceof PollutionLogicHost && tick % POLLUTION_TICK == 0) {
- doPollution();
- }
- emitEnergy();
+ consumeEnergy();
}
/**
* Runs only on server side
*/
protected boolean checkRecipe() {
- if (!(this instanceof ProcessingLogicHost)) {
- return false;
- }
- ProcessingLogic logic = ((ProcessingLogicHost) this).getProcessingLogic();
- logic.clear();
- CheckRecipeResult result = logic.setInputItems(getInputItems())
- .setInputFluids(getInputFluids())
- .setCurrentOutputItems(
- outputInventory.getStacks()
- .toArray(new ItemStack[0]))
- .process();
- setDuration(logic.getDuration());
- setEut(logic.getCalculatedEut());
- setItemOutputs(logic.getOutputItems());
- setFluidOutputs(logic.getOutputFluids());
- return result.wasSuccessful();
- }
-
- /**
- * Runs only on server side
- */
- protected void doPollution() {
- PollutionLogic logic = ((PollutionLogicHost) this).getPollutionLogic();
-
- if (logic == null) {
- return;
- }
-
- GT_Pollution.addPollution(getWorld(), getXCoord() >> 4, getZCoord() >> 4, logic.getPollutionAmount());
+ return false;
}
/**
* Runs only on server side
*/
- protected void emitEnergy() {}
-
- /**
- * Runs only on server side
- */
protected void consumeEnergy() {
- PowerLogic logic = ((PowerLogicHost) this).getPowerLogic(ForgeDirection.UNKNOWN);
+ PowerLogic logic = getPowerLogic();
- if (logic == null) {
- return;
- }
+ P processing = getProcessingLogic();
- if (!logic.removeEnergyUnsafe(eut)) {
+ if (!logic.removeEnergyUnsafe(processing.getCalculatedEut())) {
stopMachine(true);
}
}
@@ -603,9 +407,8 @@ public abstract class MultiTileBasicMachine extends TickableMultiTileEntity impl
}
public void startSoundLoop(byte aIndex, double aX, double aY, double aZ) {
- if (aIndex == PROCESS_START_SOUND_INDEX) {
- if (getProcessStartSound() != null)
- GT_Utility.doSoundAtClient(getProcessStartSound(), getTimeBetweenProcessSounds(), 1.0F, aX, aY, aZ);
+ if (aIndex == PROCESS_START_SOUND_INDEX && getProcessStartSound() != null) {
+ GT_Utility.doSoundAtClient(getProcessStartSound(), getTimeBetweenProcessSounds(), 1.0F, aX, aY, aZ);
}
}
@@ -619,18 +422,18 @@ public abstract class MultiTileBasicMachine extends TickableMultiTileEntity impl
@SideOnly(Side.CLIENT)
protected void doActivitySound(ResourceLocation activitySound) {
- if (isActive() && activitySound != null) {
- if (activitySoundLoop == null) {
- activitySoundLoop = new GT_SoundLoop(activitySound, this, false, true);
- Minecraft.getMinecraft()
- .getSoundHandler()
- .playSound(activitySoundLoop);
- }
- } else {
- if (activitySoundLoop != null) {
- activitySoundLoop = null;
- }
+ if (isActive() && activitySound != null && activitySoundLoop == null) {
+ activitySoundLoop = new GT_SoundLoop(activitySound, this, false, true);
+ Minecraft.getMinecraft()
+ .getSoundHandler()
+ .playSound(activitySoundLoop);
+ return;
}
+
+ if (activitySoundLoop != null) {
+ activitySoundLoop = null;
+ }
+
}
@SideOnly(Side.CLIENT)
@@ -639,105 +442,69 @@ public abstract class MultiTileBasicMachine extends TickableMultiTileEntity impl
}
protected ItemStack[] getInputItems() {
- return inputInventory.getStacks()
- .toArray(new ItemStack[0]);
+ return itemInput.getStoredItems();
}
protected FluidStack[] getInputFluids() {
- return Arrays.stream(inputTanks)
- .map(FluidTankGT::get)
- .toArray(FluidStack[]::new);
- }
-
- protected void outputItems() {
- outputItems(itemsToOutput);
- itemsToOutput = null;
- }
-
- protected void outputItems(ItemStack... itemsToOutput) {
- outputItems(outputInventory, itemsToOutput);
+ return fluidInput.getStoredFluids();
}
- protected void outputItems(IItemHandlerModifiable inventory, ItemStack... itemsToOutput) {
- if (itemsToOutput == null || inventory == null) {
- return;
- }
- for (ItemStack item : itemsToOutput) {
- int index = 0;
- while (item != null && item.stackSize > 0 && index < inventory.getSlots()) {
- item = inventory.insertItem(index++, item.copy(), false);
- }
- }
- }
-
- protected void outputFluids() {
- outputFluids(fluidsToOutput);
- fluidsToOutput = null;
- }
-
- protected void outputFluids(FluidStack... fluidsToOutput) {
- outputFluids(outputTanks, fluidsToOutput);
- }
-
- protected void outputFluids(FluidTankGT[] tankArray, FluidStack... fluidsToOutput) {
- if (fluidsToOutput == null) {
- return;
- }
- for (FluidStack fluid : fluidsToOutput) {
- tryToFillTanks(fluid, tankArray);
- }
- }
-
- protected void tryToFillTanks(FluidStack fluid, FluidTankGT... tanks) {
- for (FluidTankGT tank : tanks) {
- if (tank.canFillAll(fluid)) {
- fluid.amount -= tank.add(fluid.amount, fluid);
- }
- }
- }
-
- public long getProgress() {
- return progressTime;
+ @Override
+ public int getProgress() {
+ P processing = getProcessingLogic();
+ return processing.getProgress();
}
- public long getMaxProgress() {
- return maxProgressTime;
+ @Override
+ public int getMaxProgress() {
+ P processing = getProcessingLogic();
+ return processing.getDuration();
}
- public boolean increaseProgress(int aProgressAmountInTicks) {
- progressTime += aProgressAmountInTicks;
+ @Override
+ public boolean increaseProgress(int progressAmount) {
+ P processing = getProcessingLogic();
+ processing.increaseProgress(progressAmount);
return true;
}
+ @Override
public boolean hasThingsToDo() {
return getMaxProgress() > 0;
}
+ @Override
public boolean hasWorkJustBeenEnabled() {
return wasEnabled;
}
+ @Override
public void enableWorking() {
wasEnabled = true;
canWork = true;
}
+ @Override
public void disableWorking() {
canWork = false;
}
+ @Override
public boolean wasShutdown() {
return powerShutDown;
}
+ @Override
public boolean isAllowedToWork() {
return canWork;
}
+ @Override
public boolean isActive() {
return active;
}
+ @Override
public void setActive(boolean active) {
this.active = active;
}
@@ -766,37 +533,18 @@ public abstract class MultiTileBasicMachine extends TickableMultiTileEntity impl
this.acceptsFuel = acceptsFuel;
}
- protected boolean isWireless() {
- return isWireless;
- }
-
- protected void setWireless(boolean isWireless) {
- this.isWireless = isWireless;
- }
-
- protected boolean drainEut(long eut) {
- return decreaseStoredEnergyUnits(eut, false);
- }
-
- protected boolean generateEut(long eut) {
- return increaseStoredEnergyUnits(eut, true);
- }
-
- protected boolean isGenerator() {
- return false;
- }
-
protected boolean consumeFuel() {
+ if (isElectric() || isSteam()) return false;
if (isActive() && burnTime <= 0) {
- for (int i = 0; i < inputInventory.getSlots(); i++) {
- if (inputInventory.getStackInSlot(i) != null) {
- int checkBurnTime = TileEntityFurnace.getItemBurnTime(inputInventory.getStackInSlot(i)) / 10;
- if (checkBurnTime <= 0) continue;
- inputInventory.getStackInSlot(i).stackSize--;
- burnTime = checkBurnTime;
- totalBurnTime = checkBurnTime;
- break;
- }
+ for (int i = 0; i < itemInput.getSlots(); i++) {
+ ItemStack item = itemInput.getItemInSlot(i);
+ if (item == null) continue;
+ int checkBurnTime = TileEntityFurnace.getItemBurnTime(item) / 10;
+ if (checkBurnTime <= 0) continue;
+ item.stackSize--;
+ burnTime = checkBurnTime;
+ totalBurnTime = checkBurnTime;
+ break;
}
updateSlots();
}
@@ -806,8 +554,7 @@ public abstract class MultiTileBasicMachine extends TickableMultiTileEntity impl
totalBurnTime = 0;
return false;
}
-
- return true;
+ return false;
}
@Override
@@ -826,38 +573,36 @@ public abstract class MultiTileBasicMachine extends TickableMultiTileEntity impl
list.add("Fuel: " + EnumChatFormatting.GOLD + burnTime + "/" + totalBurnTime);
}
- if (this instanceof PowerLogicHost powerLogicHost) {
- PowerLogic logic = powerLogicHost.getPowerLogic(facing);
- if (isElectric) {
- list.add(
- StatCollector.translateToLocal("GT5U.multiblock.energy") + ": "
- + EnumChatFormatting.GREEN
- + GT_Utility.formatNumbers(logic.getStoredEnergy())
- + EnumChatFormatting.RESET
- + " EU / "
- + EnumChatFormatting.YELLOW
- + GT_Utility.formatNumbers(logic.getCapacity())
- + EnumChatFormatting.RESET
- + " EU");
- list.add(
- StatCollector.translateToLocal("GT5U.multiblock.usage") + ": "
- + EnumChatFormatting.RED
- + GT_Utility.formatNumbers(eut)
- + EnumChatFormatting.RESET
- + " EU/t");
- list.add(
- StatCollector.translateToLocal("GT5U.multiblock.mei") + ": "
- + EnumChatFormatting.YELLOW
- + GT_Utility.formatNumbers(logic.getVoltage())
- + EnumChatFormatting.RESET
- // TODO: Put ampere getter here, once that's variable
- + " EU/t(*2A) "
- + StatCollector.translateToLocal("GT5U.machines.tier")
- + ": "
- + EnumChatFormatting.YELLOW
- + VN[GT_Utility.getTier(logic.getVoltage())]
- + EnumChatFormatting.RESET);
- }
+ PowerLogic logic = getPowerLogic();
+ if (isElectric) {
+ list.add(
+ StatCollector.translateToLocal("GT5U.multiblock.energy") + ": "
+ + EnumChatFormatting.GREEN
+ + GT_Utility.formatNumbers(logic.getStoredEnergy())
+ + EnumChatFormatting.RESET
+ + " EU / "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(logic.getCapacity())
+ + EnumChatFormatting.RESET
+ + " EU");
+ list.add(
+ StatCollector.translateToLocal("GT5U.multiblock.usage") + ": "
+ + EnumChatFormatting.RED
+ + GT_Utility.formatNumbers(getProcessingLogic().getCalculatedEut())
+ + EnumChatFormatting.RESET
+ + " EU/t");
+ list.add(
+ StatCollector.translateToLocal("GT5U.multiblock.mei") + ": "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(logic.getVoltage())
+ + EnumChatFormatting.RESET
+ // TODO: Put ampere getter here, once that's variable
+ + " EU/t(*2A) "
+ + StatCollector.translateToLocal("GT5U.machines.tier")
+ + ": "
+ + EnumChatFormatting.YELLOW
+ + VN[GT_Utility.getTier(logic.getVoltage())]
+ + EnumChatFormatting.RESET);
}
addProgressStringToScanner(player, logLevel, list);
@@ -873,6 +618,9 @@ public abstract class MultiTileBasicMachine extends TickableMultiTileEntity impl
}
protected void addProgressStringToScanner(EntityPlayer player, int logLevel, ArrayList<String> list) {
+ P processing = getProcessingLogic();
+ int progressTime = processing.getProgress();
+ int maxProgressTime = processing.getDuration();
list.add(
StatCollector.translateToLocal("GT5U.multiblock.Progress") + ": "
+ EnumChatFormatting.GREEN
@@ -886,7 +634,6 @@ public abstract class MultiTileBasicMachine extends TickableMultiTileEntity impl
}
protected void stopMachine(boolean powerShutDown) {
- progressTime = 0;
setActive(false);
disableWorking();
if (powerShutDown) {
@@ -896,50 +643,10 @@ public abstract class MultiTileBasicMachine extends TickableMultiTileEntity impl
}
protected void updateSlots() {
- for (int i = 0; i < inputInventory.getSlots(); i++) {
- ItemStack item = inputInventory.getStackInSlot(i);
- if (item != null && item.stackSize <= 0) {
- inputInventory.setStackInSlot(i, null);
- }
- }
-
- for (FluidTankGT inputTank : inputTanks) {
- if (inputTank == null) {
- continue;
- }
-
- if (inputTank.get() != null && inputTank.get().amount <= 0) {
- inputTank.setEmpty();
- continue;
- }
-
- FluidStack afterRecipe = inputTank.get();
- FluidStack beforeRecipe = inputTank.get(Integer.MAX_VALUE);
- if (afterRecipe == null || beforeRecipe == null) {
- continue;
- }
- int difference = beforeRecipe.amount - afterRecipe.amount;
- inputTank.remove(difference);
- }
- }
-
- /**
- * Must always be a positive. If the multi generates Eu/t isGenerator() should be overridden to true
- */
- protected void setEut(long eut) {
- if (eut < 0) {
- eut = -eut;
- }
-
- this.eut = eut;
- }
-
- protected void setDuration(long duration) {
- if (duration < 0) {
- duration = -duration;
- }
-
- maxProgressTime = duration;
+ itemInput.update(false);
+ itemOutput.update(false);
+ fluidInput.update();
+ fluidOutput.update();
}
@Override
@@ -956,53 +663,149 @@ public abstract class MultiTileBasicMachine extends TickableMultiTileEntity impl
setActive((booleans & ACTIVE) == ACTIVE);
}
- protected boolean hasItemInput() {
+ public boolean hasItemInput() {
return true;
}
- protected boolean hasItemOutput() {
+ public boolean hasItemOutput() {
return true;
}
- protected boolean hasFluidInput() {
+ public boolean hasFluidInput() {
return true;
}
- protected boolean hasFluidOutput() {
+ public boolean hasFluidOutput() {
return true;
}
- protected void setItemOutputs(ItemStack... outputs) {
- itemsToOutput = outputs;
- }
-
- protected void setFluidOutputs(FluidStack... outputs) {
- fluidsToOutput = outputs;
- }
-
@Override
public void setSound(byte soundEvent, int soundEventValue) {
this.soundEvent = soundEvent;
this.soundEventValue = soundEventValue;
- if (isClientSide()) {
- switch (soundEventValue) {
- case PROCESS_START_SOUND_INDEX -> {
- if (getProcessStartSound() != null) GT_Utility.doSoundAtClient(
- getProcessStartSound(),
- getTimeBetweenProcessSounds(),
- 1.0F,
- getXCoord(),
- getYCoord(),
- getZCoord());
- }
- case INTERRUPT_SOUND_INDEX -> GT_Utility.doSoundAtClient(
- SoundResource.IC2_MACHINES_INTERRUPT_ONE,
- 100,
+ if (isServerSide()) {
+ return;
+ }
+
+ switch (soundEventValue) {
+ case PROCESS_START_SOUND_INDEX -> {
+ if (getProcessStartSound() != null) GT_Utility.doSoundAtClient(
+ getProcessStartSound(),
+ getTimeBetweenProcessSounds(),
1.0F,
getXCoord(),
getYCoord(),
getZCoord());
}
+ case INTERRUPT_SOUND_INDEX -> GT_Utility.doSoundAtClient(
+ SoundResource.IC2_MACHINES_INTERRUPT_ONE,
+ 100,
+ 1.0F,
+ getXCoord(),
+ getYCoord(),
+ getZCoord());
}
+
+ }
+
+ @Nullable
+ public ItemInventoryLogic getItemLogic(@Nonnull ForgeDirection side, @Nonnull InventoryType type) {
+ if (side == facing) return null;
+ return switch (type) {
+ case Input -> itemInput;
+ case Output -> itemOutput;
+ default -> null;
+ };
+ }
+
+ @Nullable
+ public FluidInventoryLogic getFluidLogic(@Nonnull ForgeDirection side, @Nonnull InventoryType type) {
+ if (side == facing) return null;
+ return switch (type) {
+ case Input -> fluidInput;
+ case Output -> fluidOutput;
+ default -> null;
+ };
}
+
+ @Override
+ @Nonnull
+ public P getProcessingLogic() {
+ if (processingLogic == null) {
+ processingLogic = createProcessingLogic().setMachineHost(this);
+ }
+ return Objects.requireNonNull(processingLogic);
+ }
+
+ @OverrideOnly
+ @Nonnull
+ protected abstract P createProcessingLogic();
+
+ @Override
+ public boolean isInputSeparated() {
+ return false;
+ }
+
+ @Nonnull
+ @Override
+ public VoidingMode getVoidMode() {
+ return voidingMode;
+ }
+
+ @Override
+ public boolean needsUpdate() {
+ return processingUpdate;
+ }
+
+ @Override
+ public void setProcessingUpdate(boolean update) {
+ processingUpdate = update;
+ }
+
+ @Override
+ @Nonnull
+ public PowerLogic getPowerLogic(@Nonnull ForgeDirection side) {
+ if (side == facing) return new NullPowerLogic();
+ return power;
+ }
+
+ @Override
+ @Nonnull
+ public ForgeDirection getPowerOutputSide() {
+ return Objects.requireNonNull(facing.getOpposite());
+ }
+
+ protected void updatePowerLogic() {
+ power.setEnergyCapacity(GT_Values.V[tier] * power.getMaxAmperage() * 2 * MINUTE);
+ power.setMaxVoltage(GT_Values.V[tier]);
+ power.setMaxAmperage(1);
+ }
+
+ @Nonnull
+ protected PowerLogic createPowerLogic() {
+ return new PowerLogic().setMaxAmperage(1)
+ .setType(PowerLogic.RECEIVER);
+ }
+
+ @Nonnull
+ protected GUIProvider<?> createGUIProvider() {
+ return new MachineGUIProvider<>(this);
+ }
+
+ @Nonnull
+ public GUIProvider<?> getGUI(@Nonnull UIBuildContext uiContext) {
+ return guiProvider;
+ }
+
+ @Override
+ public ItemStack getAsItem() {
+ return MultiTileEntityRegistry.getRegistry(getMultiTileEntityRegistryID())
+ .getItem(getMultiTileEntityID());
+ }
+
+ @Override
+ public String getMachineName() {
+ return StatCollector.translateToLocal(getAsItem().getUnlocalizedName());
+ }
+
}
diff --git a/src/main/java/gregtech/api/multitileentity/multiblock/base/ComplexParallelController.java b/src/main/java/gregtech/api/multitileentity/multiblock/base/ComplexParallelController.java
index 808c16a200..cdcb77d6e5 100644
--- a/src/main/java/gregtech/api/multitileentity/multiblock/base/ComplexParallelController.java
+++ b/src/main/java/gregtech/api/multitileentity/multiblock/base/ComplexParallelController.java
@@ -2,7 +2,8 @@ package gregtech.api.multitileentity.multiblock.base;
import java.util.ArrayList;
import java.util.List;
-import java.util.stream.LongStream;
+
+import javax.annotation.Nonnull;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
@@ -12,206 +13,58 @@ import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.StatCollector;
import net.minecraft.world.World;
-import net.minecraftforge.fluids.FluidStack;
-import gregtech.api.enums.GT_Values;
import gregtech.api.logic.ComplexParallelProcessingLogic;
-import gregtech.api.logic.interfaces.PollutionLogicHost;
import gregtech.api.util.GT_Utility;
import gregtech.api.util.GT_Waila;
import mcp.mobius.waila.api.IWailaConfigHandler;
import mcp.mobius.waila.api.IWailaDataAccessor;
-public abstract class ComplexParallelController<T extends ComplexParallelController<T>> extends PowerController<T> {
+public abstract class ComplexParallelController<C extends ComplexParallelController<C, P>, P extends ComplexParallelProcessingLogic<P>>
+ extends Controller<C, P> {
- protected ComplexParallelProcessingLogic processingLogic;
protected int maxComplexParallels = 0;
protected int currentComplexParallels = 0;
- protected long[] maxProgressTimes = new long[0];
- protected long[] progressTimes = new long[0];
public ComplexParallelController() {
isSimpleMachine = false;
}
- protected void setMaxComplexParallels(int parallel) {
- if (parallel != maxComplexParallels) {
- if (maxComplexParallels != 0) {
- stopMachine(false);
- }
- maxProgressTimes = new long[parallel];
- progressTimes = new long[parallel];
+ protected void setMaxComplexParallels(int parallel, boolean stopMachine) {
+ if (parallel != maxComplexParallels && maxComplexParallels != 0 && stopMachine) {
+ stopMachine(false);
}
maxComplexParallels = parallel;
- }
-
- @Override
- protected void runMachine(long tick) {
- if (acceptsFuel() && isActive()) {
- if (!consumeFuel()) {
- stopMachine(true);
- return;
- }
- }
-
- if (hasThingsToDo()) {
- markDirty();
- runningTick(tick);
- }
- if ((tick % TICKS_BETWEEN_RECIPE_CHECKS == 0 || hasWorkJustBeenEnabled() || hasInventoryBeenModified())
- && maxComplexParallels != currentComplexParallels) {
- if (isAllowedToWork() && maxComplexParallels > currentComplexParallels) {
- wasEnabled = false;
- boolean started = false;
- for (int i = 0; i < maxComplexParallels; i++) {
- if (maxProgressTimes[i] <= 0 && checkRecipe(i)) {
- currentComplexParallels++;
- started = true;
- }
- }
- if (started) {
- setActive(true);
- updateSlots();
- markDirty();
- issueClientUpdate();
- }
- }
- }
- }
-
- @Override
- protected void runningTick(long tick) {
- consumeEnergy();
- boolean allStopped = true;
- for (int i = 0; i < maxComplexParallels; i++) {
- if (maxProgressTimes[i] > 0 && ++progressTimes[i] >= maxProgressTimes[i]) {
- progressTimes[i] = 0;
- maxProgressTimes[i] = 0;
- outputItems(i);
- outputFluids(i);
- if (isAllowedToWork()) {
- if (checkRecipe(i)) {
- allStopped = false;
- } else {
- currentComplexParallels--;
- }
- }
- updateSlots();
- } else if (maxProgressTimes[i] > 0) {
- allStopped = false;
- }
- }
- if (allStopped) {
- setActive(false);
- issueClientUpdate();
- }
-
- if (this instanceof PollutionLogicHost && tick % POLLUTION_TICK == 0) {
- doPollution();
- }
- emitEnergy();
- }
-
- protected boolean checkRecipe(int index) {
- ComplexParallelProcessingLogic processingLogic = getComplexProcessingLogic();
- if (processingLogic == null || index < 0 || index >= maxComplexParallels) {
- return false;
- }
- processingLogic.clear(index);
- boolean result = processingLogic.setInputItems(index, getInputItems(index))
- .setInputFluids(index, getInputFluids(index))
- .setTileEntity(this)
- .setVoidProtection(index, isVoidProtectionEnabledForItem(index), isVoidProtectionEnabledForFluid(index))
- .setEut(index, getEutForComplexParallel(index))
- .setPerfectOverclock(hasPerfectOverclock())
- .process(index);
- setDuration(index, processingLogic.getDuration(index));
- setEut(processingLogic.getTotalEU());
- return result;
- }
-
- protected void outputItems(int index) {
- ComplexParallelProcessingLogic processingLogic = getComplexProcessingLogic();
- if (processingLogic != null && index >= 0 && index < maxComplexParallels) {
- outputItems(processingLogic.getOutputItems(index));
- }
- }
-
- protected void outputFluids(int index) {
- ComplexParallelProcessingLogic processingLogic = getComplexProcessingLogic();
- if (processingLogic != null && index >= 0 && index < maxComplexParallels) {
- outputFluids(processingLogic.getOutputFluids(index));
- }
- }
-
- protected ComplexParallelProcessingLogic getComplexProcessingLogic() {
- return processingLogic;
- }
-
- @Override
- public boolean hasThingsToDo() {
- return LongStream.of(maxProgressTimes)
- .sum() > 0;
+ setProcessingUpdate(true);
}
@Override
protected void stopMachine(boolean powerShutDown) {
super.stopMachine(powerShutDown);
- for (int i = 0; i < maxComplexParallels; i++) {
- maxProgressTimes[i] = 0;
- }
- }
-
- protected void setDuration(int index, long duration) {
- if (duration < 0) {
- duration = -duration;
- }
- if (index >= 0 && index < maxComplexParallels) {
- maxProgressTimes[index] = duration;
- }
- }
-
- protected ItemStack[] getInputItems(int index) {
- return getInputItems();
- }
-
- protected FluidStack[] getInputFluids(int index) {
- return getInputFluids();
- }
-
- protected boolean isVoidProtectionEnabledForItem(int index) {
- return protectsExcessItem();
- }
-
- protected boolean isVoidProtectionEnabledForFluid(int index) {
- return protectsExcessFluid();
}
protected boolean hasPerfectOverclock() {
return false;
}
- protected long getEutForComplexParallel(int index) {
- // As default behavior we'll give the parallel all remaining EU we have
- return GT_Values.V[tier] - eut;
- }
-
@Override
protected void addProgressStringToScanner(EntityPlayer player, int logLevel, ArrayList<String> list) {
+ P processing = getProcessingLogic();
for (int i = 0; i < maxComplexParallels; i++) {
list.add(
StatCollector.translateToLocal("GT5U.multiblock.Progress") + " "
+ (i + 1)
+ ": "
+ EnumChatFormatting.GREEN
- + GT_Utility.formatNumbers(progressTimes[i] > 20 ? progressTimes[i] / 20 : progressTimes[i])
+ + GT_Utility.formatNumbers(
+ processing.getProgress(i) > 20 ? processing.getProgress(i) / 20 : processing.getProgress(i))
+ EnumChatFormatting.RESET
- + (progressTimes[i] > 20 ? " s / " : " ticks / ")
+ + (processing.getProgress(i) > 20 ? " s / " : " ticks / ")
+ EnumChatFormatting.YELLOW
- + GT_Utility
- .formatNumbers(maxProgressTimes[i] > 20 ? maxProgressTimes[i] / 20 : maxProgressTimes[i])
+ + GT_Utility.formatNumbers(
+ processing.getDuration(i) > 20 ? processing.getDuration(i) / 20 : processing.getDuration(i))
+ EnumChatFormatting.RESET
- + (maxProgressTimes[i] > 20 ? " s" : " ticks"));
+ + (processing.getDuration(i) > 20 ? " s" : " ticks"));
}
}
@@ -219,10 +72,11 @@ public abstract class ComplexParallelController<T extends ComplexParallelControl
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);
+ P processing = getProcessingLogic();
tag.setInteger("maxComplexParallels", maxComplexParallels);
for (int i = 0; i < maxComplexParallels; i++) {
- tag.setLong("maxProgress" + i, maxProgressTimes[i]);
- tag.setLong("progress" + i, progressTimes[i]);
+ tag.setInteger("maxProgress" + i, processing.getDuration(i));
+ tag.setInteger("progress" + i, processing.getProgress(i));
}
}
@@ -233,8 +87,8 @@ public abstract class ComplexParallelController<T extends ComplexParallelControl
final NBTTagCompound tag = accessor.getNBTData();
maxComplexParallels = tag.getInteger("maxComplexParallels");
for (int i = 0; i < maxComplexParallels; i++) {
- long maxProgress = tag.getLong("maxProgress" + i);
- long progress = tag.getLong("progress" + i);
+ long maxProgress = tag.getInteger("maxProgress" + i);
+ long progress = tag.getInteger("progress" + i);
currentTip.add(
"Process " + (i + 1)
+ ": "
@@ -242,4 +96,16 @@ public abstract class ComplexParallelController<T extends ComplexParallelControl
.getMachineProgressString(maxProgress > 0 && maxProgress >= progress, maxProgress, progress));
}
}
+
+ @Override
+ public void setProcessingLogicPower(@Nonnull P processingLogic) {
+ processingLogic.setAmperageOC(true);
+ processingLogic.setAvailableAmperage(getPowerLogic().getMaxAmperage() / maxComplexParallels);
+ processingLogic.setAvailableVoltage(getPowerLogic().getVoltage() / maxComplexParallels);
+ }
+
+ @Override
+ public void updateProcessingLogic(@Nonnull P processingLogic) {
+ processingLogic.setMaxComplexParallel(maxComplexParallels);
+ }
}
diff --git a/src/main/java/gregtech/api/multitileentity/multiblock/base/Controller.java b/src/main/java/gregtech/api/multitileentity/multiblock/base/Controller.java
index 606d957fd6..8ac908be12 100644
--- a/src/main/java/gregtech/api/multitileentity/multiblock/base/Controller.java
+++ b/src/main/java/gregtech/api/multitileentity/multiblock/base/Controller.java
@@ -1,261 +1,109 @@
package gregtech.api.multitileentity.multiblock.base;
-import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofChain;
-import static gregtech.GT_Mod.GT_FML_LOGGER;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.EV_Conveyor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.EV_Emitter;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.EV_FieldGenerator;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.EV_Motor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.EV_Piston;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.EV_Pump;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.EV_RobotArm;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.EV_Sensor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.HV_Conveyor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.HV_Emitter;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.HV_FieldGenerator;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.HV_Motor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.HV_Piston;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.HV_Pump;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.HV_RobotArm;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.HV_Sensor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.IV_Conveyor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.IV_Emitter;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.IV_FieldGenerator;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.IV_Motor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.IV_Piston;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.IV_Pump;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.IV_RobotArm;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.IV_Sensor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.LV_Conveyor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.LV_Emitter;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.LV_FieldGenerator;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.LV_Motor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.LV_Piston;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.LV_Pump;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.LV_RobotArm;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.LV_Sensor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.LuV_Conveyor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.LuV_Emitter;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.LuV_FieldGenerator;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.LuV_Motor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.LuV_Piston;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.LuV_Pump;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.LuV_RobotArm;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.LuV_Sensor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.MAX_Conveyor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.MAX_Emitter;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.MAX_FieldGenerator;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.MAX_Motor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.MAX_Piston;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.MAX_Pump;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.MAX_RobotArm;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.MAX_Sensor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.MV_Conveyor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.MV_Emitter;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.MV_FieldGenerator;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.MV_Motor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.MV_Piston;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.MV_Pump;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.MV_RobotArm;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.MV_Sensor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UEV_Conveyor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UEV_Emitter;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UEV_FieldGenerator;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UEV_Motor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UEV_Piston;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UEV_Pump;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UEV_RobotArm;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UEV_Sensor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UHV_Conveyor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UHV_Emitter;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UHV_FieldGenerator;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UHV_Motor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UHV_Piston;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UHV_Pump;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UHV_RobotArm;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UHV_Sensor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UIV_Conveyor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UIV_Emitter;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UIV_FieldGenerator;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UIV_Motor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UIV_Piston;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UIV_Pump;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UIV_RobotArm;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UIV_Sensor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UMV_Conveyor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UMV_Emitter;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UMV_FieldGenerator;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UMV_Motor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UMV_Piston;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UMV_Pump;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UMV_RobotArm;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UMV_Sensor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UV_Conveyor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UV_Emitter;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UV_FieldGenerator;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UV_Motor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UV_Piston;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UV_Pump;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UV_RobotArm;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UV_Sensor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UXV_Conveyor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UXV_Emitter;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UXV_FieldGenerator;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UXV_Motor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UXV_Piston;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UXV_Pump;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UXV_RobotArm;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.UXV_Sensor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.ZPM_Conveyor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.ZPM_Emitter;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.ZPM_FieldGenerator;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.ZPM_Motor;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.ZPM_Piston;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.ZPM_Pump;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.ZPM_RobotArm;
-import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.ZPM_Sensor;
-import static gregtech.loaders.preload.GT_Loader_MultiTileEntities.COMPONENT_CASING_REGISTRY_NAME;
-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 gregtech.api.util.GT_Utility.moveMultipleItemStacks;
+import static gregtech.common.misc.WirelessNetworkManager.strongCheckOrAddUser;
+import static mcp.mobius.waila.api.SpecialChars.*;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
-import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
-import net.minecraft.block.Block;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
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.nbt.NBTTagList;
import net.minecraft.tileentity.TileEntity;
-import net.minecraft.util.IIcon;
+import net.minecraft.util.StatCollector;
import net.minecraft.world.World;
-import net.minecraftforge.common.util.Constants;
import net.minecraftforge.common.util.ForgeDirection;
-import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidStack;
-import net.minecraftforge.fluids.FluidTankInfo;
-import net.minecraftforge.fluids.IFluidTank;
-import org.apache.commons.lang3.tuple.ImmutablePair;
-import org.apache.commons.lang3.tuple.Pair;
import org.lwjgl.input.Keyboard;
import com.gtnewhorizon.structurelib.StructureLibAPI;
import com.gtnewhorizon.structurelib.alignment.IAlignment;
import com.gtnewhorizon.structurelib.alignment.IAlignmentLimits;
-import com.gtnewhorizon.structurelib.alignment.constructable.IConstructable;
import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
import com.gtnewhorizon.structurelib.alignment.enumerable.Flip;
import com.gtnewhorizon.structurelib.alignment.enumerable.Rotation;
import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
-import com.gtnewhorizon.structurelib.structure.IStructureElement;
-import com.gtnewhorizon.structurelib.structure.IStructureElementChain;
import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
import com.gtnewhorizon.structurelib.util.Vec3Impl;
-import com.gtnewhorizons.modularui.api.ModularUITextures;
-import com.gtnewhorizons.modularui.api.drawable.ItemDrawable;
-import com.gtnewhorizons.modularui.api.forge.IItemHandler;
-import com.gtnewhorizons.modularui.api.forge.IItemHandlerModifiable;
-import com.gtnewhorizons.modularui.api.forge.ItemStackHandler;
-import com.gtnewhorizons.modularui.api.forge.ListItemHandler;
-import com.gtnewhorizons.modularui.api.math.Pos2d;
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.api.widget.Widget;
-import com.gtnewhorizons.modularui.common.widget.DrawableWidget;
-import com.gtnewhorizons.modularui.common.widget.FluidSlotWidget;
-import com.gtnewhorizons.modularui.common.widget.MultiChildWidget;
-import com.gtnewhorizons.modularui.common.widget.Scrollable;
-import com.gtnewhorizons.modularui.common.widget.SlotWidget;
-import com.gtnewhorizons.modularui.common.widget.TabButton;
-import com.gtnewhorizons.modularui.common.widget.TabContainer;
import cpw.mods.fml.common.network.NetworkRegistry;
-import gnu.trove.list.TIntList;
-import gnu.trove.list.array.TIntArrayList;
-import gregtech.api.enums.GT_Values;
import gregtech.api.enums.GT_Values.NBT;
-import gregtech.api.enums.OrePrefixes;
-import gregtech.api.enums.TextureSet;
+import gregtech.api.enums.InventoryType;
import gregtech.api.enums.VoidingMode;
-import gregtech.api.fluid.FluidTankGT;
-import gregtech.api.gui.modularui.GT_UITextures;
import gregtech.api.interfaces.IDescribable;
import gregtech.api.interfaces.fluid.IFluidStore;
-import gregtech.api.interfaces.modularui.ControllerWithOptionalFeatures;
+import gregtech.api.logic.ControllerFluidLogic;
+import gregtech.api.logic.ControllerItemLogic;
+import gregtech.api.logic.FluidInventoryLogic;
+import gregtech.api.logic.ItemInventoryLogic;
+import gregtech.api.logic.MuTEProcessingLogic;
import gregtech.api.logic.PowerLogic;
-import gregtech.api.logic.ProcessingLogic;
-import gregtech.api.logic.interfaces.PowerLogicHost;
-import gregtech.api.logic.interfaces.ProcessingLogicHost;
-import gregtech.api.multitileentity.MultiTileEntityContainer;
-import gregtech.api.multitileentity.MultiTileEntityRegistry;
+import gregtech.api.multitileentity.enums.MultiTileCasingPurpose;
import gregtech.api.multitileentity.interfaces.IMultiBlockController;
import gregtech.api.multitileentity.interfaces.IMultiBlockPart;
-import gregtech.api.multitileentity.interfaces.IMultiTileEntity;
import gregtech.api.multitileentity.interfaces.IMultiTileEntity.IMTE_AddToolTips;
import gregtech.api.multitileentity.machine.MultiTileBasicMachine;
import gregtech.api.multitileentity.multiblock.casing.FunctionalCasing;
import gregtech.api.multitileentity.multiblock.casing.UpgradeCasing;
+import gregtech.api.net.GT_Packet_MultiTileEntity;
import gregtech.api.objects.GT_ItemStack;
-import gregtech.api.recipe.RecipeMap;
-import gregtech.api.recipe.check.CheckRecipeResult;
-import gregtech.api.recipe.check.CheckRecipeResultRegistry;
import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
import gregtech.api.util.GT_Utility;
import gregtech.api.util.GT_Waila;
-import gregtech.common.tileentities.casings.upgrade.Inventory;
import mcp.mobius.waila.api.IWailaConfigHandler;
import mcp.mobius.waila.api.IWailaDataAccessor;
/**
* Multi Tile Entities - or MuTEs - don't have dedicated hatches, but their casings can become hatches.
*/
-public abstract class Controller<T extends Controller<T>> extends MultiTileBasicMachine
- implements IAlignment, IConstructable, IMultiBlockController, IDescribable, IMTE_AddToolTips,
- ISurvivalConstructable, ControllerWithOptionalFeatures {
+public abstract class Controller<C extends Controller<C, P>, P extends MuTEProcessingLogic<P>>
+ extends MultiTileBasicMachine<P>
+ implements IAlignment, IMultiBlockController, IDescribable, IMTE_AddToolTips, ISurvivalConstructable {
public static final String ALL_INVENTORIES_NAME = "all";
+ protected static final int AUTO_OUTPUT_FREQUENCY_TICK = 20;
private static final Map<Integer, GT_Multiblock_Tooltip_Builder> tooltip = new ConcurrentHashMap<>();
private final List<UpgradeCasing> upgradeCasings = new ArrayList<>();
private final List<FunctionalCasing> functionalCasings = new ArrayList<>();
protected BuildState buildState = new BuildState();
- protected Map<String, String> multiBlockInputInventoryNames = new LinkedHashMap<>();
- protected Map<String, String> multiBlockOutputInventoryNames = new LinkedHashMap<>();
- protected Map<String, String> multiBlockInputInventoryToTankLink = new LinkedHashMap<>();
- protected Map<String, IItemHandlerModifiable> multiBlockInputInventory = new LinkedHashMap<>();
- protected Map<String, IItemHandlerModifiable> multiBlockOutputInventory = new LinkedHashMap<>();
-
- protected Map<String, String> multiBlockInputTankNames = new LinkedHashMap<>();
- protected Map<String, String> multiBlockOutputTankNames = new LinkedHashMap<>();
- protected Map<String, FluidTankGT[]> multiBlockInputTank = new LinkedHashMap<>();
- protected Map<String, FluidTankGT[]> multiBlockOutputTank = new LinkedHashMap<>();
-
private boolean structureOkay = false, structureChanged = false;
private ExtendedFacing extendedFacing = ExtendedFacing.DEFAULT;
private IAlignmentLimits limits = getInitialAlignmentLimits();
- private String inventoryName;
- private String tankName;
protected boolean separateInputs = getDefaultInputSeparationMode();
protected VoidingMode voidingMode = getDefaultVoidingMode();
protected boolean batchMode = getDefaultBatchMode();
protected boolean recipeLock = getDefaultRecipeLockingMode();
+ protected boolean shouldSort = false;
/** If this is set to true, the machine will get default WAILA behavior */
protected boolean isSimpleMachine = true;
+ protected boolean isCleanroom = false;
+ protected ControllerItemLogic controllerItemInput = new ControllerItemLogic();
+ protected ControllerItemLogic controllerItemOutput = new ControllerItemLogic();
+ protected ControllerFluidLogic controllerFluidInput = new ControllerFluidLogic();
+ protected ControllerFluidLogic controllerFluidOutput = new ControllerFluidLogic();
+
// A list of sides
// Each side has a list of parts that have a cover that need to be ticked
protected List<LinkedList<WeakReference<IMultiBlockPart>>> registeredCoveredParts = Arrays.asList(
@@ -266,6 +114,15 @@ public abstract class Controller<T extends Controller<T>> extends MultiTileBasic
new LinkedList<>(),
new LinkedList<>());
+ // A list for each purpose that a casing can register to, to be ticked
+ protected List<LinkedList<WeakReference<IMultiBlockPart>>> registeredTickableParts = new ArrayList<>();
+
+ public Controller() {
+ for (int i = 0; i < MultiTileCasingPurpose.values().length; i++) {
+ registeredTickableParts.add(new LinkedList<>());
+ }
+ }
+
/** Registry ID of the required casing */
public abstract short getCasingRegistryID();
@@ -288,7 +145,7 @@ public abstract class Controller<T extends Controller<T>> extends MultiTileBasic
* other instances, even for those of the same class.
*/
@Override
- public abstract IStructureDefinition<T> getStructureDefinition();
+ public abstract IStructureDefinition<C> getStructureDefinition();
/**
* Checks the Machine.
@@ -296,16 +153,20 @@ public abstract class Controller<T extends Controller<T>> extends MultiTileBasic
* NOTE: If using `buildState` be sure to `startBuilding()` and either `endBuilding()` or `failBuilding()`
*/
public boolean checkMachine() {
+ calculateTier();
+ updatePowerLogic();
+ return tier > 0;
+ }
+
+ protected void calculateTier() {
double sum = 0;
if (functionalCasings == null || functionalCasings.size() == 0) {
- return false;
+ return;
}
for (FunctionalCasing casing : functionalCasings) {
sum += casing.getPartTier() * casing.getPartModifier();
}
- tier = (int) Math.floor(sum / functionalCasings.size());
- // Maximum Energy stores will have a cap of 2 minute work time of current voltage
- return tier > 0;
+ tier = (int) Math.min(Math.floor(sum / functionalCasings.size()), 14);
}
@Override
@@ -322,77 +183,26 @@ public abstract class Controller<T extends Controller<T>> extends MultiTileBasic
(byte) extendedFacing.getFlip()
.getIndex());
- saveUpgradeInventoriesToNBT(nbt);
- saveUpgradeTanksToNBT(nbt);
-
nbt.setString(NBT.VOIDING_MODE, voidingMode.name);
nbt.setBoolean(NBT.SEPARATE_INPUTS, separateInputs);
nbt.setBoolean(NBT.RECIPE_LOCK, recipeLock);
nbt.setBoolean(NBT.BATCH_MODE, batchMode);
}
- private void saveUpgradeInventoriesToNBT(NBTTagCompound nbt) {
- final NBTTagList inputInvList = new NBTTagList();
- multiBlockInputInventory.forEach((id, inv) -> {
- if (!id.equals("controller")) {
- final NBTTagCompound tTag = new NBTTagCompound();
- tTag.setString(NBT.UPGRADE_INVENTORY_UUID, id);
- tTag.setString(NBT.UPGRADE_INVENTORY_NAME, multiBlockInputInventoryNames.get(id));
- tTag.setInteger(NBT.UPGRADE_INVENTORY_SIZE, inv.getSlots());
- writeInventory(tTag, inv, NBT.INV_INPUT_LIST);
- inputInvList.appendTag(tTag);
- }
- });
- final NBTTagList outputInvList = new NBTTagList();
- multiBlockOutputInventory.forEach((id, inv) -> {
- if (!id.equals("controller")) {
- final NBTTagCompound tTag = new NBTTagCompound();
- tTag.setString(NBT.UPGRADE_INVENTORY_UUID, id);
- tTag.setString(NBT.UPGRADE_INVENTORY_NAME, multiBlockOutputInventoryNames.get(id));
- tTag.setInteger(NBT.UPGRADE_INVENTORY_SIZE, inv.getSlots());
- writeInventory(tTag, inv, NBT.INV_OUTPUT_LIST);
- outputInvList.appendTag(tTag);
- }
- });
- nbt.setTag(NBT.UPGRADE_INVENTORIES_INPUT, inputInvList);
- nbt.setTag(NBT.UPGRADE_INVENTORIES_OUTPUT, outputInvList);
- }
-
- private void saveUpgradeTanksToNBT(NBTTagCompound nbt) {
- final NBTTagList inputTankList = new NBTTagList();
- multiBlockInputTank.forEach((id, tanks) -> {
- if (!id.equals("controller") && tanks != null && tanks.length > 0) {
- final NBTTagCompound tTag = new NBTTagCompound();
- tTag.setString(NBT.UPGRADE_TANK_UUID, id);
- tTag.setString(NBT.UPGRADE_TANK_NAME, multiBlockInputTankNames.get(id));
- // We assume all tanks in the tank-array are equally sized
- tTag.setLong(NBT.UPGRADE_TANK_CAPACITY, tanks[0].capacity());
- tTag.setLong(NBT.UPGRADE_TANK_CAPACITY_MULTIPLIER, tanks[0].getCapacityMultiplier());
- tTag.setInteger(NBT.UPGRADE_TANKS_COUNT, tanks.length);
- for (int i = 0; i < tanks.length; i++) {
- tanks[i].writeToNBT(tTag, NBT.UPGRADE_TANKS_PREFIX + i);
- }
- inputTankList.appendTag(tTag);
- }
- });
- final NBTTagList outputTankList = new NBTTagList();
- multiBlockOutputTank.forEach((id, tanks) -> {
- if (!id.equals("controller") && tanks != null && tanks.length > 0) {
- final NBTTagCompound tTag = new NBTTagCompound();
- tTag.setString(NBT.UPGRADE_TANK_UUID, id);
- tTag.setString(NBT.UPGRADE_TANK_NAME, multiBlockInputTankNames.get(id));
- // We assume all tanks in the tank-array are equally sized
- tTag.setLong(NBT.UPGRADE_TANK_CAPACITY, tanks[0].capacity());
- tTag.setLong(NBT.UPGRADE_TANK_CAPACITY_MULTIPLIER, tanks[0].getCapacityMultiplier());
- tTag.setInteger(NBT.UPGRADE_TANKS_COUNT, tanks.length);
- for (int i = 0; i < tanks.length; i++) {
- tanks[i].writeToNBT(tTag, NBT.UPGRADE_TANKS_PREFIX + i);
- }
- outputTankList.appendTag(tTag);
- }
- });
- nbt.setTag(NBT.UPGRADE_TANKS_INPUT, inputTankList);
- nbt.setTag(NBT.UPGRADE_TANKS_OUTPUT, outputTankList);
+ @Override
+ protected void saveItemLogic(NBTTagCompound nbt) {
+ NBTTagCompound itemInputNBT = controllerItemInput.saveToNBT();
+ nbt.setTag(NBT.INV_INPUT_LIST, itemInputNBT);
+ NBTTagCompound itemOutputNBT = controllerItemOutput.saveToNBT();
+ nbt.setTag(NBT.INV_OUTPUT_LIST, itemOutputNBT);
+ }
+
+ @Override
+ protected void saveFluidLogic(NBTTagCompound nbt) {
+ NBTTagCompound fluidInputNBT = controllerFluidInput.saveToNBT();
+ nbt.setTag(NBT.TANK_IN, fluidInputNBT);
+ NBTTagCompound fluidOutputNBT = controllerFluidOutput.saveToNBT();
+ nbt.setTag(NBT.TANK_OUT, fluidOutputNBT);
}
@Override
@@ -401,83 +211,37 @@ public abstract class Controller<T extends Controller<T>> extends MultiTileBasic
// Multiblock inventories are a collection of inventories. The first inventory is the default internal
// inventory, and the others are added by inventory extending blocks.
- if (inputInventory != null) registerInventory("controller", "controller", inputInventory, Inventory.INPUT);
- if (outputInventory != null) registerInventory("controller", "controller", outputInventory, Inventory.OUTPUT);
-
- if (inputTanks != null) registerFluidInventory("controller", "controller", inputTanks, Inventory.INPUT);
- if (outputTanks != null) registerFluidInventory("controller", "controller", outputTanks, Inventory.OUTPUT);
structureOkay = nbt.getBoolean(NBT.STRUCTURE_OK);
extendedFacing = ExtendedFacing
.of(getFrontFacing(), Rotation.byIndex(nbt.getByte(NBT.ROTATION)), Flip.byIndex(nbt.getByte(NBT.FLIP)));
- loadUpgradeInventoriesFromNBT(nbt);
- loadUpgradeTanksFromNBT(nbt);
-
voidingMode = VoidingMode.fromName(nbt.getString(NBT.VOIDING_MODE));
separateInputs = nbt.getBoolean(NBT.SEPARATE_INPUTS);
recipeLock = nbt.getBoolean(NBT.RECIPE_LOCK);
batchMode = nbt.getBoolean(NBT.BATCH_MODE);
}
- private void loadUpgradeInventoriesFromNBT(NBTTagCompound nbt) {
- final NBTTagList listInputInventories = nbt
- .getTagList(NBT.UPGRADE_INVENTORIES_INPUT, Constants.NBT.TAG_COMPOUND);
- for (int i = 0; i < listInputInventories.tagCount(); i++) {
- final NBTTagCompound nbtInv = listInputInventories.getCompoundTagAt(i);
- final String invUUID = nbtInv.getString(NBT.UPGRADE_INVENTORY_UUID);
- final String invName = nbtInv.getString(NBT.UPGRADE_INVENTORY_NAME);
- final int invSize = nbtInv.getInteger(NBT.UPGRADE_INVENTORY_SIZE);
- final IItemHandlerModifiable inv = new ItemStackHandler(invSize);
- loadInventory(nbtInv, inv, NBT.INV_INPUT_LIST);
- registerInventory(invName, invUUID, invSize, Inventory.INPUT);
- }
-
- final NBTTagList listOutputInventories = nbt
- .getTagList(NBT.UPGRADE_INVENTORIES_OUTPUT, Constants.NBT.TAG_COMPOUND);
- for (int i = 0; i < listOutputInventories.tagCount(); i++) {
- final NBTTagCompound nbtInv = listOutputInventories.getCompoundTagAt(i);
- final String invUUID = nbtInv.getString(NBT.UPGRADE_INVENTORY_UUID);
- final String invName = nbtInv.getString(NBT.UPGRADE_INVENTORY_NAME);
- final int invSize = nbtInv.getInteger(NBT.UPGRADE_INVENTORY_SIZE);
- IItemHandlerModifiable inv = new ItemStackHandler(invSize);
- loadInventory(nbtInv, inv, NBT.INV_OUTPUT_LIST);
- registerInventory(invName, invUUID, invSize, Inventory.OUTPUT);
+ @Override
+ protected void loadItemLogic(NBTTagCompound nbt) {
+ if (!nbt.hasKey(NBT.INV_INPUT_LIST) && !nbt.hasKey(NBT.INV_OUTPUT_LIST)) {
+ controllerItemInput.addInventory(new ItemInventoryLogic(16));
+ controllerItemOutput.addInventory(new ItemInventoryLogic(16));
+ return;
}
+ controllerItemInput.loadFromNBT(nbt.getCompoundTag(NBT.INV_INPUT_LIST));
+ controllerItemOutput.loadFromNBT(nbt.getCompoundTag(NBT.INV_OUTPUT_LIST));
}
- private void loadUpgradeTanksFromNBT(NBTTagCompound nbt) {
- final NBTTagList listInputTanks = nbt.getTagList(NBT.UPGRADE_TANKS_INPUT, Constants.NBT.TAG_COMPOUND);
- for (int i = 0; i < listInputTanks.tagCount(); i++) {
- final NBTTagCompound nbtTank = listInputTanks.getCompoundTagAt(i);
- String tankUUID = nbtTank.getString(NBT.UPGRADE_TANK_UUID);
- String tankName = nbtTank.getString(NBT.UPGRADE_TANK_NAME);
- long capacity = nbtTank.getLong(NBT.UPGRADE_TANK_CAPACITY);
- long capacityMultiplier = nbtTank.getLong(NBT.UPGRADE_TANK_CAPACITY_MULTIPLIER);
- int count = nbtTank.getInteger(NBT.UPGRADE_TANKS_COUNT);
- FluidTankGT[] tanks = new FluidTankGT[count];
- for (int j = 0; j < count; j++) {
- tanks[j] = new FluidTankGT(capacity).setCapacityMultiplier(capacityMultiplier)
- .readFromNBT(nbtTank, NBT.UPGRADE_TANKS_PREFIX + j);
- }
- registerFluidInventory(tankName, tankUUID, count, capacity, capacityMultiplier, Inventory.INPUT);
- }
-
- final NBTTagList listOutputTanks = nbt.getTagList(NBT.UPGRADE_TANKS_OUTPUT, Constants.NBT.TAG_COMPOUND);
- for (int i = 0; i < listOutputTanks.tagCount(); i++) {
- final NBTTagCompound nbtTank = listOutputTanks.getCompoundTagAt(i);
- String tankUUID = nbtTank.getString(NBT.UPGRADE_TANK_UUID);
- String tankName = nbtTank.getString(NBT.UPGRADE_TANK_NAME);
- long capacity = nbtTank.getLong(NBT.UPGRADE_TANK_CAPACITY);
- long capacityMultiplier = nbtTank.getLong(NBT.UPGRADE_TANK_CAPACITY_MULTIPLIER);
- int count = nbtTank.getInteger(NBT.UPGRADE_TANKS_COUNT);
- FluidTankGT[] tanks = new FluidTankGT[count];
- for (int j = 0; j < count; j++) {
- tanks[j] = new FluidTankGT(capacity).setCapacityMultiplier(capacityMultiplier)
- .readFromNBT(nbtTank, NBT.UPGRADE_TANKS_PREFIX + j);
- }
- registerFluidInventory(tankName, tankUUID, count, capacity, capacityMultiplier, Inventory.OUTPUT);
+ @Override
+ protected void loadFluidLogic(NBTTagCompound nbt) {
+ if (!nbt.hasKey(NBT.TANK_IN) && !nbt.hasKey(NBT.TANK_OUT)) {
+ controllerFluidInput.addInventory(new FluidInventoryLogic(16, 32000));
+ controllerFluidOutput.addInventory(new FluidInventoryLogic(16, 32000));
+ return;
}
+ controllerFluidInput.loadFromNBT(nbt.getCompoundTag(NBT.TANK_IN));
+ controllerFluidOutput.loadFromNBT(nbt.getCompoundTag(NBT.TANK_OUT));
}
@Override
@@ -489,9 +253,9 @@ public abstract class Controller<T extends Controller<T>> extends MultiTileBasic
public String[] getDescription() {
if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) {
return getTooltip().getStructureInformation();
- } else {
- return getTooltip().getInformation();
}
+
+ return getTooltip().getInformation();
}
@Override
@@ -519,6 +283,7 @@ public abstract class Controller<T extends Controller<T>> extends MultiTileBasic
// Only trigger an update if forced (from onPostTick, generally), or if the structure has changed
if ((structureChanged || aForceReset)) {
+ clearSpecialLists();
structureOkay = checkMachine();
}
structureChanged = false;
@@ -531,8 +296,6 @@ public abstract class Controller<T extends Controller<T>> extends MultiTileBasic
}
public final boolean checkPiece(String piece, Vec3Impl offset) {
- functionalCasings.clear();
- upgradeCasings.clear();
return checkPiece(piece, offset.get0(), offset.get1(), offset.get2());
}
@@ -617,8 +380,8 @@ public abstract class Controller<T extends Controller<T>> extends MultiTileBasic
}
@SuppressWarnings("unchecked")
- private IStructureDefinition<Controller<T>> getCastedStructureDefinition() {
- return (IStructureDefinition<Controller<T>>) getStructureDefinition();
+ private IStructureDefinition<Controller<C, P>> getCastedStructureDefinition() {
+ return (IStructureDefinition<Controller<C, P>>) getStructureDefinition();
}
@Override
@@ -628,24 +391,27 @@ public abstract class Controller<T extends Controller<T>> extends MultiTileBasic
@Override
public void setExtendedFacing(ExtendedFacing newExtendedFacing) {
- if (extendedFacing != newExtendedFacing) {
- onStructureChange();
- if (structureOkay) stopMachine(false);
- extendedFacing = newExtendedFacing;
- structureOkay = false;
- if (isServerSide()) {
- StructureLibAPI.sendAlignment(
- this,
- new NetworkRegistry.TargetPoint(
- getWorld().provider.dimensionId,
- getXCoord(),
- getYCoord(),
- getZCoord(),
- 512));
- } else {
- issueTextureUpdate();
- }
+ if (extendedFacing == newExtendedFacing) {
+ return;
+ }
+
+ onStructureChange();
+ if (structureOkay) stopMachine(false);
+ extendedFacing = newExtendedFacing;
+ structureOkay = false;
+ if (isServerSide()) {
+ StructureLibAPI.sendAlignment(
+ this,
+ new NetworkRegistry.TargetPoint(
+ getWorld().provider.dimensionId,
+ getXCoord(),
+ getYCoord(),
+ getZCoord(),
+ 512));
+ } else {
+ issueTextureUpdate();
}
+
}
@Override
@@ -686,6 +452,31 @@ public abstract class Controller<T extends Controller<T>> extends MultiTileBasic
}
@Override
+ public void registerCaseWithPurpose(MultiTileCasingPurpose purpose, IMultiBlockPart part) {
+ final LinkedList<WeakReference<IMultiBlockPart>> tickableParts = registeredTickableParts.get(purpose.ordinal());
+ final Iterator<WeakReference<IMultiBlockPart>> it = tickableParts.iterator();
+ while (it.hasNext()) {
+ final IMultiBlockPart next = (it.next()).get();
+ if (next == null) {
+ it.remove();
+ } else if (next == part) {
+ return;
+ }
+ }
+ tickableParts.add(new WeakReference<>(part));
+ }
+
+ @Override
+ public void unregisterCaseWithPurpose(MultiTileCasingPurpose purpose, IMultiBlockPart part) {
+ final LinkedList<WeakReference<IMultiBlockPart>> tickableParts = registeredTickableParts.get(purpose.ordinal());
+ final Iterator<WeakReference<IMultiBlockPart>> it = tickableParts.iterator();
+ while (it.hasNext()) {
+ final IMultiBlockPart next = (it.next()).get();
+ if (next == null || next == part) it.remove();
+ }
+ }
+
+ @Override
public void onFirstTick(boolean isServerSide) {
super.onFirstTick(isServerSide);
if (isServerSide) {
@@ -715,7 +506,7 @@ public abstract class Controller<T extends Controller<T>> extends MultiTileBasic
}
@Override
- public void onTick(long timer, boolean isServerSide) {
+ public void onTick(long tick, boolean isServerSide) {
if (!tickCovers()) {
return;
}
@@ -723,24 +514,94 @@ public abstract class Controller<T extends Controller<T>> extends MultiTileBasic
@Override
public void onPostTick(long tick, boolean isServerSide) {
- if (isServerSide) {
- if (tick % 600 == 5) {
- clearSpecialLists();
- // Recheck the structure every 30 seconds or so
- if (!checkStructure(false)) checkStructure(true);
+ if (!isServerSide) { // client side
+ doActivitySound(getActivitySoundLoop());
+ return;
+ }
+
+ // server side
+ if (tick % 600 == 5) {
+ // Recheck the structure every 30 seconds or so
+ if (!checkStructure(false)) checkStructure(true);
+ }
+ if (checkStructure(false)) {
+ runMachine(tick);
+ pushItemOutputs(tick);
+ pushFluidOutputs(tick);
+
+ } else {
+ stopMachine(false);
+ }
+
+ }
+
+ protected void pushItemOutputs(long tick) {
+ if (tick % AUTO_OUTPUT_FREQUENCY_TICK != 0) return;
+ final LinkedList<WeakReference<IMultiBlockPart>> registeredItemOutputs = registeredTickableParts
+ .get(MultiTileCasingPurpose.ItemOutput.ordinal());
+ final Iterator<WeakReference<IMultiBlockPart>> itemOutputIterator = registeredItemOutputs.iterator();
+ while (itemOutputIterator.hasNext()) {
+ final IMultiBlockPart part = (itemOutputIterator.next()).get();
+ if (part == null) {
+ itemOutputIterator.remove();
+ continue;
}
- if (checkStructure(false)) {
- runMachine(tick);
- } else {
- stopMachine(false);
+ if (!part.shouldTick(mTickTimer)) {
+ itemOutputIterator.remove();
+ continue;
+ }
+
+ final IInventory facingInventory = part.getIInventoryAtSide(part.getFrontFacing());
+ if (facingInventory == null) {
+ continue;
+ }
+
+ moveMultipleItemStacks(
+ part,
+ facingInventory,
+ part.getFrontFacing(),
+ part.getBackFacing(),
+ null,
+ false,
+ (byte) 64,
+ (byte) 1,
+ (byte) 64,
+ (byte) 1,
+ part.getSizeInventory());
+ for (int i = 0; i < part.getSizeInventory(); i++) {
+ if (part.getStackInSlot(i) != null && part.getStackInSlot(i).stackSize <= 0) {
+ part.setInventorySlotContents(i, null);
+ }
+ }
+
+ }
+ }
+
+ protected void pushFluidOutputs(long tick) {
+ if (tick % AUTO_OUTPUT_FREQUENCY_TICK != 0) return;
+ final LinkedList<WeakReference<IMultiBlockPart>> registeredFluidOutputs = registeredTickableParts
+ .get(MultiTileCasingPurpose.FluidOutput.ordinal());
+ final Iterator<WeakReference<IMultiBlockPart>> fluidOutputIterator = registeredFluidOutputs.iterator();
+ while (fluidOutputIterator.hasNext()) {
+ final IMultiBlockPart part = (fluidOutputIterator.next()).get();
+ if (part == null) {
+ fluidOutputIterator.remove();
+ continue;
+ }
+ if (!part.shouldTick(mTickTimer)) {
+ fluidOutputIterator.remove();
}
- } else {
- doActivitySound(getActivitySoundLoop());
}
}
+ @Override
+ public void setCleanroom(boolean cleanroom) {
+ isCleanroom = cleanroom;
+ }
+
protected void clearSpecialLists() {
upgradeCasings.clear();
+ functionalCasings.clear();
}
@Override
@@ -773,47 +634,6 @@ public abstract class Controller<T extends Controller<T>> extends MultiTileBasic
this.limits = mLimits;
}
- // IMachineProgress
- @Override
- public long getProgress() {
- return progressTime;
- }
-
- @Override
- public long getMaxProgress() {
- return maxProgressTime;
- }
-
- @Override
- public boolean increaseProgress(int aProgressAmountInTicks) {
- return increaseProgressGetOverflow(aProgressAmountInTicks) != aProgressAmountInTicks;
- }
-
- @Override
- public FluidStack getDrainableFluid(ForgeDirection side) {
- return getDrainableFluid(side, null);
- }
-
- @Override
- public FluidStack getDrainableFluid(ForgeDirection side, Fluid fluidToDrain) {
- final IFluidTank tank = getFluidTankDrainable(
- side,
- fluidToDrain == null ? null : new FluidStack(fluidToDrain, 0));
- return tank == null ? null : tank.getFluid();
- }
-
- /**
- * Increases the Progress, returns the overflown Progress.
- */
- public int increaseProgressGetOverflow(int aProgress) {
- return 0;
- }
-
- @Override
- public boolean hasThingsToDo() {
- return getMaxProgress() > 0;
- }
-
public boolean isSeparateInputs() {
return separateInputs;
}
@@ -822,8 +642,6 @@ public abstract class Controller<T extends Controller<T>> extends MultiTileBasic
separateInputs = aSeparateInputs;
}
- // End IMachineProgress
-
protected IAlignmentLimits getInitialAlignmentLimits() {
return (d, r, f) -> !f.isVerticallyFliped();
}
@@ -877,226 +695,7 @@ public abstract class Controller<T extends Controller<T>> extends MultiTileBasic
}
}
- public <S> IStructureElement<S> addMultiTileCasing(String registryName, int meta, int modes) {
- MultiTileEntityRegistry registry = MultiTileEntityRegistry.getRegistry(registryName);
- int registryID = Block.getIdFromBlock(registry.mBlock);
- return addMultiTileCasing(registryID, meta, modes);
- }
-
- public <S> IStructureElement<S> addMultiTileCasing(int registryID, int meta, int modes) {
- return new IStructureElement<S>() {
-
- private final short[] DEFAULT = new short[] { 255, 255, 255, 0 };
- private IIcon[] mIcons = null;
-
- @Override
- public boolean check(S t, World world, int x, int y, int z) {
- final TileEntity tileEntity = world.getTileEntity(x, y, z);
- if (!(tileEntity instanceof MultiBlockPart part)) return false;
-
- if (registryID != part.getMultiTileEntityRegistryID() || meta != part.getMultiTileEntityID())
- return false;
-
- final IMultiBlockController tTarget = part.getTarget(false);
- if (tTarget != null && tTarget != t) return false;
-
- part.setTarget((IMultiBlockController) t, modes);
-
- ((Controller<?>) t).registerSpecialCasings(part);
- return true;
- }
-
- @Override
- public boolean spawnHint(S t, World world, int x, int y, int z, ItemStack trigger) {
- if (mIcons == null) {
- mIcons = new IIcon[6];
- Arrays.fill(mIcons, TextureSet.SET_NONE.mTextures[OrePrefixes.block.mTextureIndex].getIcon());
- // Arrays.fill(mIcons, getTexture(aCasing);
- // for (byte i : ALL_VALID_SIDES) {
- // mIcons[i] = aCasing.getIcon(i, aMeta);
- // }
- }
- final short[] RGBA = DEFAULT;
- StructureLibAPI.hintParticleTinted(world, x, y, z, mIcons, RGBA);
- // StructureLibAPI.hintParticle(world, x, y, z, aCasing, aMeta);
- return true;
- }
-
- @Override
- public boolean placeBlock(S t, World world, int x, int y, int z, ItemStack trigger) {
- final MultiTileEntityRegistry tRegistry = MultiTileEntityRegistry.getRegistry(registryID);
- final MultiTileEntityContainer tContainer = tRegistry
- .getNewTileEntityContainer(world, x, y, z, meta, null);
- if (tContainer == null) {
- GT_FML_LOGGER.error("NULL CONTAINER");
- return false;
- }
- final IMultiTileEntity te = ((IMultiTileEntity) tContainer.mTileEntity);
- if (!(te instanceof MultiBlockPart)) {
- GT_FML_LOGGER.error("Not a multiblock part");
- return false;
- }
- if (world.setBlock(x, y, z, tContainer.mBlock, 15 - tContainer.mBlockMetaData, 2)) {
- tContainer.setMultiTile(world, x, y, z);
- ((MultiBlockPart) te).setTarget(Controller.this, modes);
-
- ((Controller<?>) t).registerSpecialCasings((MultiBlockPart) te);
- }
-
- return false;
- }
-
- public IIcon getTexture(OrePrefixes aBlock) {
- return TextureSet.SET_NONE.mTextures[OrePrefixes.block.mTextureIndex].getIcon();
- }
- };
- }
-
- protected <S> IStructureElementChain<S> addMotorCasings(int modes) {
- return ofChain(
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, LV_Motor.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, MV_Motor.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, HV_Motor.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, EV_Motor.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, IV_Motor.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, LuV_Motor.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, ZPM_Motor.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UV_Motor.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UHV_Motor.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UEV_Motor.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UIV_Motor.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UMV_Motor.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UXV_Motor.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, MAX_Motor.getId(), modes));
- }
-
- protected <S> IStructureElementChain<S> addPumpCasings(int modes) {
- return ofChain(
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, LV_Pump.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, MV_Pump.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, HV_Pump.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, EV_Pump.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, IV_Pump.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, LuV_Pump.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, ZPM_Pump.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UV_Pump.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UHV_Pump.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UEV_Pump.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UIV_Pump.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UMV_Pump.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UXV_Pump.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, MAX_Pump.getId(), modes));
- }
-
- protected <S> IStructureElementChain<S> addPistonCasings(int modes) {
- return ofChain(
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, LV_Piston.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, MV_Piston.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, HV_Piston.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, EV_Piston.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, IV_Piston.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, LuV_Piston.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, ZPM_Piston.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UV_Piston.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UHV_Piston.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UEV_Piston.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UIV_Piston.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UMV_Piston.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UXV_Piston.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, MAX_Piston.getId(), modes));
- }
-
- protected <S> IStructureElementChain<S> addConveyorCasings(int modes) {
- return ofChain(
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, LV_Conveyor.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, MV_Conveyor.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, HV_Conveyor.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, EV_Conveyor.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, IV_Conveyor.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, LuV_Conveyor.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, ZPM_Conveyor.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UV_Conveyor.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UHV_Conveyor.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UEV_Conveyor.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UIV_Conveyor.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UMV_Conveyor.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UXV_Conveyor.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, MAX_Conveyor.getId(), modes));
- }
-
- protected <S> IStructureElementChain<S> addRobotArmCasings(int modes) {
- return ofChain(
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, LV_RobotArm.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, MV_RobotArm.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, HV_RobotArm.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, EV_RobotArm.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, IV_RobotArm.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, LuV_RobotArm.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, ZPM_RobotArm.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UV_RobotArm.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UHV_RobotArm.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UEV_RobotArm.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UIV_RobotArm.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UMV_RobotArm.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UXV_RobotArm.getId(), modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, MAX_RobotArm.getId(), modes));
- }
-
- protected <S> IStructureElementChain<S> addSensorCasings(int Modes) {
- return ofChain(
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, LV_Sensor.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, MV_Sensor.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, HV_Sensor.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, EV_Sensor.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, IV_Sensor.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, LuV_Sensor.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, ZPM_Sensor.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UV_Sensor.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UHV_Sensor.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UEV_Sensor.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UIV_Sensor.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UMV_Sensor.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UXV_Sensor.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, MAX_Sensor.getId(), Modes));
- }
-
- protected <S> IStructureElementChain<S> addEmitterCasings(int Modes) {
- return ofChain(
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, LV_Emitter.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, MV_Emitter.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, HV_Emitter.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, EV_Emitter.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, IV_Emitter.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, LuV_Emitter.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, ZPM_Emitter.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UV_Emitter.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UHV_Emitter.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UEV_Emitter.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UIV_Emitter.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UMV_Emitter.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UXV_Emitter.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, MAX_Emitter.getId(), Modes));
- }
-
- protected <S> IStructureElementChain<S> addFieldGeneratorCasings(int Modes) {
- return ofChain(
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, LV_FieldGenerator.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, MV_FieldGenerator.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, HV_FieldGenerator.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, EV_FieldGenerator.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, IV_FieldGenerator.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, LuV_FieldGenerator.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, ZPM_FieldGenerator.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UV_FieldGenerator.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UHV_FieldGenerator.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UEV_FieldGenerator.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UIV_FieldGenerator.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UMV_FieldGenerator.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, UXV_FieldGenerator.getId(), Modes),
- addMultiTileCasing(COMPONENT_CASING_REGISTRY_NAME, MAX_FieldGenerator.getId(), Modes));
- }
-
- protected void registerSpecialCasings(MultiBlockPart part) {
+ public void registerSpecialCasings(MultiBlockPart part) {
if (part instanceof UpgradeCasing) {
upgradeCasings.add((UpgradeCasing) part);
}
@@ -1105,728 +704,177 @@ public abstract class Controller<T extends Controller<T>> extends MultiTileBasic
}
}
- /**
- * Fluid - MultiBlock related Fluid Tank behaviour.
- */
- public void registerFluidInventory(String name, String id, int numberOfSlots, long capacity,
- long capacityMultiplier, int type) {
- if (name == null || name.equals("")
- || id == null
- || id.equals("")
- || numberOfSlots < 0
- || capacity < 0
- || capacityMultiplier < 0) {
- return;
- }
- FluidTankGT[] tanks = new FluidTankGT[numberOfSlots];
- for (int i = 0; i < numberOfSlots; i++) {
- tanks[i] = new FluidTankGT(capacity).setCapacityMultiplier(capacityMultiplier);
- }
- registerFluidInventory(name, id, tanks, type);
- }
-
- public void registerFluidInventory(String name, String id, FluidTankGT[] fluidInventory, int type) {
- if (name == null || name.equals("")
- || id == null
- || id.equals("")
- || fluidInventory == null
- || fluidInventory.length == 0) {
- return;
- }
- if (type == Inventory.INPUT || type == Inventory.BOTH) {
- if (multiBlockInputTank.containsKey(id)) return;
- multiBlockInputTank.put(id, fluidInventory);
- multiBlockInputTankNames.put(id, name);
- }
- if (type == Inventory.OUTPUT || type == Inventory.BOTH) {
- if (multiBlockOutputTank.containsKey(id)) return;
- multiBlockOutputTank.put(id, fluidInventory);
- multiBlockOutputTankNames.put(id, name);
- }
- }
-
- public void unregisterFluidInventory(String aName, String aID, int aType) {
- if ((aType == Inventory.INPUT || aType == Inventory.BOTH) && multiBlockInputTank.containsKey(aID)) {
- multiBlockInputTank.remove(aID, multiBlockInputTank.get(aID));
- multiBlockInputTankNames.remove(aID, aName);
- }
- if ((aType == Inventory.OUTPUT || aType == Inventory.BOTH) && multiBlockOutputTank.containsKey(aID)) {
- multiBlockOutputTank.remove(aID, multiBlockOutputTank.get(aID));
- multiBlockOutputTankNames.remove(aID, aName);
- }
- }
-
- protected FluidTankGT[] getTanksForInput() {
- List<FluidTankGT> tanks = new ArrayList<>();
- for (FluidTankGT[] inputTanks : multiBlockInputTank.values()) {
- tanks.addAll(Arrays.asList(inputTanks));
- }
- return tanks.toArray(new FluidTankGT[0]);
- }
-
- protected FluidTankGT[] getTanksForOutput() {
- List<FluidTankGT> tanks = new ArrayList<>();
- for (FluidTankGT[] outputTanks : multiBlockOutputTank.values()) {
- tanks.addAll(Arrays.asList(outputTanks));
- }
- return tanks.toArray(new FluidTankGT[0]);
- }
-
- protected IFluidTank getFluidTankFillable(MultiBlockPart aPart, ForgeDirection side, FluidStack aFluidToFill) {
- return getFluidTankFillable(side, aFluidToFill);
- }
-
- protected IFluidTank getFluidTankDrainable(MultiBlockPart aPart, ForgeDirection side, FluidStack aFluidToDrain) {
- return getFluidTankDrainable(side, aFluidToDrain);
- }
-
- protected IFluidTank[] getFluidTanks(MultiBlockPart aPart, ForgeDirection side) {
- return getFluidTanks(side);
- }
-
- @Override
- public int fill(MultiBlockPart aPart, ForgeDirection aDirection, FluidStack aFluid, boolean aDoFill) {
- if (aFluid == null || aFluid.amount <= 0) return 0;
- final IFluidTank tTank = getFluidTankFillable(aPart, aDirection, aFluid);
- if (tTank == null) return 0;
- final int rFilledAmount = tTank.fill(aFluid, aDoFill);
- if (rFilledAmount > 0 && aDoFill) hasInventoryChanged = true;
- return rFilledAmount;
- }
-
- @Override
- public FluidStack drain(MultiBlockPart aPart, ForgeDirection aDirection, FluidStack aFluid, boolean aDoDrain) {
- if (aFluid == null || aFluid.amount <= 0) return null;
- final IFluidTank tTank = getFluidTankDrainable(aPart, aDirection, aFluid);
- if (tTank == null || tTank.getFluid() == null
- || tTank.getFluidAmount() == 0
- || !tTank.getFluid()
- .isFluidEqual(aFluid))
- return null;
- final FluidStack rDrained = tTank.drain(aFluid.amount, aDoDrain);
- if (rDrained != null && aDoDrain) markInventoryBeenModified();
- return rDrained;
- }
-
- @Override
- public FluidStack drain(MultiBlockPart aPart, ForgeDirection aDirection, int aAmountToDrain, boolean aDoDrain) {
- if (aAmountToDrain <= 0) return null;
- final IFluidTank tTank = getFluidTankDrainable(aPart, aDirection, null);
- if (tTank == null || tTank.getFluid() == null || tTank.getFluidAmount() == 0) return null;
- final FluidStack rDrained = tTank.drain(aAmountToDrain, aDoDrain);
- if (rDrained != null && aDoDrain) markInventoryBeenModified();
- return rDrained;
- }
-
- @Override
- public boolean canFill(MultiBlockPart aPart, ForgeDirection aDirection, Fluid aFluid) {
- if (aFluid == null) return false;
- final IFluidTank tTank = getFluidTankFillable(aPart, aDirection, new FluidStack(aFluid, 0));
- return tTank != null && (tTank.getFluid() == null || tTank.getFluid()
- .getFluid() == aFluid);
- }
-
- @Override
- public boolean canDrain(MultiBlockPart aPart, ForgeDirection aDirection, Fluid aFluid) {
- if (aFluid == null) return false;
- final IFluidTank tTank = getFluidTankDrainable(aPart, aDirection, new FluidStack(aFluid, 0));
- return tTank != null && (tTank.getFluid() != null && tTank.getFluid()
- .getFluid() == aFluid);
- }
-
- @Override
- public FluidTankInfo[] getTankInfo(MultiBlockPart aPart, ForgeDirection aDirection) {
- final IFluidTank[] tTanks = getFluidTanks(aPart, aDirection);
- if (tTanks == null || tTanks.length <= 0) return GT_Values.emptyFluidTankInfo;
- final FluidTankInfo[] rInfo = new FluidTankInfo[tTanks.length];
- for (int i = 0; i < tTanks.length; i++) rInfo[i] = new FluidTankInfo(tTanks[i]);
- return rInfo;
- }
-
- @Override
- public IFluidTank[] getFluidTanksForGUI(MultiBlockPart aPart) {
- final String lockedInventory = aPart.getLockedInventory();
- if (lockedInventory == null) {
- if (aPart.modeSelected(MultiBlockPart.FLUID_IN)) return getTanksForInput();
- else if (aPart.modeSelected(MultiBlockPart.FLUID_OUT)) return getTanksForOutput();
- } else {
- final Map<String, FluidTankGT[]> tankMap = getMultiBlockTankArray(aPart);
- if (tankMap == null) return GT_Values.emptyFluidTank;
- final FluidTankGT[] tanks = tankMap.get(lockedInventory);
- return tanks != null ? tanks : GT_Values.emptyFluidTank;
- }
- return GT_Values.emptyFluidTank;
- }
-
- // #region Energy
- @Override
- public PowerLogic getPowerLogic(IMultiBlockPart part, ForgeDirection side) {
- if (!(this instanceof PowerLogicHost powerLogicHost)) {
- return null;
- }
-
- if (part.getFrontFacing() != side) {
- return null;
- }
-
- return powerLogicHost.getPowerLogic(side);
- }
- // #endregion Energy
-
- /**
- * Item - MultiBlock related Item behaviour.
- */
- @Override
- public void registerInventory(String aName, String aID, int aInventorySize, int aType) {
- registerInventory(aName, aID, new ItemStackHandler(aInventorySize), aType);
- }
-
- public void registerInventory(String name, String id, IItemHandlerModifiable inventory, int type) {
- if (name == null || name.equals("") || id == null || id.equals("") || inventory == null) {
- return;
- }
- if (type == Inventory.INPUT || type == Inventory.BOTH) {
- if (multiBlockInputInventory.containsKey(id)) return;
- multiBlockInputInventory.put(id, inventory);
- multiBlockInputInventoryNames.put(id, name);
- }
- if (type == Inventory.OUTPUT || type == Inventory.BOTH) {
- if (multiBlockOutputInventory.containsKey(id)) return;
- multiBlockOutputInventory.put(id, inventory);
- multiBlockOutputInventoryNames.put(id, name);
- }
- }
-
- @Override
- public void unregisterInventory(String aName, String aID, int aType) {
- if ((aType == Inventory.INPUT || aType == Inventory.BOTH) && multiBlockInputInventory.containsKey(aID)) {
- multiBlockInputInventory.remove(aID, multiBlockInputInventory.get(aID));
- multiBlockInputInventoryNames.remove(aID, aName);
- }
- if ((aType == Inventory.OUTPUT || aType == Inventory.BOTH) && multiBlockOutputInventory.containsKey(aID)) {
- multiBlockOutputInventory.remove(aID, multiBlockOutputInventory.get(aID));
- multiBlockOutputInventoryNames.remove(aID, aName);
- }
- }
-
- @Override
- public void changeInventoryName(String aName, String aID, int aType) {
- if ((aType == Inventory.INPUT || aType == Inventory.BOTH) && multiBlockInputInventoryNames.containsKey(aID)) {
- multiBlockInputInventoryNames.put(aID, aName);
- }
- if ((aType == Inventory.OUTPUT || aType == Inventory.BOTH) && multiBlockOutputInventoryNames.containsKey(aID)) {
- multiBlockOutputInventoryNames.put(aID, aName);
- }
- }
-
- @Override
- public boolean hasInventoryBeenModified(MultiBlockPart aPart) {
- if (aPart.modeSelected(MultiBlockPart.ITEM_IN)) return hasInventoryBeenModified();
- else if (aPart.modeSelected(MultiBlockPart.ITEM_OUT)) return hasOutputInventoryBeenModified();
-
- return false;
- }
+ // #region Fluid - MultiBlock related Fluid Tank behaviour.
@Override
- public boolean isValidSlot(MultiBlockPart aPart, int aIndex) {
- return false;
+ @Nullable
+ public FluidInventoryLogic getFluidLogic(@Nonnull ForgeDirection side, @Nonnull InventoryType type) {
+ if (side == facing) return null;
+ return switch (type) {
+ case Input -> controllerFluidInput.getAllInventoryLogics();
+ case Output -> controllerFluidOutput.getAllInventoryLogics();
+ default -> null;
+ };
}
- @Override
- public void enableWorking() {
- super.enableWorking();
- if (!structureOkay) {
- checkStructure(true);
- }
+ @Nullable
+ public FluidInventoryLogic getFluidLogic(@Nonnull InventoryType type, @Nullable UUID id) {
+ return switch (type) {
+ case Input -> controllerFluidInput.getInventoryLogic(id);
+ case Output -> controllerFluidOutput.getInventoryLogic(id);
+ default -> null;
+ };
}
@Override
- public IItemHandlerModifiable getInventoryForGUI(MultiBlockPart aPart) {
- if (isServerSide()) {
- for (UpgradeCasing tPart : upgradeCasings) {
- if (!(tPart instanceof Inventory)) continue;
- tPart.issueClientUpdate();
+ @Nonnull
+ public UUID registerFluidInventory(int tanks, long capacity, int tier, @Nonnull InventoryType type,
+ boolean isUpgradeInventory) {
+ return switch (type) {
+ case Input -> controllerFluidInput
+ .addInventory(new FluidInventoryLogic(tanks, capacity, tier, isUpgradeInventory));
+ case Output -> controllerFluidOutput
+ .addInventory(new FluidInventoryLogic(tanks, capacity, tier, isUpgradeInventory));
+ case Both -> {
+ UUID id = controllerFluidInput
+ .addInventory(new FluidInventoryLogic(tanks, capacity, tier, isUpgradeInventory));
+ controllerFluidOutput
+ .addInventory(id, new FluidInventoryLogic(tanks, capacity, tier, isUpgradeInventory));
+ yield id;
}
- }
- final Map<String, IItemHandlerModifiable> multiBlockInventory = getMultiBlockInventory(aPart);
- if (multiBlockInventory == null) return null;
-
- final String lockedInventory = aPart.getLockedInventory();
- if (lockedInventory == null) {
- return new ListItemHandler(multiBlockInventory.values());
- } else {
- final IItemHandlerModifiable inv = multiBlockInventory.get(lockedInventory);
- return inv;
- }
- }
-
- @Override
- public boolean addStackToSlot(MultiBlockPart aPart, int aIndex, ItemStack aStack) {
- return false;
+ };
}
@Override
- public boolean addStackToSlot(MultiBlockPart aPart, int aIndex, ItemStack aStack, int aAmount) {
- return false;
- }
-
- protected Map<String, FluidTankGT[]> getMultiBlockTankArray(MultiBlockPart aPart) {
- if (aPart.modeSelected(MultiBlockPart.FLUID_IN)) return multiBlockInputTank;
- else if (aPart.modeSelected(MultiBlockPart.FLUID_OUT)) return multiBlockOutputTank;
- return null;
- }
-
- protected Map<String, String> getMultiBlockTankArrayNames(MultiBlockPart aPart) {
- if (aPart.modeSelected(MultiBlockPart.FLUID_IN)) return multiBlockInputTankNames;
- else if (aPart.modeSelected(MultiBlockPart.FLUID_OUT)) return multiBlockOutputTankNames;
- return null;
- }
-
- protected Map<String, IItemHandlerModifiable> getMultiBlockInventory(MultiBlockPart aPart) {
- if (aPart.modeSelected(MultiBlockPart.ITEM_IN)) return multiBlockInputInventory;
- else if (aPart.modeSelected(MultiBlockPart.ITEM_OUT)) return multiBlockOutputInventory;
- return null;
- }
-
- protected Map<String, String> getMultiBlockInventoryNames(MultiBlockPart aPart) {
- if (aPart.modeSelected(MultiBlockPart.ITEM_IN)) return multiBlockInputInventoryNames;
- else if (aPart.modeSelected(MultiBlockPart.ITEM_OUT)) return multiBlockOutputInventoryNames;
- return null;
- }
-
- protected Pair<IItemHandlerModifiable, Integer> getInventory(MultiBlockPart aPart, int aSlot) {
- final Map<String, IItemHandlerModifiable> multiBlockInventory = getMultiBlockInventory(aPart);
- if (multiBlockInventory == null) return null;
-
- final String invName = aPart.getLockedInventory();
- if (invName != null && !invName.isEmpty()) return new ImmutablePair<>(multiBlockInventory.get(invName), aSlot);
-
- int start = 0;
- for (IItemHandlerModifiable inv : multiBlockInventory.values()) {
- if (aSlot >= start && aSlot < start + inv.getSlots()) {
- return new ImmutablePair<>(inv, aSlot - start);
+ @Nonnull
+ public FluidInventoryLogic unregisterFluidInventory(@Nonnull UUID id, @Nonnull InventoryType type) {
+ return switch (type) {
+ case Input -> controllerFluidInput.removeInventory(id);
+ case Output -> controllerFluidOutput.removeInventory(id);
+ case Both -> {
+ FluidInventoryLogic input = controllerFluidInput.removeInventory(id);
+ FluidInventoryLogic output = controllerFluidOutput.removeInventory(id);
+ yield new FluidInventoryLogic(
+ Arrays.asList(input, output)
+ .stream()
+ .map(inv -> inv.getInventory())
+ .collect(Collectors.toList()));
}
- start += inv.getSlots();
- }
- return null;
+ };
}
@Override
- public int[] getAccessibleSlotsFromSide(MultiBlockPart aPart, ForgeDirection side) {
- final TIntList tList = new TIntArrayList();
- final Map<String, IItemHandlerModifiable> multiBlockInventory = getMultiBlockInventory(aPart);
- if (multiBlockInventory == null) return tList.toArray();
-
- final String lockedInventory = aPart.getLockedInventory();
- // Item in --> input inv
- // Item out --> output inv
-
- int start = 0;
- if (lockedInventory == null) {
- for (IItemHandlerModifiable inv : multiBlockInventory.values()) {
- for (int i = start; i < inv.getSlots() + start; i++) tList.add(i);
- start += inv.getSlots();
- }
- } else {
- final IItemHandlerModifiable inv = multiBlockInventory.get(lockedInventory);
- final int len = inv != null ? inv.getSlots() : 0;
- for (int i = 0; i < len; i++) tList.add(i);
+ public void changeFluidInventoryDisplayName(@Nullable UUID id, @Nullable String displayName,
+ @Nonnull InventoryType type) {
+ switch (type) {
+ case Input:
+ controllerFluidInput.setInventoryDisplayName(id, displayName);
+ break;
+ case Output:
+ controllerFluidOutput.setInventoryDisplayName(id, displayName);
+ break;
+ case Both:
+ controllerFluidInput.setInventoryDisplayName(id, displayName);
+ controllerFluidOutput.setInventoryDisplayName(id, displayName);
+ break;
}
- return tList.toArray();
}
- @Override
- public boolean canInsertItem(MultiBlockPart aPart, int aSlot, ItemStack aStack, ForgeDirection side) {
- final Pair<IItemHandlerModifiable, Integer> tInv = getInventory(aPart, aSlot);
- if (tInv == null) return false;
-
- final int tSlot = tInv.getRight();
- final IItemHandlerModifiable inv = tInv.getLeft();
-
- return inv.getStackInSlot(tSlot) == null || GT_Utility.areStacksEqual(aStack, inv.getStackInSlot(tSlot)); // &&
- // allowPutStack(getBaseMetaTileEntity(),
- // aIndex,
- // (byte)
- // aSide,
- // aStack)
- }
+ // #endregion Fluid
- @Override
- public boolean canExtractItem(MultiBlockPart aPart, int aSlot, ItemStack aStack, ForgeDirection side) {
- final Pair<IItemHandlerModifiable, Integer> tInv = getInventory(aPart, aSlot);
- if (tInv == null) return false;
-
- final int tSlot = tInv.getRight();
- final IItemHandlerModifiable inv = tInv.getLeft();
-
- return inv.getStackInSlot(tSlot) != null; // && allowPullStack(getBaseMetaTileEntity(), aIndex, (byte) aSide,
- // aStack);
- }
+ // #region Item - MultiBlock related Item behaviour.
@Override
- public int getSizeInventory(MultiBlockPart aPart) {
- final Map<String, IItemHandlerModifiable> multiBlockInventory = getMultiBlockInventory(aPart);
- if (multiBlockInventory == null) return 0;
-
- final String lockedInventory = aPart.getLockedInventory();
- if (lockedInventory == null) {
- int len = 0;
- for (IItemHandlerModifiable inv : multiBlockInventory.values()) len += inv.getSlots();
- return len;
- } else {
- final IItemHandlerModifiable inv = multiBlockInventory.get(lockedInventory);
- return inv != null ? inv.getSlots() : 0;
- }
+ @Nullable
+ public ItemInventoryLogic getItemLogic(@Nonnull ForgeDirection side, @Nonnull InventoryType type) {
+ if (side == facing) return null;
+ return switch (type) {
+ case Input -> controllerItemInput.getAllInventoryLogics();
+ case Output -> controllerItemOutput.getAllInventoryLogics();
+ default -> null;
+ };
}
@Override
- public ItemStack getStackInSlot(MultiBlockPart aPart, int aSlot) {
- final Pair<IItemHandlerModifiable, Integer> tInv = getInventory(aPart, aSlot);
- if (tInv == null) return null;
-
- final int tSlot = tInv.getRight();
- final IItemHandlerModifiable inv = tInv.getLeft();
- if (inv == null) return null;
-
- return inv.getStackInSlot(tSlot);
+ @Nullable
+ public ItemInventoryLogic getItemLogic(@Nonnull InventoryType type, @Nullable UUID id) {
+ return switch (type) {
+ case Input -> controllerItemInput.getInventoryLogic(id);
+ case Output -> controllerItemOutput.getInventoryLogic(id);
+ default -> null;
+ };
}
@Override
- public ItemStack decrStackSize(MultiBlockPart aPart, int aSlot, int aDecrement) {
- final ItemStack tStack = getStackInSlot(aPart, aSlot);
- ItemStack rStack = GT_Utility.copyOrNull(tStack);
- if (tStack != null) {
- if (tStack.stackSize <= aDecrement) {
- setInventorySlotContents(aPart, aSlot, null);
- } else {
- rStack = tStack.splitStack(aDecrement);
- if (tStack.stackSize == 0) setInventorySlotContents(aPart, aSlot, null);
+ @Nonnull
+ public UUID registerItemInventory(int slots, int tier, @Nonnull InventoryType type, boolean isUpgradeInventory) {
+ return switch (type) {
+ case Input -> controllerItemInput.addInventory(new ItemInventoryLogic(slots, tier, isUpgradeInventory));
+ case Output -> controllerItemOutput.addInventory(new ItemInventoryLogic(slots, tier, isUpgradeInventory));
+ case Both -> {
+ UUID id = controllerItemInput.addInventory(new ItemInventoryLogic(slots, tier, isUpgradeInventory));
+ controllerItemOutput.addInventory(id, new ItemInventoryLogic(slots, tier, isUpgradeInventory));
+ yield id;
}
- }
- return rStack;
- }
-
- @Override
- public ItemStack getStackInSlotOnClosing(MultiBlockPart aPart, int aSlot) {
- final Pair<IItemHandlerModifiable, Integer> tInv = getInventory(aPart, aSlot);
- if (tInv == null) return null;
-
- final IItemHandlerModifiable inv = tInv.getLeft();
- final int tSlot = tInv.getRight();
-
- final ItemStack rStack = inv.getStackInSlot(tSlot);
- inv.setStackInSlot(tSlot, null);
- return rStack;
- }
-
- @Override
- public void setInventorySlotContents(MultiBlockPart aPart, int aSlot, ItemStack aStack) {
- final Pair<IItemHandlerModifiable, Integer> tInv = getInventory(aPart, aSlot);
- if (tInv == null) return;
-
- final IItemHandlerModifiable inv = tInv.getLeft();
- final int tSlot = tInv.getRight();
- inv.setStackInSlot(tSlot, aStack);
- }
-
- @Override
- public List<String> getInventoryNames(MultiBlockPart aPart) {
- final List<String> inventoryNames = new ArrayList<>();
- inventoryNames.add(ALL_INVENTORIES_NAME);
- inventoryNames.addAll(getMultiBlockInventoryNames(aPart).values());
- return inventoryNames;
- }
-
- @Override
- public List<String> getInventoryIDs(MultiBlockPart aPart) {
- final List<String> tInventoryIDs = new ArrayList<>();
- tInventoryIDs.add(ALL_INVENTORIES_NAME);
- tInventoryIDs.addAll(getMultiBlockInventory(aPart).keySet());
- return tInventoryIDs;
- }
-
- @Override
- public String getInventoryName(MultiBlockPart aPart) {
- final StringBuilder str = new StringBuilder();
- str.append(getInventoryName());
- if (aPart.modeSelected(MultiBlockPart.ITEM_IN)) {
- str.append(" Input");
- } else if (aPart.modeSelected(MultiBlockPart.ITEM_OUT)) {
- str.append(" Output");
- String a;
- } else {
- str.append(" Unknown");
- }
- final String lockedInventory = aPart.getLockedInventory();
- if (lockedInventory != null && !lockedInventory.equals("")) {
- str.append(" [Locked: ")
- .append(lockedInventory)
- .append("]");
- }
-
- return str.toString();
- }
-
- @Override
- public List<String> getTankArrayNames(MultiBlockPart aPart) {
- final List<String> inventoryNames = new ArrayList<>();
- inventoryNames.add(ALL_INVENTORIES_NAME);
- inventoryNames.addAll(getMultiBlockTankArrayNames(aPart).values());
- return inventoryNames;
- }
-
- @Override
- public List<String> getTankArrayIDs(MultiBlockPart aPart) {
- final List<String> inventoryIDs = new ArrayList<>();
- inventoryIDs.add(ALL_INVENTORIES_NAME);
- inventoryIDs.addAll(getMultiBlockTankArray(aPart).keySet());
- return inventoryIDs;
- }
-
- @Override
- public boolean hasCustomInventoryName(MultiBlockPart aPart) {
- return hasCustomInventoryName();
- }
-
- @Override
- public int getInventoryStackLimit(MultiBlockPart aPart) {
- return getInventoryStackLimit();
- }
-
- @Override
- public void markDirty(MultiBlockPart aPart) {
- markDirty();
- if (aPart.modeSelected(MultiBlockPart.ITEM_OUT)) markOutputInventoryBeenModified();
- else markInventoryBeenModified();
- }
-
- @Override
- public boolean isUseableByPlayer(MultiBlockPart aPart, EntityPlayer aPlayer) {
- return isUseableByPlayer(aPlayer);
- }
-
- @Override
- public void openInventory(MultiBlockPart aPart) {
- // TODO: MultiInventory - consider the part's inventory
- openInventory();
- }
-
- @Override
- public void closeInventory(MultiBlockPart aPart) {
- // TODO: MultiInventory - consider the part's inventory
- closeInventory();
- }
-
- @Override
- public boolean isItemValidForSlot(MultiBlockPart aPart, int aSlot, ItemStack aStack) {
- return isItemValidForSlot(aSlot, aStack);
- }
-
- /*
- * Helper Methods For Recipe checking
- */
-
- @Override
- protected ItemStack[] getInputItems() {
- return getInventoriesForInput().getStacks()
- .toArray(new ItemStack[0]);
- }
-
- protected ItemStack[] getOutputItems() {
- return getInventoriesForOutput().getStacks()
- .toArray(new ItemStack[0]);
- }
-
- protected Iterable<Pair<ItemStack[], String>> getItemInputsForEachInventory() {
- return multiBlockInputInventory.entrySet()
- .stream()
- .map(
- (entry) -> Pair.of(
- entry.getValue()
- .getStacks()
- .toArray(new ItemStack[0]),
- entry.getKey()))
- .collect(Collectors.toList());
- }
-
- protected ItemStack[] getItemInputsForInventory(String id) {
- IItemHandlerModifiable inventory = multiBlockInputInventory.get(id);
- if (inventory != null) {
- return inventory.getStacks()
- .toArray(new ItemStack[0]);
- }
- return null;
+ };
}
@Override
- protected FluidStack[] getInputFluids() {
- List<FluidStack> fluidStacks = new ArrayList<>();
- for (FluidTankGT[] inputTanks : multiBlockInputTank.values()) {
- for (FluidTankGT inputTank : inputTanks) {
- FluidStack fluidStack = inputTank.get();
- if (fluidStack != null) {
- fluidStacks.add(fluidStack);
- }
+ public ItemInventoryLogic unregisterItemInventory(@Nonnull UUID id, @Nonnull InventoryType type) {
+ return switch (type) {
+ case Input -> controllerItemInput.removeInventory(id);
+ case Output -> controllerItemOutput.removeInventory(id);
+ case Both -> {
+ ItemInventoryLogic input = controllerItemInput.removeInventory(id);
+ ItemInventoryLogic output = controllerItemOutput.removeInventory(id);
+ yield new ItemInventoryLogic(
+ Arrays.asList(input, output)
+ .stream()
+ .map(inv -> inv.getInventory())
+ .collect(Collectors.toList()));
}
- }
- return fluidStacks.toArray(new FluidStack[0]);
- }
-
- protected FluidStack[] getOutputFluids() {
- List<FluidStack> fluidStacks = new ArrayList<>();
- for (FluidTankGT[] inputTanks : multiBlockInputTank.values()) {
- for (FluidTankGT inputTank : inputTanks) {
- FluidStack fluidStack = inputTank.getFluid();
- if (fluidStack != null) {
- fluidStacks.add(fluidStack);
- }
- }
- }
- return fluidStacks.toArray(new FluidStack[0]);
- }
-
- protected Iterable<Pair<FluidStack[], String>> getFluidInputsForEachTankArray() {
- return multiBlockInputTank.entrySet()
- .stream()
- .map((entry) -> Pair.of(FluidTankGT.getFluidsFromTanks(entry.getValue()), entry.getKey()))
- .collect(Collectors.toList());
- }
-
- protected FluidStack[] getFluidInputsForTankArray(String id) {
- return FluidTankGT.getFluidsFromTanks(multiBlockInputTank.get(id));
- }
-
- protected void setItemOutputs(String inventory, ItemStack... itemOutputs) {
- itemsToOutput = itemOutputs;
- inventoryName = inventory;
- }
-
- @Override
- protected void setItemOutputs(ItemStack... outputs) {
- super.setItemOutputs(outputs);
- inventoryName = null;
+ };
}
@Override
- protected void outputItems() {
- if (itemsToOutput == null) {
- return;
- }
-
- IItemHandlerModifiable inv;
- if (inventoryName != null) {
- inv = multiBlockOutputInventory.getOrDefault(inventoryName, getInventoriesForOutput());
- } else {
- inv = getInventoriesForOutput();
+ public void changeItemInventoryDisplayName(@Nullable UUID id, @Nullable String displayName,
+ @Nonnull InventoryType type) {
+ switch (type) {
+ case Input:
+ controllerItemInput.setInventoryDisplayName(id, displayName);
+ break;
+ case Output:
+ controllerItemOutput.setInventoryDisplayName(id, displayName);
+ break;
+ case Both:
+ controllerItemInput.setInventoryDisplayName(id, displayName);
+ controllerItemOutput.setInventoryDisplayName(id, displayName);
+ break;
}
- for (ItemStack item : itemsToOutput) {
- int index = 0;
- while (item != null && item.stackSize > 0 && index < inv.getSlots()) {
- item = inv.insertItem(index++, item.copy(), false);
- }
- }
- itemsToOutput = null;
}
- protected void setFluidOutputs(String tank, FluidStack... fluidOuputs) {
- fluidsToOutput = fluidOuputs;
- tankName = tank;
- }
+ // #endregion Item
- @Override
- protected void setFluidOutputs(FluidStack... outputs) {
- super.setFluidOutputs(outputs);
- tankName = null;
- }
+ // #region Energy
+ @Nonnull
@Override
- protected void outputFluids() {
- if (fluidsToOutput == null) {
- return;
- }
-
- List<FluidTankGT> tanks = Arrays.asList(outputTanks);
- for (FluidStack fluid : fluidsToOutput) {
- int index = 0;
- while (fluid != null && fluid.amount > 0 && index < tanks.size()) {
- int filled = tanks.get(index++)
- .fill(fluid, true);
- fluid.amount -= filled;
- }
- }
+ public PowerLogic getPowerLogic() {
+ return getPowerLogic(ForgeDirection.UNKNOWN);
}
- @Override
- protected void updateSlots() {
- IItemHandlerModifiable inv = getInventoriesForInput();
- for (int i = 0; i < inv.getSlots(); i++) {
- if (inv.getStackInSlot(i) != null && inv.getStackInSlot(i).stackSize <= 0) {
- inv.setStackInSlot(i, null);
- }
- }
-
- for (FluidTankGT inputTank : getTanksForInput()) {
- if (inputTank == null) {
- continue;
- }
-
- if (inputTank.get() != null && inputTank.get().amount <= 0) {
- inputTank.setEmpty();
- continue;
- }
-
- FluidStack afterRecipe = inputTank.get();
- FluidStack beforeRecipe = inputTank.get(Integer.MAX_VALUE);
- if (afterRecipe == null || beforeRecipe == null) {
- continue;
- }
- int difference = beforeRecipe.amount - afterRecipe.amount;
- inputTank.remove(difference);
- }
- }
+ // #endregion Energy
@Override
- protected boolean checkRecipe() {
- if (!(this instanceof ProcessingLogicHost)) {
- return false;
- }
- ProcessingLogic logic = ((ProcessingLogicHost) this).getProcessingLogic();
- logic.clear();
- CheckRecipeResult result = CheckRecipeResultRegistry.NO_RECIPE;
- if (isSeparateInputs()) {
- // TODO: Add separation with fluids
- for (Pair<ItemStack[], String> inventory : getItemInputsForEachInventory()) {
- IItemHandlerModifiable outputInventory = multiBlockOutputInventory
- .getOrDefault(inventory.getLeft(), null);
- result = logic.setInputItems(inventory.getLeft())
- .setCurrentOutputItems(getOutputItems())
- .process();
- if (result.wasSuccessful()) {
- inventoryName = inventory.getRight();
- break;
- }
- logic.clear();
- }
- } else {
- result = logic.setInputItems(getInputItems())
- .setCurrentOutputItems(getOutputItems())
- .setInputFluids(getInputFluids())
- .setCurrentOutputFluids(getOutputFluids())
- .process();
- }
- setDuration(logic.getDuration());
- setEut(logic.getCalculatedEut());
- setItemOutputs(logic.getOutputItems());
- setFluidOutputs(logic.getOutputFluids());
- return result.wasSuccessful();
- }
-
- public IItemHandlerModifiable getOutputInventory() {
- return outputInventory;
- }
-
- public FluidTankGT[] getOutputTanks() {
- return outputTanks;
+ protected void updateSlots() {
+ controllerItemInput.getAllInventoryLogics()
+ .update(shouldSort);
+ controllerItemOutput.getAllInventoryLogics()
+ .update(shouldSort);
+ controllerFluidInput.getAllInventoryLogics()
+ .update();
+ controllerFluidOutput.getAllInventoryLogics()
+ .update();
}
/*
@@ -1838,24 +886,6 @@ public abstract class Controller<T extends Controller<T>> extends MultiTileBasic
}
@Override
- public ModularWindow createWindow(UIBuildContext buildContext) {
- System.out.println("MultiBlockController::createWindow");
- if (!useModularUI()) return null;
-
- buildContext.setValidator(getValidator());
- final ModularWindow.Builder builder = ModularWindow.builder(getGUIWidth(), getGUIHeight());
- builder.setBackground(getGUITextureSet().getMainBackground());
- builder.setGuiTint(getGUIColorization());
- if (doesBindPlayerInventory()) {
- bindPlayerInventoryUI(builder, buildContext);
- }
- addUIWidgets(builder, buildContext);
- addTitleToUI(builder);
- addCoverTabs(builder, buildContext);
- return builder.build();
- }
-
- @Override
public boolean hasGui(ForgeDirection side) {
return true;
}
@@ -1866,222 +896,6 @@ public abstract class Controller<T extends Controller<T>> extends MultiTileBasic
}
@Override
- public int getGUIHeight() {
- return 192;
- }
-
- protected Widget getGregTechLogo() {
- return new DrawableWidget().setDrawable(getGUITextureSet().getGregTechLogo())
- .setSize(17, 17);
- }
-
- @Override
- public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
- if (isServerSide()) {
- for (UpgradeCasing tPart : upgradeCasings) {
- if (!(tPart instanceof Inventory)) continue;
- tPart.issueClientUpdate();
- }
- }
- int page = 0;
- TabContainer tabs = new TabContainer().setButtonSize(20, 24);
- tabs.addTabButton(
- new TabButton(page++)
- .setBackground(
- false,
- ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0, 1f, 0.5f),
- new ItemDrawable(getStackForm(1)).withFixedSize(16, 16)
- .withOffset(2, 4))
- .setBackground(
- true,
- ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0.5f, 1f, 1f),
- new ItemDrawable(getStackForm(1)).withFixedSize(16, 16)
- .withOffset(2, 4))
- .addTooltip(getLocalName())
- .setPos(20 * (page - 1), -20))
- .addPage(createMainPage(builder).setSize(getGUIWidth(), getGUIHeight()));
- if (hasItemInput()) {
- tabs.addTabButton(
- new TabButton(page++)
- .setBackground(
- false,
- ModularUITextures.VANILLA_TAB_TOP_MIDDLE.getSubArea(0, 0, 1f, 0.5f),
- GT_UITextures.PICTURE_ITEM_IN.withFixedSize(16, 16)
- .withOffset(2, 4))
- .setBackground(
- true,
- ModularUITextures.VANILLA_TAB_TOP_MIDDLE.getSubArea(0, 0.5f, 1f, 1f),
- GT_UITextures.PICTURE_ITEM_IN.withFixedSize(16, 16)
- .withOffset(2, 4))
- .setPos(20 * (page - 1), -20))
- .addPage(
- new MultiChildWidget().addChild(getItemInventoryInputGUI())
- .addChild(getGregTechLogo().setPos(147, 86))
- .setSize(getGUIWidth(), getGUIHeight()));
- }
-
- if (hasItemOutput()) {
- tabs.addTabButton(
- new TabButton(page++)
- .setBackground(
- false,
- ModularUITextures.VANILLA_TAB_TOP_MIDDLE.getSubArea(0, 0, 1f, 0.5f),
- GT_UITextures.PICTURE_ITEM_OUT.withFixedSize(16, 16)
- .withOffset(2, 4))
- .setBackground(
- true,
- ModularUITextures.VANILLA_TAB_TOP_MIDDLE.getSubArea(0, 0.5f, 1f, 1f),
- GT_UITextures.PICTURE_ITEM_OUT.withFixedSize(16, 16)
- .withOffset(2, 4))
- .setPos(20 * (page - 1), -20))
- .addPage(
- new MultiChildWidget().addChild(getItemInventoryOutputGUI())
- .addChild(getGregTechLogo().setPos(147, 86))
- .setSize(getGUIWidth(), getGUIHeight()));
- }
-
- if (hasFluidInput()) {
- tabs.addTabButton(
- new TabButton(page++)
- .setBackground(
- false,
- ModularUITextures.VANILLA_TAB_TOP_MIDDLE.getSubArea(0, 0, 1f, 0.5f),
- GT_UITextures.PICTURE_FLUID_IN.withFixedSize(16, 16)
- .withOffset(2, 4))
- .setBackground(
- true,
- ModularUITextures.VANILLA_TAB_TOP_MIDDLE.getSubArea(0, 0.5f, 1f, 1f),
- GT_UITextures.PICTURE_FLUID_IN.withFixedSize(16, 16)
- .withOffset(2, 4))
- .setPos(20 * (page - 1), -20))
- .addPage(
- new MultiChildWidget().addChild(getFluidInventoryInputGUI())
- .addChild(getGregTechLogo().setPos(147, 86))
- .setSize(getGUIWidth(), getGUIHeight()));
- }
-
- if (hasFluidOutput()) {
- tabs.addTabButton(
- new TabButton(page++)
- .setBackground(
- false,
- ModularUITextures.VANILLA_TAB_TOP_MIDDLE.getSubArea(0, 0, 1f, 0.5f),
- GT_UITextures.PICTURE_FLUID_OUT.withFixedSize(16, 16)
- .withOffset(2, 4))
- .setBackground(
- true,
- ModularUITextures.VANILLA_TAB_TOP_MIDDLE.getSubArea(0, 0.5f, 1f, 1f),
- GT_UITextures.PICTURE_FLUID_OUT.withFixedSize(16, 16)
- .withOffset(2, 4))
- .setPos(20 * (page - 1), -20))
- .addPage(
- new MultiChildWidget().addChild(getFluidInventoryOutputGUI())
- .addChild(getGregTechLogo().setPos(147, 86))
- .setSize(getGUIWidth(), getGUIHeight()));
- }
- builder.widget(tabs);
- }
-
- protected MultiChildWidget createMainPage(IWidgetBuilder<?> builder) {
- MultiChildWidget page = new MultiChildWidget();
- page.addChild(
- new DrawableWidget().setDrawable(GT_UITextures.PICTURE_SCREEN_BLACK)
- .setPos(7, 4)
- .setSize(160, 75))
- .addChild(createButtons(builder));
- return page;
- }
-
- protected MultiChildWidget createButtons(IWidgetBuilder<?> builder) {
- 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));
-
- return buttons;
- }
-
- protected Widget getItemInventoryInputGUI() {
- final IItemHandlerModifiable inv = getInventoriesForInput();
- final Scrollable scrollable = new Scrollable().setVerticalScroll();
- for (int rows = 0; rows * 4 < Math.min(inv.getSlots(), 128); rows++) {
- final int columnsToMake = Math.min(Math.min(inv.getSlots(), 128) - rows * 4, 4);
- for (int column = 0; column < columnsToMake; column++) {
- scrollable.widget(
- new SlotWidget(inv, rows * 4 + column).setPos(column * 18, rows * 18)
- .setSize(18, 18));
- }
- }
- return scrollable.setSize(18 * 4 + 4, 18 * 5)
- .setPos(52, 7);
- }
-
- protected Widget getItemInventoryOutputGUI() {
- final IItemHandlerModifiable inv = getInventoriesForOutput();
- final Scrollable scrollable = new Scrollable().setVerticalScroll();
- for (int rows = 0; rows * 4 < Math.min(inv.getSlots(), 128); rows++) {
- final int columnsToMake = Math.min(Math.min(inv.getSlots(), 128) - rows * 4, 4);
- for (int column = 0; column < columnsToMake; column++) {
- scrollable.widget(
- new SlotWidget(inv, rows * 4 + column).setPos(column * 18, rows * 18)
- .setSize(18, 18));
- }
- }
- return scrollable.setSize(18 * 4 + 4, 18 * 5)
- .setPos(52, 7);
- }
-
- protected IItemHandlerModifiable getInventoriesForInput() {
- return new ListItemHandler(multiBlockInputInventory.values());
- }
-
- protected IItemHandlerModifiable getInventoriesForOutput() {
- return new ListItemHandler(multiBlockOutputInventory.values());
- }
-
- protected Widget getFluidInventoryInputGUI() {
- final IFluidTank[] tanks = getTanksForInput();
- final Scrollable scrollable = new Scrollable().setVerticalScroll();
- for (int rows = 0; rows * 4 < tanks.length; rows++) {
- final int columnsToMake = Math.min(tanks.length - rows * 4, 4);
- for (int column = 0; column < columnsToMake; column++) {
- final FluidSlotWidget fluidSlot = new FluidSlotWidget(tanks[rows * 4 + column]);
- scrollable.widget(
- fluidSlot.setPos(column * 18, rows * 18)
- .setSize(18, 18));
- }
- }
- return scrollable.setSize(18 * 4 + 4, 18 * 5)
- .setPos(52, 7);
- }
-
- protected Widget getFluidInventoryOutputGUI() {
- final IFluidTank[] tanks = getTanksForOutput();
- final Scrollable scrollable = new Scrollable().setVerticalScroll();
- for (int rows = 0; rows * 4 < tanks.length; rows++) {
- final int columnsToMake = Math.min(tanks.length - rows * 4, 4);
- for (int column = 0; column < columnsToMake; column++) {
- final FluidSlotWidget fluidSlot = new FluidSlotWidget(tanks[rows * 4 + column]);
- fluidSlot.setInteraction(true, false);
- scrollable.widget(
- fluidSlot.setPos(column * 18, rows * 18)
- .setSize(18, 18));
- }
- }
- return scrollable.setSize(18 * 4 + 4, 18 * 5)
- .setPos(52, 7);
- }
-
- @Override
- public Pos2d getPowerSwitchButtonPos() {
- return new Pos2d(144, 0);
- }
-
- @Override
public boolean supportsVoidProtection() {
return true;
}
@@ -2097,23 +911,6 @@ public abstract class Controller<T extends Controller<T>> extends MultiTileBasic
}
@Override
- public List<ItemStack> getItemOutputSlots(ItemStack[] toOutput) {
- List<ItemStack> ret = new ArrayList<>();
- IItemHandler inv = getOutputInventory();
- if (inv != null && inv.getSlots() > 0) {
- for (int i = 0; i < inv.getSlots(); i++) {
- ret.add(inv.getStackInSlot(i));
- }
- }
- return ret;
- }
-
- @Override
- public List<? extends IFluidStore> getFluidOutputSlots(FluidStack[] toOutput) {
- return Arrays.asList(getOutputTanks());
- }
-
- @Override
public boolean canDumpItemToME() {
return false;
}
@@ -2124,31 +921,21 @@ public abstract class Controller<T extends Controller<T>> extends MultiTileBasic
}
@Override
- public Pos2d getVoidingModeButtonPos() {
- return new Pos2d(54, 0);
- }
-
- @Override
public boolean supportsInputSeparation() {
return true;
}
@Override
- public boolean isInputSeparationEnabled() {
+ public boolean isInputSeparated() {
return separateInputs;
}
@Override
- public void setInputSeparation(boolean enabled) {
+ public void setInputSeparation(Boolean enabled) {
this.separateInputs = enabled;
}
@Override
- public Pos2d getInputSeparationButtonPos() {
- return new Pos2d(36, 0);
- }
-
- @Override
public boolean supportsBatchMode() {
return true;
}
@@ -2159,16 +946,11 @@ public abstract class Controller<T extends Controller<T>> extends MultiTileBasic
}
@Override
- public void setBatchMode(boolean mode) {
+ public void setBatchMode(Boolean mode) {
this.batchMode = mode;
}
@Override
- public Pos2d getBatchModeButtonPos() {
- return new Pos2d(18, 0);
- }
-
- @Override
public boolean supportsSingleRecipeLocking() {
return false;
}
@@ -2179,32 +961,23 @@ public abstract class Controller<T extends Controller<T>> extends MultiTileBasic
}
@Override
- public void setRecipeLocking(boolean enabled) {
+ public void setRecipeLocking(Boolean enabled) {
this.recipeLock = enabled;
}
@Override
- public RecipeMap<?> getRecipeMap() {
- return null;
- }
-
- @Override
- public Pos2d getRecipeLockingButtonPos() {
- return new Pos2d(0, 0);
- }
-
- @Override
- public ModularWindow createWindowGUI(UIBuildContext buildContext) {
- return createWindow(buildContext);
- }
-
- @Override
public void getWailaNBTData(EntityPlayerMP player, TileEntity tile, NBTTagCompound tag, World world, int x, int y,
int z) {
super.getWailaNBTData(player, tile, tag, world, x, y, z);
- tag.setLong("progress", progressTime);
- tag.setLong("maxProgress", maxProgressTime);
+ P processing = getProcessingLogic();
+ tag.setInteger("progress", processing.getProgress());
+ tag.setInteger("maxProgress", processing.getDuration());
tag.setBoolean("structureOkay", structureOkay);
+ tag.setBoolean("isActive", isActive());
+ if (isActive()) {
+ tag.setLong("energyUsage", getProcessingLogic().getCalculatedEut());
+ tag.setLong("energyTier", tier);
+ }
}
@Override
@@ -2219,8 +992,92 @@ public abstract class Controller<T extends Controller<T>> extends MultiTileBasic
}
if (isSimpleMachine) {
boolean isActive = tag.getBoolean("isActive");
- currentTip
- .add(GT_Waila.getMachineProgressString(isActive, tag.getLong("maxProgress"), tag.getLong("progress")));
+ currentTip.add(
+ GT_Waila.getMachineProgressString(isActive, tag.getInteger("maxProgress"), tag.getInteger("progress")));
+ }
+ boolean isActive = tag.getBoolean("isActive");
+ if (isActive) {
+ long energyTier = tag.getLong("energyTier");
+ long actualEnergyUsage = tag.getLong("energyUsage");
+ if (actualEnergyUsage > 0) {
+ currentTip.add(
+ StatCollector.translateToLocalFormatted(
+ "GT5U.waila.energy.use_with_amperage",
+ GT_Utility.formatNumbers(actualEnergyUsage),
+ GT_Utility.getAmperageForTier(actualEnergyUsage, (byte) energyTier),
+ GT_Utility.getColoredTierNameFromTier((byte) energyTier)));
+ } else if (actualEnergyUsage < 0) {
+ currentTip.add(
+ StatCollector.translateToLocalFormatted(
+ "GT5U.waila.energy.produce_with_amperage",
+ GT_Utility.formatNumbers(-actualEnergyUsage),
+ GT_Utility.getAmperageForTier(-actualEnergyUsage, (byte) energyTier),
+ GT_Utility.getColoredTierNameFromTier((byte) energyTier)));
+ }
}
}
+
+ @Override
+ public GT_Packet_MultiTileEntity getClientDataPacket() {
+ final GT_Packet_MultiTileEntity packet = super.getClientDataPacket();
+
+ return packet;
+
+ }
+
+ @Override
+ public void enableWorking() {
+ super.enableWorking();
+ if (!structureOkay) {
+ checkStructure(true);
+ }
+ }
+
+ @Override
+ public List<ItemStack> getItemOutputSlots(ItemStack[] toOutput) {
+ return new ArrayList<>(0);
+ }
+
+ @Override
+ public List<? extends IFluidStore> getFluidOutputSlots(FluidStack[] toOutput) {
+ return new ArrayList<>(0);
+ }
+
+ @Override
+ @Nonnull
+ public Set<Entry<UUID, FluidInventoryLogic>> getAllFluidInventoryLogics(@Nonnull InventoryType type) {
+ return switch (type) {
+ case Input -> controllerFluidInput.getAllInventoryLogicsAsEntrySet();
+ case Output -> controllerFluidOutput.getAllInventoryLogicsAsEntrySet();
+ default -> super.getAllFluidInventoryLogics(type);
+ };
+ }
+
+ @Override
+ @Nonnull
+ public Set<Entry<UUID, ItemInventoryLogic>> getAllItemInventoryLogics(@Nonnull InventoryType type) {
+ return switch (type) {
+ case Input -> controllerItemInput.getAllInventoryLogicsAsEntrySet();
+ case Output -> controllerItemOutput.getAllInventoryLogicsAsEntrySet();
+ default -> super.getAllItemInventoryLogics(type);
+ };
+ }
+
+ @Override
+ public void setWirelessSupport(boolean canUse) {
+ if (canUse) {
+ strongCheckOrAddUser(getOwnerUuid(), getOwnerName());
+ }
+ power.setCanUseWireless(canUse, getOwnerUuid());
+ }
+
+ @Override
+ public void setLaserSupport(boolean canUse) {
+ power.setCanUseLaser(canUse);
+ }
+
+ @Override
+ public void setMaxAmperage(long amperage) {
+ power.setMaxAmperage(amperage);
+ }
}
diff --git a/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockPart.java b/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockPart.java
index db9053b0d7..223edc0761 100644
--- a/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockPart.java
+++ b/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockPart.java
@@ -2,7 +2,6 @@ package gregtech.api.multitileentity.multiblock.base;
import static com.google.common.math.LongMath.log2;
import static gregtech.api.enums.GT_Values.B;
-import static gregtech.api.enums.GT_Values.NBT;
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.ITEM_IN_SIGN;
@@ -11,13 +10,17 @@ import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_ENERGY_IN_MULTI;
import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_ENERGY_OUT_MULTI;
import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_PIPE_IN;
import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_PIPE_OUT;
-import static org.apache.commons.lang3.ObjectUtils.firstNonNull;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
@@ -25,44 +28,42 @@ import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ChunkCoordinates;
+import net.minecraft.util.StatCollector;
import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.fluids.Fluid;
-import net.minecraftforge.fluids.FluidStack;
-import net.minecraftforge.fluids.FluidTankInfo;
-import net.minecraftforge.fluids.IFluidTank;
-import com.gtnewhorizons.modularui.api.forge.IItemHandlerModifiable;
-import com.gtnewhorizons.modularui.api.screen.ModularWindow;
import com.gtnewhorizons.modularui.api.screen.ModularWindow.Builder;
import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
import com.gtnewhorizons.modularui.common.widget.DrawableWidget;
-import com.gtnewhorizons.modularui.common.widget.DropDownWidget;
-import com.gtnewhorizons.modularui.common.widget.FluidSlotWidget;
-import com.gtnewhorizons.modularui.common.widget.Scrollable;
-import com.gtnewhorizons.modularui.common.widget.SlotGroup;
-import com.gtnewhorizons.modularui.common.widget.SlotWidget;
-import com.gtnewhorizons.modularui.common.widget.TextWidget;
-
-import gregtech.api.enums.GT_Values;
+
+import gregtech.api.enums.GT_Values.NBT;
+import gregtech.api.enums.InventoryType;
import gregtech.api.fluid.FluidTankGT;
-import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.gui.GUIHost;
+import gregtech.api.gui.GUIProvider;
import gregtech.api.interfaces.ITexture;
+import gregtech.api.logic.FluidInventoryLogic;
+import gregtech.api.logic.ItemInventoryLogic;
+import gregtech.api.logic.NullPowerLogic;
import gregtech.api.logic.PowerLogic;
import gregtech.api.logic.interfaces.PowerLogicHost;
+import gregtech.api.multitileentity.MultiTileEntityRegistry;
import gregtech.api.multitileentity.base.NonTickableMultiTileEntity;
+import gregtech.api.multitileentity.enums.MultiTileCasingPurpose;
import gregtech.api.multitileentity.interfaces.IMultiBlockController;
import gregtech.api.multitileentity.interfaces.IMultiBlockPart;
-import gregtech.api.multitileentity.interfaces.IMultiTileEntity.IMTE_BreakBlock;
+import gregtech.api.multitileentity.interfaces.IMultiTileEntity;
import gregtech.api.multitileentity.interfaces.IMultiTileEntity.IMTE_HasModes;
import gregtech.api.net.GT_Packet_MultiTileEntity;
import gregtech.api.render.TextureFactory;
import gregtech.api.util.GT_Utility;
import gregtech.common.covers.CoverInfo;
+import gregtech.common.gui.PartGUIProvider;
import mcp.mobius.waila.api.IWailaConfigHandler;
import mcp.mobius.waila.api.IWailaDataAccessor;
public abstract class MultiBlockPart extends NonTickableMultiTileEntity
- implements IMultiBlockPart, IMTE_BreakBlock, IMTE_HasModes, PowerLogicHost {
+ implements IMultiBlockPart, IMTE_HasModes, PowerLogicHost, IMultiTileEntity.IMTE_AddToolTips, GUIHost {
public static final int NOTHING = 0, ENERGY_IN = B[0], ENERGY_OUT = B[1], FLUID_IN = B[2], FLUID_OUT = B[3],
ITEM_IN = B[4], ITEM_OUT = B[5];
@@ -70,16 +71,20 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity
protected final List<Integer> BASIC_MODES = new ArrayList<>(
Arrays.asList(NOTHING, ENERGY_IN, ENERGY_OUT, FLUID_IN, FLUID_OUT, ITEM_IN, ITEM_OUT));
- protected ChunkCoordinates mTargetPos = null;
- protected IMultiBlockController target = null;
+ protected Set<MultiTileCasingPurpose> registeredPurposes = new HashSet<>();
- protected int mAllowedModes = NOTHING; // BITMASK - Modes allowed for this part
- protected byte mMode = 0; // Mode selected for this part
+ protected ChunkCoordinates targetPosition = null;
- protected String mLockedInventory = GT_Values.E;
+ protected int allowedModes = NOTHING; // BITMASK - Modes allowed for this part
+ protected int mode = 0; // Mode selected for this part
+
+ protected UUID lockedInventory;
protected int mLockedInventoryIndex = 0;
protected FluidTankGT configurationTank = new FluidTankGT();
+ @Nonnull
+ protected final GUIProvider<?> guiProvider = createGUIProvider();
+
/**
* What Part Tier is this part? All Basic Casings are Tier 1, and will allow: Energy, Item, Fluid input/output. Some
* of the more advanced modes can be set to require a higher tier part.
@@ -88,33 +93,40 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity
return 1;
}
- public String getLockedInventory() {
- // TODO: Can this cause side-effects? Removed for now because it causes huge network traffic when using covers
- // issueClientUpdate();
- IMultiBlockController controller = getTarget(false);
- if (modeSelected(ITEM_IN) || modeSelected(ITEM_OUT)) {
- if (!getNameOfInventoryFromIndex(controller, mLockedInventoryIndex).equals(mLockedInventory)) {
- mLockedInventory = getNameOfInventoryFromIndex(controller, mLockedInventoryIndex);
- if (mLockedInventory.equals(Controller.ALL_INVENTORIES_NAME)) {
- mLockedInventory = "";
- }
- }
- } else {
- if (!getNameOfTankArrayFromIndex(controller, mLockedInventoryIndex).equals(mLockedInventory)) {
- mLockedInventory = getNameOfTankArrayFromIndex(controller, mLockedInventoryIndex);
- if (mLockedInventory.equals(Controller.ALL_INVENTORIES_NAME)) {
- mLockedInventory = "";
- }
+ @Override
+ public UUID getLockedInventory() {
+ return lockedInventory;
+ }
+
+ public void setTarget(IMultiBlockController newTarget, int aAllowedModes) {
+ IMultiBlockController currentTarget = getTarget(false);
+ if (currentTarget != null && currentTarget != newTarget) {
+ for (MultiTileCasingPurpose purpose : registeredPurposes) {
+ unregisterPurpose(purpose);
}
}
- return mLockedInventory.equals("") ? null : mLockedInventory;
+ targetPosition = (newTarget == null ? null : newTarget.getCoords());
+ allowedModes = aAllowedModes;
+ if (newTarget != null) {
+ registerCovers(newTarget);
+ registerPurposes();
+ }
}
- public void setTarget(IMultiBlockController aTarget, int aAllowedModes) {
- target = aTarget;
- mTargetPos = (target == null ? null : target.getCoords());
- mAllowedModes = aAllowedModes;
- if (target != null) registerCovers(target);
+ protected void registerPurpose(MultiTileCasingPurpose purpose) {
+ IMultiBlockController target = getTarget(false);
+ if (target != null) {
+ target.registerCaseWithPurpose(purpose, this);
+ registeredPurposes.add(purpose);
+ }
+ }
+
+ protected void unregisterPurpose(MultiTileCasingPurpose purpose) {
+ IMultiBlockController target = getTarget(false);
+ if (target != null) {
+ target.unregisterCaseWithPurpose(purpose, this);
+ }
+ registeredPurposes.remove(purpose);
}
@Override
@@ -125,14 +137,14 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity
} else {
tList.add("No Controller");
}
- tList.add("Casing Mode: " + getModeName(mMode));
+ tList.add("Casing Mode: " + getModeName(mode));
}
@Override
public void getWailaBody(ItemStack itemStack, List<String> currentTip, IWailaDataAccessor accessor,
IWailaConfigHandler config) {
super.getWailaBody(itemStack, currentTip, accessor, config);
- currentTip.add(String.format("Mode: %s", getModeName(mMode)));
+ currentTip.add(String.format("Mode: %s", getModeName(mode)));
if (modeSelected(FLUID_OUT)) {
if (configurationTank != null && configurationTank.get() != null) {
currentTip.add(
@@ -147,19 +159,22 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity
}
public IMultiBlockController getTarget(boolean aCheckValidity) {
- if (mTargetPos == null) return null;
- if (target == null || target.isDead()) {
- if (worldObj.blockExists(mTargetPos.posX, mTargetPos.posY, mTargetPos.posZ)) {
- final TileEntity te = worldObj.getTileEntity(mTargetPos.posX, mTargetPos.posY, mTargetPos.posZ);
- if (te instanceof IMultiBlockController) {
- target = (IMultiBlockController) te;
- // Register our covers with the controller
- registerCovers(target);
- } else {
- mTargetPos = null;
- }
- }
+ if (targetPosition == null) {
+ return null;
+ }
+
+ if (!worldObj.blockExists(targetPosition.posX, targetPosition.posY, targetPosition.posZ)) {
+ return null;
+ }
+ final TileEntity te = worldObj.getTileEntity(targetPosition.posX, targetPosition.posY, targetPosition.posZ);
+ IMultiBlockController target = null;
+ if (te instanceof IMultiBlockController targetFound) {
+ target = targetFound;
+ } else {
+ targetPosition = null;
+ return null;
}
+
if (aCheckValidity) {
return target != null && target.checkStructure(false) ? target : null;
}
@@ -175,17 +190,26 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity
}
}
+ protected void registerPurposes() {
+ for (MultiTileCasingPurpose purpose : registeredPurposes) {
+ registerPurpose(purpose);
+ }
+ }
+
@Override
public void setCoverItemAtSide(ForgeDirection side, ItemStack aCover) {
super.setCoverItemAtSide(side, aCover);
// TODO: Filter on tickable covers
final IMultiBlockController tTarget = getTarget(true);
- if (tTarget != null) {
- final CoverInfo coverInfo = getCoverInfoAtSide(side);
- if (coverInfo.isValid() && coverInfo.getTickRate() > 0) {
- tTarget.registerCoveredPartOnSide(side, this);
- }
+ if (tTarget == null) {
+ return;
}
+
+ final CoverInfo coverInfo = getCoverInfoAtSide(side);
+ if (coverInfo.isValid() && coverInfo.getTickRate() > 0) {
+ tTarget.registerCoveredPartOnSide(side, this);
+ }
+
}
public void unregisterCovers(IMultiBlockController controller) {
@@ -208,16 +232,16 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity
@Override
public void readMultiTileNBT(NBTTagCompound aNBT) {
- if (aNBT.hasKey(NBT.ALLOWED_MODES)) mAllowedModes = aNBT.getInteger(NBT.ALLOWED_MODES);
- if (aNBT.hasKey(NBT.MODE)) mMode = aNBT.getByte(NBT.MODE);
+ if (aNBT.hasKey(NBT.ALLOWED_MODES)) allowedModes = aNBT.getInteger(NBT.ALLOWED_MODES);
+ if (aNBT.hasKey(NBT.MODE)) setMode(aNBT.getByte(NBT.MODE));
if (aNBT.hasKey(NBT.TARGET)) {
- mTargetPos = new ChunkCoordinates(
+ targetPosition = new ChunkCoordinates(
aNBT.getInteger(NBT.TARGET_X),
aNBT.getShort(NBT.TARGET_Y),
aNBT.getInteger(NBT.TARGET_Z));
}
if (aNBT.hasKey(NBT.LOCKED_INVENTORY)) {
- mLockedInventory = aNBT.getString(NBT.LOCKED_INVENTORY);
+ lockedInventory = UUID.fromString(aNBT.getString(NBT.LOCKED_INVENTORY));
}
if (aNBT.hasKey(NBT.LOCKED_INVENTORY_INDEX)) {
mLockedInventoryIndex = aNBT.getInteger(NBT.LOCKED_INVENTORY_INDEX);
@@ -225,20 +249,26 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity
if (aNBT.hasKey(NBT.LOCKED_FLUID)) {
configurationTank.readFromNBT(aNBT, NBT.LOCKED_FLUID);
}
+ if (modeSelected(ITEM_OUT)) {
+ registeredPurposes.add(MultiTileCasingPurpose.ItemOutput);
+ }
+ if (modeSelected(FLUID_OUT)) {
+ registeredPurposes.add(MultiTileCasingPurpose.FluidOutput);
+ }
}
@Override
public void writeMultiTileNBT(NBTTagCompound aNBT) {
- if (mAllowedModes != NOTHING) aNBT.setInteger(NBT.ALLOWED_MODES, mAllowedModes);
- if (mMode != 0) aNBT.setInteger(NBT.MODE, mMode);
- if (mTargetPos != null) {
+ if (allowedModes != NOTHING) aNBT.setInteger(NBT.ALLOWED_MODES, allowedModes);
+ if (mode != 0) aNBT.setInteger(NBT.MODE, mode);
+ if (targetPosition != null) {
aNBT.setBoolean(NBT.TARGET, true);
- aNBT.setInteger(NBT.TARGET_X, mTargetPos.posX);
- aNBT.setShort(NBT.TARGET_Y, (short) mTargetPos.posY);
- aNBT.setInteger(NBT.TARGET_Z, mTargetPos.posZ);
+ aNBT.setInteger(NBT.TARGET_X, targetPosition.posX);
+ aNBT.setShort(NBT.TARGET_Y, (short) targetPosition.posY);
+ aNBT.setInteger(NBT.TARGET_Z, targetPosition.posZ);
}
- if (mLockedInventory != null) {
- aNBT.setString(NBT.LOCKED_INVENTORY, mLockedInventory);
+ if (lockedInventory != null) {
+ aNBT.setString(NBT.LOCKED_INVENTORY, lockedInventory.toString());
}
if (mLockedInventoryIndex != 0) {
aNBT.setInteger(NBT.LOCKED_INVENTORY_INDEX, mLockedInventoryIndex);
@@ -270,34 +300,47 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity
@Override
public void setTargetPos(ChunkCoordinates aTargetPos) {
- mTargetPos = aTargetPos;
- IMultiBlockController mTarget = getTarget(false);
- setTarget(mTarget, mAllowedModes);
+ targetPosition = aTargetPos;
+ IMultiBlockController target = getTarget(false);
+ setTarget(target, allowedModes);
}
@Override
public ChunkCoordinates getTargetPos() {
- return mTargetPos;
+ return targetPosition;
}
@Override
- public void setMode(byte aMode) {
- mMode = aMode;
+ public void setMode(int mode) {
+ if (this.mode == mode) return;
+ if (modeSelected(FLUID_OUT)) {
+ unregisterPurpose(MultiTileCasingPurpose.FluidOutput);
+ }
+ if (modeSelected(ITEM_OUT)) {
+ unregisterPurpose(MultiTileCasingPurpose.ItemOutput);
+ }
+ this.mode = mode;
+ if (modeSelected(FLUID_OUT)) {
+ registerPurpose(MultiTileCasingPurpose.FluidOutput);
+ }
+ if (modeSelected(ITEM_OUT)) {
+ registerPurpose(MultiTileCasingPurpose.ItemOutput);
+ }
}
@Override
- public byte getMode() {
- return mMode;
+ public int getMode() {
+ return mode;
}
@Override
public int getAllowedModes() {
- return mAllowedModes;
+ return allowedModes;
}
@Override
public void setAllowedModes(int aAllowedModes) {
- mAllowedModes = aAllowedModes;
+ allowedModes = aAllowedModes;
}
/**
@@ -305,7 +348,7 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity
*/
public boolean hasMode(int aMode) {
// This is not sent to the client
- return (mAllowedModes & aMode) != 0;
+ return (allowedModes & aMode) != 0;
}
/**
@@ -313,7 +356,7 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity
*/
public boolean modeSelected(int... aModes) {
for (int aMode : aModes) {
- if (hasMode(aMode) && mMode == getModeOrdinal(aMode)) return true;
+ if (hasMode(aMode) && mode == getModeOrdinal(aMode)) return true;
}
return false;
}
@@ -344,39 +387,39 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity
@Override
public ITexture getTexture(ForgeDirection side) {
ITexture texture = super.getTexture(side);
- if (mMode != 0 && side == facing) {
- if (mMode == getModeOrdinal(ITEM_IN)) {
+ if (mode != 0 && side == facing) {
+ if (mode == getModeOrdinal(ITEM_IN)) {
return TextureFactory.of(
texture,
TextureFactory.of(OVERLAY_PIPE_IN),
TextureFactory.of(ITEM_IN_SIGN),
getCoverTexture(side));
}
- if (mMode == getModeOrdinal(ITEM_OUT)) {
+ if (mode == getModeOrdinal(ITEM_OUT)) {
return TextureFactory.of(
texture,
TextureFactory.of(OVERLAY_PIPE_OUT),
TextureFactory.of(ITEM_OUT_SIGN),
getCoverTexture(side));
}
- if (mMode == getModeOrdinal(FLUID_IN)) {
+ if (mode == getModeOrdinal(FLUID_IN)) {
return TextureFactory.of(
texture,
TextureFactory.of(OVERLAY_PIPE_IN),
TextureFactory.of(FLUID_IN_SIGN),
getCoverTexture(side));
}
- if (mMode == getModeOrdinal(FLUID_OUT)) {
+ if (mode == getModeOrdinal(FLUID_OUT)) {
return TextureFactory.of(
texture,
TextureFactory.of(OVERLAY_PIPE_OUT),
TextureFactory.of(FLUID_OUT_SIGN),
getCoverTexture(side));
}
- if (mMode == getModeOrdinal(ENERGY_IN)) {
+ if (mode == getModeOrdinal(ENERGY_IN)) {
return TextureFactory.of(texture, TextureFactory.of(OVERLAY_ENERGY_IN_MULTI), getCoverTexture(side));
}
- if (mMode == getModeOrdinal(ENERGY_OUT)) {
+ if (mode == getModeOrdinal(ENERGY_OUT)) {
return TextureFactory.of(texture, TextureFactory.of(OVERLAY_ENERGY_OUT_MULTI), getCoverTexture(side));
}
}
@@ -384,11 +427,6 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity
return TextureFactory.of(texture, getCoverTexture(side));
}
- @Override
- public boolean isUseableByPlayer(EntityPlayer entityPlayer) {
- return false;
- }
-
protected String getModeName(int aMode) {
if (aMode == NOTHING) return "Nothing";
if (aMode == getModeOrdinal(ITEM_IN)) return "Item Input";
@@ -407,11 +445,11 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity
}
protected byte getNextAllowedMode(List<Integer> allowedModes) {
- if (mAllowedModes == NOTHING) return NOTHING;
+ if (this.allowedModes == NOTHING) return NOTHING;
final int numModes = allowedModes.size();
for (byte i = 1; i <= numModes; i++) {
- final byte curMode = (byte) ((mMode + i) % numModes);
+ final byte curMode = (byte) ((mode + i) % numModes);
if (curMode == NOTHING || hasMode(1 << (curMode - 1))) return curMode;
}
// Nothing valid found
@@ -420,16 +458,16 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity
@Override
public boolean onMalletRightClick(EntityPlayer aPlayer, ItemStack tCurrentItem, ForgeDirection wrenchSide, float aX,
- float aY, float aZ, ItemStack aTool) {
- if (mAllowedModes == NOTHING) return true;
- if (mMode == NOTHING) {
+ float aY, float aZ) {
+ if (allowedModes == NOTHING) return true;
+ if (mode == NOTHING) {
facing = wrenchSide;
}
- mMode = getNextAllowedMode(BASIC_MODES);
+ setMode(getNextAllowedMode(BASIC_MODES));
if (aPlayer.isSneaking()) {
facing = wrenchSide;
}
- GT_Utility.sendChatToPlayer(aPlayer, "Mode set to `" + getModeName(mMode) + "' (" + mMode + ")");
+ GT_Utility.sendChatToPlayer(aPlayer, "Mode set to `" + getModeName(mode) + "' (" + mode + ")");
sendClientData((EntityPlayerMP) aPlayer);
return true;
}
@@ -447,109 +485,50 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity
return "gt.multitileentity.multiblock.part";
}
+ @Override
+ public boolean shouldTick(long tickTimer) {
+ return modeSelected(ITEM_OUT, FLUID_OUT);
+ }
+
/**
* TODO: Make sure the energy/item/fluid hatch is facing that way! or has that mode enabled on that side Check
* SIDE_UNKNOWN for or coverbehavior
*/
- /**
- * Fluid - Depending on the part type - proxy it to the multiblock controller, if we have one
- */
+ // #region Fluid - Depending on the part type - proxy it to the multiblock controller, if we have one
@Override
- public int fill(ForgeDirection aDirection, FluidStack aFluidStack, boolean aDoFill) {
- if (!modeSelected(FLUID_IN)) return 0;
+ @Nullable
+ public FluidInventoryLogic getFluidLogic(@Nonnull ForgeDirection side, @Nonnull InventoryType type) {
+ if (side != facing && side != ForgeDirection.UNKNOWN) return null;
- if (aFluidStack == null || isWrongFluid(aFluidStack.getFluid())) return 0;
- if (aDirection != ForgeDirection.UNKNOWN
- && (facing.compareTo(aDirection) != 0 || !coverLetsFluidIn(aDirection, aFluidStack.getFluid()))) return 0;
- final IMultiBlockController controller = getTarget(true);
- return controller == null ? 0 : controller.fill(this, aDirection, aFluidStack, aDoFill);
- }
+ if (!modeSelected(FLUID_IN, FLUID_OUT)) return null;
- @Override
- public FluidStack drain(ForgeDirection aDirection, FluidStack aFluidStack, boolean aDoDrain) {
- if (!modeSelected(FLUID_OUT)) return null;
- if (aFluidStack == null || isWrongFluid(aFluidStack.getFluid())) return null;
- if (aDirection != ForgeDirection.UNKNOWN
- && (facing.compareTo(aDirection) != 0 || !coverLetsFluidOut(aDirection, aFluidStack.getFluid())))
- return null;
- final IMultiBlockController controller = getTarget(true);
- return controller == null ? null : controller.drain(this, aDirection, aFluidStack, aDoDrain);
- }
-
- @Override
- public FluidStack drain(ForgeDirection aDirection, int aAmountToDrain, boolean aDoDrain) {
- if (!modeSelected(FLUID_OUT)) return null;
- final IMultiBlockController controller = getTarget(true);
+ IMultiBlockController controller = getTarget(false);
if (controller == null) return null;
- FluidStack aFluidStack = null;
- if (getLockedFluid() != null) {
- aFluidStack = controller.getDrainableFluid(aDirection, getLockedFluid());
- } else {
- aFluidStack = controller.getDrainableFluid(aDirection);
- }
- if (aFluidStack == null || isWrongFluid(aFluidStack.getFluid())) return null;
- if (aDirection != ForgeDirection.UNKNOWN
- && (facing.compareTo(aDirection) != 0 || !coverLetsFluidOut(aDirection, aFluidStack.getFluid())))
- return null;
- return controller.drain(this, aDirection, aFluidStack, aDoDrain);
- }
-
- @Override
- public boolean canFill(ForgeDirection aDirection, Fluid aFluid) {
- if (!modeSelected(FLUID_IN)) return false;
-
- if (aDirection != ForgeDirection.UNKNOWN
- && (facing.compareTo(aDirection) != 0 || !coverLetsFluidIn(aDirection, aFluid))) return false;
- if (isWrongFluid(aFluid)) return false;
- final IMultiBlockController controller = getTarget(true);
- return controller != null && controller.canFill(this, aDirection, aFluid);
+ return controller
+ .getFluidLogic(modeSelected(FLUID_IN) ? InventoryType.Input : InventoryType.Output, lockedInventory);
}
- @Override
- public boolean canDrain(ForgeDirection aDirection, Fluid aFluid) {
- if (!modeSelected(FLUID_OUT)) return false;
- if (aDirection != ForgeDirection.UNKNOWN
- && (facing.compareTo(aDirection) != 0 || !coverLetsFluidOut(aDirection, aFluid))) return false;
- if (isWrongFluid(aFluid)) return false;
- final IMultiBlockController controller = getTarget(true);
- return controller != null && controller.canDrain(this, aDirection, aFluid);
- }
-
- @Override
- public FluidTankInfo[] getTankInfo(ForgeDirection aDirection) {
- if (!modeSelected(FLUID_IN, FLUID_OUT)
- || (aDirection != ForgeDirection.UNKNOWN && facing.compareTo(aDirection) != 0))
- return GT_Values.emptyFluidTankInfo;
- final IMultiBlockController controller = getTarget(true);
- if (controller == null) return GT_Values.emptyFluidTankInfo;
-
- final CoverInfo coverInfo = getCoverInfoAtSide(aDirection);
-
- if ((controller.isLiquidInput(aDirection) && coverInfo.letsFluidIn(null, controller))
- || (controller.isLiquidOutput(aDirection) && coverInfo.letsFluidOut(null, controller)))
- return controller.getTankInfo(this, aDirection);
-
- return GT_Values.emptyFluidTankInfo;
- }
+ // #endregion Fluid
// #region Energy - Depending on the part type - proxy to the multiblock controller, if we have one
@Override
- public PowerLogic getPowerLogic(ForgeDirection side) {
- if (facing == side) {
- return null;
+ @Nonnull
+ public PowerLogic getPowerLogic(@Nonnull ForgeDirection side) {
+ if (side != facing && side != ForgeDirection.UNKNOWN) {
+ return new NullPowerLogic();
}
if (!modeSelected(ENERGY_IN, ENERGY_OUT)) {
- return null;
+ return new NullPowerLogic();
}
final IMultiBlockController controller = getTarget(true);
if (controller == null) {
- return null;
+ return new NullPowerLogic();
}
- return controller.getPowerLogic(this, side);
+ return controller.getPowerLogic();
}
@Override
@@ -562,119 +541,32 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity
return modeSelected(ENERGY_OUT);
}
- // #endregion
-
- /**
- * Inventory - Depending on the part type - proxy to the multiblock controller, if we have one
- */
- @Override
- public boolean hasInventoryBeenModified() {
- final IMultiBlockController controller = getTarget(true);
- return (controller != null && controller.hasInventoryBeenModified(this));
- }
-
- @Override
- public boolean isValidSlot(int aIndex) {
- final IMultiBlockController controller = getTarget(true);
- return (controller != null && controller.isValidSlot(this, aIndex));
- }
-
- @Override
- public boolean addStackToSlot(int aIndex, ItemStack aStack) {
- if (!modeSelected(ITEM_IN, ITEM_OUT)) return false;
- final IMultiBlockController controller = getTarget(true);
- return (controller != null && controller.addStackToSlot(this, aIndex, aStack));
- }
-
- @Override
- public boolean addStackToSlot(int aIndex, ItemStack aStack, int aAmount) {
- if (!modeSelected(ITEM_IN, ITEM_OUT)) return false;
- final IMultiBlockController controller = getTarget(true);
- return (controller != null && controller.addStackToSlot(this, aIndex, aStack, aAmount));
- }
+ // #endregion Energy
- @Override
- public int[] getAccessibleSlotsFromSide(int ordinalSide) {
- final ForgeDirection side = ForgeDirection.getOrientation(ordinalSide);
- if (!modeSelected(ITEM_IN, ITEM_OUT) || (facing != ForgeDirection.UNKNOWN && facing.compareTo(side) != 0))
- return GT_Values.emptyIntArray;
- final IMultiBlockController controller = getTarget(true);
- return controller != null ? controller.getAccessibleSlotsFromSide(this, side) : GT_Values.emptyIntArray;
- }
+ // #region Item - Depending on the part type - proxy to the multiblock controller, if we have one
@Override
- public boolean canInsertItem(int aSlot, ItemStack aStack, int ordinalSide) {
- final ForgeDirection side = ForgeDirection.getOrientation(ordinalSide);
- if (!modeSelected(ITEM_IN, ITEM_OUT)
- || (facing != ForgeDirection.UNKNOWN && (facing.compareTo(side) != 0 || !coverLetsItemsIn(side, aSlot))))
- return false;
- final IMultiBlockController controller = getTarget(true);
- return (controller != null && controller.canInsertItem(this, aSlot, aStack, side));
- }
+ @Nullable
+ public ItemInventoryLogic getItemLogic(@Nonnull ForgeDirection side, @Nonnull InventoryType unused) {
+ if (side != facing && side != ForgeDirection.UNKNOWN) return null;
- @Override
- public boolean canExtractItem(int aSlot, ItemStack aStack, int ordinalSide) {
- final ForgeDirection side = ForgeDirection.getOrientation(ordinalSide);
- if (!modeSelected(ITEM_IN, ITEM_OUT)
- || (facing != ForgeDirection.UNKNOWN && (facing.compareTo(side) != 0 || !coverLetsItemsOut(side, aSlot))))
- return false;
- final IMultiBlockController controller = getTarget(true);
- return (controller != null && controller.canExtractItem(this, aSlot, aStack, side));
- }
-
- @Override
- public int getSizeInventory() {
- if (!modeSelected(ITEM_IN, ITEM_OUT)) return 0;
- final IMultiBlockController controller = getTarget(true);
- return controller != null ? controller.getSizeInventory(this) : 0;
- }
-
- @Override
- public ItemStack getStackInSlot(int aSlot) {
if (!modeSelected(ITEM_IN, ITEM_OUT)) return null;
- final IMultiBlockController controller = getTarget(true);
- return controller != null ? controller.getStackInSlot(this, aSlot) : null;
- }
-
- @Override
- public ItemStack decrStackSize(int aSlot, int aDecrement) {
- if (!modeSelected(ITEM_IN, ITEM_OUT)) return null;
- final IMultiBlockController controller = getTarget(true);
- return controller != null ? controller.decrStackSize(this, aSlot, aDecrement) : null;
- }
- @Override
- public ItemStack getStackInSlotOnClosing(int aSlot) {
- final IMultiBlockController controller = getTarget(true);
- return controller != null ? controller.getStackInSlotOnClosing(this, aSlot) : null;
- }
-
- @Override
- public void setInventorySlotContents(int aSlot, ItemStack aStack) {
- final IMultiBlockController controller = getTarget(true);
- if (controller != null) controller.setInventorySlotContents(this, aSlot, aStack);
- }
-
- @Override
- public String getInventoryName() {
- final IMultiBlockController controller = getTarget(true);
- if (controller != null) return controller.getInventoryName(this);
- return firstNonNull(getCustomName(), getTileEntityName());
- }
+ final IMultiBlockController controller = getTarget(false);
+ if (controller == null) return null;
- @Override
- public int getInventoryStackLimit() {
- final IMultiBlockController controller = getTarget(true);
- return controller != null ? controller.getInventoryStackLimit(this) : 0;
+ return controller
+ .getItemLogic(modeSelected(ITEM_IN) ? InventoryType.Input : InventoryType.Output, lockedInventory);
}
@Override
- public boolean isItemValidForSlot(int aSlot, ItemStack aStack) {
- final IMultiBlockController controller = getTarget(true);
- return controller != null && controller.isItemValidForSlot(this, aSlot, aStack);
+ @Nullable
+ public InventoryType getItemInventoryType() {
+ if (!modeSelected(ITEM_IN, ITEM_OUT)) return InventoryType.Both;
+ return modeSelected(ITEM_IN) ? InventoryType.Input : InventoryType.Output;
}
- // End Inventory
+ // #endregion Item
// === Modular UI ===
@Override
@@ -700,62 +592,6 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity
return getTarget(true) != null;
}
- protected void addItemInventory(Builder builder, UIBuildContext buildContext) {
- final IMultiBlockController controller = getTarget(false);
- if (controller == null) {
- return;
- }
- final IItemHandlerModifiable inv = controller.getInventoryForGUI(this);
- final Scrollable scrollable = new Scrollable().setVerticalScroll();
- for (int rows = 0; rows * 4 < Math.min(inv.getSlots(), 128); rows++) {
- int columnsToMake = Math.min(Math.min(inv.getSlots(), 128) - rows * 4, 4);
- for (int column = 0; column < columnsToMake; column++) {
- scrollable.widget(
- new SlotWidget(inv, rows * 4 + column).setPos(column * 18, rows * 18)
- .setSize(18, 18));
- }
- }
- builder.widget(
- scrollable.setSize(18 * 4 + 4, 18 * 4)
- .setPos(52, 18));
- DropDownWidget dropDown = new DropDownWidget();
- dropDown.addDropDownItemsSimple(
- controller.getInventoryNames(this),
- (buttonWidget, index, label, setSelected) -> buttonWidget.setOnClick((clickData, widget) -> {
- if (getNameOfInventoryFromIndex(controller, index).equals(Controller.ALL_INVENTORIES_NAME)) {
- mLockedInventory = GT_Values.E;
- mLockedInventoryIndex = 0;
- } else {
- mLockedInventory = getNameOfInventoryFromIndex(controller, index);
- mLockedInventoryIndex = index;
- }
- setSelected.run();
- }),
- true);
- builder.widget(
- dropDown.setSelected(mLockedInventoryIndex)
- .setExpandedMaxHeight(60)
- .setDirection(DropDownWidget.Direction.DOWN)
- .setPos(53, 5)
- .setSize(70, 11));
- }
-
- protected String getNameOfInventoryFromIndex(final IMultiBlockController controller, int index) {
- final List<String> invNames = controller.getInventoryIDs(this);
- if (index > invNames.size()) {
- return invNames.get(0);
- }
- return invNames.get(index);
- }
-
- protected String getNameOfTankArrayFromIndex(final IMultiBlockController controller, int index) {
- final List<String> tankNames = controller.getTankArrayIDs(this);
- if (index > tankNames.size()) {
- return tankNames.get(0);
- }
- return tankNames.get(index);
- }
-
protected boolean isWrongFluid(Fluid fluid) {
if (fluid == null) {
return true;
@@ -776,98 +612,34 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity
return null;
}
- protected void addFluidInventory(Builder builder, UIBuildContext buildContext) {
- final IMultiBlockController controller = getTarget(false);
+ @Override
+ public void addUIWidgets(Builder builder, UIBuildContext buildContext) {
+ super.addUIWidgets(builder, buildContext);
+ IMultiBlockController controller = getTarget(false);
if (controller == null) {
return;
}
- builder.widget(
- new DrawableWidget().setDrawable(GT_UITextures.PICTURE_SCREEN_BLACK)
- .setPos(7, 4)
- .setSize(85, 95));
- if (modeSelected(FLUID_OUT)) {
+ if ((modeSelected(ITEM_IN, ITEM_OUT))) {
builder.widget(
- new DrawableWidget().setDrawable(GT_UITextures.PICTURE_SCREEN_BLACK)
- .setPos(getGUIWidth() - 77, 4)
- .setSize(70, 40))
- .widget(
- new TextWidget("Locked Fluid").setDefaultColor(COLOR_TEXT_WHITE.get())
- .setPos(getGUIWidth() - 72, 8));
- }
- final IFluidTank[] tanks = controller.getFluidTanksForGUI(this);
- final Scrollable scrollable = new Scrollable().setVerticalScroll();
- for (int rows = 0; rows * 4 < tanks.length; rows++) {
- int columnsToMake = Math.min(tanks.length - rows * 4, 4);
- for (int column = 0; column < columnsToMake; column++) {
- FluidSlotWidget fluidSlot = new FluidSlotWidget(tanks[rows * 4 + column]);
- if (modeSelected(FLUID_OUT)) {
- fluidSlot.setInteraction(true, false);
- }
- scrollable.widget(
- fluidSlot.setPos(column * 18, rows * 18)
- .setSize(18, 18));
- }
+ controller
+ .getItemLogic(modeSelected(ITEM_IN) ? InventoryType.Input : InventoryType.Output, lockedInventory)
+ .getGuiPart()
+ .setSize(18 * 4 + 4, 18 * 5)
+ .setPos(52, 7));
}
- builder.widget(
- scrollable.setSize(18 * 4 + 4, 18 * 4)
- .setPos(12, 21));
- DropDownWidget dropDown = new DropDownWidget();
- dropDown.addDropDownItemsSimple(
- controller.getTankArrayNames(this),
- (buttonWidget, index, label, setSelected) -> buttonWidget.setOnClick((clickData, widget) -> {
- if (getNameOfTankArrayFromIndex(controller, index).equals(Controller.ALL_INVENTORIES_NAME)) {
- mLockedInventory = GT_Values.E;
- mLockedInventoryIndex = 0;
- } else {
- mLockedInventory = getNameOfTankArrayFromIndex(controller, index);
- mLockedInventoryIndex = index;
- }
- setSelected.run();
- }),
- true);
- builder.widget(
- dropDown.setSelected(mLockedInventoryIndex)
- .setExpandedMaxHeight(60)
- .setDirection(DropDownWidget.Direction.DOWN)
- .setPos(13, 8)
- .setSize(70, 11));
- }
- @Override
- public void addUIWidgets(Builder builder, UIBuildContext buildContext) {
- if (modeSelected(ITEM_IN, ITEM_OUT)) {
- addItemInventory(builder, buildContext);
- return;
- }
- if (modeSelected(FLUID_IN, FLUID_OUT)) {
- addFluidInventory(builder, buildContext);
- if (modeSelected(FLUID_OUT)) {
- builder.widget(
- SlotGroup.ofFluidTanks(Collections.singletonList(configurationTank), 1)
- .startFromSlot(0)
- .endAtSlot(0)
- .phantom(true)
- .build()
- .setPos(getGUIWidth() - 72, 20));
- }
- return;
+ if ((modeSelected(FLUID_IN, FLUID_OUT))) {
+ builder.widget(
+ controller
+ .getFluidLogic(modeSelected(FLUID_IN) ? InventoryType.Input : InventoryType.Output, lockedInventory)
+ .getGuiPart()
+ .setSize(18 * 4 + 4, 18 * 5)
+ .setPos(52, 7));
}
}
- @Override
- public ModularWindow createWindow(UIBuildContext buildContext) {
- if (isServerSide()) {
- issueClientUpdate();
- }
- System.out.println("MultiBlockPart::createWindow");
- if (modeSelected(NOTHING, ENERGY_IN, ENERGY_OUT) || mMode == NOTHING) {
- IMultiBlockController controller = getTarget(false);
- if (controller == null) {
- return super.createWindow(buildContext);
- }
- return controller.createWindowGUI(buildContext);
- }
- return super.createWindow(buildContext);
+ protected boolean canOpenControllerGui() {
+ return true;
}
@Override
@@ -891,4 +663,62 @@ public abstract class MultiBlockPart extends NonTickableMultiTileEntity
super.addGregTechLogo(builder);
}
}
+
+ @Override
+ public void addToolTips(List<String> list, ItemStack stack, boolean f3_h) {
+ list.add("A MultiTileEntity Casing");
+ }
+
+ public String getInventoryName() {
+ IMultiBlockController controller = getTarget(false);
+ if (controller == null) return "";
+ if (modeSelected(ITEM_IN, ITEM_OUT)) {
+ InventoryType type = modeSelected(ITEM_IN) ? InventoryType.Input : InventoryType.Output;
+ ItemInventoryLogic itemLogic = controller.getItemLogic(type, lockedInventory);
+ return itemLogic.getDisplayName();
+ }
+ if (modeSelected(FLUID_IN, FLUID_OUT)) {
+ InventoryType type = modeSelected(FLUID_IN) ? InventoryType.Input : InventoryType.Output;
+ FluidInventoryLogic fluidLogic = controller.getFluidLogic(type, lockedInventory);
+ return fluidLogic.getDisplayName();
+ }
+ return "";
+ }
+
+ @Override
+ @Nonnull
+ public ForgeDirection getPowerOutputSide() {
+ if (!modeSelected(ENERGY_OUT)) return ForgeDirection.UNKNOWN;
+ return facing;
+ }
+
+ @Nonnull
+ protected GUIProvider<?> createGUIProvider() {
+ return new PartGUIProvider<>(this);
+ }
+
+ @Override
+ @Nonnull
+ public GUIProvider<?> getGUI(@Nonnull UIBuildContext uiContext) {
+ IMultiBlockController controller = getTarget(false);
+ if (controller == null) return guiProvider;
+ if (!modeSelected(NOTHING, ENERGY_IN, ENERGY_OUT)) return guiProvider;
+ if (!canOpenControllerGui()) return guiProvider;
+ if (uiContext.getPlayer()
+ .isSneaking()) return guiProvider;
+ GUIProvider<?> controllerGUI = controller.getGUI(uiContext);
+ return controllerGUI;
+ }
+
+ @Override
+ public ItemStack getAsItem() {
+ return MultiTileEntityRegistry.getRegistry(getMultiTileEntityRegistryID())
+ .getItem(getMultiTileEntityID());
+ }
+
+ @Override
+ public String getMachineName() {
+ return StatCollector.translateToLocal(getAsItem().getUnlocalizedName());
+ }
+
}
diff --git a/src/main/java/gregtech/api/multitileentity/multiblock/base/PowerController.java b/src/main/java/gregtech/api/multitileentity/multiblock/base/PowerController.java
deleted file mode 100644
index 532f171717..0000000000
--- a/src/main/java/gregtech/api/multitileentity/multiblock/base/PowerController.java
+++ /dev/null
@@ -1,92 +0,0 @@
-package gregtech.api.multitileentity.multiblock.base;
-
-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.StatCollector;
-import net.minecraft.world.World;
-import net.minecraftforge.common.util.ForgeDirection;
-
-import gregtech.api.enums.GT_Values;
-import gregtech.api.logic.PowerLogic;
-import gregtech.api.logic.interfaces.PowerLogicHost;
-import gregtech.api.util.GT_Utility;
-import mcp.mobius.waila.api.IWailaConfigHandler;
-import mcp.mobius.waila.api.IWailaDataAccessor;
-
-public abstract class PowerController<T extends PowerController<T>> extends Controller<T> implements PowerLogicHost {
-
- public PowerController() {
- super();
- power = new PowerLogic().setType(PowerLogic.RECEIVER);
- }
-
- protected PowerLogic power;
-
- @Override
- public void writeMultiTileNBT(NBTTagCompound nbt) {
- super.writeMultiTileNBT(nbt);
- power.writeToNBT(nbt);
- }
-
- @Override
- public void readMultiTileNBT(NBTTagCompound nbt) {
- super.readMultiTileNBT(nbt);
- power.loadFromNBT(nbt);
- }
-
- @Override
- public PowerLogic getPowerLogic(ForgeDirection side) {
- return power;
- }
-
- @Override
- public boolean checkMachine() {
- boolean result = super.checkMachine();
- power.setEnergyCapacity(GT_Values.V[tier] * 2 * 60 * 20);
- power.setAmperage(2);
- power.setMaxVoltage(GT_Values.V[tier]);
- return result;
- }
-
- @Override
- public void getWailaNBTData(EntityPlayerMP player, TileEntity tile, NBTTagCompound tag, World world, int x, int y,
- int z) {
- super.getWailaNBTData(player, tile, tag, world, x, y, z);
- tag.setBoolean("isActive", isActive());
- if (isActive()) {
- tag.setLong("energyUsage", eut);
- tag.setLong("energyTier", tier);
- }
- }
-
- @Override
- public void getWailaBody(ItemStack itemStack, List<String> currentTip, IWailaDataAccessor accessor,
- IWailaConfigHandler config) {
- super.getWailaBody(itemStack, currentTip, accessor, config);
- final NBTTagCompound tag = accessor.getNBTData();
- boolean isActive = tag.getBoolean("isActive");
- if (isActive) {
- long energyTier = tag.getLong("energyTier");
- long actualEnergyUsage = tag.getLong("energyUsage");
- if (actualEnergyUsage > 0) {
- currentTip.add(
- StatCollector.translateToLocalFormatted(
- "GT5U.waila.energy.use_with_amperage",
- GT_Utility.formatNumbers(actualEnergyUsage),
- GT_Utility.getAmperageForTier(actualEnergyUsage, (byte) energyTier),
- GT_Utility.getColoredTierNameFromTier((byte) energyTier)));
- } else if (actualEnergyUsage < 0) {
- currentTip.add(
- StatCollector.translateToLocalFormatted(
- "GT5U.waila.energy.produce_with_amperage",
- GT_Utility.formatNumbers(-actualEnergyUsage),
- GT_Utility.getAmperageForTier(-actualEnergyUsage, (byte) energyTier),
- GT_Utility.getColoredTierNameFromTier((byte) energyTier)));
- }
- }
- }
-}
diff --git a/src/main/java/gregtech/api/multitileentity/multiblock/base/StackableController.java b/src/main/java/gregtech/api/multitileentity/multiblock/base/StackableController.java
index 90a2742290..51feb363dd 100644
--- a/src/main/java/gregtech/api/multitileentity/multiblock/base/StackableController.java
+++ b/src/main/java/gregtech/api/multitileentity/multiblock/base/StackableController.java
@@ -4,11 +4,15 @@ import net.minecraft.item.ItemStack;
import com.gtnewhorizon.structurelib.util.Vec3Impl;
-public abstract class StackableController<T extends StackableController<T>> extends PowerController<T> {
+import gregtech.api.logic.MuTEProcessingLogic;
- protected static String STACKABLE_TOP = "STACKABLE_TOP";
+public abstract class StackableController<C extends StackableController<C, P>, P extends MuTEProcessingLogic<P>>
+ extends Controller<C, P> {
+
+ protected static String STACKABLE_STOP = "STACKABLE_STOP";
protected static String STACKABLE_MIDDLE = "STACKABLE_MIDDLE";
- protected static String STACKABLE_BOTTOM = "STACKABLE_BOTTOM";
+ protected static String STACKABLE_START = "STACKABLE_START";
+ protected int stackCount = 0;
/**
* construct implementation for stackable multi-blocks
@@ -19,16 +23,16 @@ public abstract class StackableController<T extends StackableController<T>> exte
final int stackCount = Math.min(blueprintCount, getMaxStacks());
buildState.startBuilding(getStartingStructureOffset());
- buildPiece(STACKABLE_BOTTOM, trigger, hintsOnly, buildState.getCurrentOffset());
+ buildPiece(getStackableStart(), trigger, hintsOnly, buildState.getCurrentOffset());
buildState.addOffset(getStartingStackOffset());
for (int i = 0; i < stackCount; i++) {
- buildPiece(STACKABLE_MIDDLE, trigger, hintsOnly, buildState.getCurrentOffset());
+ buildPiece(getStackableMiddle(i), trigger, hintsOnly, buildState.getCurrentOffset());
buildState.addOffset(getPerStackOffset());
}
if (hasTop()) {
buildState.addOffset(getAfterLastStackOffset());
- buildPiece(STACKABLE_TOP, trigger, hintsOnly, buildState.stopBuilding());
+ buildPiece(getStackableStop(), trigger, hintsOnly, buildState.stopBuilding());
} else {
buildState.stopBuilding();
}
@@ -85,27 +89,40 @@ public abstract class StackableController<T extends StackableController<T>> exte
*/
@Override
public boolean checkMachine() {
- int stackCount = 0;
+ stackCount = 0;
buildState.startBuilding(getStartingStructureOffset());
- if (!checkPiece(STACKABLE_BOTTOM, buildState.getCurrentOffset())) return buildState.failBuilding();
+ if (!checkPiece(getStackableStart(), buildState.getCurrentOffset())) return buildState.failBuilding();
buildState.addOffset(getStartingStackOffset());
for (int i = 0; i < getMaxStacks(); i++) {
- if (checkPiece(STACKABLE_MIDDLE, buildState.getCurrentOffset())) {
- buildState.addOffset(getPerStackOffset());
- stackCount++;
- } else {
+ if (!checkPiece(getStackableMiddle(i), buildState.getCurrentOffset())) {
break;
}
+
+ buildState.addOffset(getPerStackOffset());
+ stackCount++;
+
}
if (stackCount < getMinStacks()) return buildState.failBuilding();
buildState.addOffset(getAfterLastStackOffset());
- if (!checkPiece(STACKABLE_TOP, buildState.stopBuilding())) {
+ if (!checkPiece(getStackableStop(), buildState.stopBuilding())) {
return buildState.failBuilding();
}
return super.checkMachine();
}
+
+ protected String getStackableStop() {
+ return STACKABLE_STOP;
+ }
+
+ protected String getStackableMiddle(int stackIndex) {
+ return STACKABLE_MIDDLE;
+ }
+
+ protected String getStackableStart() {
+ return STACKABLE_START;
+ }
}
diff --git a/src/main/java/gregtech/api/multitileentity/multiblock/base/StackableModularController.java b/src/main/java/gregtech/api/multitileentity/multiblock/base/StackableModularController.java
new file mode 100644
index 0000000000..1dfd497151
--- /dev/null
+++ b/src/main/java/gregtech/api/multitileentity/multiblock/base/StackableModularController.java
@@ -0,0 +1,77 @@
+package gregtech.api.multitileentity.multiblock.base;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.jetbrains.annotations.NotNull;
+
+import gregtech.api.logic.MuTEProcessingLogic;
+import gregtech.api.multitileentity.interfaces.UpgradableModularMuTE;
+import gregtech.api.util.GT_StructureUtilityMuTE.UpgradeCasings;
+
+public abstract class StackableModularController<C extends StackableModularController<C, P>, P extends MuTEProcessingLogic<P>>
+ extends StackableController<C, P> implements UpgradableModularMuTE {
+
+ protected double durationMultiplier = 1;
+ protected double euTickMultiplier = 1;
+
+ private Map<UpgradeCasings, int[]> mucMap;
+
+ protected @NotNull Map<UpgradeCasings, int[]> getMucMap() {
+ if (mucMap == null) {
+ mucMap = createMucMap();
+ }
+ return mucMap;
+ }
+
+ protected static @NotNull Map<UpgradeCasings, int[]> createMucMap() {
+ Map<UpgradeCasings, int[]> mucCount = new HashMap<>();
+ mucCount.put(UpgradeCasings.Heater, new int[] { 0, 0, 0, 0, 0 });
+ mucCount.put(UpgradeCasings.Insulator, new int[] { 0, 0, 0, 0, 0 });
+ return mucCount;
+ }
+
+ @Override
+ public void increaseMucCount(UpgradeCasings casingType, int tier) {
+ Map<UpgradeCasings, int[]> mucCounters = getMucMap();
+ int[] casingCount = mucCounters.get(casingType);
+
+ switch (tier) {
+ case 0, 1, 2 -> casingCount[0] += 1;
+ case 3, 4, 5 -> casingCount[1] += 1;
+ case 6, 7, 8 -> casingCount[2] += 1;
+ case 9, 10, 11 -> casingCount[3] += 1;
+ default -> casingCount[4] += 1;
+ }
+ }
+
+ @Override
+ public void resetMucCount() {
+ Map<UpgradeCasings, int[]> mucCounters = getMucMap();
+ mucCounters.forEach((type, casingCount) -> { Arrays.fill(casingCount, 0); });
+ }
+
+ // Returns the cheapest MUC that is possible for the multi, which gets the minimum bonuses.
+ protected abstract UpgradeCasings getBaseMucType();
+
+ // Minimum parallel bonus per MUC. Higher tier MUCs multiply with this value for even more parallels.
+ protected abstract int getParallelFactor();
+
+ protected void calculateParallels() {
+ int parallelCount = 0;
+ int parallelFactor = getParallelFactor();
+ int[] parallelCasingList = mucMap.get(getBaseMucType());
+
+ for (int i = 0; i < 5; i++) {
+ // (i * 3 + 1) -> Convert MUC tier into minimum GT tier, in groups of 3 (LV, EV, LuV, UHV, UMV)
+ // If higher than multi tier, upgrade casing has no effect
+ if (i * 3 + 1 <= tier) {
+ parallelCount += parallelCasingList[i] * (i + 1) * parallelFactor;
+ }
+ }
+ maxParallel = parallelCount == 0 ? 1 : parallelCount;
+ }
+
+ protected abstract boolean calculateMucMultipliers();
+}
diff --git a/src/main/java/gregtech/api/multitileentity/multiblock/base/WallShareablePart.java b/src/main/java/gregtech/api/multitileentity/multiblock/base/WallShareablePart.java
index 62beb64022..ccde0c49e6 100644
--- a/src/main/java/gregtech/api/multitileentity/multiblock/base/WallShareablePart.java
+++ b/src/main/java/gregtech/api/multitileentity/multiblock/base/WallShareablePart.java
@@ -2,6 +2,7 @@ package gregtech.api.multitileentity.multiblock.base;
import java.util.ArrayList;
import java.util.List;
+import java.util.UUID;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ChunkCoordinates;
@@ -12,50 +13,39 @@ import gregtech.api.multitileentity.interfaces.IMultiBlockController;
public class WallShareablePart extends MultiBlockPart {
protected List<ChunkCoordinates> targetPositions = new ArrayList<>();
- protected List<IMultiBlockController> targets = new ArrayList<>();
@Override
public void setTarget(IMultiBlockController aTarget, int aAllowedModes) {
- if (targets.size() > 1 || targetPositions.size() > 1) {
- mAllowedModes = 0;
- mMode = 0;
+ if (targetPositions.size() >= 1) {
+ allowedModes = 0;
+ setMode((byte) 0);
+ targetPosition = null;
} else {
- mAllowedModes = aAllowedModes;
+ allowedModes = aAllowedModes;
}
if (aTarget == null) {
return;
}
- targets.add(aTarget);
targetPositions.add(aTarget.getCoords());
}
@Override
- public String getLockedInventory() {
- issueClientUpdate();
- if (targets.size() > 1 || targetPositions.size() > 1) {
+ public UUID getLockedInventory() {
+ if (targetPositions.size() > 1) {
return null;
}
-
- IMultiBlockController controller = getTarget(false);
- if (!getNameOfInventoryFromIndex(controller, mLockedInventoryIndex).equals(mLockedInventory)) {
- mLockedInventory = getNameOfInventoryFromIndex(controller, mLockedInventoryIndex);
- if (mLockedInventory.equals("all")) {
- mLockedInventory = "";
- }
- }
- return mLockedInventory.equals("") ? null : mLockedInventory;
+ return super.getLockedInventory();
}
@Override
public IMultiBlockController getTarget(boolean aCheckValidity) {
- if (targets.size() > 1 || targetPositions.size() > 1 || targets.size() <= 0 || targetPositions.size() <= 0) {
+ if (targetPositions.size() != 1) {
return null;
}
- target = targets.get(0);
- mTargetPos = targetPositions.get(0);
+ targetPosition = targetPositions.get(0);
return super.getTarget(aCheckValidity);
}
diff --git a/src/main/java/gregtech/api/multitileentity/multiblock/casing/UpgradeCasing.java b/src/main/java/gregtech/api/multitileentity/multiblock/casing/UpgradeCasing.java
index e3230eac02..fb045557e4 100644
--- a/src/main/java/gregtech/api/multitileentity/multiblock/casing/UpgradeCasing.java
+++ b/src/main/java/gregtech/api/multitileentity/multiblock/casing/UpgradeCasing.java
@@ -16,9 +16,12 @@ public abstract class UpgradeCasing extends MultiBlockPart {
}
@Override
- public void setTarget(IMultiBlockController aTarget, int aAllowedModes) {
- super.setTarget(aTarget, aAllowedModes);
- if (target != null) customWork(target);
+ public void setTarget(IMultiBlockController newTarget, int aAllowedModes) {
+ super.setTarget(newTarget, aAllowedModes);
+
+ if (getTarget(false) != null) {
+ customWork(getTarget(false));
+ }
}
@Override
@@ -28,4 +31,5 @@ public abstract class UpgradeCasing extends MultiBlockPart {
}
protected abstract void customWork(IMultiBlockController aTarget);
+
}
diff --git a/src/main/java/gregtech/api/net/GT_Packet_MultiTileEntity.java b/src/main/java/gregtech/api/net/GT_Packet_MultiTileEntity.java
index b9e334d67b..b7bd8dbc02 100644
--- a/src/main/java/gregtech/api/net/GT_Packet_MultiTileEntity.java
+++ b/src/main/java/gregtech/api/net/GT_Packet_MultiTileEntity.java
@@ -21,7 +21,7 @@ import io.netty.buffer.ByteBuf;
public class GT_Packet_MultiTileEntity extends GT_Packet_New {
public static final int COVERS = B[0], REDSTONE = B[1], MODES = B[2], CONTROLLER = B[3], INVENTORY_INDEX = B[4],
- INVENTORY_NAME = B[5], BOOLEANS = B[6], SOUND = B[7];
+ INVENTORY_NAME_ID = B[5], BOOLEANS = B[6], SOUND = B[7];
private int features = 0;
@@ -32,14 +32,14 @@ public class GT_Packet_MultiTileEntity extends GT_Packet_New {
private ChunkCoordinates mTargetPos = null;
private int mLockedInventoryIndex;
private String mInventoryName;
- private int mInventoryLength;
+ private String inventoryID;
private int booleans;
private byte soundEvent;
private int soundEventValue;
// MultiBlockPart
- private byte mMode;
- private int mAllowedModes;
+ private int mode;
+ private int allowedModes;
public GT_Packet_MultiTileEntity() {
super(true);
@@ -77,10 +77,10 @@ public class GT_Packet_MultiTileEntity extends GT_Packet_New {
mRedstone = aRedstoneData;
}
- public void setModes(byte aMode, int aAllowedModes) {
+ public void setModes(int mode, int allowedModes) {
features |= MODES;
- mMode = aMode;
- mAllowedModes = aAllowedModes;
+ this.mode = mode;
+ this.allowedModes = allowedModes;
}
public void setTargetPos(int aX, short aY, int aZ) {
@@ -94,9 +94,10 @@ public class GT_Packet_MultiTileEntity extends GT_Packet_New {
}
- public void setInventoryName(String aInventoryName) {
- features |= INVENTORY_NAME;
+ public void setInventoryName(String aInventoryName, String inventoryID) {
+ features |= INVENTORY_NAME_ID;
mInventoryName = aInventoryName;
+ this.inventoryID = inventoryID;
}
/**
@@ -140,8 +141,8 @@ public class GT_Packet_MultiTileEntity extends GT_Packet_New {
aOut.writeByte(mRedstone);
}
if ((features & MODES) == MODES) {
- aOut.writeByte(mMode);
- aOut.writeInt(mAllowedModes);
+ aOut.writeInt(mode);
+ aOut.writeInt(allowedModes);
}
if ((features & CONTROLLER) == CONTROLLER) {
aOut.writeInt(mTargetPos.posX);
@@ -151,16 +152,20 @@ public class GT_Packet_MultiTileEntity extends GT_Packet_New {
if ((features & INVENTORY_INDEX) == INVENTORY_INDEX) {
aOut.writeInt(mLockedInventoryIndex);
}
- if ((features & INVENTORY_NAME) == INVENTORY_NAME) {
+ if ((features & INVENTORY_NAME_ID) == INVENTORY_NAME_ID) {
if (mInventoryName != null && mInventoryName.length() > 0) {
- mInventoryLength = mInventoryName.length();
- aOut.writeInt(mInventoryLength);
- for (char tChar : mInventoryName.toCharArray()) {
- aOut.writeChar(tChar);
- }
+ byte[] bytes = mInventoryName.getBytes();
+ aOut.writeInt(bytes.length);
+ aOut.writeBytes(bytes);
+ } else {
+ aOut.writeInt(0);
+ }
+ if (inventoryID != null && inventoryID.length() > 0) {
+ byte[] bytes = inventoryID.getBytes();
+ aOut.writeInt(bytes.length);
+ aOut.writeBytes(bytes);
} else {
- mInventoryLength = 0;
- aOut.writeInt(mInventoryLength);
+ aOut.writeInt(0);
}
}
@@ -203,7 +208,7 @@ public class GT_Packet_MultiTileEntity extends GT_Packet_New {
packet.setRedstoneData(aData.readByte());
}
if ((packetFeatures & MODES) == MODES) {
- packet.setModes(aData.readByte(), aData.readInt());
+ packet.setModes(aData.readInt(), aData.readInt());
}
if ((packetFeatures & CONTROLLER) == CONTROLLER) {
packet.setTargetPos(aData.readInt(), aData.readShort(), aData.readInt());
@@ -211,19 +216,30 @@ public class GT_Packet_MultiTileEntity extends GT_Packet_New {
if ((packetFeatures & INVENTORY_INDEX) == INVENTORY_INDEX) {
packet.setInventoryIndex(aData.readInt());
}
- if ((packetFeatures & INVENTORY_NAME) == INVENTORY_NAME) {
- int tLength = aData.readInt();
- String tName;
- if (tLength > 0) {
- StringBuilder tNameBuilder = new StringBuilder();
- for (int i = 0; i < tLength; i++) {
- tNameBuilder.append(aData.readChar());
+ if ((packetFeatures & INVENTORY_NAME_ID) == INVENTORY_NAME_ID) {
+ int nameLength = aData.readInt();
+ String inventoryName;
+ if (nameLength > 0) {
+ byte[] bytes = new byte[nameLength];
+ for (int i = 0; i < nameLength; i++) {
+ bytes[i] = aData.readByte();
+ }
+ inventoryName = new String(bytes);
+ } else {
+ inventoryName = null;
+ }
+ int idLength = aData.readInt();
+ String inventoryID;
+ if (idLength > 0) {
+ byte[] bytes = new byte[idLength];
+ for (int i = 0; i < idLength; i++) {
+ bytes[i] = aData.readByte();
}
- tName = tNameBuilder.toString();
+ inventoryID = new String(bytes);
} else {
- tName = null;
+ inventoryID = null;
}
- packet.setInventoryName(tName);
+ packet.setInventoryName(inventoryName, inventoryID);
}
if ((packetFeatures & BOOLEANS) == BOOLEANS) {
@@ -246,19 +262,24 @@ public class GT_Packet_MultiTileEntity extends GT_Packet_New {
if (tBlock instanceof MultiTileEntityBlock mteBlock) {
final IMultiTileEntity mte = mteBlock.receiveMultiTileEntityData(aWorld, mX, mY, mZ, mRID, mID);
if (mte == null) return;
- mte.receiveClientEvent(GregTechTileClientEvents.CHANGE_COMMON_DATA, mCommonData);
- mte.receiveClientEvent(GregTechTileClientEvents.CHANGE_COLOR, mColor);
+ mte.receiveClientData(GregTechTileClientEvents.CHANGE_COMMON_DATA, mCommonData);
+ mte.receiveClientData(GregTechTileClientEvents.CHANGE_COLOR, mColor);
if ((features & COVERS) == COVERS) {
mteBlock.receiveCoverData(mte, mC0, mC1, mC2, mC3, mC4, mC5);
}
if ((features & REDSTONE) == REDSTONE) {
- mte.receiveClientEvent(GregTechTileClientEvents.CHANGE_REDSTONE_OUTPUT, mRedstone);
+ mte.receiveClientData(GregTechTileClientEvents.CHANGE_REDSTONE_OUTPUT, mRedstone);
}
if ((features & MODES) == MODES && mte instanceof IMultiTileEntity.IMTE_HasModes mteModes) {
- mteModes.setMode(mMode);
- mteModes.setAllowedModes(mAllowedModes);
+ mteModes.setMode(mode);
+ mteModes.setAllowedModes(allowedModes);
+ }
+
+ if ((features & INVENTORY_NAME_ID) == INVENTORY_NAME_ID && mte instanceof Inventory invUpg) {
+ invUpg.setInventoryName(mInventoryName);
+ invUpg.setInventoryId(inventoryID);
}
if ((features & CONTROLLER) == CONTROLLER && mte instanceof IMultiBlockPart) {
@@ -271,10 +292,6 @@ public class GT_Packet_MultiTileEntity extends GT_Packet_New {
mtePart.setLockedInventoryIndex(mLockedInventoryIndex);
}
- if ((features & INVENTORY_NAME) == INVENTORY_NAME && mte instanceof Inventory invUpg) {
- invUpg.setInventoryName(mInventoryName);
- }
-
if ((features & BOOLEANS) == BOOLEANS && mte instanceof IMultiTileMachine) {
final IMultiTileMachine machine = (IMultiTileMachine) mte;
machine.setBooleans(booleans);
@@ -287,6 +304,7 @@ public class GT_Packet_MultiTileEntity extends GT_Packet_New {
}
} catch (Exception e) {
+ e.printStackTrace();
GT_Mod.GT_FML_LOGGER.error(
"Exception setting tile entity data for tile entity {} at ({}, {}, {})",
tTileEntity,
diff --git a/src/main/java/gregtech/api/objects/GT_ItemStack.java b/src/main/java/gregtech/api/objects/GT_ItemStack.java
index 1273b7111d..210f807c5d 100644
--- a/src/main/java/gregtech/api/objects/GT_ItemStack.java
+++ b/src/main/java/gregtech/api/objects/GT_ItemStack.java
@@ -6,18 +6,20 @@ import net.minecraft.item.ItemStack;
import gregtech.api.enums.GT_Values;
import gregtech.api.util.GT_Utility;
+import gregtech.api.util.item.ItemHolder;
/**
* An optimization of {@link ItemStack} to have a better {@code hashcode} and {@code equals} in order to improve
* {@code HashMap} and {@code Set} performance
*/
-public class GT_ItemStack {
+public class GT_ItemStack extends ItemHolder {
public final Item mItem;
public final byte mStackSize;
public final short mMetaData;
public GT_ItemStack(Item aItem, long aStackSize, long aMetaData) {
+ super(new ItemStack(aItem, 1, (int) aMetaData));
mItem = aItem;
mStackSize = (byte) aStackSize;
mMetaData = (short) aMetaData;
diff --git a/src/main/java/gregtech/api/recipe/check/CheckRecipeResult.java b/src/main/java/gregtech/api/recipe/check/CheckRecipeResult.java
index eeb01077de..8af5c58f5e 100644
--- a/src/main/java/gregtech/api/recipe/check/CheckRecipeResult.java
+++ b/src/main/java/gregtech/api/recipe/check/CheckRecipeResult.java
@@ -1,5 +1,7 @@
package gregtech.api.recipe.check;
+import javax.annotation.Nonnull;
+
import net.minecraft.network.PacketBuffer;
/**
@@ -13,6 +15,7 @@ public interface CheckRecipeResult {
/**
* @return Unique registry ID
*/
+ @Nonnull
String getID();
/**
@@ -23,17 +26,19 @@ public interface CheckRecipeResult {
/**
* @return Actual text to show on client GUI
*/
+ @Nonnull
String getDisplayString();
/**
* Create new instance to receive packet.
*/
+ @Nonnull
CheckRecipeResult newInstance();
/**
* Encode value to sync.
*/
- void encode(PacketBuffer buffer);
+ void encode(@Nonnull PacketBuffer buffer);
/**
* Decode synced value.
diff --git a/src/main/java/gregtech/api/recipe/check/CheckRecipeResultRegistry.java b/src/main/java/gregtech/api/recipe/check/CheckRecipeResultRegistry.java
index 4c089c7203..e141c39a67 100644
--- a/src/main/java/gregtech/api/recipe/check/CheckRecipeResultRegistry.java
+++ b/src/main/java/gregtech/api/recipe/check/CheckRecipeResultRegistry.java
@@ -3,6 +3,8 @@ package gregtech.api.recipe.check;
import java.util.HashMap;
import java.util.Map;
+import javax.annotation.Nonnull;
+
public final class CheckRecipeResultRegistry {
private static final Map<String, CheckRecipeResult> registry = new HashMap<>();
@@ -39,14 +41,17 @@ public final class CheckRecipeResultRegistry {
/**
* Successfully found recipe.
*/
+ @Nonnull
public static final CheckRecipeResult SUCCESSFUL = SimpleCheckRecipeResult.ofSuccess("success");
/**
* All requirements met to generator power.
*/
+ @Nonnull
public static final CheckRecipeResult GENERATING = SimpleCheckRecipeResult.ofSuccess("generating");
/**
* Cannot find recipe.
*/
+ @Nonnull
public static final CheckRecipeResult NO_RECIPE = SimpleCheckRecipeResult.ofFailure("no_recipe");
/**
* Cannot process recipe because item output is full.
@@ -59,6 +64,7 @@ public final class CheckRecipeResultRegistry {
/**
* Default unknown state.
*/
+ @Nonnull
public static final CheckRecipeResult NONE = SimpleCheckRecipeResult.ofFailure("none");
/**
* Code crashed.
@@ -67,26 +73,32 @@ public final class CheckRecipeResultRegistry {
/**
* Cannot find valid fuel for generator.
*/
+ @Nonnull
public static final CheckRecipeResult NO_FUEL_FOUND = SimpleCheckRecipeResult.ofFailure("no_fuel");
/**
* Cannot find valid turbine.
*/
+ @Nonnull
public static final CheckRecipeResult NO_TURBINE_FOUND = SimpleCheckRecipeResult.ofFailure("no_turbine");
/**
* No data sticks found for Assembly Line.
*/
+ @Nonnull
public static final CheckRecipeResult NO_DATA_STICKS = SimpleCheckRecipeResult.ofFailure("no_data_sticks");
/**
* EU/t overflowed.
*/
+ @Nonnull
public static final CheckRecipeResult POWER_OVERFLOW = SimpleCheckRecipeResult.ofFailure("power_overflow");
/**
* Progress time overflowed.
*/
+ @Nonnull
public static final CheckRecipeResult DURATION_OVERFLOW = SimpleCheckRecipeResult.ofFailure("duration_overflow");
/**
* Machine had an internal error
*/
+ @Nonnull
public static final CheckRecipeResult INTERNAL_ERROR = SimpleCheckRecipeResult.ofFailure("internal_error");
/** Multiblock ore drill has no drilling fluid */
public static final CheckRecipeResult NO_DRILLING_FLUID = SimpleCheckRecipeResult.ofFailure("no_drilling_fluid");
@@ -99,6 +111,7 @@ public final class CheckRecipeResultRegistry {
/**
* Cannot process recipe because the machine cannot handle required EUt.
*/
+ @Nonnull
public static CheckRecipeResult insufficientPower(long required) {
return new ResultInsufficientPower(required);
}
@@ -106,6 +119,7 @@ public final class CheckRecipeResultRegistry {
/**
* Cannot process recipe because the machine cannot handle its heat.
*/
+ @Nonnull
public static CheckRecipeResult insufficientHeat(int required) {
return new ResultInsufficientHeat(required);
}
@@ -113,6 +127,7 @@ public final class CheckRecipeResultRegistry {
/**
* Cannot process recipe because the machine is tiered and its tier is too low.
*/
+ @Nonnull
public static CheckRecipeResult insufficientMachineTier(int required) {
return new ResultInsufficientMachineTier(required);
}
@@ -120,6 +135,7 @@ public final class CheckRecipeResultRegistry {
/**
* Cannot process recipe because the machine doesn't have enough startup power.
*/
+ @Nonnull
public static CheckRecipeResult insufficientStartupPower(int required) {
return new ResultInsufficientStartupPower(required);
}
diff --git a/src/main/java/gregtech/api/recipe/check/ResultInsufficientHeat.java b/src/main/java/gregtech/api/recipe/check/ResultInsufficientHeat.java
index 96c8955130..26c3530ba3 100644
--- a/src/main/java/gregtech/api/recipe/check/ResultInsufficientHeat.java
+++ b/src/main/java/gregtech/api/recipe/check/ResultInsufficientHeat.java
@@ -1,5 +1,9 @@
package gregtech.api.recipe.check;
+import java.util.Objects;
+
+import javax.annotation.Nonnull;
+
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.StatCollector;
@@ -15,6 +19,7 @@ public class ResultInsufficientHeat implements CheckRecipeResult {
}
@Override
+ @Nonnull
public String getID() {
return "insufficient_heat";
}
@@ -25,25 +30,28 @@ public class ResultInsufficientHeat implements CheckRecipeResult {
}
@Override
+ @Nonnull
public String getDisplayString() {
- return StatCollector.translateToLocalFormatted(
- "GT5U.gui.text.insufficient_heat",
- GT_Utility.formatNumbers(required),
- HeatingCoilLevel.getDisplayNameFromHeat(required, true));
+ return Objects.requireNonNull(
+ StatCollector.translateToLocalFormatted(
+ "GT5U.gui.text.insufficient_heat",
+ GT_Utility.formatNumbers(required),
+ HeatingCoilLevel.getDisplayNameFromHeat(required, true)));
}
@Override
+ @Nonnull
public CheckRecipeResult newInstance() {
return new ResultInsufficientHeat(0);
}
@Override
- public void encode(PacketBuffer buffer) {
+ public void encode(@Nonnull PacketBuffer buffer) {
buffer.writeVarIntToBuffer(required);
}
@Override
- public void decode(PacketBuffer buffer) {
+ public void decode(@Nonnull PacketBuffer buffer) {
required = buffer.readVarIntFromBuffer();
}
diff --git a/src/main/java/gregtech/api/recipe/check/ResultInsufficientMachineTier.java b/src/main/java/gregtech/api/recipe/check/ResultInsufficientMachineTier.java
index 1e00e791d1..742eb3ef7a 100644
--- a/src/main/java/gregtech/api/recipe/check/ResultInsufficientMachineTier.java
+++ b/src/main/java/gregtech/api/recipe/check/ResultInsufficientMachineTier.java
@@ -1,5 +1,9 @@
package gregtech.api.recipe.check;
+import java.util.Objects;
+
+import javax.annotation.Nonnull;
+
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.StatCollector;
@@ -14,6 +18,7 @@ public class ResultInsufficientMachineTier implements CheckRecipeResult {
}
@Override
+ @Nonnull
public String getID() {
return "insufficient_machine_tier";
}
@@ -24,23 +29,27 @@ public class ResultInsufficientMachineTier implements CheckRecipeResult {
}
@Override
+ @Nonnull
public String getDisplayString() {
- return StatCollector
- .translateToLocalFormatted("GT5U.gui.text.insufficient_machine_tier", GT_Utility.formatNumbers(required));
+ return Objects.requireNonNull(
+ StatCollector.translateToLocalFormatted(
+ "GT5U.gui.text.insufficient_machine_tier",
+ GT_Utility.formatNumbers(required)));
}
@Override
+ @Nonnull
public CheckRecipeResult newInstance() {
return new ResultInsufficientMachineTier(0);
}
@Override
- public void encode(PacketBuffer buffer) {
+ public void encode(@Nonnull PacketBuffer buffer) {
buffer.writeVarIntToBuffer(required);
}
@Override
- public void decode(PacketBuffer buffer) {
+ public void decode(@Nonnull PacketBuffer buffer) {
required = buffer.readVarIntFromBuffer();
}
diff --git a/src/main/java/gregtech/api/recipe/check/ResultInsufficientPower.java b/src/main/java/gregtech/api/recipe/check/ResultInsufficientPower.java
index ca6b31ccef..fdc06c0c07 100644
--- a/src/main/java/gregtech/api/recipe/check/ResultInsufficientPower.java
+++ b/src/main/java/gregtech/api/recipe/check/ResultInsufficientPower.java
@@ -1,5 +1,9 @@
package gregtech.api.recipe.check;
+import java.util.Objects;
+
+import javax.annotation.Nonnull;
+
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.StatCollector;
@@ -14,6 +18,7 @@ public class ResultInsufficientPower implements CheckRecipeResult {
}
@Override
+ @Nonnull
public String getID() {
return "insufficient_power";
}
@@ -24,25 +29,28 @@ public class ResultInsufficientPower implements CheckRecipeResult {
}
@Override
+ @Nonnull
public String getDisplayString() {
- return StatCollector.translateToLocalFormatted(
- "GT5U.gui.text.insufficient_power",
- GT_Utility.formatNumbers(required),
- GT_Utility.getColoredTierNameFromVoltage(required));
+ return Objects.requireNonNull(
+ StatCollector.translateToLocalFormatted(
+ "GT5U.gui.text.insufficient_power",
+ GT_Utility.formatNumbers(required),
+ GT_Utility.getColoredTierNameFromVoltage(required)));
}
@Override
+ @Nonnull
public CheckRecipeResult newInstance() {
return new ResultInsufficientPower(0);
}
@Override
- public void encode(PacketBuffer buffer) {
+ public void encode(@Nonnull PacketBuffer buffer) {
buffer.writeLong(required);
}
@Override
- public void decode(PacketBuffer buffer) {
+ public void decode(@Nonnull PacketBuffer buffer) {
required = buffer.readLong();
}
diff --git a/src/main/java/gregtech/api/recipe/check/ResultInsufficientStartupPower.java b/src/main/java/gregtech/api/recipe/check/ResultInsufficientStartupPower.java
index 42b352563d..62d2dd1fb2 100644
--- a/src/main/java/gregtech/api/recipe/check/ResultInsufficientStartupPower.java
+++ b/src/main/java/gregtech/api/recipe/check/ResultInsufficientStartupPower.java
@@ -1,5 +1,9 @@
package gregtech.api.recipe.check;
+import java.util.Objects;
+
+import javax.annotation.Nonnull;
+
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.StatCollector;
@@ -14,6 +18,7 @@ public class ResultInsufficientStartupPower implements CheckRecipeResult {
}
@Override
+ @Nonnull
public String getID() {
return "insufficient_startup_power";
}
@@ -24,23 +29,27 @@ public class ResultInsufficientStartupPower implements CheckRecipeResult {
}
@Override
+ @Nonnull
public String getDisplayString() {
- return StatCollector
- .translateToLocalFormatted("GT5U.gui.text.insufficient_startup_power", GT_Utility.formatNumbers(required));
+ return Objects.requireNonNull(
+ StatCollector.translateToLocalFormatted(
+ "GT5U.gui.text.insufficient_startup_power",
+ GT_Utility.formatNumbers(required)));
}
@Override
+ @Nonnull
public CheckRecipeResult newInstance() {
return new ResultInsufficientStartupPower(0);
}
@Override
- public void encode(PacketBuffer buffer) {
+ public void encode(@Nonnull PacketBuffer buffer) {
buffer.writeVarIntToBuffer(required);
}
@Override
- public void decode(PacketBuffer buffer) {
+ public void decode(@Nonnull PacketBuffer buffer) {
required = buffer.readVarIntFromBuffer();
}
diff --git a/src/main/java/gregtech/api/recipe/check/SimpleCheckRecipeResult.java b/src/main/java/gregtech/api/recipe/check/SimpleCheckRecipeResult.java
index ed4c95f880..58c85bbe9d 100644
--- a/src/main/java/gregtech/api/recipe/check/SimpleCheckRecipeResult.java
+++ b/src/main/java/gregtech/api/recipe/check/SimpleCheckRecipeResult.java
@@ -2,6 +2,8 @@ package gregtech.api.recipe.check;
import java.util.Objects;
+import javax.annotation.Nonnull;
+
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.StatCollector;
@@ -33,24 +35,26 @@ public class SimpleCheckRecipeResult implements CheckRecipeResult {
}
@Override
+ @Nonnull
public String getDisplayString() {
- return StatCollector.translateToLocal("GT5U.gui.text." + key);
+ return Objects.requireNonNull(StatCollector.translateToLocal("GT5U.gui.text." + key));
}
@Override
+ @Nonnull
public CheckRecipeResult newInstance() {
return new SimpleCheckRecipeResult(false, "", false);
}
@Override
- public void encode(PacketBuffer buffer) {
+ public void encode(@Nonnull PacketBuffer buffer) {
buffer.writeBoolean(success);
NetworkUtils.writeStringSafe(buffer, key);
buffer.writeBoolean(persistsOnShutdown);
}
@Override
- public void decode(PacketBuffer buffer) {
+ public void decode(@Nonnull PacketBuffer buffer) {
success = buffer.readBoolean();
key = NetworkUtils.readStringSafe(buffer);
persistsOnShutdown = buffer.readBoolean();
@@ -74,6 +78,7 @@ public class SimpleCheckRecipeResult implements CheckRecipeResult {
* Creates new result with successful state. Add your localized description with `GT5U.gui.text.{key}`.
* This is already registered to registry.
*/
+ @Nonnull
public static CheckRecipeResult ofSuccess(String key) {
return new SimpleCheckRecipeResult(true, key, false);
}
@@ -82,6 +87,7 @@ public class SimpleCheckRecipeResult implements CheckRecipeResult {
* Creates new result with failed state. Add your localized description with `GT5U.gui.text.{key}`.
* This is already registered to registry.
*/
+ @Nonnull
public static CheckRecipeResult ofFailure(String key) {
return new SimpleCheckRecipeResult(false, key, false);
}
diff --git a/src/main/java/gregtech/api/task/TaskHost.java b/src/main/java/gregtech/api/task/TaskHost.java
new file mode 100644
index 0000000000..d6377949c1
--- /dev/null
+++ b/src/main/java/gregtech/api/task/TaskHost.java
@@ -0,0 +1,18 @@
+package gregtech.api.task;
+
+import javax.annotation.Nonnull;
+
+import org.jetbrains.annotations.ApiStatus;
+
+/**
+ * Classes implementing this interface can have {@link TickableTask} to run. Tasks with conflicting name should not be
+ * allowed, to prevent them from overwriting others' NBT load/save.
+ */
+public interface TaskHost {
+
+ /**
+ * This method should be called ONLY by {@link TickableTask} constructor.
+ */
+ @ApiStatus.OverrideOnly
+ void registerTask(@Nonnull TickableTask<?> task);
+}
diff --git a/src/main/java/gregtech/api/task/TickableTask.java b/src/main/java/gregtech/api/task/TickableTask.java
new file mode 100644
index 0000000000..3bbeb216e7
--- /dev/null
+++ b/src/main/java/gregtech/api/task/TickableTask.java
@@ -0,0 +1,48 @@
+package gregtech.api.task;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.nbt.NBTTagCompound;
+
+/**
+ * This class aims at separating logic run on {@link TaskHost}, rather than using interface layers.
+ * It has two main functionalities: Run tick and Save/Load.
+ *
+ * @param <T> Type of the host
+ */
+public abstract class TickableTask<T extends TaskHost> {
+
+ @Nonnull
+ protected final T taskHost;
+
+ public TickableTask(@Nonnull T taskHost) {
+ this.taskHost = taskHost;
+ taskHost.registerTask(this);
+ }
+
+ /**
+ * @return Name of this task. Tasks with conflicting name cannot be registered to the same machine.
+ */
+ @Nonnull
+ public abstract String getName();
+
+ /**
+ * Called once per world tick.
+ */
+ public abstract void update(long tick, boolean isServerSide);
+
+ /**
+ * Save info to NBT.
+ */
+ public void writeToNBT(@Nonnull NBTTagCompound nbt) {}
+
+ /**
+ * Read info from NBT.
+ */
+ public void readFromNBT(@Nonnull NBTTagCompound nbt) {}
+
+ @Override
+ public String toString() {
+ return "TickableTask{" + "name=" + getName() + ", taskHost=" + taskHost + "}";
+ }
+}
diff --git a/src/main/java/gregtech/api/task/tasks/PollutionTask.java b/src/main/java/gregtech/api/task/tasks/PollutionTask.java
new file mode 100644
index 0000000000..060a91acab
--- /dev/null
+++ b/src/main/java/gregtech/api/task/tasks/PollutionTask.java
@@ -0,0 +1,45 @@
+package gregtech.api.task.tasks;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.tileentity.TileEntity;
+
+import gregtech.api.enums.TickTime;
+import gregtech.api.interfaces.tileentity.IMachineProgress;
+import gregtech.api.task.TaskHost;
+import gregtech.api.task.TickableTask;
+import gregtech.common.GT_Pollution;
+
+public class PollutionTask<T extends TaskHost & IMachineProgress> extends TickableTask<T> {
+
+ private int pollutionPerSecond;
+ private static final int POLLUTION_TICK = TickTime.SECOND;
+
+ public PollutionTask(@Nonnull T taskHost) {
+ super(taskHost);
+ }
+
+ public PollutionTask<T> setPollutionPerSecond(int pollutionPerSecond) {
+ this.pollutionPerSecond = pollutionPerSecond;
+ return this;
+ }
+
+ public int getPollutionPerSecond() {
+ return pollutionPerSecond;
+ }
+
+ @Nonnull
+ @Override
+ public String getName() {
+ return "pollution";
+ }
+
+ @Override
+ public void update(long tick, boolean isServerSide) {
+ if (isServerSide && tick % POLLUTION_TICK == 0 && taskHost.hasThingsToDo()) {
+ if (taskHost instanceof final TileEntity entity) {
+ GT_Pollution.addPollution(entity, getPollutionPerSecond());
+ }
+ }
+ }
+}
diff --git a/src/main/java/gregtech/api/task/tasks/PowerOutputTask.java b/src/main/java/gregtech/api/task/tasks/PowerOutputTask.java
new file mode 100644
index 0000000000..ef800635fb
--- /dev/null
+++ b/src/main/java/gregtech/api/task/tasks/PowerOutputTask.java
@@ -0,0 +1,32 @@
+package gregtech.api.task.tasks;
+
+import javax.annotation.Nonnull;
+
+import gregtech.api.interfaces.tileentity.IMachineProgress;
+import gregtech.api.logic.interfaces.PowerLogicHost;
+import gregtech.api.task.TaskHost;
+import gregtech.api.task.TickableTask;
+
+public class PowerOutputTask<T extends PowerLogicHost & TaskHost & IMachineProgress> extends TickableTask<T> {
+
+ private static final String NAME = "powerOutput";
+
+ public PowerOutputTask(@Nonnull T taskHost) {
+ super(taskHost);
+ }
+
+ @Override
+ @Nonnull
+ public String getName() {
+ return NAME;
+ }
+
+ @Override
+ public void update(long tick, boolean isServerSide) {
+ if (!isServerSide) return;
+ if (!taskHost.isActive()) return;
+ if (!taskHost.isEnergyEmitter()) return;
+ taskHost.emitEnergyFromLogic();
+ }
+
+}
diff --git a/src/main/java/gregtech/api/task/tasks/ProcessingTask.java b/src/main/java/gregtech/api/task/tasks/ProcessingTask.java
new file mode 100644
index 0000000000..410c8d7a6f
--- /dev/null
+++ b/src/main/java/gregtech/api/task/tasks/ProcessingTask.java
@@ -0,0 +1,51 @@
+package gregtech.api.task.tasks;
+
+import javax.annotation.Nonnull;
+
+import gregtech.api.interfaces.tileentity.IMachineProgress;
+import gregtech.api.logic.MuTEProcessingLogic;
+import gregtech.api.logic.interfaces.ProcessingLogicHost;
+import gregtech.api.task.TaskHost;
+import gregtech.api.task.TickableTask;
+
+public class ProcessingTask<T extends TaskHost & ProcessingLogicHost<P> & IMachineProgress, P extends MuTEProcessingLogic<P>>
+ extends TickableTask<T> {
+
+ public ProcessingTask(@Nonnull T taskHost) {
+ super(taskHost);
+ }
+
+ private static final String NAME = "processing";
+
+ @Override
+ @Nonnull
+ public String getName() {
+ return NAME;
+ }
+
+ @Override
+ public void update(long tick, boolean isServerSide) {
+ if (!isServerSide) return;
+ if (!taskHost.isAllowedToWork()) return;
+ final P logic = taskHost.getProcessingLogic();
+ if (taskHost.needsUpdate()) {
+ taskHost.updateProcessingLogic(logic);
+ taskHost.setProcessingUpdate(false);
+ }
+ if (logic.canWork() && tick % 100 == 0) {
+ taskHost.setProcessingLogicPower(logic);
+ logic.startCheck();
+ if (logic.getResult()
+ .wasSuccessful()) {
+ taskHost.setActive(true);
+ }
+ }
+
+ if (taskHost.hasThingsToDo()) {
+ logic.progress();
+ } else {
+ taskHost.setActive(false);
+ }
+ }
+
+}
diff --git a/src/main/java/gregtech/api/util/GT_OverclockCalculator.java b/src/main/java/gregtech/api/util/GT_OverclockCalculator.java
index 8e896fd8de..1b8748237d 100644
--- a/src/main/java/gregtech/api/util/GT_OverclockCalculator.java
+++ b/src/main/java/gregtech/api/util/GT_OverclockCalculator.java
@@ -152,6 +152,7 @@ public class GT_OverclockCalculator {
/**
* @param recipeEUt Sets the Recipe's starting voltage
*/
+ @Nonnull
public GT_OverclockCalculator setRecipeEUt(long recipeEUt) {
this.recipeVoltage = recipeEUt;
return this;
@@ -160,6 +161,7 @@ public class GT_OverclockCalculator {
/**
* @param machineVoltage Sets the EUt that the machine can use. This is the voltage of the machine
*/
+ @Nonnull
public GT_OverclockCalculator setEUt(long machineVoltage) {
this.machineVoltage = machineVoltage;
return this;
@@ -168,6 +170,7 @@ public class GT_OverclockCalculator {
/**
* @param duration Sets the duration of the recipe
*/
+ @Nonnull
public GT_OverclockCalculator setDuration(int duration) {
this.duration = duration;
return this;
@@ -176,6 +179,7 @@ public class GT_OverclockCalculator {
/**
* @param machineAmperage Sets the Amperage that the machine can support
*/
+ @Nonnull
public GT_OverclockCalculator setAmperage(long machineAmperage) {
this.machineAmperage = machineAmperage;
return this;
@@ -184,6 +188,7 @@ public class GT_OverclockCalculator {
/**
* @param recipeAmperage Sets the Amperage of the recipe
*/
+ @Nonnull
public GT_OverclockCalculator setRecipeAmperage(long recipeAmperage) {
this.recipeAmperage = recipeAmperage;
return this;
@@ -192,6 +197,7 @@ public class GT_OverclockCalculator {
/**
* Enables Perfect OC in calculation
*/
+ @Nonnull
public GT_OverclockCalculator enablePerfectOC() {
this.durationDecreasePerOC = 2;
return this;
@@ -200,6 +206,7 @@ public class GT_OverclockCalculator {
/**
* Set if we should be calculating overclocking using EBF's perfectOC
*/
+ @Nonnull
public GT_OverclockCalculator setHeatOC(boolean heatOC) {
this.heatOC = heatOC;
return this;
@@ -208,6 +215,7 @@ public class GT_OverclockCalculator {
/**
* Sets if we should add a heat discount at the end of calculating an overclock, just like the EBF
*/
+ @Nonnull
public GT_OverclockCalculator setHeatDiscount(boolean heatDiscount) {
this.heatDiscount = heatDiscount;
return this;
@@ -216,6 +224,7 @@ public class GT_OverclockCalculator {
/**
* Sets the starting heat of the recipe
*/
+ @Nonnull
public GT_OverclockCalculator setRecipeHeat(int recipeHeat) {
this.recipeHeat = recipeHeat;
return this;
@@ -224,6 +233,7 @@ public class GT_OverclockCalculator {
/**
* Sets the heat of the coils on the machine
*/
+ @Nonnull
public GT_OverclockCalculator setMachineHeat(int machineHeat) {
this.machineHeat = machineHeat;
return this;
@@ -232,6 +242,7 @@ public class GT_OverclockCalculator {
/**
* Sets an EUtDiscount. 0.9 is 10% less energy. 1.1 is 10% more energy
*/
+ @Nonnull
public GT_OverclockCalculator setEUtDiscount(float aEUtDiscount) {
this.eutDiscount = aEUtDiscount;
return this;
@@ -240,6 +251,7 @@ public class GT_OverclockCalculator {
/**
* Sets a Speed Boost for the multiblock. 0.9 is 10% faster. 1.1 is 10% slower
*/
+ @Nonnull
public GT_OverclockCalculator setSpeedBoost(float aSpeedBoost) {
this.speedBoost = aSpeedBoost;
return this;
@@ -248,6 +260,7 @@ public class GT_OverclockCalculator {
/**
* Sets the parallel that the multiblock uses
*/
+ @Nonnull
public GT_OverclockCalculator setParallel(int aParallel) {
this.parallel = aParallel;
return this;
@@ -257,6 +270,7 @@ public class GT_OverclockCalculator {
* Sets the heat discount during OC calculation if HeatOC is used. Default: 0.95 = 5% discount Used like a EU/t
* Discount
*/
+ @Nonnull
public GT_OverclockCalculator setHeatDiscountMultiplier(float heatDiscountExponent) {
this.heatDiscountExponent = heatDiscountExponent;
return this;
@@ -266,6 +280,7 @@ public class GT_OverclockCalculator {
* Sets the Overclock that should be calculated when one. This uses BitShifting! Default is 2, which is a 4x
* decrease
*/
+ @Nonnull
public GT_OverclockCalculator setHeatPerfectOC(int heatPerfectOC) {
this.durationDecreasePerHeatOC = heatPerfectOC;
return this;
@@ -274,6 +289,7 @@ public class GT_OverclockCalculator {
/**
* Sets the amount that the EUt increases per overclock. This uses BitShifting! Default is 2, which is a 4x increase
*/
+ @Nonnull
public GT_OverclockCalculator setEUtIncreasePerOC(int aEUtIncreasePerOC) {
this.eutIncreasePerOC = aEUtIncreasePerOC;
return this;
@@ -283,6 +299,7 @@ public class GT_OverclockCalculator {
* Sets the amount that the duration decreases per overclock. This uses BitShifting! Default is 1, which halves the
* duration
*/
+ @Nonnull
public GT_OverclockCalculator setDurationDecreasePerOC(int durationDecreasePerOC) {
this.durationDecreasePerOC = durationDecreasePerOC;
return this;
@@ -292,6 +309,7 @@ public class GT_OverclockCalculator {
* Set One Tick Discount on EUt based on Duration Decrease Per Overclock. This functions the same as single
* blocks.
*/
+ @Nonnull
public GT_OverclockCalculator setOneTickDiscount(boolean oneTickDiscount) {
this.oneTickDiscount = oneTickDiscount;
return this;
@@ -301,22 +319,26 @@ public class GT_OverclockCalculator {
* Limit the amount of overclocks that can be performed, regardless of how much power is available. Mainly used for
* fusion reactors.
*/
+ @Nonnull
public GT_OverclockCalculator limitOverclockCount(int maxOverclocks) {
this.limitOverclocks = true;
this.maxOverclocks = maxOverclocks;
return this;
}
+ @Nonnull
public GT_OverclockCalculator setLaserOC(boolean laserOC) {
this.laserOC = laserOC;
return this;
}
+ @Nonnull
public GT_OverclockCalculator setAmperageOC(boolean amperageOC) {
this.amperageOC = amperageOC;
return this;
}
+ @Nonnull
public GT_OverclockCalculator setLaserOCPenalty(double laserOCPenalty) {
this.laserOCPenalty = laserOCPenalty;
return this;
@@ -325,6 +347,7 @@ public class GT_OverclockCalculator {
/**
* Set a supplier for calculating custom duration for when its needed under one tick
*/
+ @Nonnull
public GT_OverclockCalculator setDurationUnderOneTickSupplier(Supplier<Double> supplier) {
this.durationUnderOneTickSupplier = supplier;
return this;
@@ -333,6 +356,7 @@ public class GT_OverclockCalculator {
/**
* Sets if we should do overclocking or not
*/
+ @Nonnull
public GT_OverclockCalculator setNoOverclock(boolean noOverclock) {
this.noOverclock = noOverclock;
return this;
@@ -341,6 +365,7 @@ public class GT_OverclockCalculator {
/**
* Call this when all values have been put it.
*/
+ @Nonnull
public GT_OverclockCalculator calculate() {
if (calculated) {
throw new IllegalStateException("Tried to calculate overclocks twice");
diff --git a/src/main/java/gregtech/api/util/GT_ParallelHelper.java b/src/main/java/gregtech/api/util/GT_ParallelHelper.java
index 6ec736b15f..ff739664f4 100644
--- a/src/main/java/gregtech/api/util/GT_ParallelHelper.java
+++ b/src/main/java/gregtech/api/util/GT_ParallelHelper.java
@@ -13,6 +13,8 @@ import net.minecraftforge.fluids.FluidStack;
import gregtech.api.interfaces.tileentity.IRecipeLockable;
import gregtech.api.interfaces.tileentity.IVoidable;
+import gregtech.api.logic.FluidInventoryLogic;
+import gregtech.api.logic.ItemInventoryLogic;
import gregtech.api.objects.XSTR;
import gregtech.api.recipe.RecipeMap;
import gregtech.api.recipe.check.CheckRecipeResult;
@@ -61,6 +63,14 @@ public class GT_ParallelHelper {
*/
private ItemStack[] itemInputs;
/**
+ * The inputs of the machine for current recipe check
+ */
+ private ItemInventoryLogic itemInputInventory;
+ /**
+ * The output item inventory of the machine
+ */
+ private ItemInventoryLogic itemOutputInventory;
+ /**
* The outputs of the recipe with the applied parallel
*/
private ItemStack[] itemOutputs;
@@ -69,6 +79,14 @@ public class GT_ParallelHelper {
*/
private FluidStack[] fluidInputs;
/**
+ * The inputs of the machine for the current recipe check
+ */
+ private FluidInventoryLogic fluidInputInventory;
+ /**
+ * The output fluid inventory of the machine;
+ */
+ private FluidInventoryLogic fluidOutputInventory;
+ /**
* The outputs of the recipe with the applied parallel
*/
private FluidStack[] fluidOutputs;
@@ -117,18 +135,25 @@ public class GT_ParallelHelper {
* Calculator to use for overclocking
*/
private GT_OverclockCalculator calculator;
-
+ @Nonnull
private CheckRecipeResult result = CheckRecipeResultRegistry.NONE;
private Function<Integer, ItemStack[]> customItemOutputCalculation;
private Function<Integer, FluidStack[]> customFluidOutputCalculation;
+ /**
+ * MuTE Mode this is a mode for changing how the GT_ParallelHelper works as Mutes don't use ItemStack and FluidStack
+ * arrays for inputs
+ */
+ private boolean muteMode = false;
+
public GT_ParallelHelper() {}
/**
* Sets machine, with current configuration for void protection mode.
*/
+ @Nonnull
public GT_ParallelHelper setMachine(IVoidable machine) {
return setMachine(machine, machine.protectsExcessItem(), machine.protectsExcessFluid());
}
@@ -136,6 +161,7 @@ public class GT_ParallelHelper {
/**
* Sets machine, with void protection mode forcibly.
*/
+ @Nonnull
public GT_ParallelHelper setMachine(IVoidable machine, boolean protectExcessItem, boolean protectExcessFluid) {
this.protectExcessItem = protectExcessItem;
this.protectExcessFluid = protectExcessFluid;
@@ -146,11 +172,13 @@ public class GT_ParallelHelper {
/**
* Sets the recipe, which will be used for the parallel calculation
*/
+ @Nonnull
public GT_ParallelHelper setRecipe(@Nonnull GT_Recipe aRecipe) {
recipe = Objects.requireNonNull(aRecipe);
return this;
}
+ @Nonnull
public GT_ParallelHelper setRecipeLocked(IRecipeLockable singleRecipeMachine, boolean isRecipeLocked) {
this.singleRecipeMachine = singleRecipeMachine;
this.isRecipeLocked = isRecipeLocked;
@@ -160,6 +188,7 @@ public class GT_ParallelHelper {
/**
* Sets the items available for the recipe check
*/
+ @Nonnull
public GT_ParallelHelper setItemInputs(ItemStack... aItemInputs) {
this.itemInputs = aItemInputs;
return this;
@@ -168,6 +197,7 @@ public class GT_ParallelHelper {
/**
* Sets the fluid inputs available for the recipe check
*/
+ @Nonnull
public GT_ParallelHelper setFluidInputs(FluidStack... aFluidInputs) {
this.fluidInputs = aFluidInputs;
return this;
@@ -176,6 +206,7 @@ public class GT_ParallelHelper {
/**
* Sets the available eut when trying for more parallels
*/
+ @Nonnull
public GT_ParallelHelper setAvailableEUt(long aAvailableEUt) {
this.availableEUt = aAvailableEUt;
return this;
@@ -184,11 +215,13 @@ public class GT_ParallelHelper {
/**
* Sets the modifier for recipe eut. 1 does nothing 0.9 is 10% less. 1.1 is 10% more
*/
+ @Nonnull
public GT_ParallelHelper setEUtModifier(float aEUtModifier) {
this.eutModifier = aEUtModifier;
return this;
}
+ @Nonnull
public GT_ParallelHelper setCalculator(GT_OverclockCalculator calculator) {
this.calculator = calculator;
return this;
@@ -199,6 +232,7 @@ public class GT_ParallelHelper {
*
* @param consume Should we consume inputs
*/
+ @Nonnull
public GT_ParallelHelper setConsumption(boolean consume) {
this.consume = consume;
return this;
@@ -207,6 +241,7 @@ public class GT_ParallelHelper {
/**
* Sets the MaxParallel a multi can handle
*/
+ @Nonnull
public GT_ParallelHelper setMaxParallel(int maxParallel) {
this.maxParallel = maxParallel;
return this;
@@ -216,6 +251,7 @@ public class GT_ParallelHelper {
* Enables Batch mode. Can do up to an additional processed recipes of mCurrentParallel * mBatchModifier A batch
* modifier of 1 does nothing
*/
+ @Nonnull
public GT_ParallelHelper enableBatchMode(int batchModifier) {
this.batchMode = batchModifier > 1;
this.batchModifier = batchModifier;
@@ -227,6 +263,7 @@ public class GT_ParallelHelper {
*
* @param calculateOutputs Should we calculate outputs with the helper or not
*/
+ @Nonnull
public GT_ParallelHelper setOutputCalculation(boolean calculateOutputs) {
this.calculateOutputs = calculateOutputs;
return this;
@@ -236,6 +273,7 @@ public class GT_ParallelHelper {
* Set a custom way to calculate item outputs. You are given the amount of parallels and must return an ItemStack
* array
*/
+ @Nonnull
public GT_ParallelHelper setCustomItemOutputCalculation(Function<Integer, ItemStack[]> custom) {
customItemOutputCalculation = custom;
return this;
@@ -245,11 +283,30 @@ public class GT_ParallelHelper {
* Set a custom way to calculate item outputs. You are given the amount of parallels and must return a FluidStack
* array
*/
+ @Nonnull
public GT_ParallelHelper setCustomFluidOutputCalculation(Function<Integer, FluidStack[]> custom) {
customFluidOutputCalculation = custom;
return this;
}
+ @Nonnull
+ public GT_ParallelHelper setMuTEMode(boolean muteMode) {
+ this.muteMode = muteMode;
+ return this;
+ }
+
+ @Nonnull
+ public GT_ParallelHelper setItemInputInventory(ItemInventoryLogic itemInputInventory) {
+ this.itemInputInventory = itemInputInventory;
+ return this;
+ }
+
+ @Nonnull
+ public GT_ParallelHelper setFluidInputInventory(FluidInventoryLogic fluidInputInventory) {
+ this.fluidInputInventory = fluidInputInventory;
+ return this;
+ }
+
/**
* Sets method for calculating max parallel from given inputs.
*/
@@ -266,9 +323,22 @@ public class GT_ParallelHelper {
return this;
}
+ @Nonnull
+ public GT_ParallelHelper setItemOutputInventory(ItemInventoryLogic itemOutputInventory) {
+ this.itemOutputInventory = itemOutputInventory;
+ return this;
+ }
+
+ @Nonnull
+ public GT_ParallelHelper setFluidOutputInventory(FluidInventoryLogic fluidOutputInventory) {
+ this.fluidOutputInventory = fluidOutputInventory;
+ return this;
+ }
+
/**
* Finishes the GT_ParallelHelper. Anything changed after this will not effect anything
*/
+ @Nonnull
public GT_ParallelHelper build() {
if (built) {
throw new IllegalStateException("Tried to build twice");
@@ -407,7 +477,7 @@ public class GT_ParallelHelper {
// Let's look at how many parallels we can get with void protection
if (protectExcessItem || protectExcessFluid) {
- if (machine == null) {
+ if (machine == null && !muteMode) {
throw new IllegalStateException("Tried to calculate void protection, but machine is not set");
}
VoidProtectionHelper voidProtectionHelper = new VoidProtectionHelper();
@@ -415,6 +485,9 @@ public class GT_ParallelHelper {
.setItemOutputs(truncatedItemOutputs)
.setFluidOutputs(truncatedFluidOutputs)
.setMaxParallel(maxParallel)
+ .setItemOutputInventory(itemOutputInventory)
+ .setFluidOutputInventory(fluidOutputInventory)
+ .setMuTEMode(muteMode)
.build();
maxParallel = Math.min(voidProtectionHelper.getMaxParallel(), maxParallel);
if (voidProtectionHelper.isItemFull()) {
diff --git a/src/main/java/gregtech/api/util/GT_Recipe.java b/src/main/java/gregtech/api/util/GT_Recipe.java
index 159ac1bbd1..0e4ef2162d 100644
--- a/src/main/java/gregtech/api/util/GT_Recipe.java
+++ b/src/main/java/gregtech/api/util/GT_Recipe.java
@@ -7,6 +7,7 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -23,6 +24,8 @@ import gregtech.GT_Mod;
import gregtech.api.GregTech_API;
import gregtech.api.enums.ItemList;
import gregtech.api.enums.Materials;
+import gregtech.api.logic.FluidInventoryLogic;
+import gregtech.api.logic.ItemInventoryLogic;
import gregtech.api.objects.GT_ItemStack;
import gregtech.api.recipe.RecipeCategory;
import gregtech.api.recipe.RecipeMap;
@@ -31,6 +34,7 @@ import gregtech.api.recipe.RecipeMetadataKey;
import gregtech.api.recipe.metadata.EmptyRecipeMetadataStorage;
import gregtech.api.recipe.metadata.IRecipeMetadataStorage;
import gregtech.api.util.extensions.ArrayExt;
+import gregtech.api.util.item.ItemHolder;
import ic2.core.Ic2Items;
public class GT_Recipe implements Comparable<GT_Recipe> {
@@ -548,6 +552,60 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
return currentParallel;
}
+ public boolean isRecipePossible(@Nullable ItemInventoryLogic itemInput, @Nullable FluidInventoryLogic fluidInput) {
+ return getAmountOfRecipesDone(itemInput, fluidInput, 1, true) > 0;
+ }
+
+ public long getAmountOfRecipesDone(@Nullable ItemInventoryLogic itemInput, @Nullable FluidInventoryLogic fluidInput,
+ long maxParallel, boolean simulate) {
+ if (itemInput == null) {
+ itemInput = new ItemInventoryLogic(0);
+ }
+
+ if (fluidInput == null) {
+ fluidInput = new FluidInventoryLogic(0, 0);
+ }
+
+ itemInput.startRecipeCheck();
+ Map<ItemHolder, Long> recipeItems = getItemInputsAsItemMap();
+ for (Entry<ItemHolder, Long> entry : recipeItems.entrySet()) {
+ maxParallel = Math
+ .min(maxParallel, itemInput.calculateAmountOfTimesItemCanBeTaken(entry.getKey(), entry.getValue()));
+ }
+
+ for (FluidStack fluid : mFluidInputs) {
+ if (fluid == null) continue;
+ maxParallel = Math
+ .min(maxParallel, fluidInput.calculateAmountOfTimesFluidCanBeTaken(fluid.getFluid(), fluid.amount));
+ }
+
+ if (simulate) {
+ itemInput.stopRecipeCheck();
+ return maxParallel;
+ }
+
+ for (Entry<ItemHolder, Long> entry : recipeItems.entrySet()) {
+ itemInput.subtractItemAmount(entry.getKey(), entry.getValue() * maxParallel, false);
+ }
+
+ for (FluidStack fluid : mFluidInputs) {
+ if (fluid == null) continue;
+ fluidInput.drain(fluid.getFluid(), fluid.amount * maxParallel, false);
+ }
+ itemInput.stopRecipeCheck();
+ return maxParallel;
+ }
+
+ private Map<ItemHolder, Long> getItemInputsAsItemMap() {
+ Map<ItemHolder, Long> items = new HashMap<>();
+ for (ItemStack item : mInputs) {
+ if (item == null) continue;
+ ItemHolder itemHolder = new ItemHolder(item);
+ items.put(itemHolder, items.getOrDefault(itemHolder, 0L) + item.stackSize);
+ }
+ return items;
+ }
+
@Override
public int compareTo(GT_Recipe recipe) {
// first lowest tier recipes
@@ -720,6 +778,25 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
return this;
}
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) return true;
+ if (!(other instanceof GT_Recipe recipe)) return false;
+ for (int i = 0; i < Math.min(mInputs.length, recipe.mInputs.length); i++) {
+ if (mInputs[i] == null && recipe.mInputs[i] == null) continue;
+ if (mInputs[i] == null || recipe.mInputs[i] == null) return false;
+ ItemHolder currentIH = new ItemHolder(mInputs[i]);
+ ItemHolder otherIH = new ItemHolder(recipe.mInputs[i]);
+ if (!currentIH.equals(otherIH)) return false;
+ }
+ for (int i = 0; i < Math.min(mFluidInputs.length, recipe.mFluidInputs.length); i++) {
+ if (mFluidInputs[i] == null && recipe.mFluidInputs[i] == null) continue;
+ if (mFluidInputs[i] == null || recipe.mFluidInputs[i] == null) return false;
+ if (!FluidStack.areFluidStackTagsEqual(mFluidInputs[i], recipe.mFluidInputs[i])) return false;
+ }
+ return mDuration == recipe.mDuration && mEUt == recipe.mEUt && mSpecialValue == recipe.mSpecialValue;
+ }
+
public static class GT_Recipe_AssemblyLine {
public static final ArrayList<GT_Recipe_AssemblyLine> sAssemblylineRecipes = new ArrayList<>();
diff --git a/src/main/java/gregtech/api/util/GT_StructureUtilityMuTE.java b/src/main/java/gregtech/api/util/GT_StructureUtilityMuTE.java
new file mode 100644
index 0000000000..8e8d027463
--- /dev/null
+++ b/src/main/java/gregtech/api/util/GT_StructureUtilityMuTE.java
@@ -0,0 +1,271 @@
+package gregtech.api.util;
+
+import static gregtech.GT_Mod.GT_FML_LOGGER;
+import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.*;
+import static gregtech.api.multitileentity.enums.GT_MultiTileUpgradeCasing.*;
+import static gregtech.loaders.preload.GT_Loader_MultiTileEntities.*;
+
+import java.util.Arrays;
+
+import net.minecraft.block.Block;
+import net.minecraft.item.ItemStack;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.IIcon;
+import net.minecraft.world.World;
+
+import com.gtnewhorizon.structurelib.StructureLibAPI;
+import com.gtnewhorizon.structurelib.structure.IStructureElement;
+
+import gregtech.api.enums.GT_Values;
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.enums.TextureSet;
+import gregtech.api.multitileentity.MultiTileEntityContainer;
+import gregtech.api.multitileentity.MultiTileEntityRegistry;
+import gregtech.api.multitileentity.enums.GT_MultiTileUpgradeCasing;
+import gregtech.api.multitileentity.interfaces.IMultiBlockController;
+import gregtech.api.multitileentity.interfaces.IMultiTileEntity;
+import gregtech.api.multitileentity.multiblock.base.Controller;
+import gregtech.api.multitileentity.multiblock.base.MultiBlockPart;
+
+public class GT_StructureUtilityMuTE {
+
+ public static final MuTEStructureCasing MOTOR_CASINGS = FunctionalCasings.Motor.getCasing();
+ public static final MuTEStructureCasing PUMP_CASINGS = FunctionalCasings.Pump.getCasing();
+ public static final MuTEStructureCasing CONVEYOR_CASINGS = FunctionalCasings.Conveyor.getCasing();
+ public static final MuTEStructureCasing PISTON_CASINGS = FunctionalCasings.Piston.getCasing();
+ public static final MuTEStructureCasing ROBOT_ARM_CASINGS = FunctionalCasings.RobotArm.getCasing();
+ public static final MuTEStructureCasing EMITTER_CASINGS = FunctionalCasings.Emitter.getCasing();
+ public static final MuTEStructureCasing SENSOR_CASINGS = FunctionalCasings.Sensor.getCasing();
+ public static final MuTEStructureCasing FIELD_GENERATOR_CASINGS = FunctionalCasings.FieldGenerator.getCasing();
+ public static final MuTEStructureCasing INVENTORY_CASINGS = UpgradeCasings.Inventory.getCasing();
+ public static final MuTEStructureCasing TANK_CASINGS = UpgradeCasings.Tank.getCasing();
+ public static final MuTEStructureCasing AMPERAGE_CASINGS = UpgradeCasings.Amperage.getCasing();
+ public static final MuTEStructureCasing LASER_CASINGS = UpgradeCasings.Laser.getCasing();
+ public static final MuTEStructureCasing WIRELESS_CASINGS = UpgradeCasings.Wireless.getCasing();
+ public static final MuTEStructureCasing CLEANROOM_CASINGS = UpgradeCasings.Cleanroom.getCasing();
+ public static final MuTEStructureCasing HEATER_CASINGS = UpgradeCasings.Heater.getCasing();
+ public static final MuTEStructureCasing INSULATOR_CASINGS = UpgradeCasings.Insulator.getCasing();
+
+ public enum FunctionalCasings {
+
+ Motor(COMPONENT_CASING_REGISTRY_NAME, LV_Motor.getId(), MV_Motor.getId(), HV_Motor.getId(), EV_Motor.getId(),
+ IV_Motor.getId(), LuV_Motor.getId(), ZPM_Motor.getId(), UV_Motor.getId(), UHV_Motor.getId(),
+ UEV_Motor.getId(), UIV_Motor.getId(), UMV_Motor.getId(), UXV_Motor.getId(), MAX_Motor.getId()),
+
+ Pump(COMPONENT_CASING_REGISTRY_NAME, LV_Pump.getId(), MV_Pump.getId(), HV_Pump.getId(), EV_Pump.getId(),
+ IV_Pump.getId(), LuV_Pump.getId(), ZPM_Pump.getId(), UV_Pump.getId(), UHV_Pump.getId(), UEV_Pump.getId(),
+ UIV_Pump.getId(), UMV_Pump.getId(), UXV_Pump.getId(), MAX_Pump.getId()),
+
+ Conveyor(COMPONENT_CASING_REGISTRY_NAME, LV_Conveyor.getId(), MV_Conveyor.getId(), HV_Conveyor.getId(),
+ EV_Conveyor.getId(), IV_Conveyor.getId(), LuV_Conveyor.getId(), ZPM_Conveyor.getId(), UV_Conveyor.getId(),
+ UHV_Conveyor.getId(), UEV_Conveyor.getId(), UIV_Conveyor.getId(), UMV_Conveyor.getId(),
+ UXV_Conveyor.getId(), MAX_Conveyor.getId()),
+
+ Piston(COMPONENT_CASING_REGISTRY_NAME, LV_Piston.getId(), MV_Piston.getId(), HV_Piston.getId(),
+ EV_Piston.getId(), IV_Piston.getId(), LuV_Piston.getId(), ZPM_Piston.getId(), UV_Piston.getId(),
+ UHV_Piston.getId(), UEV_Piston.getId(), UIV_Piston.getId(), UMV_Piston.getId(), UXV_Piston.getId(),
+ MAX_Piston.getId()),
+
+ RobotArm(COMPONENT_CASING_REGISTRY_NAME, LV_RobotArm.getId(), MV_RobotArm.getId(), HV_RobotArm.getId(),
+ EV_RobotArm.getId(), IV_RobotArm.getId(), LuV_RobotArm.getId(), ZPM_RobotArm.getId(), UV_RobotArm.getId(),
+ UHV_RobotArm.getId(), UEV_RobotArm.getId(), UIV_RobotArm.getId(), UMV_RobotArm.getId(),
+ UXV_RobotArm.getId(), MAX_RobotArm.getId()),
+
+ Emitter(COMPONENT_CASING_REGISTRY_NAME, LV_Emitter.getId(), MV_Emitter.getId(), HV_Emitter.getId(),
+ EV_Emitter.getId(), IV_Emitter.getId(), LuV_Emitter.getId(), ZPM_Emitter.getId(), UV_Emitter.getId(),
+ UHV_Emitter.getId(), UEV_Emitter.getId(), UIV_Emitter.getId(), UMV_Emitter.getId(), UXV_Emitter.getId(),
+ MAX_Emitter.getId()),
+
+ Sensor(COMPONENT_CASING_REGISTRY_NAME, LV_Sensor.getId(), MV_Sensor.getId(), HV_Sensor.getId(),
+ EV_Sensor.getId(), IV_Sensor.getId(), LuV_Sensor.getId(), ZPM_Sensor.getId(), UV_Sensor.getId(),
+ UHV_Sensor.getId(), UEV_Sensor.getId(), UIV_Sensor.getId(), UMV_Sensor.getId(), UXV_Sensor.getId(),
+ MAX_Sensor.getId()),
+
+ FieldGenerator(COMPONENT_CASING_REGISTRY_NAME, LV_FieldGenerator.getId(), MV_FieldGenerator.getId(),
+ HV_FieldGenerator.getId(), EV_FieldGenerator.getId(), IV_FieldGenerator.getId(), LuV_FieldGenerator.getId(),
+ ZPM_FieldGenerator.getId(), UV_FieldGenerator.getId(), UHV_FieldGenerator.getId(),
+ UEV_FieldGenerator.getId(), UIV_FieldGenerator.getId(), UMV_FieldGenerator.getId(),
+ UXV_FieldGenerator.getId(), MAX_FieldGenerator.getId());
+
+ private final MuTEStructureCasing casing;
+
+ FunctionalCasings(String registryName, Integer... validIds) {
+ casing = createMuTEStructureCasing(registryName, validIds);
+ }
+
+ public MuTEStructureCasing getCasing() {
+ return casing;
+ }
+ }
+
+ public enum UpgradeCasings {
+
+ Inventory(UPGRADE_CASING_REGISTRY_NAME, ULV_Inventory.getId(), LV_Inventory.getId(), MV_Inventory.getId(),
+ HV_Inventory.getId(), EV_Inventory.getId(), IV_Inventory.getId(), LuV_Inventory.getId(),
+ ZPM_Inventory.getId(), UV_Inventory.getId(), UHV_Inventory.getId(), UEV_Inventory.getId(),
+ UIV_Inventory.getId(), UMV_Inventory.getId(), UXV_Inventory.getId(), MAX_Inventory.getId()),
+
+ Tank(UPGRADE_CASING_REGISTRY_NAME, ULV_Tank.getId(), LV_Tank.getId(), MV_Tank.getId(), HV_Tank.getId(),
+ EV_Tank.getId(), IV_Tank.getId(), LuV_Tank.getId(), ZPM_Tank.getId(), UV_Tank.getId(), UHV_Tank.getId(),
+ UEV_Tank.getId(), UIV_Tank.getId(), UMV_Tank.getId(), UXV_Tank.getId(), MAX_Tank.getId()),
+
+ Amperage(UPGRADE_CASING_REGISTRY_NAME, Amp_4.getId(), Amp_16.getId(), Amp_64.getId(), Amp_256.getId(),
+ Amp_1_024.getId(), Amp_4_096.getId(), Amp_16_384.getId(), Amp_65_536.getId(), Amp_262_144.getId(),
+ Amp_1_048_576.getId()),
+
+ Laser(UPGRADE_CASING_REGISTRY_NAME, GT_MultiTileUpgradeCasing.Laser.getId()),
+
+ Wireless(UPGRADE_CASING_REGISTRY_NAME, GT_MultiTileUpgradeCasing.Wireless.getId()),
+
+ Cleanroom(UPGRADE_CASING_REGISTRY_NAME, GT_MultiTileUpgradeCasing.Cleanroom.getId()),
+
+ Heater(UPGRADE_CASING_REGISTRY_NAME, Heater_Prototype.getId(), Heater_IndustrialGrade.getId(),
+ Heater_NextGen.getId(), Heater_Omnipotent.getId(), Heater_OmegaType.getId()),
+
+ Insulator(UPGRADE_CASING_REGISTRY_NAME, Insulator_Prototype.getId(), Insulator_IndustrialGrade.getId(),
+ Insulator_NextGen.getId(), Insulator_Omnipotent.getId(), Insulator_OmegaType.getId());
+
+ private final MuTEStructureCasing casing;
+
+ UpgradeCasings(String registryName, Integer... validIds) {
+ casing = createMuTEStructureCasing(registryName, validIds);
+ }
+
+ public MuTEStructureCasing getCasing() {
+ return casing;
+ }
+ }
+
+ /**
+ * Specify all casing sets that are valid for a multiblock structure position. The first casing will be used as
+ * default when doing auto place
+ *
+ * @param modes Allowed modes on the casings
+ * @param validCasings Allowed casing sets
+ * @return Structure Element
+ * @param <T> Multiblock class
+ */
+ public static <T> IStructureElement<T> ofMuTECasings(int modes, MuTEStructureCasing... validCasings) {
+ if (validCasings == null || validCasings.length == 0) {
+ throw new IllegalArgumentException();
+ }
+ return new IStructureElement<>() {
+
+ final MuTEStructureCasing[] allowedCasings = validCasings;
+ private final static short[] DEFAULT = new short[] { 255, 255, 255, 0 };
+ private static IIcon[] mIcons = null;
+
+ @Override
+ public boolean check(T t, World world, int x, int y, int z) {
+ final TileEntity tileEntity = world.getTileEntity(x, y, z);
+ if (!(tileEntity instanceof MultiBlockPart part)) return false;
+
+ for (MuTEStructureCasing casing : allowedCasings) {
+ if (casing.isCasingValid(part.getMultiTileEntityRegistryID(), part.getMultiTileEntityID())) {
+ final IMultiBlockController tTarget = part.getTarget(false);
+ if (tTarget != null && tTarget != t) return false;
+
+ part.setTarget((IMultiBlockController) t, modes);
+
+ ((Controller<?, ?>) t).registerSpecialCasings(part);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean spawnHint(T t, World world, int x, int y, int z, ItemStack trigger) {
+ // Moved here from Controller. TODO: Proper implementation
+ if (mIcons == null) {
+ mIcons = new IIcon[6];
+ Arrays.fill(mIcons, TextureSet.SET_NONE.mTextures[OrePrefixes.block.mTextureIndex].getIcon());
+ }
+ final short[] RGBA = DEFAULT;
+ StructureLibAPI.hintParticleTinted(world, x, y, z, mIcons, RGBA);
+ return true;
+ }
+
+ @Override
+ public boolean placeBlock(T t, World world, int x, int y, int z, ItemStack trigger) {
+ final MultiTileEntityRegistry tRegistry = MultiTileEntityRegistry
+ .getRegistry(validCasings[0].getRegistryId());
+ if (tRegistry == null) {
+ GT_FML_LOGGER.error("NULL REGISTRY");
+ return false;
+ }
+ final MultiTileEntityContainer tContainer = tRegistry
+ .getNewTileEntityContainer(world, x, y, z, validCasings[0].defaultMeta, null);
+ if (tContainer == null) {
+ GT_FML_LOGGER.error("NULL CONTAINER");
+ return false;
+ }
+ final IMultiTileEntity te = ((IMultiTileEntity) tContainer.mTileEntity);
+ if (!(te instanceof MultiBlockPart)) {
+ GT_FML_LOGGER.error("Not a multiblock part");
+ return false;
+ }
+ if (world.setBlock(x, y, z, tContainer.mBlock, 15 - tContainer.mBlockMetaData, 2)) {
+ tContainer.setMultiTile(world, x, y, z);
+ ((MultiBlockPart) te).setTarget((IMultiBlockController) t, modes);
+
+ ((Controller<?, ?>) t).registerSpecialCasings((MultiBlockPart) te);
+ }
+
+ return false;
+ }
+ };
+ }
+
+ public static MuTEStructureCasing createMuTEStructureCasing(String registryName, Integer... validIds) {
+ return new MuTEStructureCasing(registryName, validIds);
+ }
+
+ /**
+ * Object used to store a set of casings (e.g. all motor casings)
+ */
+ public static class MuTEStructureCasing {
+
+ private String registryName;
+ private int registryId = GT_Values.W;
+ private final int defaultMeta;
+ private final Integer[] validIds;
+
+ public MuTEStructureCasing(String registryName, Integer... validIds) {
+ MultiTileEntityRegistry registry = MultiTileEntityRegistry.getRegistry(registryName);
+ if (validIds == null || validIds.length == 0 || registry == null) {
+ throw new IllegalArgumentException();
+ }
+ this.registryName = registryName;
+ this.validIds = validIds;
+ this.defaultMeta = validIds[0];
+ }
+
+ public boolean isCasingValid(int registryId, int id) {
+ if (getRegistryId() != registryId) {
+ return false;
+ }
+ for (Integer validId : validIds) {
+ if (validId == id) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public int getDefaultMeta() {
+ return defaultMeta;
+ }
+
+ public int getRegistryId() {
+ // TODO: MuTE registry seems to somehow shift, probably due to NBT shenanigans. Lazy init circumvents this
+ // but it should be properly fixed in the future
+ if (registryId == GT_Values.W) {
+ MultiTileEntityRegistry registry = MultiTileEntityRegistry.getRegistry(registryName);
+ registryId = Block.getIdFromBlock(registry.mBlock);
+ }
+ return registryId;
+ }
+ }
+}
diff --git a/src/main/java/gregtech/api/util/VoidProtectionHelper.java b/src/main/java/gregtech/api/util/VoidProtectionHelper.java
index 3a41bba934..245fc24bda 100644
--- a/src/main/java/gregtech/api/util/VoidProtectionHelper.java
+++ b/src/main/java/gregtech/api/util/VoidProtectionHelper.java
@@ -10,9 +10,12 @@ import net.minecraft.item.ItemStack;
import net.minecraftforge.fluids.FluidStack;
import com.gtnewhorizon.gtnhlib.util.map.ItemStackMap;
+import com.gtnewhorizons.modularui.api.fluids.IFluidTankLong;
import gregtech.api.interfaces.fluid.IFluidStore;
import gregtech.api.interfaces.tileentity.IVoidable;
+import gregtech.api.logic.FluidInventoryLogic;
+import gregtech.api.logic.ItemInventoryLogic;
/**
* Helper class to calculate how many parallels of items / fluids can fit in the output buses / hatches.
@@ -52,9 +55,21 @@ public class VoidProtectionHelper {
*/
private FluidStack[] fluidOutputs;
/**
+ * The item output inventory
+ */
+ private ItemInventoryLogic itemOutputInventory;
+ /**
+ * The fluid output inventory
+ */
+ private FluidInventoryLogic fluidOutputInventory;
+ /**
* Has this helper been built?
*/
private boolean built;
+ /**
+ * Is this helper working for a MuTE?
+ */
+ private boolean muteMode;
public VoidProtectionHelper() {}
@@ -93,6 +108,21 @@ public class VoidProtectionHelper {
return this;
}
+ public VoidProtectionHelper setItemOutputInventory(ItemInventoryLogic itemOutputInventory) {
+ this.itemOutputInventory = itemOutputInventory;
+ return this;
+ }
+
+ public VoidProtectionHelper setFluidOutputInventory(FluidInventoryLogic fluidOutputInventory) {
+ this.fluidOutputInventory = fluidOutputInventory;
+ return this;
+ }
+
+ public VoidProtectionHelper setMuTEMode(boolean muteMode) {
+ this.muteMode = muteMode;
+ return this;
+ }
+
/**
* Finishes the VoidProtectionHelper. Anything changed after this will not affect anything
*/
@@ -241,11 +271,95 @@ public class VoidProtectionHelper {
return aParallelQueue.element().batch;
}
+ private int calculateMaxFluidParallelsMuTE() {
+ if (fluidOutputs.length > fluidOutputInventory.getInventory()
+ .getTanks()) {
+ return 0;
+ }
+
+ // A map to hold the items we will be 'inputting' into the output hatches. These fluidstacks are actually
+ // the recipe outputs.
+ Map<FluidStack, Integer> tFluidOutputMap = new HashMap<>();
+
+ // Map that keeps track of the number of parallel crafts we can accommodate for each fluid output.
+ // In the pair, we keep track of number of full crafts plus mb of fluid in a partial craft, to avoid
+ // issues with floating point math not being completely accurate when summing.
+ Map<FluidStack, ParallelData> tParallels = new HashMap<>();
+
+ // Iterate over the outputs, calculating require stack spacing they will require.
+ for (FluidStack aY : fluidOutputs) {
+ if (aY == null || aY.amount <= 0) {
+ continue;
+ }
+ tFluidOutputMap.merge(aY, aY.amount, Integer::sum);
+ tParallels.put(aY, new ParallelData(0, 0));
+ }
+
+ if (tFluidOutputMap.isEmpty()) {
+ // nothing to output, bail early
+ return maxParallel;
+ }
+
+ for (int i = 0; i < fluidOutputInventory.getInventory()
+ .getTanks(); i++) {
+ IFluidTankLong tank = fluidOutputInventory.getInventory()
+ .getFluidTank(i);
+ long tSpaceLeft = tank.getCapacityLong() - tank.getFluidAmountLong();
+ // check if hatch filled
+ if (tSpaceLeft <= 0) continue;
+ // check if hatch is empty and unrestricted
+ if (tank.getStoredFluid() == null) continue;
+
+ for (Map.Entry<FluidStack, ParallelData> entry : tParallels.entrySet()) {
+ FluidStack tFluidOutput = entry.getKey();
+ if (tank.fill(tFluidOutput.getFluid(), tFluidOutput.amount, false) == tFluidOutput.amount) continue;
+ // this fluid is not prevented by restrictions on output hatch
+ ParallelData tParallel = entry.getValue();
+ Integer tCraftSize = tFluidOutputMap.get(tFluidOutput);
+ tParallel.batch += (tParallel.partial + tSpaceLeft) / tCraftSize;
+ tParallel.partial = (tParallel.partial + tSpaceLeft) % tCraftSize;
+ }
+ }
+ // now that all partial/restricted hatches have been counted, create a priority queue for our outputs
+ // the lowest priority fluid is the number of complete parallel crafts we can support
+ PriorityQueue<ParallelStackInfo<FluidStack>> aParallelQueue = new PriorityQueue<>(
+ Comparator.comparing(i -> i.batch));
+ for (Map.Entry<FluidStack, ParallelData> entry : tParallels.entrySet()) {
+ aParallelQueue
+ .add(new ParallelStackInfo<>(entry.getValue().batch, entry.getValue().partial, entry.getKey()));
+ }
+ // add extra parallels for open slots as well
+ for (int i = 0; i < fluidOutputInventory.getInventory()
+ .getTanks(); i++) {
+ IFluidTankLong tank = fluidOutputInventory.getInventory()
+ .getFluidTank(i);
+ // partially filled or restricted hatch. done in the last pass
+ if (tank.getStoredFluid() != null) continue;
+
+ ParallelStackInfo<FluidStack> tParallel = aParallelQueue.poll();
+ assert tParallel != null; // will always be true, specifying assert here to avoid IDE/compiler warnings
+ Integer tCraftSize = tFluidOutputMap.get(tParallel.stack);
+ long tSpaceLeft = tank.getCapacityLong();
+ tParallel.batch += (tParallel.partial + tSpaceLeft) / tCraftSize;
+ tParallel.partial = (tParallel.partial + tSpaceLeft) % tCraftSize;
+ aParallelQueue.add(tParallel);
+ }
+
+ return aParallelQueue.element().batch;
+ }
+
/**
* Calculates the max parallels one can do with items if void protection is on
*/
private int calculateMaxItemParallels() {
- List<ItemStack> busStacks = machine.getItemOutputSlots(itemOutputs);
+ List<ItemStack> busStacks;
+
+ if (muteMode) {
+ busStacks = itemOutputInventory.getInventory()
+ .getStacks();
+ } else {
+ busStacks = machine.getItemOutputSlots(itemOutputs);
+ }
// A map to hold the items we will be 'inputting' into the output buses. These itemstacks are actually the
// recipe outputs.
Map<ItemStack, Integer> tItemOutputMap = new ItemStackMap<>();
@@ -320,9 +434,9 @@ public class VoidProtectionHelper {
private static class ParallelData {
private int batch;
- private int partial;
+ private long partial;
- private ParallelData(int batch, int partial) {
+ private ParallelData(int batch, long partial) {
this.batch = batch;
this.partial = partial;
}
@@ -331,10 +445,10 @@ public class VoidProtectionHelper {
private static class ParallelStackInfo<T> {
private int batch;
- private int partial;
+ private long partial;
private final T stack;
- private ParallelStackInfo(int batch, int partial, T stack) {
+ private ParallelStackInfo(int batch, long partial, T stack) {
this.batch = batch;
this.partial = partial;
this.stack = stack;
diff --git a/src/main/java/gregtech/api/util/item/ItemHolder.java b/src/main/java/gregtech/api/util/item/ItemHolder.java
new file mode 100644
index 0000000000..4675d0ba0e
--- /dev/null
+++ b/src/main/java/gregtech/api/util/item/ItemHolder.java
@@ -0,0 +1,79 @@
+package gregtech.api.util.item;
+
+import static net.minecraftforge.oredict.OreDictionary.getOreIDs;
+
+import java.util.Arrays;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.init.Items;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+
+import gregtech.api.util.GT_Utility;
+
+public class ItemHolder {
+
+ private final Item item;
+ private final int meta;
+ private final NBTTagCompound tag;
+ private final int[] oreIDs;
+
+ public ItemHolder(@Nonnull ItemStack item) {
+ this.item = item.getItem();
+ this.meta = Items.feather.getDamage(item);
+ this.tag = item.getTagCompound();
+ this.oreIDs = getOreIDs(item);
+ }
+
+ public Item getItem() {
+ return item;
+ }
+
+ public int getMeta() {
+ return meta;
+ }
+
+ public NBTTagCompound getNBT() {
+ return tag;
+ }
+
+ public int[] getOreDictTagIDs() {
+ return oreIDs;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) return true;
+ if (!(other instanceof ItemHolder otherIH)) return false;
+ if (Arrays.stream(oreIDs)
+ .anyMatch(id -> {
+ for (int i = 0; i < otherIH.getOreDictTagIDs().length; i++) {
+ if (id == otherIH.getOreDictTagIDs()[i]) return true;
+ }
+ return false;
+ })) {
+ return true;
+ }
+
+ if (item != otherIH.getItem() || meta != otherIH.getMeta()) {
+ return false;
+ }
+ if (this.tag == null && otherIH.getNBT() == null) return true;
+ if (this.tag == null || otherIH.getNBT() == null) return false;
+ return this.tag.equals(otherIH);
+ }
+
+ @Override
+ public int hashCode() {
+ return GT_Utility.stackToInt(toStack());
+ }
+
+ @Nonnull
+ private ItemStack toStack() {
+ ItemStack item = new ItemStack(this.item, 1, meta);
+ item.stackTagCompound = tag;
+ return item;
+ }
+}
diff --git a/src/main/java/gregtech/api/util/recipe/RecipeInputRequirements.java b/src/main/java/gregtech/api/util/recipe/RecipeInputRequirements.java
new file mode 100644
index 0000000000..590c104101
--- /dev/null
+++ b/src/main/java/gregtech/api/util/recipe/RecipeInputRequirements.java
@@ -0,0 +1,77 @@
+package gregtech.api.util.recipe;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidStack;
+
+import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.item.ItemHolder;
+
+public class RecipeInputRequirements {
+
+ protected Map<ItemHolder, Long> itemInputs = new HashMap<>();
+ protected Set<ItemHolder> itemInputsMet = new HashSet<>();
+ protected boolean metAllItem = false;
+ protected Map<Fluid, Long> fluidInputs = new HashMap<>();
+ protected Set<Fluid> fluidInputsMet = new HashSet<>();
+ protected boolean metAllFluid = false;
+
+ public RecipeInputRequirements(@Nonnull GT_Recipe recipe) {
+ this(recipe.mInputs, recipe.mFluidInputs);
+ }
+
+ public RecipeInputRequirements(@Nonnull ItemStack[] itemInputs, @Nonnull FluidStack[] fluidInputs) {
+ for (ItemStack item : itemInputs) {
+ if (item == null) continue;
+ ItemHolder itemIH = new ItemHolder(item);
+ this.itemInputs.put(itemIH, this.itemInputs.getOrDefault(itemIH, 0L) + item.stackSize);
+ }
+
+ for (FluidStack fluid : fluidInputs) {
+ if (fluid == null) continue;
+ this.fluidInputs.put(fluid.getFluid(), this.fluidInputs.getOrDefault(fluid.getFluid(), 0L) + fluid.amount);
+ }
+ }
+
+ /**
+ *
+ * @param itemInputs we have and want to fill this request
+ * @return {@code true} when all item inputs are met
+ */
+ public boolean tryToFillItemRequirements(Map<ItemHolder, Long> itemInputs) {
+ if (metAllItem) return metAllItem;
+ for (Entry<ItemHolder, Long> entry : itemInputs.entrySet()) {
+ if (itemInputsMet.contains(entry.getKey())) continue;
+ if (!this.itemInputs.containsKey(entry.getKey())) continue;
+ if (this.itemInputs.get(entry.getKey()) > entry.getValue()) continue;
+ itemInputsMet.add(entry.getKey());
+ }
+ metAllItem = itemInputsMet.containsAll(this.itemInputs.keySet());
+ return metAllItem;
+ }
+
+ /**
+ *
+ * @param fluidInputs we have and want to fill this request
+ * @return {@code true} when all fluid inputs are met
+ */
+ public boolean tryToFillFluidRequirements(Map<Fluid, Long> fluidInputs) {
+ if (metAllFluid) return metAllFluid;
+ for (Entry<Fluid, Long> entry : fluidInputs.entrySet()) {
+ if (fluidInputsMet.contains(entry.getKey())) continue;
+ if (!this.fluidInputs.containsKey(entry.getKey())) continue;
+ if (this.fluidInputs.get(entry.getKey()) > entry.getValue()) continue;
+ fluidInputsMet.add(entry.getKey());
+ }
+ metAllFluid = fluidInputsMet.containsAll(this.fluidInputs.keySet());
+ return metAllFluid;
+ }
+}