diff --git a/.github/workflows/format_java.yml b/.github/workflows/format_java.yml index e8d233df439..a838fb89497 100644 --- a/.github/workflows/format_java.yml +++ b/.github/workflows/format_java.yml @@ -5,9 +5,7 @@ on: push: branches: - master - paths: ['src/main/java/**', 'src/test/**'] pull_request: - paths: ['src/main/java/**', 'src/test/**'] concurrency: group: formatting-${{ github.head_ref || github.ref }} diff --git a/.github/workflows/test_java.yml b/.github/workflows/test_java.yml index 0faabb0cf0c..5ee8e5d2ed6 100644 --- a/.github/workflows/test_java.yml +++ b/.github/workflows/test_java.yml @@ -6,8 +6,6 @@ on: branches: - master pull_request: - branches: - - '*' concurrency: group: tests-${{ github.head_ref || github.ref }} diff --git a/.github/workflows/validate_gradle_wrapper.yml b/.github/workflows/validate_gradle_wrapper.yml index 8824259410d..f8463eac5e4 100644 --- a/.github/workflows/validate_gradle_wrapper.yml +++ b/.github/workflows/validate_gradle_wrapper.yml @@ -8,8 +8,6 @@ on: paths: - 'gradle/**' pull_request: - branches: - - '*' paths: - 'gradle/**' @@ -26,4 +24,4 @@ jobs: uses: actions/checkout@v4 - name: Validate Gradle Wrapper - uses: gradle/actions/wrapper-validation + uses: gradle/actions/wrapper-validation@v3 diff --git a/dependencies.gradle b/dependencies.gradle index 9011b72660f..845a3af15be 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -41,8 +41,8 @@ dependencies { // Published dependencies api("codechicken:codechickenlib:3.2.3.358") api("com.cleanroommc:modularui:2.4.3") { transitive = false } - api("com.cleanroommc:groovyscript:1.1.0") { transitive = false } - api("CraftTweaker2:CraftTweaker2-MC1120-Main:1.12-4.1.20.698") + api("com.cleanroommc:groovyscript:1.1.1") { transitive = false } + api("CraftTweaker2:CraftTweaker2-MC1120-Main:1.12-4.1.20.700") api("appeng:ae2-uel:v0.56.4") { transitive = false } api rfg.deobf("curse.maven:ctm-267602:2915363") // CTM 1.0.2.31 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 033e24c4cdf..e6441136f3d 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1af9e0930b8..a4413138c96 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index fcb6fca147c..b740cf13397 100755 --- a/gradlew +++ b/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -83,7 +83,8 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -144,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -152,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -201,11 +202,11 @@ fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/gradlew.bat b/gradlew.bat index 6689b85beec..7101f8e4676 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -43,11 +43,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/src/main/java/gregtech/api/capability/IDistillationTower.java b/src/main/java/gregtech/api/capability/IDistillationTower.java new file mode 100644 index 00000000000..e7bf447518b --- /dev/null +++ b/src/main/java/gregtech/api/capability/IDistillationTower.java @@ -0,0 +1,22 @@ +package gregtech.api.capability; + +import gregtech.api.metatileentity.multiblock.IMultiblockPart; + +import net.minecraft.util.math.BlockPos; + +import java.util.List; + +/** + * intended for use in conjunction with {@link gregtech.api.capability.impl.DistillationTowerLogicHandler} + * use with distillation tower type multiblocks + */ +public interface IDistillationTower { + + List getMultiblockParts(); + + BlockPos getPos(); + + void invalidateStructure(); + + boolean allowSameFluidFillForOutputs(); +} diff --git a/src/main/java/gregtech/api/capability/impl/DistillationTowerLogicHandler.java b/src/main/java/gregtech/api/capability/impl/DistillationTowerLogicHandler.java new file mode 100644 index 00000000000..e674db66763 --- /dev/null +++ b/src/main/java/gregtech/api/capability/impl/DistillationTowerLogicHandler.java @@ -0,0 +1,199 @@ +package gregtech.api.capability.impl; + +import gregtech.api.capability.IDistillationTower; +import gregtech.api.capability.IMultipleTankHandler; +import gregtech.api.metatileentity.multiblock.IMultiblockAbilityPart; +import gregtech.api.metatileentity.multiblock.MultiblockAbility; +import gregtech.api.pattern.BlockPattern; +import gregtech.api.util.GTLog; +import gregtech.common.metatileentities.multi.multiblockpart.MetaTileEntityMultiblockPart; + +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.FluidTankInfo; +import net.minecraftforge.fluids.IFluidTank; +import net.minecraftforge.fluids.capability.FluidTankProperties; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fluids.capability.IFluidTankProperties; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * Allows hatchscan behavior to be used on fluid outputs. Not a child of {@link AbstractRecipeLogic} + * for compatibility with other children. + */ +public class DistillationTowerLogicHandler { + + protected final IDistillationTower tower; + + private int layerCount; + private List orderedFluidOutputs; + private IMultipleTankHandler fluidTanks; + + public DistillationTowerLogicHandler(IDistillationTower tower) { + this.tower = tower; + } + + /** + * Applies fluids to outputs on a sorted one fluid -> one hatch basis + * + * @param fluids the fluids to output. Will be automatically trimmed if there are not enough output hatches. + * @param doFill whether the application should be simulated or not. + * @return whether the fluids were successfully applied to the outputs or not. + */ + public boolean applyFluidToOutputs(List fluids, boolean doFill) { + boolean valid = true; + for (int i = 0; i < Math.min(fluids.size(), this.getOrderedFluidOutputs().size()); i++) { + IFluidHandler handler = this.getOrderedFluidOutputs().get(i); + int accepted = handler.fill(fluids.get(i), doFill); + if (accepted != fluids.get(i).amount) valid = false; + if (!doFill && !valid) break; + } + return valid; + } + + /** + * Called on structure formation to determine the number of layers in the distillation tower.
+ *
+ * Needs to be overriden for multiblocks that have different assemblies than the standard distillation tower. + * + * @param structurePattern the structure pattern + */ + public void determineLayerCount(@NotNull BlockPattern structurePattern) { + this.setLayerCount(structurePattern.formedRepetitionCount[1] + 1); + } + + /** + * Called on structure formation to determine the ordered list of fluid handlers in the distillation tower.
+ *
+ * Needs to be overriden for multiblocks that have different assemblies than the standard distillation tower. + */ + public void determineOrderedFluidOutputs() { + // noinspection SimplifyStreamApiCallChains + List fluidExportParts = tower.getMultiblockParts().stream() + .filter(iMultiblockPart -> iMultiblockPart instanceof IMultiblockAbilityPartabilityPart && + abilityPart.getAbility() == MultiblockAbility.EXPORT_FLUIDS && + abilityPart instanceof MetaTileEntityMultiblockPart) + .map(iMultiblockPart -> (MetaTileEntityMultiblockPart) iMultiblockPart) + .collect(Collectors.toList()); + // the fluidExportParts should come sorted in smallest Y first, largest Y last. + List orderedHandlerList = new ObjectArrayList<>(); + List tankList = new ObjectArrayList<>(); + int firstY = tower.getPos().getY() + 1; + int exportIndex = 0; + for (int y = firstY; y < firstY + this.getLayerCount(); y++) { + if (fluidExportParts.size() <= exportIndex) { + orderedHandlerList.add(FakeTank.INSTANCE); + tankList.add(FakeTank.INSTANCE); + continue; + } + MetaTileEntityMultiblockPart part = fluidExportParts.get(exportIndex); + if (part.getPos().getY() == y) { + List hatchTanks = new ObjectArrayList<>(); + // noinspection unchecked + ((IMultiblockAbilityPart) part).registerAbilities(hatchTanks); + orderedHandlerList.add(new FluidTankList(false, hatchTanks)); + tankList.addAll(hatchTanks); + exportIndex++; + } else if (part.getPos().getY() > y) { + orderedHandlerList.add(FakeTank.INSTANCE); + tankList.add(FakeTank.INSTANCE); + } else { + GTLog.logger.error( + "The Distillation Tower at {} had a fluid export hatch with an unexpected Y position.", + tower.getPos()); + tower.invalidateStructure(); + this.setOrderedFluidOutputs(new ObjectArrayList<>()); + this.setFluidTanks(new FluidTankList(false)); + } + } + this.setOrderedFluidOutputs(orderedHandlerList); + this.setFluidTanks(new FluidTankList(tower.allowSameFluidFillForOutputs(), tankList)); + } + + /** + * Should be called on structure invalidation. + */ + public void invalidate() { + this.setLayerCount(0); + this.setOrderedFluidOutputs(null); + } + + protected void setLayerCount(int layerCount) { + this.layerCount = layerCount; + } + + public int getLayerCount() { + return layerCount; + } + + protected void setOrderedFluidOutputs(List orderedFluidOutputs) { + this.orderedFluidOutputs = orderedFluidOutputs; + } + + public List getOrderedFluidOutputs() { + return orderedFluidOutputs; + } + + protected void setFluidTanks(IMultipleTankHandler fluidTanks) { + this.fluidTanks = fluidTanks; + } + + public IMultipleTankHandler getFluidTanks() { + return fluidTanks; + } + + // an endless void devouring any fluid sent to it + protected static class FakeTank implements IFluidHandler, IFluidTank { + + protected static final FakeTank INSTANCE = new FakeTank(); + public static final FluidTankInfo FAKE_TANK_INFO = new FluidTankInfo(null, Integer.MAX_VALUE); + public static final IFluidTankProperties FAKE_TANK_PROPERTIES = new FluidTankProperties(null, Integer.MAX_VALUE, + true, false); + public static final IFluidTankProperties[] FAKE_TANK_PROPERTIES_ARRAY = new IFluidTankProperties[] { + FAKE_TANK_PROPERTIES }; + + @Override + public IFluidTankProperties[] getTankProperties() { + return FAKE_TANK_PROPERTIES_ARRAY; + } + + @Override + public FluidStack getFluid() { + return null; + } + + @Override + public int getFluidAmount() { + return 0; + } + + @Override + public int getCapacity() { + return Integer.MAX_VALUE; + } + + @Override + public FluidTankInfo getInfo() { + return FAKE_TANK_INFO; + } + + @Override + public int fill(FluidStack resource, boolean doFill) { + return resource.amount; + } + + @Override + public FluidStack drain(FluidStack resource, boolean doDrain) { + return null; + } + + @Override + public FluidStack drain(int maxDrain, boolean doDrain) { + return null; + } + } +} diff --git a/src/main/java/gregtech/api/capability/impl/miner/MinerLogic.java b/src/main/java/gregtech/api/capability/impl/miner/MinerLogic.java index 5b1ca454f3d..3439aca4a57 100644 --- a/src/main/java/gregtech/api/capability/impl/miner/MinerLogic.java +++ b/src/main/java/gregtech/api/capability/impl/miner/MinerLogic.java @@ -157,8 +157,10 @@ public void performMining() { // drill a hole beneath the miner and extend the pipe downwards by one WorldServer world = (WorldServer) metaTileEntity.getWorld(); if (mineY.get() < pipeY.get()) { - world.destroyBlock( - new BlockPos(metaTileEntity.getPos().getX(), pipeY.get(), metaTileEntity.getPos().getZ()), false); + var pipePos = new BlockPos(metaTileEntity.getPos().getX(), pipeY.get(), metaTileEntity.getPos().getZ()); + if (world.getTileEntity(pipePos) == null && + world.getBlockState(pipePos).getBlockHardness(world, pipePos) >= 0) + world.destroyBlock(pipePos, false); pipeY.decrementAndGet(); incrementPipeLength(); } diff --git a/src/main/java/gregtech/api/unification/OreDictUnifier.java b/src/main/java/gregtech/api/unification/OreDictUnifier.java index a945fe5b4f5..aeaf123cdb2 100644 --- a/src/main/java/gregtech/api/unification/OreDictUnifier.java +++ b/src/main/java/gregtech/api/unification/OreDictUnifier.java @@ -217,8 +217,13 @@ public static boolean hasOreDictionary(@NotNull ItemStack itemStack, @NotNull St return wildcardNames != null && wildcardNames != names && wildcardNames.contains(oreDictName); } - public static List getAllWithOreDictionaryName(String oreDictionaryName) { - return oreDictNameStacks.get(oreDictionaryName).stream() + public static @NotNull List<@NotNull ItemStack> getAllWithOreDictionaryName(@NotNull String oreDictionaryName) { + var stacks = oreDictNameStacks.get(oreDictionaryName); + if (stacks == null) { + return Collections.emptyList(); + } + + return stacks.stream() .map(ItemStack::copy) .collect(Collectors.toList()); } diff --git a/src/main/java/gregtech/common/items/behaviors/LighterBehaviour.java b/src/main/java/gregtech/common/items/behaviors/LighterBehaviour.java index bdff9524d0d..66941091218 100644 --- a/src/main/java/gregtech/common/items/behaviors/LighterBehaviour.java +++ b/src/main/java/gregtech/common/items/behaviors/LighterBehaviour.java @@ -133,9 +133,11 @@ public EnumActionResult onItemUseFirst(@NotNull EntityPlayer player, @NotNull Wo } BlockPos offset = pos.offset(side); - world.setBlockState(offset, Blocks.FIRE.getDefaultState(), 11); - if (!world.isRemote) { - CriteriaTriggers.PLACED_BLOCK.trigger((EntityPlayerMP) player, offset, stack); + if (world.isAirBlock(offset)) { + world.setBlockState(offset, Blocks.FIRE.getDefaultState(), 11); + if (!world.isRemote) { + CriteriaTriggers.PLACED_BLOCK.trigger((EntityPlayerMP) player, offset, stack); + } } return EnumActionResult.SUCCESS; } diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityDistillationTower.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityDistillationTower.java index 41e1da2ea88..8c8ac6f5407 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityDistillationTower.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityDistillationTower.java @@ -1,11 +1,11 @@ package gregtech.common.metatileentities.multi.electric; +import gregtech.api.capability.IDistillationTower; import gregtech.api.capability.IMultipleTankHandler; -import gregtech.api.capability.impl.FluidTankList; +import gregtech.api.capability.impl.DistillationTowerLogicHandler; import gregtech.api.capability.impl.MultiblockRecipeLogic; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; -import gregtech.api.metatileentity.multiblock.IMultiblockAbilityPart; import gregtech.api.metatileentity.multiblock.IMultiblockPart; import gregtech.api.metatileentity.multiblock.MultiblockAbility; import gregtech.api.metatileentity.multiblock.RecipeMapMultiblockController; @@ -14,7 +14,6 @@ import gregtech.api.pattern.PatternMatchContext; import gregtech.api.recipes.Recipe; import gregtech.api.recipes.RecipeMaps; -import gregtech.api.util.GTLog; import gregtech.api.util.GTTransferUtils; import gregtech.api.util.GTUtility; import gregtech.api.util.RelativeDirection; @@ -23,7 +22,6 @@ import gregtech.client.renderer.texture.Textures; import gregtech.common.blocks.BlockMetalCasing.MetalCasingType; import gregtech.common.blocks.MetaBlocks; -import gregtech.common.metatileentities.multi.multiblockpart.MetaTileEntityMultiblockPart; import gregtech.core.sound.GTSoundEvents; import net.minecraft.block.state.IBlockState; @@ -33,46 +31,46 @@ import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextFormatting; import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.IFluidTank; -import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import net.minecraftforge.items.IItemHandlerModifiable; -import com.cleanroommc.modularui.utils.FluidTankHandler; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jetbrains.annotations.NotNull; import java.util.List; import java.util.function.Function; -import java.util.stream.Collectors; import static gregtech.api.util.RelativeDirection.*; -public class MetaTileEntityDistillationTower extends RecipeMapMultiblockController { +public class MetaTileEntityDistillationTower extends RecipeMapMultiblockController implements IDistillationTower { - private final boolean useAdvHatchLogic; - - protected int layerCount; - protected List orderedFluidOutputs; + protected DistillationTowerLogicHandler handler; + @SuppressWarnings("unused") // backwards compatibility public MetaTileEntityDistillationTower(ResourceLocation metaTileEntityId) { this(metaTileEntityId, false); } public MetaTileEntityDistillationTower(ResourceLocation metaTileEntityId, boolean useAdvHatchLogic) { super(metaTileEntityId, RecipeMaps.DISTILLATION_RECIPES); - this.useAdvHatchLogic = useAdvHatchLogic; if (useAdvHatchLogic) { this.recipeMapWorkable = new DistillationTowerRecipeLogic(this); - } + this.handler = new DistillationTowerLogicHandler(this); + } else this.handler = null; } @Override public MetaTileEntity createMetaTileEntity(IGregTechTileEntity tileEntity) { - return new MetaTileEntityDistillationTower(metaTileEntityId, this.useAdvHatchLogic); + return new MetaTileEntityDistillationTower(metaTileEntityId, this.handler != null); } + /** + * Used if MultiblockPart Abilities need to be sorted a certain way, like + * Distillation Tower and Assembly Line.
+ *
+ * There will be consequences if this is changed. Make sure to set the logic handler to one with + * a properly overriden {@link DistillationTowerLogicHandler#determineOrderedFluidOutputs()} + */ @Override protected Function multiblockPartSorter() { return RelativeDirection.UP.getSorter(getFrontFacing(), getUpwardsFacing(), isFlipped()); @@ -80,7 +78,9 @@ protected Function multiblockPartSorter() { /** * Whether this multi can be rotated or face upwards.
- * There will be consequences if this returns true. Go override {@link #determineOrderedFluidOutputs()} + *
+ * There will be consequences if this returns true. Make sure to set the logic handler to one with + * a properly overriden {@link DistillationTowerLogicHandler#determineOrderedFluidOutputs()} */ @Override public boolean allowsExtendedFacing() { @@ -106,68 +106,15 @@ protected void addDisplayText(List textList) { @Override protected void formStructure(PatternMatchContext context) { super.formStructure(context); - if (!useAdvHatchLogic || this.structurePattern == null) return; - this.layerCount = determineLayerCount(this.structurePattern); - this.orderedFluidOutputs = determineOrderedFluidOutputs(); - } - - /** - * Needs to be overriden for multiblocks that have different assemblies than the standard distillation tower. - * - * @param structurePattern the structure pattern - * @return the number of layers that could hold output hatches - */ - protected int determineLayerCount(@NotNull BlockPattern structurePattern) { - return structurePattern.formedRepetitionCount[1] + 1; - } - - /** - * Needs to be overriden for multiblocks that have different assemblies than the standard distillation tower. - * - * @return the fluid hatches of the multiblock, in order, with null entries for layers that do not have hatches. - */ - protected List determineOrderedFluidOutputs() { - List fluidExportParts = this.getMultiblockParts().stream() - .filter(iMultiblockPart -> iMultiblockPart instanceof IMultiblockAbilityPartabilityPart && - abilityPart.getAbility() == MultiblockAbility.EXPORT_FLUIDS && - abilityPart instanceof MetaTileEntityMultiblockPart) - .map(iMultiblockPart -> (MetaTileEntityMultiblockPart) iMultiblockPart) - .collect(Collectors.toList()); - // the fluidExportParts should come sorted in smallest Y first, largest Y last. - List orderedHandlerList = new ObjectArrayList<>(); - int firstY = this.getPos().getY() + 1; - int exportIndex = 0; - for (int y = firstY; y < firstY + this.layerCount; y++) { - if (fluidExportParts.size() <= exportIndex) { - orderedHandlerList.add(null); - continue; - } - MetaTileEntityMultiblockPart part = fluidExportParts.get(exportIndex); - if (part.getPos().getY() == y) { - List hatchTanks = new ObjectArrayList<>(); - // noinspection unchecked - ((IMultiblockAbilityPart) part).registerAbilities(hatchTanks); - if (hatchTanks.size() == 1) - orderedHandlerList.add(FluidTankHandler.getTankFluidHandler(hatchTanks.get(0))); - else orderedHandlerList.add(new FluidTankList(false, hatchTanks)); - exportIndex++; - } else if (part.getPos().getY() > y) { - orderedHandlerList.add(null); - } else { - GTLog.logger.error("The Distillation Tower at " + this.getPos() + - " had a fluid export hatch with an unexpected Y position."); - this.invalidateStructure(); - return new ObjectArrayList<>(); - } - } - return orderedHandlerList; + if (this.handler == null || this.structurePattern == null) return; + handler.determineLayerCount(this.structurePattern); + handler.determineOrderedFluidOutputs(); } @Override public void invalidateStructure() { super.invalidateStructure(); - this.layerCount = 0; - this.orderedFluidOutputs = null; + if (this.handler != null) handler.invalidate(); } @Override @@ -189,7 +136,7 @@ public void invalidateStructure() { } @Override - protected boolean allowSameFluidFillForOutputs() { + public boolean allowSameFluidFillForOutputs() { return false; } @@ -217,7 +164,8 @@ protected ICubeRenderer getFrontOverlay() { @Override public int getFluidOutputLimit() { - return this.layerCount; + if (this.handler != null) return this.handler.getLayerCount(); + else return super.getFluidOutputLimit(); } protected class DistillationTowerRecipeLogic extends MultiblockRecipeLogic { @@ -226,24 +174,10 @@ public DistillationTowerRecipeLogic(MetaTileEntityDistillationTower tileEntity) super(tileEntity); } - protected boolean applyFluidToOutputs(List fluids, boolean doFill) { - boolean valid = true; - for (int i = 0; i < fluids.size(); i++) { - IFluidHandler handler = orderedFluidOutputs.get(i); - // void if no hatch is found on that fluid's layer - // this is considered trimming and thus ignores canVoid - if (handler == null) continue; - int accepted = handler.fill(fluids.get(i), doFill); - if (accepted != fluids.get(i).amount) valid = false; - if (!doFill && !valid) break; - } - return valid; - } - @Override protected void outputRecipeOutputs() { GTTransferUtils.addItemsToItemHandler(getOutputInventory(), false, itemOutputs); - this.applyFluidToOutputs(fluidOutputs, true); + handler.applyFluidToOutputs(fluidOutputs, true); } @Override @@ -268,9 +202,9 @@ protected boolean setupAndConsumeRecipeInputs(@NotNull Recipe recipe, return false; } - // Perform layerwise fluid checks + // We have already trimmed fluid outputs at this time if (!metaTileEntity.canVoidRecipeFluidOutputs() && - !this.applyFluidToOutputs(recipe.getAllFluidOutputs(), false)) { + !handler.applyFluidToOutputs(recipe.getAllFluidOutputs(), false)) { this.isOutputsFull = true; return false; } @@ -282,5 +216,10 @@ protected boolean setupAndConsumeRecipeInputs(@NotNull Recipe recipe, } return false; } + + @Override + protected IMultipleTankHandler getOutputTank() { + return handler.getFluidTanks(); + } } } diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityHPCA.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityHPCA.java index 06f8286d8ff..0345a985bd8 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityHPCA.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityHPCA.java @@ -167,7 +167,7 @@ protected void updateFormedValid() { } private void consumeEnergy() { - int energyToConsume = hpcaHandler.getCurrentEUt(); + long energyToConsume = hpcaHandler.getCurrentEUt(); boolean hasMaintenance = ConfigHolder.machines.enableMaintenance && hasMaintenanceMechanics(); if (hasMaintenance) { // 10% more energy per maintenance problem @@ -377,7 +377,7 @@ protected ModularUI.Builder createUITemplate(EntityPlayer entityPlayer) { protected void addDisplayText(List textList) { MultiblockDisplayText.builder(textList, isStructureFormed()) .setWorkingStatus(true, hpcaHandler.getAllocatedCWUt() > 0) // transform into two-state system for - // display + // display .setWorkingStatusKeys( "gregtech.multiblock.idling", "gregtech.multiblock.idling", @@ -580,7 +580,7 @@ public static class HPCAGridHandler { // cached gui info // holding these values past the computation clear because GUI is too "late" to read the state in time - private int cachedEUt; + private long cachedEUt; private int cachedCWUt; public HPCAGridHandler(@Nullable MetaTileEntityHPCA controller) { @@ -760,10 +760,10 @@ public int getMaxCWUt() { } /** The current EU/t this HPCA should use, considering passive drain, current computation, etc.. */ - public int getCurrentEUt() { + public long getCurrentEUt() { int maximumCWUt = Math.max(1, getMaxCWUt()); // behavior is no different setting this to 1 if it is 0 - int maximumEUt = getMaxEUt(); - int upkeepEUt = getUpkeepEUt(); + long maximumEUt = getMaxEUt(); + long upkeepEUt = getUpkeepEUt(); if (maximumEUt == upkeepEUt) { return maximumEUt; @@ -775,8 +775,8 @@ public int getCurrentEUt() { } /** The amount of EU/t this HPCA uses just to stay on with 0 output computation. */ - public int getUpkeepEUt() { - int upkeepEUt = 0; + public long getUpkeepEUt() { + long upkeepEUt = 0; for (var component : components) { upkeepEUt += component.getUpkeepEUt(); } @@ -784,8 +784,8 @@ public int getUpkeepEUt() { } /** The maximum EU/t that this HPCA could ever use with the given configuration. */ - public int getMaxEUt() { - int maximumEUt = 0; + public long getMaxEUt() { + long maximumEUt = 0; for (var component : components) { maximumEUt += component.getMaxEUt(); } diff --git a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityDrum.java b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityDrum.java index 7a5ef5b4d38..2292338425f 100644 --- a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityDrum.java +++ b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityDrum.java @@ -9,7 +9,6 @@ import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.recipes.ModHandler; import gregtech.api.unification.material.Material; -import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.api.unification.material.properties.PropertyKey; import gregtech.api.util.GTUtility; import gregtech.client.renderer.texture.Textures; @@ -54,26 +53,59 @@ public class MetaTileEntityDrum extends MetaTileEntity { + private final IPropertyFluidFilter fluidFilter; + private final boolean isWood; + private final int color; private final int tankSize; - private final Material material; + private FilteredFluidHandler fluidTank; private boolean isAutoOutput = false; - public MetaTileEntityDrum(ResourceLocation metaTileEntityId, Material material, int tankSize) { + /** + * @param metaTileEntityId the id for the MTE + * @param material the material the drum is made of, must have + * {@link gregtech.api.unification.material.properties.FluidProperty}. + * @param tankSize the size of the storage tank + */ + public MetaTileEntityDrum(ResourceLocation metaTileEntityId, @NotNull Material material, int tankSize) { super(metaTileEntityId); + IPropertyFluidFilter filter = material.getProperty(PropertyKey.FLUID_PIPE); + if (filter == null) { + throw new IllegalArgumentException("Material " + material + " requires FluidPipeProperty for Drums"); + } + this.fluidFilter = filter; + this.isWood = ModHandler.isMaterialWood(material); + this.color = material.getMaterialRGB(); + this.tankSize = tankSize; + initializeInventory(); + } + + /** + * + * @param metaTileEntityId the id for the MTE + * @param fluidFilter the filter for which fluids can be stored + * @param isWood if the drum is made of wood + * @param color the color of the drum in RGB format + * @param tankSize the size of the storage tank + */ + public MetaTileEntityDrum(ResourceLocation metaTileEntityId, @NotNull IPropertyFluidFilter fluidFilter, + boolean isWood, int color, int tankSize) { + super(metaTileEntityId); + this.fluidFilter = fluidFilter; + this.isWood = isWood; + this.color = color; this.tankSize = tankSize; - this.material = material; initializeInventory(); } @Override public MetaTileEntity createMetaTileEntity(IGregTechTileEntity tileEntity) { - return new MetaTileEntityDrum(metaTileEntityId, material, tankSize); + return new MetaTileEntityDrum(metaTileEntityId, fluidFilter, isWood, color, tankSize); } @Override public String getHarvestTool() { - return ModHandler.isMaterialWood(material) ? ToolClasses.AXE : ToolClasses.WRENCH; + return isWood ? ToolClasses.AXE : ToolClasses.WRENCH; } @Override @@ -83,14 +115,14 @@ public boolean hasFrontFacing() { @Override protected void initializeInventory() { - if (this.material == null) return; // call before field initialization, should be called later with fields set - super.initializeInventory(); - IPropertyFluidFilter filter = this.material.getProperty(PropertyKey.FLUID_PIPE); - if (filter == null) { - throw new IllegalArgumentException( - String.format("Material %s requires FluidPipeProperty for Drums", material)); + // call before field initialization, should be called later with fields set + if (this.fluidFilter == null) { + return; } - this.fluidInventory = this.fluidTank = new FilteredFluidHandler(tankSize).setFilter(filter); + + super.initializeInventory(); + this.fluidTank = new FilteredFluidHandler(tankSize).setFilter(this.fluidFilter); + this.fluidInventory = this.fluidTank; } @Override @@ -203,27 +235,26 @@ private void toggleOutput() { @Override @SideOnly(Side.CLIENT) public Pair getParticleTexture() { - if (ModHandler.isMaterialWood(material)) { + if (isWood) { return Pair.of(Textures.WOODEN_DRUM.getParticleTexture(), getPaintingColorForRendering()); } else { - int color = ColourRGBA.multiply( - GTUtility.convertRGBtoOpaqueRGBA_CL(material.getMaterialRGB()), - GTUtility.convertRGBtoOpaqueRGBA_CL(getPaintingColorForRendering())); - color = GTUtility.convertOpaqueRGBA_CLtoRGB(color); + int color = GTUtility.convertOpaqueRGBA_CLtoRGB(ColourRGBA.multiply( + GTUtility.convertRGBtoOpaqueRGBA_CL(this.color), + GTUtility.convertRGBtoOpaqueRGBA_CL(getPaintingColorForRendering()))); return Pair.of(Textures.DRUM.getParticleTexture(), color); } } @Override public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, IVertexOperation[] pipeline) { - if (ModHandler.isMaterialWood(material)) { + if (isWood) { ColourMultiplier multiplier = new ColourMultiplier( GTUtility.convertRGBtoOpaqueRGBA_CL(getPaintingColorForRendering())); Textures.WOODEN_DRUM.render(renderState, translation, ArrayUtils.add(pipeline, multiplier), getFrontFacing()); } else { ColourMultiplier multiplier = new ColourMultiplier( - ColourRGBA.multiply(GTUtility.convertRGBtoOpaqueRGBA_CL(material.getMaterialRGB()), + ColourRGBA.multiply(GTUtility.convertRGBtoOpaqueRGBA_CL(this.color), GTUtility.convertRGBtoOpaqueRGBA_CL(getPaintingColorForRendering()))); Textures.DRUM.render(renderState, translation, ArrayUtils.add(pipeline, multiplier), getFrontFacing()); Textures.DRUM_OVERLAY.render(renderState, translation, pipeline); @@ -243,8 +274,7 @@ public int getDefaultPaintingColor() { @SideOnly(Side.CLIENT) public void addInformation(ItemStack stack, @Nullable World player, List tooltip, boolean advanced) { tooltip.add(I18n.format("gregtech.universal.tooltip.fluid_storage_capacity", tankSize)); - FluidPipeProperties pipeProperties = material.getProperty(PropertyKey.FLUID_PIPE); - pipeProperties.appendTooltips(tooltip, true, true); + this.fluidFilter.appendTooltips(tooltip, true, true); if (TooltipHelper.isShiftDown()) { tooltip.add(I18n.format("gregtech.tool_action.screwdriver.access_covers")); diff --git a/src/main/java/gregtech/integration/forestry/mutation/MaterialMutationCondition.java b/src/main/java/gregtech/integration/forestry/mutation/MaterialMutationCondition.java index a4ea54cdf23..c063f0fbed8 100644 --- a/src/main/java/gregtech/integration/forestry/mutation/MaterialMutationCondition.java +++ b/src/main/java/gregtech/integration/forestry/mutation/MaterialMutationCondition.java @@ -2,6 +2,8 @@ import gregtech.api.unification.OreDictUnifier; import gregtech.api.unification.material.Material; +import gregtech.api.unification.ore.OrePrefix; +import gregtech.api.unification.stack.UnificationEntry; import gregtech.api.util.LocalizationUtils; import net.minecraft.block.Block; @@ -19,22 +21,21 @@ import forestry.api.genetics.IGenome; import forestry.api.genetics.IMutationCondition; import forestry.core.tiles.TileUtil; +import org.jetbrains.annotations.NotNull; import java.util.HashSet; import java.util.Set; -import static org.apache.commons.lang3.StringUtils.capitalize; - public class MaterialMutationCondition implements IMutationCondition { - private final Set acceptedBlocks = new HashSet(); + private final Set acceptedBlocks = new HashSet<>(); private final String displayName; - public MaterialMutationCondition(Material material) { + public MaterialMutationCondition(@NotNull Material material) { this.displayName = LocalizationUtils.format("gregtech.mutation.block_of", material.getLocalizedName()); - String oredictName = "block" + capitalize(material.getName()); + String oreDictName = new UnificationEntry(OrePrefix.block, material).toString(); - for (ItemStack ore : OreDictUnifier.getAllWithOreDictionaryName(oredictName)) { + for (ItemStack ore : OreDictUnifier.getAllWithOreDictionaryName(oreDictName)) { if (!ore.isEmpty()) { Item oreItem = ore.getItem(); Block oreBlock = Block.getBlockFromItem(oreItem); @@ -45,8 +46,10 @@ public MaterialMutationCondition(Material material) { } } - public float getChance(World world, BlockPos pos, IAllele allele0, IAllele allele1, IGenome genome0, - IGenome genome1, IClimateProvider climate) { + @Override + public float getChance(@NotNull World world, @NotNull BlockPos pos, @NotNull IAllele allele0, + @NotNull IAllele allele1, @NotNull IGenome genome0, + @NotNull IGenome genome1, @NotNull IClimateProvider climate) { TileEntity tile; do { pos = pos.down(); @@ -57,7 +60,8 @@ public float getChance(World world, BlockPos pos, IAllele allele0, IAllele allel return this.acceptedBlocks.contains(blockState) ? 1.0F : 0.0F; } - public String getDescription() { + @Override + public @NotNull String getDescription() { return LocalizationUtils.format("for.mutation.condition.resource", this.displayName); } } diff --git a/src/test/java/gregtech/common/metatileentities/multiblock/hpca/HPCATest.java b/src/test/java/gregtech/common/metatileentities/multiblock/hpca/HPCATest.java index 3542313a3f0..fab2e1dbcd5 100644 --- a/src/test/java/gregtech/common/metatileentities/multiblock/hpca/HPCATest.java +++ b/src/test/java/gregtech/common/metatileentities/multiblock/hpca/HPCATest.java @@ -30,16 +30,16 @@ public void Test_Edge_No_Computation() { .coolingAmount(4))); final int maxCWUt = handler.getMaxCWUt(); - final int upkeepEUt = handler.getUpkeepEUt(); - final int maxEUt = handler.getMaxEUt(); + final long upkeepEUt = handler.getUpkeepEUt(); + final long maxEUt = handler.getMaxEUt(); final int maxCoolingDemand = handler.getMaxCoolantDemand(); final int maxCoolingAmount = handler.getMaxCoolingAmount(); int allocated; double temperatureChange; assertThat(maxCWUt, is(0)); - assertThat(upkeepEUt, is(32 * 4)); - assertThat(maxEUt, is(128 * 4)); + assertThat(upkeepEUt, is(32L * 4L)); + assertThat(maxEUt, is(128L * 4L)); assertThat(maxCoolingDemand, is(0)); assertThat(maxCoolingAmount, is(4 * 4)); @@ -69,14 +69,14 @@ public void Test_Edge_Equal_Upkeep_Max_EUt() { .coolingAmount(2))); final int maxCWUt = handler.getMaxCWUt(); - final int upkeepEUt = handler.getUpkeepEUt(); - final int maxEUt = handler.getMaxEUt(); + final long upkeepEUt = handler.getUpkeepEUt(); + final long maxEUt = handler.getMaxEUt(); final int maxCoolingDemand = handler.getMaxCoolingDemand(); final int maxCoolingAmount = handler.getMaxCoolingAmount(); int allocated, requested; double temperatureChange; - final int FIXED_EUT = 32 * 8; + final long FIXED_EUT = 32 * 8; assertThat(maxCWUt, is(4 * 4)); assertThat(upkeepEUt, is(FIXED_EUT)); assertThat(maxEUt, is(FIXED_EUT)); @@ -115,12 +115,13 @@ public void Test_Random() { .EUt(() -> r.nextInt(128)) .coolingAmount(() -> r.nextInt(128)))); - final int maxEUt = handler.getMaxEUt(); - final int upkeepEUt = handler.getUpkeepEUt(); + final long maxEUt = handler.getMaxEUt(); + final long upkeepEUt = handler.getUpkeepEUt(); final int maxCWUt = handler.getMaxCWUt(); final int maxCoolingDemand = handler.getMaxCoolingDemand(); final int maxCoolingAmount = handler.getMaxCoolingAmount(); - int allocated, requested, currentEUt; + int allocated, requested; + long currentEUt; double temperatureChange; // exit, we unit test these edge cases elsewhere