diff options
135 files changed, 7992 insertions, 4570 deletions
diff --git a/src/main/java/gregtech/GT_Mod.java b/src/main/java/gregtech/GT_Mod.java index 59ee674e75..645702055b 100644 --- a/src/main/java/gregtech/GT_Mod.java +++ b/src/main/java/gregtech/GT_Mod.java @@ -61,7 +61,6 @@ import gregtech.api.enums.Textures; import gregtech.api.gui.modularui.GT_UIInfos; import gregtech.api.interfaces.internal.IGT_Mod; import gregtech.api.metatileentity.BaseMetaPipeEntity; -import gregtech.api.objects.GT_ItemStack; import gregtech.api.objects.ItemData; import gregtech.api.objects.XSTR; import gregtech.api.recipe.RecipeMaps; @@ -76,6 +75,7 @@ import gregtech.api.util.GT_Recipe; import gregtech.api.util.GT_RecipeRegistrator; import gregtech.api.util.GT_SpawnEventHandler; import gregtech.api.util.GT_Utility; +import gregtech.api.util.item.ItemHolder; import gregtech.common.GT_DummyWorld; import gregtech.common.GT_Network; import gregtech.common.GT_Proxy; @@ -286,7 +286,9 @@ public class GT_Mod implements IGT_Mod { new GT_Loader_ItemData().run(); new GT_Loader_Item_Block_And_Fluid().run(); new GT_Loader_MetaTileEntities().run(); - new GT_Loader_MultiTileEntities().run(); + if (GT_Values.enableMultiTileEntities) { + new GT_Loader_MultiTileEntities().run(); + } new GT_Loader_CircuitBehaviors().run(); new GT_CoverBehaviorLoader().run(); @@ -794,10 +796,10 @@ public class GT_Mod implements IGT_Mod { GT_Utility.reInit(); GT_Recipe.reInit(); try { - for (Map<? extends GT_ItemStack, ?> gt_itemStackMap : GregTech_API.sItemStackMappings) { + for (Map<? extends ItemHolder, ?> gt_itemStackMap : GregTech_API.sItemStackMappings) { GT_Utility.reMap(gt_itemStackMap); } - for (SetMultimap<? extends GT_ItemStack, ?> gt_itemStackMap : GregTech_API.itemStackMultiMaps) { + for (SetMultimap<? extends ItemHolder, ?> gt_itemStackMap : GregTech_API.itemStackMultiMaps) { GT_Utility.reMap(gt_itemStackMap); } } catch (Throwable e) { 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; + } +} diff --git a/src/main/java/gregtech/common/GT_Proxy.java b/src/main/java/gregtech/common/GT_Proxy.java index 31f7bf4943..24e8b9d271 100644 --- a/src/main/java/gregtech/common/GT_Proxy.java +++ b/src/main/java/gregtech/common/GT_Proxy.java @@ -139,7 +139,6 @@ import gregtech.api.enums.TierEU; import gregtech.api.enums.ToolDictNames; import gregtech.api.fluid.GT_FluidFactory; import gregtech.api.interfaces.IBlockOnWalkOver; -import gregtech.api.interfaces.IGlobalWirelessEnergy; import gregtech.api.interfaces.IProjectileItem; import gregtech.api.interfaces.IToolStats; import gregtech.api.interfaces.internal.IGT_Mod; @@ -176,7 +175,7 @@ import gregtech.common.misc.GlobalEnergyWorldSavedData; import gregtech.common.misc.GlobalMetricsCoverDatabase; import gregtech.common.misc.spaceprojects.SpaceProjectWorldSavedData; -public abstract class GT_Proxy implements IGT_Mod, IGuiHandler, IFuelHandler, IGlobalWirelessEnergy { +public abstract class GT_Proxy implements IGT_Mod, IGuiHandler, IFuelHandler { private static final EnumSet<OreGenEvent.GenerateMinable.EventType> PREVENTED_ORES = EnumSet.of( OreGenEvent.GenerateMinable.EventType.COAL, diff --git a/src/main/java/gregtech/common/covers/GT_Cover_Pump.java b/src/main/java/gregtech/common/covers/GT_Cover_Pump.java index c19f9d0d3a..a31a18c821 100644 --- a/src/main/java/gregtech/common/covers/GT_Cover_Pump.java +++ b/src/main/java/gregtech/common/covers/GT_Cover_Pump.java @@ -45,33 +45,35 @@ public class GT_Cover_Pump extends GT_CoverBehavior { return aCoverVariable; } } - if ((aTileEntity instanceof IFluidHandler)) { - final IFluidHandler tTank2 = aTileEntity.getITankContainerAtSide(side); - if (tTank2 != null) { - // aTileEntity.decreaseStoredEnergyUnits(GT_Utility.getTier(this.mTransferRate), true); - final IFluidHandler tTank1 = (IFluidHandler) aTileEntity; - if (aCoverVariable % 2 == 0) { - FluidStack tLiquid = tTank1.drain(side, this.mTransferRate, false); - if (tLiquid != null) { - tLiquid = tLiquid.copy(); - tLiquid.amount = tTank2.fill(side.getOpposite(), tLiquid, false); - if (tLiquid.amount > 0 && canTransferFluid(tLiquid)) { - tTank2.fill(side.getOpposite(), tTank1.drain(side, tLiquid.amount, true), true); - } - } - } else { - FluidStack tLiquid = tTank2.drain(side.getOpposite(), this.mTransferRate, false); - if (tLiquid != null) { - tLiquid = tLiquid.copy(); - tLiquid.amount = tTank1.fill(side, tLiquid, false); - if (tLiquid.amount > 0 && canTransferFluid(tLiquid)) { - tTank1.fill(side, tTank2.drain(side.getOpposite(), tLiquid.amount, true), true); - } - } + + if (aTileEntity instanceof IFluidHandler current) { + final IFluidHandler toAccess = aTileEntity.getITankContainerAtSide(side); + transferFluid(current, toAccess, side, aCoverVariable % 2); + } + return aCoverVariable; + } + + protected void transferFluid(IFluidHandler current, IFluidHandler toAccess, ForgeDirection side, + int exportOrImport) { + if (exportOrImport == 0) { + FluidStack liquid = current.drain(side, this.mTransferRate, false); + if (liquid != null) { + liquid = liquid.copy(); + liquid.amount = toAccess.fill(side.getOpposite(), liquid, false); + if (liquid.amount > 0 && canTransferFluid(liquid)) { + toAccess.fill(side.getOpposite(), current.drain(side, liquid.amount, true), true); } } + return; + } + FluidStack liquid = toAccess.drain(side.getOpposite(), this.mTransferRate, false); + if (liquid != null) { + liquid = liquid.copy(); + liquid.amount = current.fill(side, liquid, false); + if (liquid.amount > 0 && canTransferFluid(liquid)) { + current.fill(side, toAccess.drain(side.getOpposite(), liquid.amount, true), true); + } } - return aCoverVariable; } protected boolean canTransferFluid(FluidStack fluid) { diff --git a/src/main/java/gregtech/common/gui/ComplexParallelMachineGUIProvider.java b/src/main/java/gregtech/common/gui/ComplexParallelMachineGUIProvider.java new file mode 100644 index 0000000000..89b42c8500 --- /dev/null +++ b/src/main/java/gregtech/common/gui/ComplexParallelMachineGUIProvider.java @@ -0,0 +1,32 @@ +package gregtech.common.gui; + +import javax.annotation.Nonnull; + +import com.gtnewhorizons.modularui.api.screen.ModularWindow.Builder; +import com.gtnewhorizons.modularui.api.screen.UIBuildContext; + +import gregtech.api.gui.GUIHost; +import gregtech.api.logic.ComplexParallelProcessingLogic; +import gregtech.api.logic.interfaces.PowerLogicHost; +import gregtech.api.logic.interfaces.ProcessingLogicHost; + +/** + * Default GUI class for machines with complex parallel + */ +public class ComplexParallelMachineGUIProvider<T extends GUIHost & ProcessingLogicHost<? extends ComplexParallelProcessingLogic<?>> & PowerLogicHost> + extends MachineGUIProvider<T> { + + public ComplexParallelMachineGUIProvider(@Nonnull T host) { + super(host); + } + + @Override + protected void attachSynchHandlers(@Nonnull Builder builder, @Nonnull UIBuildContext uiContext) { + + } + + @Override + protected void addWidgets(@Nonnull Builder builder, @Nonnull UIBuildContext uiContext) { + + } +} diff --git a/src/main/java/gregtech/common/gui/MachineGUIProvider.java b/src/main/java/gregtech/common/gui/MachineGUIProvider.java new file mode 100644 index 0000000000..91d14c209a --- /dev/null +++ b/src/main/java/gregtech/common/gui/MachineGUIProvider.java @@ -0,0 +1,498 @@ +package gregtech.common.gui; + +import static gregtech.api.metatileentity.BaseTileEntity.BUTTON_FORBIDDEN_TOOLTIP; +import static gregtech.api.metatileentity.BaseTileEntity.TOOLTIP_DELAY; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; + +import javax.annotation.Nonnull; + +import net.minecraft.util.StatCollector; + +import com.gtnewhorizons.modularui.api.ModularUITextures; +import com.gtnewhorizons.modularui.api.drawable.IDrawable; +import com.gtnewhorizons.modularui.api.drawable.ItemDrawable; +import com.gtnewhorizons.modularui.api.drawable.UITexture; +import com.gtnewhorizons.modularui.api.math.Pos2d; +import com.gtnewhorizons.modularui.api.screen.ModularWindow.Builder; +import com.gtnewhorizons.modularui.api.screen.UIBuildContext; +import com.gtnewhorizons.modularui.api.widget.IWidgetBuilder; +import com.gtnewhorizons.modularui.api.widget.Widget; +import com.gtnewhorizons.modularui.common.widget.ButtonWidget; +import com.gtnewhorizons.modularui.common.widget.DrawableWidget; +import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget; +import com.gtnewhorizons.modularui.common.widget.MultiChildWidget; +import com.gtnewhorizons.modularui.common.widget.TabButton; +import com.gtnewhorizons.modularui.common.widget.TabContainer; +import com.gtnewhorizons.modularui.common.widget.TextWidget; + +import gregtech.api.enums.InventoryType; +import gregtech.api.enums.SoundResource; +import gregtech.api.enums.VoidingMode; +import gregtech.api.gui.GUIHost; +import gregtech.api.gui.GUIProvider; +import gregtech.api.gui.modularui.GT_UITextures; +import gregtech.api.gui.modularui.GUITextureSet; +import gregtech.api.logic.MuTEProcessingLogic; +import gregtech.api.logic.PowerLogic; +import gregtech.api.logic.interfaces.PowerLogicHost; +import gregtech.api.logic.interfaces.ProcessingLogicHost; + +/** + * Default GUI a machine will use to show its information + */ +public class MachineGUIProvider<T extends GUIHost & ProcessingLogicHost<? extends MuTEProcessingLogic<?>> & PowerLogicHost> + extends GUIProvider<T> { + + private static final int LOGO_SIZE = 17; + @Nonnull + protected static final Pos2d POWER_SWITCH_BUTTON_DEFAULT_POS = new Pos2d(144, 0); + @Nonnull + protected static final Pos2d VOIDING_MODE_BUTTON_DEFAULT_POS = new Pos2d(54, 0); + @Nonnull + protected static final Pos2d INPUT_SEPARATION_BUTTON_DEFAULT_POS = new Pos2d(36, 0); + @Nonnull + protected static final Pos2d BATCH_MODE_BUTTON_DEFAULT_POS = new Pos2d(18, 0); + @Nonnull + protected static final Pos2d RECIPE_LOCKING_BUTTON_DEFAULT_POS = new Pos2d(0, 0); + + public MachineGUIProvider(@Nonnull T host) { + super(host); + } + + @Override + protected void attachSynchHandlers(@Nonnull Builder builder, @Nonnull UIBuildContext uiContext) { + + } + + @Override + protected void addWidgets(@Nonnull Builder builder, @Nonnull UIBuildContext uiContext) { + int page = 0; + builder.setBackground(GT_UITextures.BACKGROUND_SINGLEBLOCK_DEFAULT); + MultiChildWidget mainTab = new MultiChildWidget(); + mainTab.setSize(host.getWidth(), host.getHeight()); + createMainTab(mainTab, builder, uiContext); + TabContainer tabs = new TabContainer().setButtonSize(20, 24); + tabs.addTabButton( + new TabButton(page++) + .setBackground( + false, + ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0, 1f, 0.5f), + new ItemDrawable(host.getAsItem()).withFixedSize(16, 16) + .withOffset(2, 4)) + .setBackground( + true, + ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0.5f, 1f, 1f), + new ItemDrawable(host.getAsItem()).withFixedSize(16, 16) + .withOffset(2, 4)) + .addTooltip(host.getMachineName()) + .setPos(20 * (page - 1), -20)) + .addPage(mainTab); + if (host.hasItemInput()) { + MultiChildWidget itemInputTab = new MultiChildWidget(); + itemInputTab.setSize(host.getWidth(), host.getHeight()); + createItemInputTab(itemInputTab, builder, uiContext); + tabs.addTabButton( + new TabButton(page++) + .setBackground( + false, + ModularUITextures.VANILLA_TAB_TOP_MIDDLE.getSubArea(0, 0, 1f, 0.5f), + GT_UITextures.PICTURE_ITEM_IN.withFixedSize(16, 16) + .withOffset(2, 4)) + .setBackground( + true, + ModularUITextures.VANILLA_TAB_TOP_MIDDLE.getSubArea(0, 0.5f, 1f, 1f), + GT_UITextures.PICTURE_ITEM_IN.withFixedSize(16, 16) + .withOffset(2, 4)) + .addTooltip("Item Input Inventory") + .setPos(20 * (page - 1), -20)) + .addPage(itemInputTab.addChild(getLogo().setPos(147, 86))); + } + + if (host.hasItemOutput()) { + MultiChildWidget itemOutputTab = new MultiChildWidget(); + itemOutputTab.setSize(host.getWidth(), host.getHeight()); + createItemOutputTab(itemOutputTab, builder, uiContext); + tabs.addTabButton( + new TabButton(page++) + .setBackground( + false, + ModularUITextures.VANILLA_TAB_TOP_MIDDLE.getSubArea(0, 0, 1f, 0.5f), + GT_UITextures.PICTURE_ITEM_OUT.withFixedSize(16, 16) + .withOffset(2, 4)) + .setBackground( + true, + ModularUITextures.VANILLA_TAB_TOP_MIDDLE.getSubArea(0, 0.5f, 1f, 1f), + GT_UITextures.PICTURE_ITEM_OUT.withFixedSize(16, 16) + .withOffset(2, 4)) + .addTooltip("Item Output Inventory") + .setPos(20 * (page - 1), -20)) + .addPage(itemOutputTab.addChild(getLogo().setPos(147, 86))); + } + + if (host.hasFluidInput()) { + MultiChildWidget fluidInputTab = new MultiChildWidget(); + fluidInputTab.setSize(host.getWidth(), host.getHeight()); + createFluidInputTab(fluidInputTab, builder, uiContext); + tabs.addTabButton( + new TabButton(page++) + .setBackground( + false, + ModularUITextures.VANILLA_TAB_TOP_MIDDLE.getSubArea(0, 0, 1f, 0.5f), + GT_UITextures.PICTURE_FLUID_IN.withFixedSize(16, 16) + .withOffset(2, 4)) + .setBackground( + true, + ModularUITextures.VANILLA_TAB_TOP_MIDDLE.getSubArea(0, 0.5f, 1f, 1f), + GT_UITextures.PICTURE_FLUID_IN.withFixedSize(16, 16) + .withOffset(2, 4)) + .addTooltip("Fluid Input Tanks") + .setPos(20 * (page - 1), -20)) + .addPage(fluidInputTab.addChild(getLogo().setPos(147, 86))); + } + + if (host.hasFluidOutput()) { + MultiChildWidget fluidOutputTab = new MultiChildWidget(); + fluidOutputTab.setSize(host.getWidth(), host.getHeight()); + createFluidOutputTab(fluidOutputTab, builder, uiContext); + tabs.addTabButton( + new TabButton(page++) + .setBackground( + false, + ModularUITextures.VANILLA_TAB_TOP_MIDDLE.getSubArea(0, 0, 1f, 0.5f), + GT_UITextures.PICTURE_FLUID_OUT.withFixedSize(16, 16) + .withOffset(2, 4)) + .setBackground( + true, + ModularUITextures.VANILLA_TAB_TOP_MIDDLE.getSubArea(0, 0.5f, 1f, 1f), + GT_UITextures.PICTURE_FLUID_OUT.withFixedSize(16, 16) + .withOffset(2, 4)) + .addTooltip("Fluid Output Tanks") + .setPos(20 * (page - 1), -20)) + .addPage(fluidOutputTab.addChild(getLogo().setPos(147, 86))); + } + MultiChildWidget powerInfoTab = new MultiChildWidget(); + powerInfoTab.setSize(host.getWidth(), host.getHeight()); + createPowerTab(powerInfoTab, builder, uiContext); + tabs.addTabButton( + new TabButton(page++) + .setBackground( + false, + ModularUITextures.VANILLA_TAB_TOP_MIDDLE.getSubArea(0, 0, 1f, 0.5f), + GT_UITextures.PICTURE_FLUID_OUT.withFixedSize(16, 16) + .withOffset(2, 4)) + .setBackground( + true, + ModularUITextures.VANILLA_TAB_TOP_MIDDLE.getSubArea(0, 0.5f, 1f, 1f), + GT_UITextures.PICTURE_FLUID_OUT.withFixedSize(16, 16) + .withOffset(2, 4)) + .addTooltip("Power Information") + .setPos(20 * (page - 1), -20)) + .addPage(powerInfoTab.addChild(getLogo().setPos(147, 86))); + builder.widget(tabs); + } + + protected void createMainTab(@Nonnull MultiChildWidget tab, @Nonnull Builder builder, + @Nonnull UIBuildContext uiBuildContext) { + MultiChildWidget buttons = new MultiChildWidget(); + buttons.setSize(16, 167) + .setPos(7, 86); + buttons.addChild(createPowerSwitchButton(builder)) + .addChild(createVoidExcessButton(builder)) + .addChild(createInputSeparationButton(builder)) + .addChild(createBatchModeButton(builder)) + .addChild(createLockToSingleRecipeButton(builder)); + tab.addChild( + new DrawableWidget().setDrawable(GT_UITextures.PICTURE_SCREEN_BLACK) + .setPos(7, 4) + .setSize(160, 75)) + .addChild(buttons); + } + + protected void createItemInputTab(@Nonnull MultiChildWidget tab, @Nonnull Builder builder, + @Nonnull UIBuildContext uiBuildContext) { + tab.addChild( + host.getItemLogic(InventoryType.Input, null) + .getGuiPart() + .setSize(18 * 4 + 9, 5 * 18) + .setPos(host.getWidth() / 2 - 2 * 18, 10)); + } + + protected void createItemOutputTab(@Nonnull MultiChildWidget tab, @Nonnull Builder builder, + @Nonnull UIBuildContext uiBuildContext) { + tab.addChild( + host.getItemLogic(InventoryType.Output, null) + .getGuiPart() + .setSize(18 * 4 + 9, 5 * 18) + .setPos(host.getWidth() / 2 - 2 * 18, 10)); + } + + protected void createFluidInputTab(@Nonnull MultiChildWidget tab, @Nonnull Builder builder, + @Nonnull UIBuildContext uiBuildContext) { + tab.addChild( + host.getFluidLogic(InventoryType.Input, null) + .getGuiPart() + .setSize(18 * 4 + 9, 5 * 18) + .setPos(host.getWidth() / 2 - 2 * 18, 10)); + } + + protected void createFluidOutputTab(@Nonnull MultiChildWidget tab, @Nonnull Builder builder, + @Nonnull UIBuildContext uiBuildContext) { + tab.addChild( + host.getFluidLogic(InventoryType.Output, null) + .getGuiPart() + .setSize(18 * 4 + 9, 5 * 18) + .setPos(host.getWidth() / 2 - 2 * 18, 10)); + } + + protected void createPowerTab(@Nonnull MultiChildWidget tab, @Nonnull Builder builder, + @Nonnull UIBuildContext uiBuildContext) { + PowerLogic power = host.getPowerLogic(); + tab.addChild( + TextWidget.dynamicString(() -> power.getStoredEnergy() + "/" + power.getCapacity() + " EU") + .setPos(10, 30)) + .addChild( + TextWidget.dynamicString(() -> power.getVoltage() + " EU/t" + "(" + power.getMaxAmperage() + " A)") + .setPos(10, 60)); + } + + /** + * Should return the logo you want to use that is pasted on each tab. Default is the GT logo. + */ + @Nonnull + protected Widget getLogo() { + DrawableWidget logo = new DrawableWidget(); + logo.setDrawable(GUITextureSet.DEFAULT.getGregTechLogo()) + .setSize(LOGO_SIZE, LOGO_SIZE); + return logo; + } + + protected Pos2d getPowerSwitchButtonPos() { + return POWER_SWITCH_BUTTON_DEFAULT_POS; + } + + protected ButtonWidget createPowerSwitchButton(IWidgetBuilder<?> builder) { + ButtonWidget button = new ButtonWidget(); + button.setOnClick((clickData, widget) -> { + if (host.isAllowedToWork()) { + host.disableWorking(); + } else { + host.enableWorking(); + } + }) + .setPlayClickSoundResource( + () -> host.isAllowedToWork() ? SoundResource.GUI_BUTTON_UP.resourceLocation + : SoundResource.GUI_BUTTON_DOWN.resourceLocation) + .setBackground(() -> { + if (host.isAllowedToWork()) { + return new IDrawable[] { GT_UITextures.BUTTON_STANDARD_PRESSED, + GT_UITextures.OVERLAY_BUTTON_POWER_SWITCH_ON }; + } else { + return new IDrawable[] { GT_UITextures.BUTTON_STANDARD, + GT_UITextures.OVERLAY_BUTTON_POWER_SWITCH_OFF }; + } + }) + .attachSyncer(new FakeSyncWidget.BooleanSyncer(host::isAllowedToWork, host::setAllowedToWork), builder) + .addTooltip(StatCollector.translateToLocal("GT5U.gui.button.power_switch")) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setPos(getPowerSwitchButtonPos()) + .setSize(16, 16); + return button; + } + + @Nonnull + protected Pos2d getVoidingModeButtonPos() { + return VOIDING_MODE_BUTTON_DEFAULT_POS; + } + + @Nonnull + protected ButtonWidget createVoidExcessButton(IWidgetBuilder<?> builder) { + ButtonWidget button = new ButtonWidget(); + button.setOnClick((clickData, widget) -> { + if (host.supportsVoidProtection()) { + Set<VoidingMode> allowed = host.getAllowedVoidingModes(); + switch (clickData.mouseButton) { + case 0 -> host.setVoidingMode( + host.getVoidingMode() + .nextInCollection(allowed)); + case 1 -> host.setVoidingMode( + host.getVoidingMode() + .previousInCollection(allowed)); + } + widget.notifyTooltipChange(); + } + }) + .setPlayClickSound(host.supportsVoidProtection()) + .setBackground(() -> { + List<UITexture> ret = new ArrayList<>(); + ret.add(host.getVoidingMode().buttonTexture); + ret.add(host.getVoidingMode().buttonOverlay); + if (!host.supportsVoidProtection()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_FORBIDDEN); + } + return ret.toArray(new IDrawable[0]); + }) + .attachSyncer( + new FakeSyncWidget.IntegerSyncer( + () -> host.getVoidingMode() + .ordinal(), + val -> host.setVoidingMode(VoidingMode.fromOrdinal(val))), + builder) + .dynamicTooltip( + () -> Arrays.asList( + StatCollector.translateToLocal("GT5U.gui.button.voiding_mode"), + StatCollector.translateToLocal( + host.getVoidingMode() + .getTransKey()))) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setPos(getVoidingModeButtonPos()) + .setSize(16, 16); + if (!host.supportsVoidProtection()) { + button.addTooltip(StatCollector.translateToLocal(BUTTON_FORBIDDEN_TOOLTIP)); + } + return button; + } + + @Nonnull + protected Pos2d getInputSeparationButtonPos() { + return INPUT_SEPARATION_BUTTON_DEFAULT_POS; + } + + protected ButtonWidget createInputSeparationButton(IWidgetBuilder<?> builder) { + ButtonWidget button = new ButtonWidget(); + button.setOnClick((clickData, widget) -> { + if (host.supportsInputSeparation()) { + host.setInputSeparation(!host.isInputSeparated()); + } + }) + .setPlayClickSound(host.supportsInputSeparation()) + .setBackground(() -> { + List<UITexture> ret = new ArrayList<>(); + if (host.isInputSeparated()) { + ret.add(GT_UITextures.BUTTON_STANDARD_PRESSED); + if (host.supportsInputSeparation()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_INPUT_SEPARATION_ON); + } else { + ret.add(GT_UITextures.OVERLAY_BUTTON_INPUT_SEPARATION_ON_DISABLED); + } + } else { + ret.add(GT_UITextures.BUTTON_STANDARD); + if (host.supportsInputSeparation()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_INPUT_SEPARATION_OFF); + } else { + ret.add(GT_UITextures.OVERLAY_BUTTON_INPUT_SEPARATION_OFF_DISABLED); + } + } + if (!host.supportsInputSeparation()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_FORBIDDEN); + } + return ret.toArray(new IDrawable[0]); + }) + .attachSyncer(new FakeSyncWidget.BooleanSyncer(host::isInputSeparated, host::setInputSeparation), builder) + .addTooltip(StatCollector.translateToLocal("GT5U.gui.button.input_separation")) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setPos(getInputSeparationButtonPos()) + .setSize(16, 16); + if (!host.supportsInputSeparation()) { + button.addTooltip(StatCollector.translateToLocal(BUTTON_FORBIDDEN_TOOLTIP)); + } + return button; + } + + @Nonnull + protected Pos2d getBatchModeButtonPos() { + return BATCH_MODE_BUTTON_DEFAULT_POS; + } + + protected ButtonWidget createBatchModeButton(IWidgetBuilder<?> builder) { + ButtonWidget button = new ButtonWidget(); + button.setOnClick((clickData, widget) -> { + if (host.supportsBatchMode()) { + host.setBatchMode(!host.isBatchModeEnabled()); + } + }) + .setPlayClickSound(host.supportsBatchMode()) + .setBackground(() -> { + List<UITexture> ret = new ArrayList<>(); + if (host.isBatchModeEnabled()) { + ret.add(GT_UITextures.BUTTON_STANDARD_PRESSED); + if (host.supportsBatchMode()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_BATCH_MODE_ON); + } else { + ret.add(GT_UITextures.OVERLAY_BUTTON_BATCH_MODE_ON_DISABLED); + } + } else { + ret.add(GT_UITextures.BUTTON_STANDARD); + if (host.supportsBatchMode()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_BATCH_MODE_OFF); + } else { + ret.add(GT_UITextures.OVERLAY_BUTTON_BATCH_MODE_OFF_DISABLED); + } + } + if (!host.supportsBatchMode()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_FORBIDDEN); + } + return ret.toArray(new IDrawable[0]); + }) + .attachSyncer(new FakeSyncWidget.BooleanSyncer(host::isBatchModeEnabled, host::setBatchMode), builder) + .addTooltip(StatCollector.translateToLocal("GT5U.gui.button.batch_mode")) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setPos(getBatchModeButtonPos()) + .setSize(16, 16); + if (!host.supportsBatchMode()) { + button.addTooltip(StatCollector.translateToLocal(BUTTON_FORBIDDEN_TOOLTIP)); + } + return button; + } + + @Nonnull + protected Pos2d getRecipeLockingButtonPos() { + return RECIPE_LOCKING_BUTTON_DEFAULT_POS; + } + + protected ButtonWidget createLockToSingleRecipeButton(IWidgetBuilder<?> builder) { + ButtonWidget button = new ButtonWidget(); + button.setOnClick((clickData, widget) -> { + if (host.supportsSingleRecipeLocking()) { + host.setRecipeLocking(!host.isRecipeLockingEnabled()); + } + }) + .setPlayClickSound(host.supportsSingleRecipeLocking()) + .setBackground(() -> { + List<UITexture> ret = new ArrayList<>(); + if (host.isRecipeLockingEnabled()) { + ret.add(GT_UITextures.BUTTON_STANDARD_PRESSED); + if (host.supportsSingleRecipeLocking()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_RECIPE_LOCKED); + } else { + ret.add(GT_UITextures.OVERLAY_BUTTON_RECIPE_LOCKED_DISABLED); + } + } else { + ret.add(GT_UITextures.BUTTON_STANDARD); + if (host.supportsSingleRecipeLocking()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_RECIPE_UNLOCKED); + } else { + ret.add(GT_UITextures.OVERLAY_BUTTON_RECIPE_UNLOCKED_DISABLED); + } + } + if (!host.supportsSingleRecipeLocking()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_FORBIDDEN); + } + return ret.toArray(new IDrawable[0]); + }) + .attachSyncer( + new FakeSyncWidget.BooleanSyncer(host::isRecipeLockingEnabled, host::setRecipeLocking), + builder) + .addTooltip(StatCollector.translateToLocal("GT5U.gui.button.lock_recipe")) + .setTooltipShowUpDelay(TOOLTIP_DELAY) + .setPos(getRecipeLockingButtonPos()) + .setSize(16, 16); + if (!host.supportsSingleRecipeLocking()) { + button.addTooltip(StatCollector.translateToLocal(BUTTON_FORBIDDEN_TOOLTIP)); + } + return button; + } +} diff --git a/src/main/java/gregtech/common/gui/PartGUIProvider.java b/src/main/java/gregtech/common/gui/PartGUIProvider.java new file mode 100644 index 0000000000..7600444f71 --- /dev/null +++ b/src/main/java/gregtech/common/gui/PartGUIProvider.java @@ -0,0 +1,33 @@ +package gregtech.common.gui; + +import javax.annotation.Nonnull; + +import com.gtnewhorizons.modularui.api.screen.ModularWindow.Builder; +import com.gtnewhorizons.modularui.api.screen.UIBuildContext; + +import gregtech.api.gui.GUIHost; +import gregtech.api.gui.GUIProvider; +import gregtech.api.logic.interfaces.FluidInventoryLogicHost; +import gregtech.api.logic.interfaces.ItemInventoryLogicHost; +import gregtech.api.logic.interfaces.PowerLogicHost; + +public class PartGUIProvider<T extends GUIHost & ItemInventoryLogicHost & PowerLogicHost & FluidInventoryLogicHost> + extends GUIProvider<T> { + + public PartGUIProvider(@Nonnull T host) { + super(host); + } + + @Override + protected void attachSynchHandlers(@Nonnull Builder builder, @Nonnull UIBuildContext uiContext) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'attachSynchHandlers'"); + } + + @Override + protected void addWidgets(@Nonnull Builder builder, @Nonnull UIBuildContext uiContext) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'addWidgets'"); + } + +} diff --git a/src/main/java/gregtech/common/misc/GT_Command.java b/src/main/java/gregtech/common/misc/GT_Command.java index 35e7a71f65..ad3293be90 100644 --- a/src/main/java/gregtech/common/misc/GT_Command.java +++ b/src/main/java/gregtech/common/misc/GT_Command.java @@ -1,5 +1,13 @@ package gregtech.common.misc; +import static gregtech.common.misc.WirelessNetworkManager.addEUToGlobalEnergyMap; +import static gregtech.common.misc.WirelessNetworkManager.getRawUUIDFromUsername; +import static gregtech.common.misc.WirelessNetworkManager.getUUIDFromUsername; +import static gregtech.common.misc.WirelessNetworkManager.getUserEU; +import static gregtech.common.misc.WirelessNetworkManager.getUsernameFromUUID; +import static gregtech.common.misc.WirelessNetworkManager.joinUserNetwork; +import static gregtech.common.misc.WirelessNetworkManager.setUserEU; + import java.lang.reflect.Field; import java.math.BigInteger; import java.util.ArrayList; @@ -16,12 +24,11 @@ import com.gtnewhorizon.structurelib.StructureLib; import gregtech.GT_Mod; import gregtech.api.enums.GT_Values; -import gregtech.api.interfaces.IGlobalWirelessEnergy; import gregtech.api.objects.GT_ChunkManager; import gregtech.api.util.GT_Utility; import gregtech.common.GT_Pollution; -public final class GT_Command extends CommandBase implements IGlobalWirelessEnergy { +public final class GT_Command extends CommandBase { @Override public String getCommandName() { @@ -355,7 +362,7 @@ public final class GT_Command extends CommandBase implements IGlobalWirelessEner "User " + formatted_username + " is currently in network of " + EnumChatFormatting.BLUE - + GetUsernameFromUUID(uuidTeam) + + getUsernameFromUUID(uuidTeam) + EnumChatFormatting.RESET + ".")); diff --git a/src/main/java/gregtech/common/misc/WirelessNetworkManager.java b/src/main/java/gregtech/common/misc/WirelessNetworkManager.java new file mode 100644 index 0000000000..dc11becdbb --- /dev/null +++ b/src/main/java/gregtech/common/misc/WirelessNetworkManager.java @@ -0,0 +1,164 @@ +package gregtech.common.misc; + +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; + +public class WirelessNetworkManager { + + private WirelessNetworkManager() {} + + // User 0 will join user 1 by calling this function. They will share the same energy network. + public static void joinUserNetwork(String user_uuid_0, String user_uuid_1) { + GlobalEnergyTeam.put(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 + // has changed their username and adjust the maps accordingly. This should be called infrequently. Ideally on first + // tick of a machine being placed only. + + public static void strongCheckOrAddUser(EntityPlayer user) { + strongCheckOrAddUser( + user.getUniqueID() + .toString(), + user.getDisplayName()); + } + + public static void strongCheckOrAddUser(UUID user_uuid, String user_name) { + strongCheckOrAddUser(user_uuid.toString(), user_name); + } + + public static 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); + } + + // ------------------------------------------------------------------------------------ + // Add EU to the users global energy. You can enter a negative number to subtract it. + // If the value goes below 0 it will return false and not perform the operation. + // BigIntegers have much slower operations than longs/ints. You should call these methods + // as infrequently as possible and bulk store values to add to the global map. + public static boolean addEUToGlobalEnergyMap(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; + } + + public static boolean addEUToGlobalEnergyMap(UUID user_uuid, BigInteger EU) { + return addEUToGlobalEnergyMap(user_uuid.toString(), EU); + } + + public static boolean addEUToGlobalEnergyMap(UUID user_uuid, long EU) { + return addEUToGlobalEnergyMap(user_uuid.toString(), BigInteger.valueOf(EU)); + } + + public static boolean addEUToGlobalEnergyMap(UUID user_uuid, int EU) { + return addEUToGlobalEnergyMap(user_uuid.toString(), BigInteger.valueOf(EU)); + } + + public static boolean addEUToGlobalEnergyMap(String user_uuid, long EU) { + return addEUToGlobalEnergyMap(user_uuid, BigInteger.valueOf(EU)); + } + + public static boolean addEUToGlobalEnergyMap(String user_uuid, int EU) { + return addEUToGlobalEnergyMap(user_uuid, BigInteger.valueOf(EU)); + } + + // ------------------------------------------------------------------------------------ + + public static BigInteger getUserEU(String user_uuid) { + return GlobalEnergy.getOrDefault(GlobalEnergyTeam.getOrDefault(user_uuid, user_uuid), BigInteger.ZERO); + } + + // This overwrites the EU in the network. Only use this if you are absolutely sure you know what you are doing. + public static void setUserEU(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); + } + + public static String getUsernameFromUUID(String uuid) { + return GlobalEnergyName.getOrDefault(GlobalEnergyTeam.getOrDefault(uuid, ""), ""); + } + + public static String getUUIDFromUsername(String username) { + return GlobalEnergyTeam.getOrDefault(GlobalEnergyName.getOrDefault(username, ""), ""); + } + + /** + * + * @param username + * @return + */ + public static String getRawUUIDFromUsername(String username) { + return GlobalEnergyName.getOrDefault(username, ""); + } + + public static void clearGlobalEnergyInformationMaps() { + // Do not use this unless you are 100% certain you know what you are doing. + GlobalEnergy.clear(); + GlobalEnergyName.clear(); + GlobalEnergyTeam.clear(); + } + + public static 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; + } +} diff --git a/src/main/java/gregtech/common/tileentities/casings/upgrade/Ampere.java b/src/main/java/gregtech/common/tileentities/casings/upgrade/Ampere.java new file mode 100644 index 0000000000..1644f8fde0 --- /dev/null +++ b/src/main/java/gregtech/common/tileentities/casings/upgrade/Ampere.java @@ -0,0 +1,47 @@ +package gregtech.common.tileentities.casings.upgrade; + +import java.util.List; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; + +import gregtech.api.enums.GT_Values; +import gregtech.api.multitileentity.interfaces.IMultiBlockController; +import gregtech.api.multitileentity.multiblock.casing.UpgradeCasing; +import gregtech.api.util.GT_Utility; + +public class Ampere extends UpgradeCasing { + + private long amperage; + + @Override + public String getTileEntityName() { + return "gt.multitileentity.multiblock.functional.amperage"; + } + + @Override + public void readMultiTileNBT(NBTTagCompound aNBT) { + super.readMultiTileNBT(aNBT); + amperage = aNBT.getInteger(GT_Values.NBT.UPGRADE_AMPERAGE); + } + + @Override + protected void customWork(IMultiBlockController target) { + target.setMaxAmperage(amperage); + } + + @Override + public boolean breakBlock() { + final IMultiBlockController controller = getTarget(false); + if (controller != null) { + controller.setMaxAmperage(2); + } + return super.breakBlock(); + } + + @Override + public void addToolTips(List<String> list, ItemStack stack, boolean f3_h) { + super.addToolTips(list, stack, f3_h); + list.add("Increases allowed amperage to " + GT_Utility.formatNumbers(amperage)); + } +} diff --git a/src/main/java/gregtech/common/tileentities/casings/upgrade/Cleanroom.java b/src/main/java/gregtech/common/tileentities/casings/upgrade/Cleanroom.java new file mode 100644 index 0000000000..641327b427 --- /dev/null +++ b/src/main/java/gregtech/common/tileentities/casings/upgrade/Cleanroom.java @@ -0,0 +1,26 @@ +package gregtech.common.tileentities.casings.upgrade; + +import gregtech.api.multitileentity.interfaces.IMultiBlockController; +import gregtech.api.multitileentity.multiblock.casing.UpgradeCasing; + +public class Cleanroom extends UpgradeCasing { + + @Override + public String getTileEntityName() { + return "gt.multitileentity.multiblock.functional.cleanroom"; + } + + @Override + protected void customWork(IMultiBlockController target) { + target.setCleanroom(true); + } + + @Override + public boolean breakBlock() { + final IMultiBlockController controller = getTarget(false); + if (controller != null) { + controller.setCleanroom(false); + } + return super.breakBlock(); + } +} diff --git a/src/main/java/gregtech/common/tileentities/casings/upgrade/Heater.java b/src/main/java/gregtech/common/tileentities/casings/upgrade/Heater.java new file mode 100644 index 0000000000..6d8bd81d0f --- /dev/null +++ b/src/main/java/gregtech/common/tileentities/casings/upgrade/Heater.java @@ -0,0 +1,21 @@ +package gregtech.common.tileentities.casings.upgrade; + +import gregtech.api.multitileentity.interfaces.IMultiBlockController; +import gregtech.api.multitileentity.interfaces.UpgradableModularMuTE; +import gregtech.api.multitileentity.multiblock.casing.UpgradeCasing; +import gregtech.api.util.GT_StructureUtilityMuTE.UpgradeCasings; + +public class Heater extends UpgradeCasing { + + @Override + public String getTileEntityName() { + return "gt.multitileentity.multiblock.modular.heater"; + } + + @Override + protected void customWork(IMultiBlockController target) { + if (target instanceof UpgradableModularMuTE upgradable) { + upgradable.increaseMucCount(UpgradeCasings.Heater, this.tier); + } + } +} diff --git a/src/main/java/gregtech/common/tileentities/casings/upgrade/Insulator.java b/src/main/java/gregtech/common/tileentities/casings/upgrade/Insulator.java new file mode 100644 index 0000000000..6cb0b630d6 --- /dev/null +++ b/src/main/java/gregtech/common/tileentities/casings/upgrade/Insulator.java @@ -0,0 +1,22 @@ +package gregtech.common.tileentities.casings.upgrade; + +import gregtech.api.multitileentity.interfaces.IMultiBlockController; +import gregtech.api.multitileentity.interfaces.UpgradableModularMuTE; +import gregtech.api.multitileentity.multiblock.casing.UpgradeCasing; +import gregtech.api.util.GT_StructureUtilityMuTE.UpgradeCasings; + +public class Insulator extends UpgradeCasing { + + @Override + public String getTileEntityName() { + return "gt.multitileentity.multiblock.modular.insulator"; + } + + @Override + protected void customWork(IMultiBlockController target) { + if (target instanceof UpgradableModularMuTE upgradable) { + upgradable.increaseMucCount(UpgradeCasings.Insulator, this.tier); + } + } + +} diff --git a/src/main/java/gregtech/common/tileentities/casings/upgrade/Inventory.java b/src/main/java/gregtech/common/tileentities/casings/upgrade/Inventory.java index e42f0bfb86..5087c7f09e 100644 --- a/src/main/java/gregtech/common/tileentities/casings/upgrade/Inventory.java +++ b/src/main/java/gregtech/common/tileentities/casings/upgrade/Inventory.java @@ -1,7 +1,9 @@ package gregtech.common.tileentities.casings.upgrade; +import java.util.List; import java.util.UUID; +import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.common.util.ForgeDirection; @@ -10,35 +12,45 @@ import com.gtnewhorizons.modularui.api.screen.UIBuildContext; import com.gtnewhorizons.modularui.common.widget.textfield.TextFieldWidget; import gregtech.api.enums.GT_Values.NBT; +import gregtech.api.enums.InventoryType; import gregtech.api.multitileentity.interfaces.IMultiBlockController; import gregtech.api.multitileentity.multiblock.casing.UpgradeCasing; import gregtech.api.net.GT_Packet_MultiTileEntity; public class Inventory extends UpgradeCasing { - public UUID mInventoryID; - public static final int INPUT = 0; - public static final int OUTPUT = 1; - public static final int BOTH = 2; - private String mInventoryName = "inventory"; - private int mInventorySize; - private final int mType = BOTH; + public UUID inventoryID; - public String getInventoryName() { - return mInventoryName; + private String inventoryName = "inventory"; + private int inventorySize; + private InventoryType type = InventoryType.Both; + + public String getCustomInventoryName() { + return inventoryName; + } + + public String getInventoryID() { + return inventoryID.toString(); } public void setInventoryName(String aInventoryName) { - mInventoryName = aInventoryName; + inventoryName = aInventoryName; + } + + public InventoryType getType() { + return type; } @Override - protected void customWork(IMultiBlockController aTarget) { - int tInvSize = mInventorySize; - if (mType == BOTH) { - tInvSize /= 2; + protected void customWork(IMultiBlockController target) { + int invSize = inventorySize; + if (type == InventoryType.Both) { + invSize /= 2; + } + target.registerItemInventory(invSize, tier, type, true); + if (isServerSide()) { + issueClientUpdate(); } - aTarget.registerInventory(mInventoryName, mInventoryID.toString(), tInvSize, mType); } @Override @@ -49,34 +61,28 @@ public class Inventory extends UpgradeCasing { @Override public void readMultiTileNBT(NBTTagCompound aNBT) { super.readMultiTileNBT(aNBT); - if (aNBT.hasKey(NBT.UPGRADE_INVENTORY_UUID)) { - mInventoryID = UUID.fromString(aNBT.getString(NBT.UPGRADE_INVENTORY_UUID)); + if (aNBT.hasKey(NBT.UPGRADE_INVENTORY_NAME)) { + inventoryName = aNBT.getString(NBT.UPGRADE_INVENTORY_NAME); } else { - mInventoryID = UUID.randomUUID(); + inventoryName = "inventory"; } - mInventorySize = aNBT.getInteger(NBT.UPGRADE_INVENTORY_SIZE); - mInventoryName = aNBT.getString(NBT.UPGRADE_INVENTORY_NAME); - + inventorySize = aNBT.getInteger(NBT.UPGRADE_INVENTORY_SIZE); } @Override public void writeMultiTileNBT(NBTTagCompound aNBT) { super.writeMultiTileNBT(aNBT); - aNBT.setString(NBT.UPGRADE_INVENTORY_UUID, mInventoryID.toString()); - aNBT.setString(NBT.UPGRADE_INVENTORY_NAME, mInventoryName); + aNBT.setString(NBT.UPGRADE_INVENTORY_UUID, inventoryID.toString()); + aNBT.setString(NBT.UPGRADE_INVENTORY_NAME, inventoryName); } @Override - protected void onBaseTEDestroyed() { - super.onBaseTEDestroyed(); - unregisterInventories(); - } - - private void unregisterInventories() { + public boolean breakBlock() { final IMultiBlockController controller = getTarget(false); if (controller != null) { - controller.unregisterInventory(mInventoryName, mInventoryID.toString(), mType); + controller.unregisterItemInventory(inventoryID, type); } + return super.breakBlock(); } @Override @@ -87,12 +93,12 @@ public class Inventory extends UpgradeCasing { @Override public void addUIWidgets(Builder builder, UIBuildContext buildContext) { builder.widget( - new TextFieldWidget().setGetter(() -> mInventoryName) + new TextFieldWidget().setGetter(() -> inventoryName) .setSetter((val) -> { - mInventoryName = val; + inventoryName = val; final IMultiBlockController controller = getTarget(false); if (controller != null) { - controller.changeInventoryName(mInventoryName, mInventoryID.toString(), mType); + controller.changeItemInventoryDisplayName(inventoryID, inventoryName, type); } }) .setSize(100, 25) @@ -100,10 +106,27 @@ public class Inventory extends UpgradeCasing { } @Override + protected boolean canOpenControllerGui() { + return false; + } + + @Override public GT_Packet_MultiTileEntity getClientDataPacket() { final GT_Packet_MultiTileEntity packet = super.getClientDataPacket(); - String name = getInventoryName(); - packet.setInventoryName(name); + String name = getCustomInventoryName(); + packet.setInventoryName(name, inventoryID.toString()); return packet; } + + @Override + public void addToolTips(List<String> list, ItemStack stack, boolean f3_h) { + super.addToolTips(list, stack, f3_h); + list.add("Adds another item inventory"); + list.add("Inventory size: " + inventorySize); + list.add("Inventory Type: " + type); + } + + public void setInventoryId(String inventoryID) { + this.inventoryID = UUID.fromString(inventoryID); + } } diff --git a/src/main/java/gregtech/common/tileentities/casings/upgrade/Laser.java b/src/main/java/gregtech/common/tileentities/casings/upgrade/Laser.java new file mode 100644 index 0000000000..ab66281f54 --- /dev/null +++ b/src/main/java/gregtech/common/tileentities/casings/upgrade/Laser.java @@ -0,0 +1,26 @@ +package gregtech.common.tileentities.casings.upgrade; + +import gregtech.api.multitileentity.interfaces.IMultiBlockController; +import gregtech.api.multitileentity.multiblock.casing.UpgradeCasing; + +public class Laser extends UpgradeCasing { + + @Override + public String getTileEntityName() { + return "gt.multitileentity.multiblock.functional.laser"; + } + + @Override + protected void customWork(IMultiBlockController target) { + target.setLaserSupport(true); + } + + @Override + public boolean breakBlock() { + final IMultiBlockController controller = getTarget(false); + if (controller != null) { + controller.setLaserSupport(false); + } + return super.breakBlock(); + } +} diff --git a/src/main/java/gregtech/common/tileentities/casings/upgrade/Tank.java b/src/main/java/gregtech/common/tileentities/casings/upgrade/Tank.java new file mode 100644 index 0000000000..ebc84be38a --- /dev/null +++ b/src/main/java/gregtech/common/tileentities/casings/upgrade/Tank.java @@ -0,0 +1,61 @@ +package gregtech.common.tileentities.casings.upgrade; + +import java.util.List; +import java.util.UUID; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; + +import gregtech.api.enums.GT_Values; +import gregtech.api.multitileentity.interfaces.IMultiBlockController; +import gregtech.api.multitileentity.multiblock.casing.UpgradeCasing; +import gregtech.api.util.GT_Utility; + +public class Tank extends UpgradeCasing { + + private int tankCount; + private int tankCapacity; + public UUID tankID; + public static final int INPUT = 0; + public static final int OUTPUT = 1; + public static final int BOTH = 2; + private String tankName = "tank"; + private int type = BOTH; + + @Override + protected void customWork(IMultiBlockController aTarget) { + + } + + @Override + public String getTileEntityName() { + return "gt.multitileentity.multiblock.tank"; + } + + public String getCustomTankName() { + return tankName; + } + + public String getTankID() { + return tankID.toString(); + } + + public int getType() { + return type; + } + + @Override + public void readMultiTileNBT(NBTTagCompound aNBT) { + super.readMultiTileNBT(aNBT); + tankCount = aNBT.getInteger(GT_Values.NBT.UPGRADE_TANK_COUNT); + tankCapacity = aNBT.getInteger(GT_Values.NBT.UPGRADE_TANK_CAPACITY); + } + + @Override + public void addToolTips(List<String> list, ItemStack stack, boolean f3_h) { + super.addToolTips(list, stack, f3_h); + list.add("Adds another tank inventory"); + list.add("Number of tanks: " + tankCount); + list.add("Tank capacity: " + GT_Utility.formatNumbers(tankCapacity) + " L"); + } +} diff --git a/src/main/java/gregtech/common/tileentities/casings/upgrade/Wireless.java b/src/main/java/gregtech/common/tileentities/casings/upgrade/Wireless.java new file mode 100644 index 0000000000..0cb6a595bf --- /dev/null +++ b/src/main/java/gregtech/common/tileentities/casings/upgrade/Wireless.java @@ -0,0 +1,26 @@ +package gregtech.common.tileentities.casings.upgrade; + +import gregtech.api.multitileentity.interfaces.IMultiBlockController; +import gregtech.api.multitileentity.multiblock.casing.UpgradeCasing; + +public class Wireless extends UpgradeCasing { + + @Override + public String getTileEntityName() { + return "gt.multitileentity.multiblock.functional.wireless"; + } + + @Override + protected void customWork(IMultiBlockController target) { + target.setWirelessSupport(true); + } + + @Override + public boolean breakBlock() { + final IMultiBlockController controller = getTarget(false); + if (controller != null) { + controller.setWirelessSupport(false); + } + return super.breakBlock(); + } +} diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_TranscendentPlasmaMixer.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_TranscendentPlasmaMixer.java index e4873f6d9d..58b42eca7f 100644 --- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_TranscendentPlasmaMixer.java +++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_TranscendentPlasmaMixer.java @@ -11,6 +11,9 @@ import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_DTPF_ON; import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FUSION1_GLOW; import static gregtech.api.enums.Textures.BlockIcons.casingTexturePages; import static gregtech.api.util.GT_StructureUtility.buildHatchAdder; +import static gregtech.common.misc.WirelessNetworkManager.addEUToGlobalEnergyMap; +import static gregtech.common.misc.WirelessNetworkManager.getUserEU; +import static gregtech.common.misc.WirelessNetworkManager.processInitialSettings; import static gregtech.common.tileentities.machines.multi.GT_MetaTileEntity_PlasmaForge.DIM_BRIDGE_CASING; import static gregtech.common.tileentities.machines.multi.GT_MetaTileEntity_PlasmaForge.DIM_INJECTION_CASING; import static gregtech.common.tileentities.machines.multi.GT_MetaTileEntity_PlasmaForge.DIM_TRANS_CASING; @@ -34,7 +37,6 @@ import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment; import com.gtnewhorizon.structurelib.structure.StructureDefinition; import gregtech.api.GregTech_API; -import gregtech.api.interfaces.IGlobalWirelessEnergy; import gregtech.api.interfaces.ITexture; import gregtech.api.interfaces.metatileentity.IMetaTileEntity; import gregtech.api.interfaces.tileentity.IGregTechTileEntity; @@ -52,7 +54,7 @@ import gregtech.common.items.GT_IntegratedCircuit_Item; public class GT_MetaTileEntity_TranscendentPlasmaMixer extends GT_MetaTileEntity_EnhancedMultiBlockBase<GT_MetaTileEntity_TranscendentPlasmaMixer> - implements IGlobalWirelessEnergy, ISurvivalConstructable { + implements ISurvivalConstructable { private static final String[][] structure = new String[][] { { " CAC ", " ABA ", " ABA ", " A~A ", " ABA ", " ABA ", " CAC " }, diff --git a/src/main/java/gregtech/common/tileentities/machines/multiblock/AdvChemicalProcessor.java b/src/main/java/gregtech/common/tileentities/machines/multiblock/AdvChemicalProcessor.java new file mode 100644 index 0000000000..a253f6ac1e --- /dev/null +++ b/src/main/java/gregtech/common/tileentities/machines/multiblock/AdvChemicalProcessor.java @@ -0,0 +1,508 @@ +package gregtech.common.tileentities.machines.multiblock; + +import static com.google.common.primitives.Ints.saturatedCast; +import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock; +import static com.gtnewhorizon.structurelib.structure.StructureUtility.transpose; +import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.ENERGY_IN; +import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.FLUID_IN; +import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.FLUID_OUT; +import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.ITEM_IN; +import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.ITEM_OUT; +import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.NOTHING; +import static gregtech.api.util.GT_StructureUtilityMuTE.MOTOR_CASINGS; +import static gregtech.api.util.GT_StructureUtilityMuTE.ofMuTECasings; + +import java.util.ArrayList; +import java.util.HashSet; + +import javax.annotation.Nonnull; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraftforge.common.util.Constants; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.IFluidTank; + +import com.gtnewhorizon.structurelib.structure.IStructureDefinition; +import com.gtnewhorizon.structurelib.structure.StructureDefinition; +import com.gtnewhorizon.structurelib.util.Vec3Impl; +import com.gtnewhorizons.modularui.api.forge.ItemStackHandler; +import com.gtnewhorizons.modularui.api.math.Alignment; +import com.gtnewhorizons.modularui.api.math.Color; +import com.gtnewhorizons.modularui.api.screen.ModularWindow; +import com.gtnewhorizons.modularui.api.screen.UIBuildContext; +import com.gtnewhorizons.modularui.api.widget.IWidgetBuilder; +import com.gtnewhorizons.modularui.common.widget.ButtonWidget; +import com.gtnewhorizons.modularui.common.widget.MultiChildWidget; +import com.gtnewhorizons.modularui.common.widget.SlotGroup; +import com.gtnewhorizons.modularui.common.widget.TextWidget; +import com.gtnewhorizons.modularui.common.widget.textfield.TextFieldWidget; + +import gregtech.api.GregTech_API; +import gregtech.api.enums.GT_Values; +import gregtech.api.enums.HeatingCoilLevel; +import gregtech.api.enums.Materials; +import gregtech.api.fluid.FluidTankGT; +import gregtech.api.gui.modularui.GT_UITextures; +import gregtech.api.multitileentity.enums.GT_MultiTileCasing; +import gregtech.api.multitileentity.multiblock.base.ComplexParallelController; +import gregtech.api.multitileentity.multiblock.casing.Glasses; +import gregtech.api.util.GT_Multiblock_Tooltip_Builder; +import gregtech.api.util.GT_StructureUtility; +import gregtech.api.util.GT_StructureUtilityMuTE; +import gregtech.common.tileentities.machines.multiblock.logic.AdvChemicalProcessorProcessingLogic; + +public class AdvChemicalProcessor + extends ComplexParallelController<AdvChemicalProcessor, AdvChemicalProcessorProcessingLogic> { + + private static IStructureDefinition<AdvChemicalProcessor> STRUCTURE_DEFINITION = null; + protected static final String STRUCTURE_PIECE_T1 = "T1"; + protected static final String STRUCTURE_PIECE_T2 = "T2"; + protected static final String STRUCTURE_PIECE_T3 = "T3"; + protected static final String STRUCTURE_PIECE_T4 = "T4"; + protected static final String STRUCTURE_PIECE_T5_6 = "T5_6"; + protected static final String STRUCTURE_PIECE_T7_8 = "T7_8"; + protected static final Vec3Impl STRUCTURE_OFFSET_T1 = new Vec3Impl(3, 1, 0); + protected static final Vec3Impl STRUCTURE_OFFSET_T2 = new Vec3Impl(1, 4, -3); + protected static final Vec3Impl STRUCTURE_OFFSET_T3 = new Vec3Impl(8, 0, 5); + protected static final Vec3Impl STRUCTURE_OFFSET_T4 = new Vec3Impl(-14, 0, 0); + protected static final Vec3Impl STRUCTURE_OFFSET_T5 = new Vec3Impl(14, 0, -6); + protected static final Vec3Impl STRUCTURE_OFFSET_T6 = new Vec3Impl(-16, 0, 0); + protected static final Vec3Impl STRUCTURE_OFFSET_T7 = new Vec3Impl(16, 0, 15); + protected static final Vec3Impl STRUCTURE_OFFSET_T8 = new Vec3Impl(-16, 0, 0); + protected static final int PROCESS_WINDOW_BASE_ID = 100; + protected static final int ITEM_WHITELIST_SLOTS = 8; + protected static final int FLUID_WHITELIST_SLOTS = 8; + protected static final int MAX_PROCESSES = 8; + protected HeatingCoilLevel coilTier; + protected final ArrayList<HashSet<String>> processWhitelists = new ArrayList<>(MAX_PROCESSES); + protected final ArrayList<ItemStackHandler> processWhitelistInventoryHandlers = new ArrayList<>(MAX_PROCESSES); + protected final ArrayList<ArrayList<IFluidTank>> processFluidWhiteLists = new ArrayList<>(MAX_PROCESSES); + protected boolean wasWhitelistOpened = false; + + public AdvChemicalProcessor() { + super(); + for (int i = 0; i < MAX_PROCESSES; i++) { + processWhitelists.add(null); + processWhitelistInventoryHandlers.add(new ItemStackHandler(ITEM_WHITELIST_SLOTS)); + ArrayList<IFluidTank> processFluidTanks = new ArrayList<>(FLUID_WHITELIST_SLOTS); + for (int j = 0; j < FLUID_WHITELIST_SLOTS; j++) { + processFluidTanks.add(new FluidTankGT()); + } + processFluidWhiteLists.add(processFluidTanks); + } + setMaxComplexParallels(1, false); + } + + @Override + public void readMultiTileNBT(NBTTagCompound nbt) { + super.readMultiTileNBT(nbt); + setMaxComplexParallels(nbt.getInteger("processors"), false); + final NBTTagCompound processWhiteLists = nbt.getCompoundTag("whiteLists"); + long capacity = 1000; + if (nbt.hasKey(GT_Values.NBT.TANK_CAPACITY)) { + capacity = saturatedCast(nbt.getLong(GT_Values.NBT.TANK_CAPACITY)); + } + for (int i = 0; i < MAX_PROCESSES; i++) { + + if (processWhiteLists == null) { + continue; + } + + final NBTTagCompound itemList = processWhiteLists.getCompoundTag("items" + i); + if (itemList != null) { + processWhitelistInventoryHandlers.get(i) + .deserializeNBT(itemList); + } + final NBTTagList fluidList = processWhiteLists.getTagList("fluids" + i, Constants.NBT.TAG_COMPOUND); + + if (fluidList == null) { + continue; + } + + for (int j = 0; j < fluidList.tagCount(); j++) { + final NBTTagCompound fluid = fluidList.getCompoundTagAt(j); + + if (fluid == null) { + continue; + } + + short index = fluid.getShort("s"); + FluidStack fluidStack = FluidStack.loadFluidStackFromNBT(fluid); + if (fluidStack != null) { + processFluidWhiteLists.get(i) + .get(index) + .fill(fluidStack, true); + } + } + } + } + + @Override + public void writeMultiTileNBT(NBTTagCompound nbt) { + super.writeMultiTileNBT(nbt); + nbt.setInteger("processors", maxComplexParallels); + final NBTTagCompound processWhiteLists = new NBTTagCompound(); + for (int i = 0; i < MAX_PROCESSES; i++) { + processWhiteLists.setTag( + "items" + i, + processWhitelistInventoryHandlers.get(i) + .serializeNBT()); + final NBTTagList fluidList = new NBTTagList(); + for (int j = 0; j < FLUID_WHITELIST_SLOTS; j++) { + final FluidStack fluidStack = processFluidWhiteLists.get(i) + .get(j) + .getFluid(); + if (fluidStack != null) { + final NBTTagCompound tag = new NBTTagCompound(); + tag.setByte("s", (byte) j); + fluidStack.writeToNBT(tag); + fluidList.appendTag(tag); + } + } + processWhiteLists.setTag("fluids" + i, fluidList); + } + nbt.setTag("whiteLists", processWhiteLists); + } + + @Override + public short getCasingRegistryID() { + return GT_MultiTileCasing.Chemical.getRegistryId(); + } + + @Override + public int getCasingMeta() { + return GT_MultiTileCasing.Chemical.getId(); + } + + @Override + public GT_Multiblock_Tooltip_Builder createTooltip() { + final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder(); + tt.addMachineType("Chemical Reactor") + .addInfo("Controller block for the Advanced Chemical Processor") + .addInfo("Does not lose efficiency when overclocked") + .addInfo("Accepts fluids instead of fluid cells") + .addInfo("Can do multiple different recipes at once") + .addInfo("By using the whitelist filter a recipe can push its output") + .addInfo("to a different recipes input to chain them") + .addInfo("Disclaimer: Still WIP - Use at your own risk") + .addInfo(GT_Values.Authorminecraft7771) + .addSeparator() + .beginStructureBlock(5, 3, 3, false) + .addController("Front center") + .addCasingInfoExactly("PTFE Pipe Machine Casing", 8, false) + .addCasingInfoExactly("Heating Coils", 3, true) + .addCasingInfoExactly("EV+ Glass", 3, true) + .addCasingInfoExactly("Motor Casing", 3, true) + .addCasingInfoExactly("Chemical Casing", 27, false) + .toolTipFinisher("Gregtech"); + return tt; + } + + @Override + public Vec3Impl getStartingStructureOffset() { + return STRUCTURE_OFFSET_T1; + } + + @Override + public boolean checkMachine() { + setCoilTier(HeatingCoilLevel.None); + buildState.startBuilding(getStartingStructureOffset()); + if (!checkPiece(STRUCTURE_PIECE_T1, buildState.getCurrentOffset())) return buildState.failBuilding(); + if (maxComplexParallels > 1) { + buildState.addOffset(STRUCTURE_OFFSET_T2); + if (!checkPiece(STRUCTURE_PIECE_T2, buildState.getCurrentOffset())) return buildState.failBuilding(); + } + if (maxComplexParallels > 2) { + buildState.addOffset(STRUCTURE_OFFSET_T3); + if (!checkPiece(STRUCTURE_PIECE_T3, buildState.getCurrentOffset())) return buildState.failBuilding(); + } + if (maxComplexParallels > 3) { + buildState.addOffset(STRUCTURE_OFFSET_T4); + if (!checkPiece(STRUCTURE_PIECE_T4, buildState.getCurrentOffset())) return buildState.failBuilding(); + } + if (maxComplexParallels > 4) { + buildState.addOffset(STRUCTURE_OFFSET_T5); + if (!checkPiece(STRUCTURE_PIECE_T5_6, buildState.getCurrentOffset())) return buildState.failBuilding(); + } + if (maxComplexParallels > 5) { + buildState.addOffset(STRUCTURE_OFFSET_T6); + if (!checkPiece(STRUCTURE_PIECE_T5_6, buildState.getCurrentOffset())) return buildState.failBuilding(); + } + if (maxComplexParallels > 6) { + buildState.addOffset(STRUCTURE_OFFSET_T7); + if (!checkPiece(STRUCTURE_PIECE_T7_8, buildState.getCurrentOffset())) return buildState.failBuilding(); + } + if (maxComplexParallels > 7) { + buildState.addOffset(STRUCTURE_OFFSET_T8); + if (!checkPiece(STRUCTURE_PIECE_T7_8, buildState.getCurrentOffset())) return buildState.failBuilding(); + } + buildState.stopBuilding(); + return super.checkMachine(); + } + + @Override + public void construct(ItemStack trigger, boolean hintsOnly) { + buildState.startBuilding(getStartingStructureOffset()); + buildPiece(STRUCTURE_PIECE_T1, trigger, hintsOnly, buildState.getCurrentOffset()); + if (maxComplexParallels > 1) { + buildState.addOffset(STRUCTURE_OFFSET_T2); + buildPiece(STRUCTURE_PIECE_T2, trigger, hintsOnly, buildState.getCurrentOffset()); + } + if (maxComplexParallels > 2) { + buildState.addOffset(STRUCTURE_OFFSET_T3); + buildPiece(STRUCTURE_PIECE_T3, trigger, hintsOnly, buildState.getCurrentOffset()); + } + if (maxComplexParallels > 3) { + buildState.addOffset(STRUCTURE_OFFSET_T4); + buildPiece(STRUCTURE_PIECE_T4, trigger, hintsOnly, buildState.getCurrentOffset()); + } + if (maxComplexParallels > 4) { + buildState.addOffset(STRUCTURE_OFFSET_T5); + buildPiece(STRUCTURE_PIECE_T5_6, trigger, hintsOnly, buildState.getCurrentOffset()); + } + if (maxComplexParallels > 5) { + buildState.addOffset(STRUCTURE_OFFSET_T6); + buildPiece(STRUCTURE_PIECE_T5_6, trigger, hintsOnly, buildState.getCurrentOffset()); + } + if (maxComplexParallels > 6) { + buildState.addOffset(STRUCTURE_OFFSET_T7); + buildPiece(STRUCTURE_PIECE_T7_8, trigger, hintsOnly, buildState.getCurrentOffset()); + } + if (maxComplexParallels > 7) { + buildState.addOffset(STRUCTURE_OFFSET_T8); + buildPiece(STRUCTURE_PIECE_T7_8, trigger, hintsOnly, buildState.getCurrentOffset()); + } + + buildState.stopBuilding(); + } + + @Override + public IStructureDefinition<AdvChemicalProcessor> getStructureDefinition() { + if (STRUCTURE_DEFINITION == null) { + STRUCTURE_DEFINITION = StructureDefinition.<AdvChemicalProcessor>builder() + .addShape( + STRUCTURE_PIECE_T1, + transpose( + new String[][] { { "CPCPC", "CCCCC", "CPCPC" }, { "CGC~C", "GWWWU", "CGCCC" }, + { "CPCPC", "CTTTC", "CPCPC" } })) + .addShape( + STRUCTURE_PIECE_T2, + new String[][] { { " ", " ", " ", " ", " ", " F F ", " B B " }, + { " ", " ", " ", " ", " ", " F F ", " B B " }, + { " ", " ", " ", " ", " ", " F F ", " BBB " }, + { " C ", " CGC ", " CGC ", " CGC ", " CGC ", " CGC ", " BCCCB " }, + { " BBB ", " C C ", " C C ", " C C ", " C C ", " C C ", "BCPPPCB" }, + { " CBBBC ", " G W G ", " G W G ", " G W G ", " G W G ", " G W G ", "BCPCPCB" }, + { " BBB ", " C C ", " C C ", " C C ", " C C ", " C C ", "BCPPPCB" }, + { " C ", " CGC ", " CGC ", " CGC ", " CGC ", " CGC ", " BCCCB " }, + { " ", " ", " ", " ", " ", " ", " BBB " } }) + .addShape( + STRUCTURE_PIECE_T3, + new String[][] { + { " ", " ", " ", " ", " ", " ", " BBB " }, + { " C ", " CGC ", " CGC ", " CGC ", " CGC ", " CGC ", " BCCCB " }, + { " BBB ", " C C ", " C C ", " C C ", " C C ", " C CFFF", "BCPPPCBBB" }, + { " CBBBC ", " G W G ", " G W G ", " G W G ", " G W G ", " G W G ", "BCPCPCB " }, + { " BBB ", " C C ", " C C ", " C C ", " C C ", " C CFFF", "BCPPPCBBB" }, + { " C ", " CGC ", " CGC ", " CGC ", " CGC ", " CGC ", " BCCCB " }, + { " ", " ", " ", " ", " ", " ", " BBB " } }) + .addShape( + STRUCTURE_PIECE_T4, + new String[][] { + { " ", " ", " ", " ", " ", " ", " BBB " }, + { " C ", " CGC ", " CGC ", " CGC ", " CGC ", " CGC ", " BCCCB " }, + { " BBB ", " C C ", " C C ", " C C ", " C C ", "FFFC C ", "BBBCPPPCB" }, + { " CBBBC ", " G W G ", " G W G ", " G W G ", " G W G ", " G W G ", " BCPCPCB" }, + { " BBB ", " C C ", " C C ", " C C ", " C C ", "FFFC C ", "BBBCPPPCB" }, + { " C ", " CGC ", " CGC ", " CGC ", " CGC ", " CGC ", " BCCCB " }, + { " ", " ", " ", " ", " ", " ", " BBB " } }) + .addShape( + STRUCTURE_PIECE_T5_6, + new String[][] { { " ", " ", " ", " ", " ", " F F ", " " }, + { " ", " ", " ", " ", " ", " F F ", " B B " }, + { " ", " ", " ", " ", " ", " F F ", " B B " }, + { " ", " ", " ", " ", " ", " F F ", " BBB " }, + { " C ", " CGC ", " CGC ", " CGC ", " CGC ", " CGC ", " BCCCB " }, + { " BBB ", " C C ", " C C ", " C C ", " C C ", " C C ", "BCPPPCB" }, + { " CBBBC ", " G W G ", " G W G ", " G W G ", " G W G ", " G W G ", "BCPCPCB" }, + { " BBB ", " C C ", " C C ", " C C ", " C C ", " C C ", "BCPPPCB" }, + { " C ", " CGC ", " CGC ", " CGC ", " CGC ", " CGC ", " BCCCB " }, + { " ", " ", " ", " ", " ", " ", " BBB " } }) + .addShape( + STRUCTURE_PIECE_T7_8, + new String[][] { { " ", " ", " ", " ", " ", " ", " BBB " }, + { " C ", " CGC ", " CGC ", " CGC ", " CGC ", " CGC ", " BCCCB " }, + { " BBB ", " C C ", " C C ", " C C ", " C C ", " C C ", "BCPPPCB" }, + { " CBBBC ", " G W G ", " G W G ", " G W G ", " G W G ", " G W G ", "BCPCPCB" }, + { " BBB ", " C C ", " C C ", " C C ", " C C ", " C C ", "BCPPPCB" }, + { " C ", " CGC ", " CGC ", " CGC ", " CGC ", " CGC ", " BCCCB " }, + { " ", " ", " ", " ", " ", " F F ", " BBB " }, + { " ", " ", " ", " ", " ", " F F ", " B B " }, + { " ", " ", " ", " ", " ", " F F ", " B B " }, + { " ", " ", " ", " ", " ", " F F ", " " } }) + .addElement( + 'C', + ofMuTECasings( + FLUID_IN | ITEM_IN | FLUID_OUT | ITEM_OUT | ENERGY_IN, + GT_MultiTileCasing.Chemical.getCasing())) + .addElement('P', ofBlock(GregTech_API.sBlockCasings8, 1)) + .addElement('T', ofMuTECasings(NOTHING, MOTOR_CASINGS)) + .addElement( + 'W', + GT_StructureUtility.ofCoil(AdvChemicalProcessor::setCoilTier, AdvChemicalProcessor::getCoilTier)) + .addElement('G', Glasses.chainAllGlasses()) + .addElement('B', ofBlock(GregTech_API.sBlockCasings4, 1)) + .addElement('F', GT_StructureUtility.ofFrame(Materials.Steel)) + .addElement( + 'U', + ofMuTECasings( + FLUID_IN | ITEM_IN | FLUID_OUT | ITEM_OUT | ENERGY_IN, + GT_MultiTileCasing.Chemical.getCasing(), + GT_StructureUtilityMuTE.INVENTORY_CASINGS)) + .build(); + } + return STRUCTURE_DEFINITION; + } + + @Override + protected void setMaxComplexParallels(int parallel, boolean stopMachine) { + super.setMaxComplexParallels(parallel, stopMachine); + onStructureChange(); + } + + protected MultiChildWidget createMainPage(IWidgetBuilder<?> builder) { + MultiChildWidget child = new MultiChildWidget(); + for (int i = 0; i < MAX_PROCESSES; i++) { + final int processIndex = i; + child.addChild( + new ButtonWidget().setPlayClickSound(true) + .setOnClick( + (clickData, widget) -> { + if (!widget.isClient()) widget.getContext() + .openSyncedWindow(PROCESS_WINDOW_BASE_ID + processIndex); + }) + .setBackground(GT_UITextures.BUTTON_STANDARD, GT_UITextures.OVERLAY_BUTTON_WHITELIST) + .setSize(18, 18) + .setEnabled((widget -> processIndex < maxComplexParallels)) + .setPos(20 * (i % 4) + 18, 18 + (i / 4) * 20)); + } + child.addChild( + new TextFieldWidget().setGetterInt(() -> maxComplexParallels) + .setSetterInt(parallel -> setMaxComplexParallels(parallel, true)) + .setNumbers(1, MAX_PROCESSES) + .setTextColor(Color.WHITE.normal) + .setTextAlignment(Alignment.Center) + .addTooltip("Tier") + .setBackground(GT_UITextures.BACKGROUND_TEXT_FIELD) + .setSize(18, 18) + .setPos(130, 85)); + return child; + } + + @Override + public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) { + super.addUIWidgets(builder, buildContext); + for (int i = 0; i < MAX_PROCESSES; i++) { + final int processIndex = i; + buildContext.addSyncedWindow( + PROCESS_WINDOW_BASE_ID + i, + (player) -> createProcessConfigWindow(player, processIndex)); + } + buildContext.addCloseListener(() -> { + // Reset HashSet, we will let it re-generate on next item output + if (wasWhitelistOpened) { + for (int i = 0; i < MAX_PROCESSES; i++) { + processWhitelists.set(i, null); + } + wasWhitelistOpened = false; + } + }); + } + + protected ModularWindow createProcessConfigWindow(final EntityPlayer player, final int processIndex) { + wasWhitelistOpened = true; + ModularWindow.Builder builder = ModularWindow.builder(86, 100); + builder.widget( + new TextWidget("Process " + processIndex).setTextAlignment(Alignment.Center) + .setPos(13, 7)); + builder.setBackground(GT_UITextures.BACKGROUND_SINGLEBLOCK_DEFAULT); + builder.widget( + SlotGroup.ofItemHandler(processWhitelistInventoryHandlers.get(processIndex), 4) + .startFromSlot(0) + .endAtSlot(ITEM_WHITELIST_SLOTS - 1) + .phantom(true) + .background(getGUITextureSet().getItemSlot()) + .build() + .setPos(7, 19)); + builder.widget( + SlotGroup.ofFluidTanks(processFluidWhiteLists.get(processIndex), 4) + .startFromSlot(0) + .endAtSlot(FLUID_WHITELIST_SLOTS - 1) + .phantom(true) + .build() + .setPos(7, 55)); + return builder.build(); + } + + @Override + public String getTileEntityName() { + return "gt.multitileentity.multiblock.advchemicalprocessor"; + } + + @Override + public String getLocalName() { + return "Advanced Chemical Processor"; + } + + public void setCoilTier(HeatingCoilLevel coilTier) { + this.coilTier = coilTier; + } + + public HeatingCoilLevel getCoilTier() { + return coilTier; + } + + @Override + protected boolean hasPerfectOverclock() { + return true; + } + + protected void generateWhitelist(int processIndex) { + HashSet<String> whitelist = new HashSet<>(); + for (ItemStack itemStack : processWhitelistInventoryHandlers.get(processIndex) + .getStacks()) { + if (itemStack != null) { + whitelist.add(getWhitelistString(itemStack)); + } + } + for (IFluidTank tank : processFluidWhiteLists.get(processIndex)) { + if (tank.getFluid() != null) { + whitelist.add(getWhitelistString(tank.getFluid())); + } + } + processWhitelists.set(processIndex, whitelist); + } + + protected String getWhitelistString(ItemStack itemStack) { + if (itemStack != null) { + return itemStack.getUnlocalizedName(); + } + return null; + } + + protected String getWhitelistString(FluidStack fluidStack) { + if (fluidStack != null) { + return fluidStack.getUnlocalizedName(); + } + return null; + } + + @Override + @Nonnull + protected AdvChemicalProcessorProcessingLogic createProcessingLogic() { + return new AdvChemicalProcessorProcessingLogic(); + } +} diff --git a/src/main/java/gregtech/common/tileentities/machines/multiblock/AdvChemicalReactor.java b/src/main/java/gregtech/common/tileentities/machines/multiblock/AdvChemicalReactor.java deleted file mode 100644 index 38ed9b6603..0000000000 --- a/src/main/java/gregtech/common/tileentities/machines/multiblock/AdvChemicalReactor.java +++ /dev/null @@ -1,434 +0,0 @@ -package gregtech.common.tileentities.machines.multiblock; - -import static com.google.common.primitives.Ints.saturatedCast; -import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock; -import static com.gtnewhorizon.structurelib.structure.StructureUtility.transpose; -import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.ENERGY_IN; -import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.FLUID_IN; -import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.FLUID_OUT; -import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.ITEM_IN; -import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.ITEM_OUT; -import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.NOTHING; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; - -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; -import net.minecraftforge.common.util.Constants; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.IFluidTank; - -import org.apache.commons.lang3.ArrayUtils; - -import com.gtnewhorizon.structurelib.structure.IStructureDefinition; -import com.gtnewhorizon.structurelib.structure.StructureDefinition; -import com.gtnewhorizon.structurelib.util.Vec3Impl; -import com.gtnewhorizons.modularui.api.forge.ItemStackHandler; -import com.gtnewhorizons.modularui.api.math.Alignment; -import com.gtnewhorizons.modularui.api.screen.ModularWindow; -import com.gtnewhorizons.modularui.api.screen.UIBuildContext; -import com.gtnewhorizons.modularui.api.widget.IWidgetBuilder; -import com.gtnewhorizons.modularui.common.widget.ButtonWidget; -import com.gtnewhorizons.modularui.common.widget.MultiChildWidget; -import com.gtnewhorizons.modularui.common.widget.SlotGroup; -import com.gtnewhorizons.modularui.common.widget.TextWidget; - -import gregtech.api.GregTech_API; -import gregtech.api.enums.GT_Values; -import gregtech.api.enums.HeatingCoilLevel; -import gregtech.api.fluid.FluidTankGT; -import gregtech.api.gui.modularui.GT_UITextures; -import gregtech.api.logic.ComplexParallelProcessingLogic; -import gregtech.api.multitileentity.enums.GT_MultiTileCasing; -import gregtech.api.multitileentity.multiblock.base.ComplexParallelController; -import gregtech.api.multitileentity.multiblock.casing.Glasses; -import gregtech.api.recipe.RecipeMap; -import gregtech.api.recipe.RecipeMaps; -import gregtech.api.util.GT_Multiblock_Tooltip_Builder; -import gregtech.api.util.GT_StructureUtility; -import gregtech.common.tileentities.casings.upgrade.Inventory; - -public class AdvChemicalReactor extends ComplexParallelController<AdvChemicalReactor> { - - private static IStructureDefinition<AdvChemicalReactor> STRUCTURE_DEFINITION = null; - protected static final String STRUCTURE_PIECE_T1 = "T1"; - protected static final Vec3Impl STRUCTURE_OFFSET = new Vec3Impl(3, 1, 0); - protected static final int PROCESS_WINDOW_BASE_ID = 100; - protected static final int ITEM_WHITELIST_SLOTS = 8; - protected static final int FLUID_WHITELIST_SLOTS = 8; - protected static final int MAX_PROCESSES = 4; - protected int numberOfProcessors = MAX_PROCESSES; // TODO: Set this value depending on structure - protected HeatingCoilLevel coilTier; - protected final ArrayList<HashSet<String>> processWhitelists = new ArrayList<>(MAX_PROCESSES); - protected final ArrayList<ItemStackHandler> processWhitelistInventoryHandlers = new ArrayList<>(MAX_PROCESSES); - protected final ArrayList<ArrayList<IFluidTank>> processFluidWhiteLists = new ArrayList<>(MAX_PROCESSES); - protected boolean wasWhitelistOpened = false; - - public AdvChemicalReactor() { - super(); - for (int i = 0; i < MAX_PROCESSES; i++) { - processWhitelists.add(null); - processWhitelistInventoryHandlers.add(new ItemStackHandler(ITEM_WHITELIST_SLOTS)); - ArrayList<IFluidTank> processFluidTanks = new ArrayList<>(FLUID_WHITELIST_SLOTS); - for (int j = 0; j < FLUID_WHITELIST_SLOTS; j++) { - processFluidTanks.add(new FluidTankGT()); - } - processFluidWhiteLists.add(processFluidTanks); - } - processingLogic = new ComplexParallelProcessingLogic(getRecipeMap(), MAX_PROCESSES); - } - - @Override - public RecipeMap<?> getRecipeMap() { - return RecipeMaps.chemicalReactorRecipes; - } - - @Override - public void readMultiTileNBT(NBTTagCompound nbt) { - super.readMultiTileNBT(nbt); - final NBTTagCompound processWhiteLists = nbt.getCompoundTag("whiteLists"); - long capacity = 1000; - if (nbt.hasKey(GT_Values.NBT.TANK_CAPACITY)) { - capacity = saturatedCast(nbt.getLong(GT_Values.NBT.TANK_CAPACITY)); - } - for (int i = 0; i < MAX_PROCESSES; i++) { - registerInventory("processInventory" + i, "processInventory" + i, 8, Inventory.INPUT); - registerFluidInventory( - "processInventory" + i, - "processInventory" + i, - 8, - capacity, - maxParallel * 2L, - Inventory.INPUT); - if (processWhiteLists != null) { - final NBTTagCompound itemList = processWhiteLists.getCompoundTag("items" + i); - if (itemList != null) { - processWhitelistInventoryHandlers.get(i) - .deserializeNBT(itemList); - } - final NBTTagList fluidList = processWhiteLists.getTagList("fluids" + i, Constants.NBT.TAG_COMPOUND); - if (fluidList != null) { - for (int j = 0; j < fluidList.tagCount(); j++) { - final NBTTagCompound fluid = fluidList.getCompoundTagAt(j); - if (fluid != null) { - short index = fluid.getShort("s"); - FluidStack fluidStack = FluidStack.loadFluidStackFromNBT(fluid); - if (fluidStack != null) { - processFluidWhiteLists.get(i) - .get(index) - .fill(fluidStack, true); - } - } - } - } - } - } - } - - @Override - public void writeMultiTileNBT(NBTTagCompound nbt) { - super.writeMultiTileNBT(nbt); - final NBTTagCompound processWhiteLists = new NBTTagCompound(); - for (int i = 0; i < MAX_PROCESSES; i++) { - processWhiteLists.setTag( - "items" + i, - processWhitelistInventoryHandlers.get(i) - .serializeNBT()); - final NBTTagList fluidList = new NBTTagList(); - for (int j = 0; j < FLUID_WHITELIST_SLOTS; j++) { - final FluidStack fluidStack = processFluidWhiteLists.get(i) - .get(j) - .getFluid(); - if (fluidStack != null) { - final NBTTagCompound tag = new NBTTagCompound(); - tag.setByte("s", (byte) j); - fluidStack.writeToNBT(tag); - fluidList.appendTag(tag); - } - } - processWhiteLists.setTag("fluids" + i, fluidList); - } - nbt.setTag("whiteLists", processWhiteLists); - } - - @Override - public short getCasingRegistryID() { - return 0; - } - - @Override - public int getCasingMeta() { - return GT_MultiTileCasing.Chemical.getId(); - } - - @Override - public GT_Multiblock_Tooltip_Builder createTooltip() { - final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder(); - tt.addMachineType("Chemical Reactor") - .addInfo("Controller block for the Advanced Chemical Reactor") - .addInfo("Does not lose efficiency when overclocked") - .addInfo("Accepts fluids instead of fluid cells") - .addInfo("Can do multiple different recipes at once") - .addInfo("By using the whitelist filter a recipe can push its output") - .addInfo("to a different recipes input to chain them") - .addInfo(GT_Values.Authorminecraft7771) - .addSeparator() - .beginStructureBlock(5, 3, 3, false) - .addController("Front center") - .addCasingInfoExactly("PTFE Pipe Machine Casing", 8, false) - .addCasingInfoExactly("Heating Coils", 3, true) - .addCasingInfoExactly("EV+ Glass", 3, true) - .addCasingInfoExactly("Motor Casing", 3, true) - .addCasingInfoExactly("Chemical Casing", 27, false) - .toolTipFinisher("Gregtech"); - return tt; - } - - @Override - public Vec3Impl getStartingStructureOffset() { - return STRUCTURE_OFFSET; - } - - @Override - public boolean checkMachine() { - setCoilTier(HeatingCoilLevel.None); - setMaxComplexParallels(MAX_PROCESSES); - buildState.startBuilding(getStartingStructureOffset()); - boolean result = checkPiece(STRUCTURE_PIECE_T1, buildState.stopBuilding()); - return result && super.checkMachine(); - } - - @Override - public void construct(ItemStack trigger, boolean hintsOnly) { - buildState.startBuilding(getStartingStructureOffset()); - buildPiece(STRUCTURE_PIECE_T1, trigger, hintsOnly, buildState.stopBuilding()); - } - - @Override - public IStructureDefinition<AdvChemicalReactor> getStructureDefinition() { - if (STRUCTURE_DEFINITION == null) { - STRUCTURE_DEFINITION = StructureDefinition.<AdvChemicalReactor>builder() - .addShape( - STRUCTURE_PIECE_T1, - transpose( - new String[][] { { "CPCPC", "CCCCC", "CPCPC" }, { "CGC~C", "GWWWC", "CGCCC" }, - { "CPCPC", "CTTTC", "CPCPC" } })) - .addElement( - 'C', - addMultiTileCasing( - "gt.multitileentity.casings", - getCasingMeta(), - FLUID_IN | ITEM_IN | FLUID_OUT | ITEM_OUT | ENERGY_IN)) - .addElement('P', ofBlock(GregTech_API.sBlockCasings8, 1)) - .addElement('T', addMotorCasings(NOTHING)) - .addElement( - 'W', - GT_StructureUtility.ofCoil(AdvChemicalReactor::setCoilTier, AdvChemicalReactor::getCoilTier)) - .addElement('G', Glasses.chainAllGlasses()) - .build(); - } - return STRUCTURE_DEFINITION; - } - - @Override - protected FluidStack[] getInputFluids(int index) { - if (index < 0 || index >= MAX_PROCESSES) { - return null; - } - if (separateInputs) { - return ArrayUtils.addAll( - getFluidInputsForTankArray("processInventory" + index), - FluidTankGT.getFluidsFromTanks(inputTanks)); - } else { - return super.getInputFluids(index); - } - } - - @Override - protected ItemStack[] getInputItems(int index) { - if (index < 0 || index >= MAX_PROCESSES) { - return null; - } - if (separateInputs) { - return ArrayUtils.addAll( - getItemInputsForInventory("processInventory" + index), - inputInventory.getStacks() - .toArray(new ItemStack[0])); - } else { - return super.getInputItems(index); - } - } - - @Override - protected void outputItems(int index) { - ComplexParallelProcessingLogic processingLogic = getComplexProcessingLogic(); - if (processingLogic != null && index >= 0 && index < maxComplexParallels) { - for (int i = 0; i < MAX_PROCESSES; i++) { - // Regenerate whitelist, if it has been reset - if (processWhitelists.get(i) == null) { - generateWhitelist(i); - } - int outputIndex = i; - // Output items that are on the whitelist of this process - outputItems( - multiBlockInputInventory.get("processInventory" + i), - Arrays.stream(processingLogic.getOutputItems(index)) - .filter( - itemStack -> processWhitelists.get(outputIndex) - .contains(getWhitelistString(itemStack))) - .toArray(ItemStack[]::new)); - } - // Output remaining items - if (processingLogic.getOutputItems(index) != null && processingLogic.getOutputItems(index).length > 0) { - outputItems(processingLogic.getOutputItems(index)); - } - } - } - - @Override - protected void outputFluids(int index) { - ComplexParallelProcessingLogic processingLogic = getComplexProcessingLogic(); - if (processingLogic != null && index >= 0 && index < maxComplexParallels) { - for (int i = 0; i < MAX_PROCESSES; i++) { - // Regenerate whitelist, if it has been reset - if (processWhitelists.get(i) == null) { - generateWhitelist(i); - } - int outputIndex = i; - // Output fluids that are on the whitelist of this process - outputFluids( - multiBlockInputTank.get("processInventory" + i), - Arrays.stream(processingLogic.getOutputFluids(index)) - .filter( - fluidStack -> processWhitelists.get(outputIndex) - .contains(getWhitelistString(fluidStack))) - .toArray(FluidStack[]::new)); - } - // Output remaining fluids - if (processingLogic.getOutputFluids(index) != null && processingLogic.getOutputFluids(index).length > 0) { - outputFluids(processingLogic.getOutputFluids(index)); - } - } - } - - @Override - protected MultiChildWidget createMainPage(IWidgetBuilder<?> builder) { - MultiChildWidget child = super.createMainPage(builder); - for (int i = 0; i < MAX_PROCESSES; i++) { - final int processIndex = i; - child.addChild( - new ButtonWidget().setPlayClickSound(true) - .setOnClick( - (clickData, widget) -> { - if (!widget.isClient()) widget.getContext() - .openSyncedWindow(PROCESS_WINDOW_BASE_ID + processIndex); - }) - .setBackground(GT_UITextures.BUTTON_STANDARD, GT_UITextures.OVERLAY_BUTTON_WHITELIST) - .setSize(18, 18) - .setPos(20 * i + 18, 18)); - } - return child; - } - - @Override - public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) { - super.addUIWidgets(builder, buildContext); - for (int i = 0; i < MAX_PROCESSES; i++) { - final int processIndex = i; - buildContext.addSyncedWindow( - PROCESS_WINDOW_BASE_ID + i, - (player) -> createProcessConfigWindow(player, processIndex)); - } - buildContext.addCloseListener(() -> { - // Reset HashSet, we will let it re-generate on next item output - if (wasWhitelistOpened) { - for (int i = 0; i < MAX_PROCESSES; i++) { - processWhitelists.set(i, null); - } - wasWhitelistOpened = false; - } - }); - } - - protected ModularWindow createProcessConfigWindow(final EntityPlayer player, final int processIndex) { - wasWhitelistOpened = true; - ModularWindow.Builder builder = ModularWindow.builder(86, 100); - builder.widget( - new TextWidget("Process " + processIndex).setTextAlignment(Alignment.Center) - .setPos(13, 7)); - builder.setBackground(GT_UITextures.BACKGROUND_SINGLEBLOCK_DEFAULT); - builder.widget( - SlotGroup.ofItemHandler(processWhitelistInventoryHandlers.get(processIndex), 4) - .startFromSlot(0) - .endAtSlot(ITEM_WHITELIST_SLOTS - 1) - .phantom(true) - .background(getGUITextureSet().getItemSlot()) - .build() - .setPos(7, 19)); - builder.widget( - SlotGroup.ofFluidTanks(processFluidWhiteLists.get(processIndex), 4) - .startFromSlot(0) - .endAtSlot(FLUID_WHITELIST_SLOTS - 1) - .phantom(true) - .build() - .setPos(7, 55)); - return builder.build(); - } - - @Override - public String getTileEntityName() { - return "gt.multitileentity.multiblock.advchemicalreactor"; - } - - @Override - public String getLocalName() { - return "Advanced Chemical Reactor"; - } - - public void setCoilTier(HeatingCoilLevel coilTier) { - this.coilTier = coilTier; - } - - public HeatingCoilLevel getCoilTier() { - return coilTier; - } - - @Override - protected boolean hasPerfectOverclock() { - return true; - } - - protected void generateWhitelist(int processIndex) { - HashSet<String> whitelist = new HashSet<>(); - for (ItemStack itemStack : processWhitelistInventoryHandlers.get(processIndex) - .getStacks()) { - if (itemStack != null) { - whitelist.add(getWhitelistString(itemStack)); - } - } - for (IFluidTank tank : processFluidWhiteLists.get(processIndex)) { - if (tank.getFluid() != null) { - whitelist.add(getWhitelistString(tank.getFluid())); - } - } - processWhitelists.set(processIndex, whitelist); - } - - protected String getWhitelistString(ItemStack itemStack) { - if (itemStack != null) { - return itemStack.getUnlocalizedName(); - } - return null; - } - - protected String getWhitelistString(FluidStack fluidStack) { - if (fluidStack != null) { - return fluidStack.getUnlocalizedName(); - } - return null; - } -} diff --git a/src/main/java/gregtech/common/tileentities/machines/multiblock/CokeOven.java b/src/main/java/gregtech/common/tileentities/machines/multiblock/CokeOven.java index 13f60da821..06fc7b42b1 100644 --- a/src/main/java/gregtech/common/tileentities/machines/multiblock/CokeOven.java +++ b/src/main/java/gregtech/common/tileentities/machines/multiblock/CokeOven.java @@ -2,9 +2,12 @@ package gregtech.common.tileentities.machines.multiblock; import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.ITEM_IN; import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.ITEM_OUT; +import static gregtech.api.util.GT_StructureUtilityMuTE.ofMuTECasings; import java.util.List; +import javax.annotation.Nonnull; + import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; import net.minecraft.item.ItemStack; @@ -16,34 +19,29 @@ import com.gtnewhorizon.structurelib.structure.StructureDefinition; import com.gtnewhorizon.structurelib.util.Vec3Impl; import com.gtnewhorizons.modularui.api.math.Alignment; import com.gtnewhorizons.modularui.api.screen.ModularWindow; -import com.gtnewhorizons.modularui.api.screen.UIBuildContext; import com.gtnewhorizons.modularui.common.internal.network.NetworkUtils; import com.gtnewhorizons.modularui.common.widget.DrawableWidget; -import com.gtnewhorizons.modularui.common.widget.SlotWidget; import com.gtnewhorizons.modularui.common.widget.TextWidget; import gregtech.GT_Mod; import gregtech.api.enums.GT_Values; -import gregtech.api.logic.PollutionLogic; -import gregtech.api.logic.ProcessingLogic; -import gregtech.api.logic.interfaces.PollutionLogicHost; -import gregtech.api.logic.interfaces.ProcessingLogicHost; import gregtech.api.multitileentity.enums.GT_MultiTileCasing; import gregtech.api.multitileentity.multiblock.base.Controller; +import gregtech.api.task.tasks.PollutionTask; import gregtech.api.util.GT_Multiblock_Tooltip_Builder; import gregtech.common.tileentities.machines.multiblock.logic.CokeOvenProcessingLogic; -public class CokeOven extends Controller<CokeOven> implements PollutionLogicHost, ProcessingLogicHost { +public class CokeOven extends Controller<CokeOven, CokeOvenProcessingLogic> { private static IStructureDefinition<CokeOven> STRUCTURE_DEFINITION = null; private static final Vec3Impl OFFSET = new Vec3Impl(1, 1, 0); private static final String MAIN = "Main"; - private static final PollutionLogic POLLUTION_LOGIC = new PollutionLogic().setPollutionAmount(10); - private final ProcessingLogic PROCESSING_LOGIC = new CokeOvenProcessingLogic(); + private static final int POLLUTION_AMOUNT = 10; public CokeOven() { super(); setElectric(false); + new PollutionTask<>(this).setPollutionPerSecond(POLLUTION_AMOUNT); } @Override @@ -81,7 +79,7 @@ public class CokeOven extends Controller<CokeOven> implements PollutionLogicHost .addInfo("Used for charcoal") .beginStructureBlock(3, 3, 3, true) .addCasingInfoExactly("Coke Oven Bricks", 25, false) - .addPollutionAmount(POLLUTION_LOGIC.getPollutionAmount()) + .addPollutionAmount(POLLUTION_AMOUNT) .toolTipFinisher(GT_Values.AuthorBlueWeabo); return tt; } @@ -98,29 +96,18 @@ public class CokeOven extends Controller<CokeOven> implements PollutionLogicHost .addShape( MAIN, new String[][] { { "AAA", "A~A", "AAA" }, { "AAA", "A-A", "AAA" }, { "AAA", "AAA", "AAA" } }) - .addElement('A', addMultiTileCasing("gt.multitileentity.casings", getCasingMeta(), ITEM_IN | ITEM_OUT)) + .addElement('A', ofMuTECasings(ITEM_IN | ITEM_OUT, GT_MultiTileCasing.CokeOven.getCasing())) .build(); } return STRUCTURE_DEFINITION; } @Override - protected boolean hasFluidInput() { + public boolean hasFluidInput() { return false; } @Override - public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) { - builder.widget( - new SlotWidget(inputInventory, 0).setPos(18, 18) - .setSize(18, 18)); - builder.widget( - new SlotWidget(outputInventory, 0).setPos(36, 36) - .setSize(18, 18)); - builder.widget(createButtons(builder)); - } - - @Override protected void addTitleTextStyle(ModularWindow.Builder builder, String title) { final int TAB_PADDING = 3; final int TITLE_PADDING = 2; @@ -159,12 +146,8 @@ public class CokeOven extends Controller<CokeOven> implements PollutionLogicHost } @Override - public PollutionLogic getPollutionLogic() { - return POLLUTION_LOGIC; - } - - @Override - public ProcessingLogic getProcessingLogic() { - return PROCESSING_LOGIC; + @Nonnull + protected CokeOvenProcessingLogic createProcessingLogic() { + return new CokeOvenProcessingLogic(); } } diff --git a/src/main/java/gregtech/common/tileentities/machines/multiblock/DistillationTower.java b/src/main/java/gregtech/common/tileentities/machines/multiblock/DistillationTower.java new file mode 100644 index 0000000000..326bfcc9ee --- /dev/null +++ b/src/main/java/gregtech/common/tileentities/machines/multiblock/DistillationTower.java @@ -0,0 +1,174 @@ +package gregtech.common.tileentities.machines.multiblock; + +import static com.gtnewhorizon.structurelib.structure.StructureUtility.*; +import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.*; +import static gregtech.api.util.GT_StructureUtilityMuTE.MOTOR_CASINGS; +import static gregtech.api.util.GT_StructureUtilityMuTE.ofMuTECasings; + +import javax.annotation.Nonnull; + +import com.gtnewhorizon.structurelib.structure.IStructureDefinition; +import com.gtnewhorizon.structurelib.structure.StructureDefinition; +import com.gtnewhorizon.structurelib.util.Vec3Impl; + +import gregtech.api.GregTech_API; +import gregtech.api.enums.GT_Values; +import gregtech.api.enums.HeatingCoilLevel; +import gregtech.api.enums.Materials; +import gregtech.api.multitileentity.enums.GT_MultiTileCasing; +import gregtech.api.multitileentity.multiblock.base.StackableController; +import gregtech.api.util.GT_Multiblock_Tooltip_Builder; +import gregtech.api.util.GT_StructureUtility; +import gregtech.common.tileentities.machines.multiblock.logic.DistillationTowerProcessingLogic; + +public class DistillationTower extends StackableController<DistillationTower, DistillationTowerProcessingLogic> { + + private static IStructureDefinition<DistillationTower> STRUCTURE_DEFINITION_MEGA = null; + private static final Vec3Impl STRUCTURE_OFFSET_MEGA = new Vec3Impl(8, 3, 0); + private static final Vec3Impl STRUCTURE_OFFSET_MEGA_START = new Vec3Impl(0, 3, 0); + private static final Vec3Impl STRUCTURE_OFFSET_MEGA_STOP = new Vec3Impl(0, 5, 0); + private static final Vec3Impl STRUCTURE_OFFSET_MEGA_STACK = new Vec3Impl(0, 3, 0); + private static final String STACKABLE_MIDDLE_1 = "STACKABLE_MIDDLE_1"; + private static final String STACKABLE_MIDDLE_2 = "STACKABLE_MIDDLE_2"; + private boolean isMega = true; + + @Override + public short getCasingRegistryID() { + return 0; + } + + @Override + public int getCasingMeta() { + return GT_MultiTileCasing.Distillation.getId(); + } + + @Override + public GT_Multiblock_Tooltip_Builder createTooltip() { + final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder(); + tt.addMachineType("Distillation Tower") + .addInfo("Controller block for the Distillation Tower") + .addInfo("Can be specialised to be a mega structure") + .addInfo(GT_Values.Authorminecraft7771) + .addSeparator() + .beginStructureBlock(5, 3, 3, false) + .addController("Front center") + .toolTipFinisher("Gregtech"); + return tt; + } + + @Override + public Vec3Impl getStartingStructureOffset() { + return STRUCTURE_OFFSET_MEGA; + } + + @Override + public IStructureDefinition<DistillationTower> getStructureDefinition() { + if (STRUCTURE_DEFINITION_MEGA == null) { + STRUCTURE_DEFINITION_MEGA = StructureDefinition.<DistillationTower>builder() + .addShape( + STACKABLE_START, + transpose( + // spotless:off + new String[][]{ + {" "," "," "," "," "," ECCCCCE "," CCCCCCC "," C C "," EC CE "," CC CC "," CC CC ABA "," CC CC B B "," CC CC ABA "," CC CC "," EC CE "," C C "," CCCCCCC "," ECCCCCE "," "}, + {" "," EEE "," E "," E "," E "," E E E "," CCCCCCC "," C C "," EC CE "," C C "," C C ABA "," C C B B "," C C ABA "," C C "," EC CE "," C C "," CCCCCCC "," E E "," "}, + {" CCCCC "," CCCCC "," CCCCC "," "," "," E E "," CCCCCCC "," C C "," EC CE "," C C "," C C ABA "," C C B B "," C C ABA "," C C "," EC CE "," C C "," CCCCCCC "," E E "," "}, + {" CXC~C "," BDDDB "," CBCBC "," B B "," B B "," E B B E "," CCCCCCC "," C C "," EC CE "," C C "," C C AAA "," C C A A "," C C AAA "," C C "," EC CE "," C C "," CCCCCCC "," E E "," "}, + {" CCCCC "," CCCCC "," CCCCC "," "," CCCCCCCCCCC "," CAAAAAAAAAC ","CCCACCCCCCCACCC ","CAACAAAAAAACAAC ","CACAADDDDDAACAC ","CACADDDDDDDACACCCCC","CACADDAAADDACACCCCC","CACADDAAADDACACCCCC","CACADDAAADDACACCCCC","CACADDDDDDDACACCCCC","CACAADDDDDAACAC ","CAACAAAAAAACAAC ","CCCACCCCCCCACCC "," CAAAAAAAAAC "," CCCCCCCCCCC "} + })) + .addShape( + STACKABLE_STOP, + transpose( + new String[][]{ + {" "," "," "," "," "," "," "," "," "," "," CCC "," CCC "," CCC "," "," "," "," "," "," "}, + {" "," "," "," "," "," E E "," E E "," E E "," EEEEAAAAAEEEE "," AAAAAAA "," AA AA "," AA AA "," AA AA "," AAAAAAA "," EEEEAAAAAEEEE "," E E "," E E "," E E "," "}, + {" "," "," "," "," "," ECCCCCE "," CCCCCCCCC "," CCCCCCCCCCC "," ECCC CCCE "," CCC CCC "," CCC CCC "," CCC CCC "," CCC CCC "," CCC CCC "," ECCC CCCE "," CCCCCCCCCCC "," CCCCCCCCC "," ECCCCCE "," "}, + {" "," "," "," "," "," E E "," CCCCCCC "," C C "," EC CE "," C C "," C C "," C C "," C C "," C C "," EC CE "," C C "," CCCCCCC "," E E "," "}, + {" "," "," "," "," "," E E "," CCCCCCC "," C C "," EC CE "," C C "," C CAAAAA "," C CABBBA "," C CAAAAA "," C C "," EC CE "," C C "," CCCCCCC "," E E "," "}, + {" "," "," "," "," "," ECCCCCE "," CCCCCCC "," C C "," EC CE "," CC CC "," CC CABBBA "," CC C B "," CC CABBBA "," CC CC "," EC CE "," C C "," CCCCCCC "," ECCCCCE "," "}, + {" "," "," "," "," "," E E "," CCCCCCC "," C C "," EC CE "," C C "," C CAAABA "," C CAAA B "," C CAAABA "," C C "," EC CE "," C C "," CCCCCCC "," E E "," "}, + {" "," "," "," "," "," E E "," CCCCCCC "," C C "," EC CE "," C C "," C C ABA "," C C A B "," C C ABA "," C C "," EC CE "," C C "," CCCCCCC "," E E "," "}, + })) + .addShape( + STACKABLE_MIDDLE_1, + transpose( + new String[][]{ + {" "," "," "," "," "," E E "," CCCCCCC "," C C "," EC CE "," C C "," C C ABA "," C C B B "," C C ABA "," C C "," EC CE "," C C "," CCCCCCC "," E E "," "}, + {" "," "," "," "," "," E E "," CCCCCCC "," C C "," EC CE "," C C "," C C ABA "," C C B B "," C C ABA "," C C "," EC CE "," C C "," CCCCCCC "," E E "," "}, + {" "," "," "," "," "," E E "," CCCCCCC "," C C "," EC CE "," C C "," C C ABA "," C C B B "," C C ABA "," C C "," EC CE "," C C "," CCCCCCC "," E E "," "}, + })) + .addShape( + STACKABLE_MIDDLE_2, + transpose( + new String[][]{ + {" "," "," "," "," "," ECCCCCE "," CCCCCCC "," C C "," EC CE "," CC CC "," CC CC ABA "," CC CC B B "," CC CC ABA "," CC CC "," EC CE "," C C "," CCCCCCC "," ECCCCCE "," "}, + {" "," "," "," "," "," E E "," CCCCCCC "," C C "," EC CE "," C C "," C C ABA "," C C B B "," C C ABA "," C C "," EC CE "," C C "," CCCCCCC "," E E "," "}, + {" "," "," "," "," "," E E "," CCCCCCC "," C C "," EC CE "," C C "," C C ABA "," C C B B "," C C ABA "," C C "," EC CE "," C C "," CCCCCCC "," E E "," "}, + })) + // spotless:on + .addElement( + 'C', + ofMuTECasings( + FLUID_IN | ITEM_IN | FLUID_OUT | ITEM_OUT | ENERGY_IN, + GT_MultiTileCasing.Distillation.getCasing())) + .addElement('E', GT_StructureUtility.ofFrame(Materials.StainlessSteel)) + .addElement('A', ofBlock(GregTech_API.sBlockCasings2, 0)) + .addElement('B', ofBlock(GregTech_API.sBlockCasings2, 13)) + .addElement('X', ofMuTECasings(NOTHING, MOTOR_CASINGS)) + .addElement('D', GT_StructureUtility.ofCoil((tile, meta) -> {}, (tile) -> HeatingCoilLevel.None)) + .build(); + } + return STRUCTURE_DEFINITION_MEGA; + } + + @Override + public int getFluidOutputCount() { + return 12; + } + + @Override + public int getMinStacks() { + return 0; + } + + @Override + public int getMaxStacks() { + return 9; + } + + @Override + public Vec3Impl getStartingStackOffset() { + return STRUCTURE_OFFSET_MEGA_START; + } + + @Override + public Vec3Impl getPerStackOffset() { + return STRUCTURE_OFFSET_MEGA_STACK; + } + + @Override + public Vec3Impl getAfterLastStackOffset() { + return STRUCTURE_OFFSET_MEGA_STOP; + } + + @Override + public String getTileEntityName() { + return "gt.multitileentity.multiblock.distillationtower"; + } + + @Override + public String getLocalName() { + return "Distillation Tower"; + } + + @Override + protected String getStackableMiddle(int stackIndex) { + return stackIndex % 2 == 0 ? STACKABLE_MIDDLE_1 : STACKABLE_MIDDLE_2; + } + + @Override + @Nonnull + protected DistillationTowerProcessingLogic createProcessingLogic() { + return new DistillationTowerProcessingLogic(); + } +} diff --git a/src/main/java/gregtech/common/tileentities/machines/multiblock/LaserEngraver.java b/src/main/java/gregtech/common/tileentities/machines/multiblock/LaserEngraver.java new file mode 100644 index 0000000000..93bcc09a0b --- /dev/null +++ b/src/main/java/gregtech/common/tileentities/machines/multiblock/LaserEngraver.java @@ -0,0 +1,305 @@ +package gregtech.common.tileentities.machines.multiblock; + +import static com.gtnewhorizon.structurelib.structure.StructureUtility.*; +import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlockUnlocalizedName; +import static gregtech.api.enums.Mods.*; +import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.*; +import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.ENERGY_IN; +import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.FLUID_OUT; +import static gregtech.api.util.GT_StructureUtilityMuTE.*; + +import java.util.UUID; + +import javax.annotation.Nonnull; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; + +import com.gtnewhorizon.structurelib.structure.IStructureDefinition; +import com.gtnewhorizon.structurelib.structure.StructureDefinition; +import com.gtnewhorizon.structurelib.util.Vec3Impl; +import com.gtnewhorizons.modularui.api.math.Alignment; +import com.gtnewhorizons.modularui.api.math.Color; +import com.gtnewhorizons.modularui.api.widget.IWidgetBuilder; +import com.gtnewhorizons.modularui.common.widget.ButtonWidget; +import com.gtnewhorizons.modularui.common.widget.MultiChildWidget; +import com.gtnewhorizons.modularui.common.widget.textfield.TextFieldWidget; + +import gregtech.api.GregTech_API; +import gregtech.api.enums.GT_Values; +import gregtech.api.enums.Materials; +import gregtech.api.gui.modularui.GT_UITextures; +import gregtech.api.multitileentity.enums.GT_MultiTileCasing; +import gregtech.api.multitileentity.multiblock.base.ComplexParallelController; +import gregtech.api.recipe.RecipeMap; +import gregtech.api.util.GT_Multiblock_Tooltip_Builder; +import gregtech.api.util.GT_StructureUtility; +import gregtech.common.tileentities.machines.multiblock.logic.LaserEngraverProcessingLogic; + +public class LaserEngraver extends ComplexParallelController<LaserEngraver, LaserEngraverProcessingLogic> { + + private static IStructureDefinition<LaserEngraver> STRUCTURE_DEFINITION = null; + protected static final String STRUCTURE_MAIN = "Main"; + protected static final String STRUCTURE_PIECE_T1 = "T1"; + protected static final String STRUCTURE_PIECE_T2 = "T2"; + protected static final String STRUCTURE_PIECE_T3 = "T3"; + protected static final String STRUCTURE_PIECE_T4 = "T4"; + protected static final String STRUCTURE_PIECE_T5 = "T5"; + protected static final String STRUCTURE_PIECE_T6 = "T6"; + protected static final int PROCESS_WINDOW_BASE_ID = 100; + protected static final Vec3Impl STRUCTURE_OFFSET_T1 = new Vec3Impl(3, 1, 0); + protected static final Vec3Impl STRUCTURE_OFFSET_T2 = new Vec3Impl(1, 3, 0); + protected static final Vec3Impl STRUCTURE_OFFSET_T3 = new Vec3Impl(-6, 0, -5); + protected static final Vec3Impl STRUCTURE_OFFSET_T4 = new Vec3Impl(18, 0, 0); + protected static final Vec3Impl STRUCTURE_OFFSET_T5 = new Vec3Impl(-18, 0, 9); + protected static final Vec3Impl STRUCTURE_OFFSET_T6 = new Vec3Impl(18, 0, 0); + protected static final int MAX_PROCESSES = 6; + protected RecipeMap<?> recipeMap; + private UUID LaserEngraver; + + @Override + public String getTileEntityName() { + return "gt.multitileentity.multiblock.laserengraver"; + } + + @Override + public Vec3Impl getStartingStructureOffset() { + return STRUCTURE_OFFSET_T1; + } + + @Override + public boolean checkMachine() { + buildState.startBuilding(getStartingStructureOffset()); + if (!checkPiece(STRUCTURE_PIECE_T1, buildState.getCurrentOffset())) return buildState.failBuilding(); + if (maxComplexParallels > 1) { + buildState.addOffset(STRUCTURE_OFFSET_T2); + if (!checkPiece(STRUCTURE_PIECE_T2, buildState.getCurrentOffset())) return buildState.failBuilding(); + } + if (maxComplexParallels > 2) { + buildState.addOffset(STRUCTURE_OFFSET_T3); + if (!checkPiece(STRUCTURE_PIECE_T3, buildState.getCurrentOffset())) return buildState.failBuilding(); + } + if (maxComplexParallels > 3) { + buildState.addOffset(STRUCTURE_OFFSET_T4); + if (!checkPiece(STRUCTURE_PIECE_T4, buildState.getCurrentOffset())) return buildState.failBuilding(); + } + if (maxComplexParallels > 4) { + buildState.addOffset(STRUCTURE_OFFSET_T5); + if (!checkPiece(STRUCTURE_PIECE_T5, buildState.getCurrentOffset())) return buildState.failBuilding(); + } + if (maxComplexParallels > 5) { + buildState.addOffset(STRUCTURE_OFFSET_T6); + if (!checkPiece(STRUCTURE_PIECE_T6, buildState.getCurrentOffset())) return buildState.failBuilding(); + } + buildState.stopBuilding(); + return super.checkMachine(); + } + + @Override + public void construct(ItemStack trigger, boolean hintsOnly) { + buildState.startBuilding(getStartingStructureOffset()); + buildPiece(STRUCTURE_PIECE_T1, trigger, hintsOnly, buildState.getCurrentOffset()); + if (maxComplexParallels > 1) { + buildState.addOffset(STRUCTURE_OFFSET_T2); + buildPiece(STRUCTURE_PIECE_T2, trigger, hintsOnly, buildState.getCurrentOffset()); + } + if (maxComplexParallels > 2) { + buildState.addOffset(STRUCTURE_OFFSET_T3); + buildPiece(STRUCTURE_PIECE_T3, trigger, hintsOnly, buildState.getCurrentOffset()); + } + if (maxComplexParallels > 3) { + buildState.addOffset(STRUCTURE_OFFSET_T4); + buildPiece(STRUCTURE_PIECE_T4, trigger, hintsOnly, buildState.getCurrentOffset()); + } + if (maxComplexParallels > 4) { + buildState.addOffset(STRUCTURE_OFFSET_T5); + buildPiece(STRUCTURE_PIECE_T5, trigger, hintsOnly, buildState.getCurrentOffset()); + } + if (maxComplexParallels > 5) { + buildState.addOffset(STRUCTURE_OFFSET_T6); + buildPiece(STRUCTURE_PIECE_T6, trigger, hintsOnly, buildState.getCurrentOffset()); + } + buildState.stopBuilding(); + } + + @Override + public IStructureDefinition<LaserEngraver> getStructureDefinition() { + if (STRUCTURE_DEFINITION == null) { + STRUCTURE_DEFINITION = StructureDefinition.<LaserEngraver>builder() + .addShape( + STRUCTURE_PIECE_T1, + transpose( + // spotless:off + new String[][]{{"ACADA", "AAAAA", "AAAAA"}, {"GGA~A", "H I", "GGAAA"}, + {"AAAAA", "ABBBA", "AAAAA"}})) + .addShape( + STRUCTURE_PIECE_T2, + new String[][]{{" ", " ", " ", " ", " ", " "}, + {" K ", " K ", " K ", " ", " ", " "}, + {" K ", " ", " ", " ", " ", " "}, + {" K ", " ", " ", " ", " ", " "}, + {" K ", " ", " ", " ", " ", " "}, + {" K ", "FBF FBF", " G G ", " G G ", " G G ", "FBF FBF"}, + {" KKKKK ", "BIB BIB", "G G G G", "G G G G", "G G G G", "BHB BHB"}, + {" K K ", "FBF FBF", " G G ", " G G ", " G G ", "FBF FBF"}, + {" K K ", " ", " ", " ", " ", " "}, + {" K K ", "FBF FBF", " G G ", " G G ", " G G ", "FBF FBF"}, + {" KKKKK ", "BIB BIB", "G G G G", "G G G G", "G G G G", "BHB BHB"}, + {" ", "FBF FBF", " G G ", " G G ", " G G ", "FBF FBF",}}) + .addShape( + STRUCTURE_PIECE_T3, + new String[][]{ + {" ", " BBBBB FBF ", " BGGGB G ", " BGGGB G ", " BMLMB G ", " BBBBB FBF "}, + {" KKKKKKK ", " BBAAABB BIB ", " B B G G ", " B B G G ", " B B G G ", " BBBBBBB BHB "}, + {" K ", " BABBBAB FBF ", " G G G ", " G G G ", " M HHH M G ", " BBBBBBB FBF "}, + {"KKKKKK ", " BABIBAB ", " G G ", " G G ", " L HHH L ", " BBBBBBB "}, + {" K ", " BABBBAB FBF ", " G G G ", " G G G ", " M HHH M G ", " BBBBBBB FBF "}, + {" KKKKKKK ", " BBAAABB BIB ", " B B G G ", " B B G G ", " B B G G ", " BBBBBBB BHB "}, + {" ", " BBBBB FBF ", " BGGGB G ", " BGGGB G ", " BMLMB G ", " BBBBB FBF "}}) + .addShape( + STRUCTURE_PIECE_T4, + new String[][]{ + {" ", "FBF BBBBB ", " G BGGGB ", " G BGGGB ", " G BNLNB ", "FBF BBBBB "}, + {" KKKKKKK ", "BIB BBAAABB ", "G G B B ", "G G B B ", "G G B B ", "BHB BBBBBBB "}, + {" K ", "FBF BABBBAB ", " G G G ", " G G G ", " G N HHH N ", "FBF BBBBBBB "}, + {" KKKKKK", " BABIBAB ", " G G ", " G G ", " L HHH L ", " BBBBBBB "}, + {" K ", "FBF BABBBAB ", " G G G ", " G G G ", " G N HHH N ", "FBF BBBBBBB "}, + {" KKKKKKK ", "BIB BBAAABB ", "G G B B ", "G G B B ", "G G B B ", "BHB BBBBBBB "}, + {" ", "FBF BBBBB ", " G BGGGB ", " G BGGGB ", " G BNLNB ", "FBF BBBBB "}}) + .addShape( + STRUCTURE_PIECE_T5, + new String[][]{ + {" ", " BBBBB FBF ", " BGGGB G ", " BGGGB G ", " BOLOB G ", " BBBBB FBF "}, + {" KKKKKKK ", " BBAAABB BIB ", " B B G G ", " B B G G ", " B B G G ", " BBBBBBB BHB "}, + {" K ", " BABBBAB FBF ", " G G G ", " G G G ", " O HHH O G ", " BBBBBBB FBF "}, + {" K ", " BABIBAB ", " G G ", " G G ", " L HHH L ", " BBBBBBB "}, + {" K ", " BABBBAB FBF ", " G G G ", " G G G ", " O HHH O G ", " BBBBBBB FBF "}, + {" KKKKKKK ", " BBAAABB BIB ", " B B G G ", " B B G G ", " B B G G ", " BBBBBBB BHB "}, + {" K ", " BBBBB FBF ", " BGGGB G ", " BGGGB G ", " BOLOB G ", " BBBBB FBF "}, + {" K ", " ", " ", " ", " "}, + {" K ", " ", " ", " ", " "}, + {" K ", " ", " ", " ", " "}}) + .addShape( + STRUCTURE_PIECE_T6, + new String[][]{ + {" ", "FBF BBBBB ", " G BGGGB ", " G BGGGB ", " G BPLPB ", "FBF BBBBB "}, + {" KKKKKKK ", "BIB BBAAABB ", "G G B B ", "G G B B ", "G G B B ", "BHB BBBBBBB "}, + {" K ", "FBF BABBBAB ", " G G G ", " G G G ", " G P HHH P ", "FBF BBBBBBB "}, + {" K ", " BABIBAB ", " G G ", " G G ", " L HHH L ", " BBBBBBB "}, + {" K ", "FBF BABBBAB ", " G G G ", " G G G ", " G P HHH P ", "FBF BBBBBBB "}, + {" KKKKKKK ", "BIB BBAAABB ", "G G B B ", "G G B B ", "G G B B ", "BHB BBBBBBB "}, + {" K ", "FBF BBBBB ", " G BGGGB ", " G BGGGB ", " G BPLPB ", "FBF BBBBB "}, + {" K ", " ", " ", " ", " "}, + {" K ", " ", " ", " ", " "}, + {" K ", " ", " ", " ", " "}}) + // spotless:on + .addElement( + 'A', + ofMuTECasings( + FLUID_IN | ITEM_IN | FLUID_OUT | ITEM_OUT | ENERGY_IN, + GT_MultiTileCasing.LaserEngraver.getCasing())) + .addElement( + 'B', + ofMuTECasings( + FLUID_IN | ITEM_IN | FLUID_OUT | ITEM_OUT | ENERGY_IN, + GT_MultiTileCasing.BlackLaserEngraverCasing.getCasing())) + .addElement( + 'C', + ofMuTECasings(NOTHING, CLEANROOM_CASINGS, GT_MultiTileCasing.LaserEngraver.getCasing())) + .addElement('D', ofMuTECasings(NOTHING, WIRELESS_CASINGS, GT_MultiTileCasing.LaserEngraver.getCasing())) + .addElement('E', ofMuTECasings(NOTHING, MOTOR_CASINGS)) + .addElement('F', GT_StructureUtility.ofFrame(Materials.Naquadah) + + ) + .addElement('H', ofMuTECasings(NOTHING, GT_MultiTileCasing.Mirror.getCasing())) + + .addElement( + 'G', + ofChain( + ofBlockUnlocalizedName(IndustrialCraft2.ID, "blockAlloyGlass", 0, true), + ofBlockUnlocalizedName(BartWorks.ID, "BW_GlasBlocks", 0, true), + ofBlockUnlocalizedName(BartWorks.ID, "BW_GlasBlocks2", 0, true), + ofBlockUnlocalizedName(Thaumcraft.ID, "blockCosmeticOpaque", 2, false))) + .addElement('I', ofMuTECasings(NOTHING, EMITTER_CASINGS)) + .addElement('K', ofBlock(GregTech_API.sBlockCasings3, 11)) + .addElement('L', ofMuTECasings(NOTHING, ROBOT_ARM_CASINGS)) + .addElement('M', ofMuTECasings(NOTHING, GT_MultiTileCasing.LaserEngraverUpgrade1.getCasing())) + .addElement('N', ofMuTECasings(NOTHING, GT_MultiTileCasing.LaserEngraverUpgrade2.getCasing())) + .addElement('O', ofMuTECasings(NOTHING, GT_MultiTileCasing.LaserEngraverUpgrade3.getCasing())) + .addElement('P', ofMuTECasings(NOTHING, GT_MultiTileCasing.LaserEngraverUpgrade4.getCasing())) + .build(); + buildState.stopBuilding(); + } + return STRUCTURE_DEFINITION; + } + + protected MultiChildWidget createMainPage(IWidgetBuilder<?> builder) { + MultiChildWidget child = new MultiChildWidget(); + for (int i = 0; i < MAX_PROCESSES; i++) { + final int processIndex = i; + child.addChild( + new ButtonWidget().setPlayClickSound(true) + .setOnClick( + (clickData, widget) -> { + if (!widget.isClient()) widget.getContext() + .openSyncedWindow(PROCESS_WINDOW_BASE_ID + processIndex); + }) + .setBackground(GT_UITextures.BUTTON_STANDARD, GT_UITextures.OVERLAY_BUTTON_WHITELIST) + .setSize(18, 18) + .setEnabled((widget -> processIndex < maxComplexParallels)) + .setPos(20 * (i % 4) + 18, 18 + (i / 4) * 20)); + } + child.addChild( + new TextFieldWidget().setGetterInt(() -> maxComplexParallels) + .setSetterInt(parallel -> setMaxComplexParallels(parallel, true)) + .setNumbers(1, MAX_PROCESSES) + .setTextColor(Color.WHITE.normal) + .setTextAlignment(Alignment.Center) + .addTooltip("Tier") + .setBackground(GT_UITextures.BACKGROUND_TEXT_FIELD) + .setSize(18, 18) + .setPos(130, 85)); + return child; + } + + @Override + public short getCasingRegistryID() { + return 0; + } + + @Override + public void readMultiTileNBT(NBTTagCompound nbt) { + super.readMultiTileNBT(nbt); + setMaxComplexParallels(nbt.getInteger("processors"), false); + } + + @Override + public void writeMultiTileNBT(NBTTagCompound nbt) { + super.writeMultiTileNBT(nbt); + nbt.setInteger("processors", maxComplexParallels); + } + + @Override + public int getCasingMeta() { + return GT_MultiTileCasing.LaserEngraver.getId(); + } + + @Override + protected GT_Multiblock_Tooltip_Builder createTooltip() { + final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder(); + tt.addMachineType("Laser Engraver") + .addInfo("Used for Engraving") + .addSeparator() + .beginStructureBlock(3, 3, 5, true) + .addController("Front right center") + .toolTipFinisher(GT_Values.AuthorTheEpicGamer274); + return tt; + } + + @Override + @Nonnull + protected LaserEngraverProcessingLogic createProcessingLogic() { + return new LaserEngraverProcessingLogic(); + } + +} diff --git a/src/main/java/gregtech/common/tileentities/machines/multiblock/LayeredCokeBattery.java b/src/main/java/gregtech/common/tileentities/machines/multiblock/LayeredCokeBattery.java new file mode 100644 index 0000000000..3b00708e40 --- /dev/null +++ b/src/main/java/gregtech/common/tileentities/machines/multiblock/LayeredCokeBattery.java @@ -0,0 +1,295 @@ +package gregtech.common.tileentities.machines.multiblock; + +import static com.gtnewhorizon.structurelib.structure.StructureUtility.*; +import static gregtech.api.enums.Mods.*; +import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.ENERGY_IN; +import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.FLUID_IN; +import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.FLUID_OUT; +import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.ITEM_IN; +import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.ITEM_OUT; +import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.NOTHING; +import static gregtech.api.util.GT_StructureUtilityMuTE.AMPERAGE_CASINGS; +import static gregtech.api.util.GT_StructureUtilityMuTE.HEATER_CASINGS; +import static gregtech.api.util.GT_StructureUtilityMuTE.INSULATOR_CASINGS; +import static gregtech.api.util.GT_StructureUtilityMuTE.MOTOR_CASINGS; +import static gregtech.api.util.GT_StructureUtilityMuTE.ofMuTECasings; + +import java.util.Arrays; +import java.util.Map; + +import javax.annotation.Nonnull; + +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; + +import com.gtnewhorizon.structurelib.structure.IStructureDefinition; +import com.gtnewhorizon.structurelib.structure.StructureDefinition; +import com.gtnewhorizon.structurelib.util.Vec3Impl; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import gregtech.api.GregTech_API; +import gregtech.api.enums.Materials; +import gregtech.api.enums.SoundResource; +import gregtech.api.multitileentity.enums.GT_MultiTileCasing; +import gregtech.api.multitileentity.multiblock.base.StackableModularController; +import gregtech.api.util.GT_Multiblock_Tooltip_Builder; +import gregtech.api.util.GT_StructureUtility; +import gregtech.api.util.GT_StructureUtilityMuTE.UpgradeCasings; +import gregtech.common.tileentities.machines.multiblock.logic.LayeredCokeBatteryProcessingLogic; + +public class LayeredCokeBattery + extends StackableModularController<LayeredCokeBattery, LayeredCokeBatteryProcessingLogic> { + + private static IStructureDefinition<LayeredCokeBattery> STRUCTURE_DEFINITION_MEGA = null; + protected static final String STRUCTURE_PIECE_BASE = "T1"; + private static final Vec3Impl STRUCTURE_OFFSET_BASE = new Vec3Impl(2, 2, 0); + private static final Vec3Impl STRUCTURE_OFFSET_MEGA_POSITION = new Vec3Impl(4, 7, -4); + private static final Vec3Impl STRUCTURE_OFFSET_MEGA_START = new Vec3Impl(0, 0, -3); + private static final Vec3Impl STRUCTURE_OFFSET_MEGA_STACK = new Vec3Impl(0, 0, -2); + private static final Vec3Impl STRUCTURE_OFFSET_MEGA_STOP = new Vec3Impl(0, 0, -1); + + @Override + public String getTileEntityName() { + return "gt.multitileentity.multiblock.layeredcokebattery"; + } + + @Override + public String getLocalName() { + return "Layered Coke Battery"; + } + + @Override + public Vec3Impl getStartingStructureOffset() { + return STRUCTURE_OFFSET_BASE; + } + + public UpgradeCasings getBaseMucType() { + return UpgradeCasings.Heater; + } + + public int getParallelFactor() { + return 2; + } + + @Override + public void construct(ItemStack trigger, boolean hintsOnly) { + final int blueprintCount = (trigger.stackSize - 1) + getMinStacks(); + final int stackCount = Math.min(blueprintCount, getMaxStacks()); + + buildState.startBuilding(getStartingStructureOffset()); + buildPiece(STRUCTURE_PIECE_BASE, trigger, hintsOnly, buildState.getCurrentOffset()); + buildState.addOffset(getMegaPositionOffset()); + + if (stackCount >= 1) { + buildPiece(STACKABLE_START, trigger, hintsOnly, buildState.getCurrentOffset()); + buildState.addOffset(getStartingStackOffset()); + + for (int i = 0; i < stackCount; i++) { + buildPiece(STACKABLE_MIDDLE, trigger, hintsOnly, buildState.getCurrentOffset()); + buildState.addOffset(getPerStackOffset()); + } + if (hasTop()) { + buildPiece(STACKABLE_STOP, trigger, hintsOnly, buildState.getCurrentOffset()); + } + } + + buildState.stopBuilding(); + } + + @Override + public IStructureDefinition<LayeredCokeBattery> getStructureDefinition() { + if (STRUCTURE_DEFINITION_MEGA == null) { + STRUCTURE_DEFINITION_MEGA = StructureDefinition.<LayeredCokeBattery>builder() + .addShape( + STRUCTURE_PIECE_BASE, + transpose( + new String[][] { { " AAA ", "AAAAA", "AEEEP", "AAAAA" }, { " AAA ", "A A", "A A", "AAAAA" }, + { " A~A ", "A A", "A A", "AAAAA" }, { " AAA ", "A A", "A A", "AAAAA" }, + { " AAA ", "AAAAA", "AAAAA", "AAAAA" } })) + .addShape( + STACKABLE_STOP, + transpose( + new String[][] { { "AHFFFFAFFFFHA", "AAAAAAAAAAAAA" }, { " B B B B B B ", "AFAFAFAFAFAFA" }, + { "HB B B B B BH", "AFAFAFAFAFAFA" }, { " B B B B B B ", "AFAFAFAFAFAFA" }, + { " B B B B B B ", "AFAFAFAFAFAFA" }, { " B B B B B B ", "AFAFAFAFAFAFA" }, + { " B B B B B B ", "AFAFAFAFAFAFA" }, { " B B B B B B ", "AFAFAFAFAFAFA" }, + { " B B B B B B ", "AFAFAFAFAFAFA" }, { "HB B B B B BH", "AFAFAFAFAFAFA" }, + { " B B B B B B ", "AFAFAFAFAFAFA" }, { "AAAAAAAAAAAAA", "AAAAAAAAAAAAA" } })) + .addShape( + STACKABLE_MIDDLE, + transpose( + new String[][] { { "AHFFFFAFFFFHA", "AAAAAAAAAAAAA" }, { " B A B ", "AAAAAAAAAAAAA" }, + { "HB A BH", "AAAAAAAAAAAAA" }, { " B A B ", "AAAAAAAAAAAAA" }, + { " B A B ", "AAAAAAAAAAAAA" }, { " B A B ", "AAAAAAAAAAAAA" }, + { " B A B ", "AAAAAAAAAAAAA" }, { " B A B ", "AAAAAAAAAAAAA" }, + { " B A B ", "AAAAAAAAAAAAA" }, { "HB A BH", "AAAAAAAAAAAAA" }, + { " B A B ", "AAAAAAAAAAAAA" }, { "AAAAAAAAAAAAA", "AAAAAAAAAAAAA" } })) + .addShape( + STACKABLE_START, + transpose( + new String[][] { { "AAAAAAAAAAAAA", "AHFFFFAFFFFHA", "AAAAAAAAAAAAA" }, + { "AFAFAFAFAFAFA", " B B B B B B ", "AAAAAAAAAAAAA" }, + { "AFAFAFAFAFAFA", "HB B B B B BH", "AAAAAAAAAAAAA" }, + { "AFAFAFAFAFAFA", " B B B B B B ", "AAAAAAAAAAAAA" }, + { "AFAFAFAFAFAFA", " B B B B B B ", "AAAAAAAAAAAAA" }, + { "AFAFAFAFAFAFA", " B B B B B B ", "AAAAAAAAAAAAA" }, + { "AFAFAFAFAFAFA", " B B B B B B ", "AAAAAAAAAAAAA" }, + { "AFAFAFAFAFAFA", " B B B B B B ", "AAAAAAAAAAAAA" }, + { "AFAFAFAFAFAFA", " B B B B B B ", "AAAAAAAAAAAAA" }, + { "AFAFAFAFAFAFA", "HB B B B B BH", "AAAAAAAAAAAAA" }, + { "AFAFAFAFAFAFA", " B B B B B B ", "AAAAAAAAAAAAA" }, + { "AAAAAAAAAAAAA", "AAAAAAAAAAAAA", "AAAAAAAAAAAAA" } })) + .addElement( + 'A', + ofMuTECasings( + FLUID_IN | ITEM_IN | FLUID_OUT | ITEM_OUT | ENERGY_IN, + GT_MultiTileCasing.Chemical.getCasing())) + .addElement( + 'B', + ofMuTECasings( + FLUID_IN | ITEM_IN | FLUID_OUT | ITEM_OUT | ENERGY_IN, + GT_MultiTileCasing.Distillation.getCasing())) + .addElement('C', ofBlock(GregTech_API.sBlockCasings4, 1)) + .addElement('D', GT_StructureUtility.ofFrame(Materials.Steel)) + .addElement('E', ofMuTECasings(NOTHING, MOTOR_CASINGS)) + .addElement( + 'F', + ofChain( + ofBlockUnlocalizedName(IndustrialCraft2.ID, "blockAlloyGlass", 0, true), + ofBlockUnlocalizedName(BartWorks.ID, "BW_GlasBlocks", 0, true), + ofBlockUnlocalizedName(BartWorks.ID, "BW_GlasBlocks2", 0, true), + ofBlockUnlocalizedName(Thaumcraft.ID, "blockCosmeticOpaque", 2, false))) + .addElement('H', ofMuTECasings(NOTHING, HEATER_CASINGS, INSULATOR_CASINGS)) + .addElement('P', ofMuTECasings(NOTHING, AMPERAGE_CASINGS)) + .build(); + } + return STRUCTURE_DEFINITION_MEGA; + } + + public boolean checkMachine() { + stackCount = 0; + resetMucCount(); + + buildState.startBuilding(getStartingStructureOffset()); + if (!checkPiece(STRUCTURE_PIECE_BASE, buildState.getCurrentOffset())) return buildState.failBuilding(); + + buildState.addOffset(getMegaPositionOffset()); + if (!checkPiece(STACKABLE_START, buildState.getCurrentOffset())) { + return buildState.failBuilding(); + } + + buildState.addOffset(getStartingStackOffset()); + for (int i = 0; i < getMaxStacks(); i++) { + if (!checkPiece(getStackableMiddle(i), buildState.getCurrentOffset())) { + break; + } + + buildState.addOffset(getPerStackOffset()); + stackCount++; + } + if (stackCount < getMinStacks()) return buildState.failBuilding(); + + if (!checkPiece(getStackableStop(), buildState.stopBuilding())) { + return buildState.failBuilding(); + } + + calculateTier(); + if (!calculateMucMultipliers()) { + return false; + } + calculateParallels(); + updatePowerLogic(); + return tier > 0; + } + + protected boolean calculateMucMultipliers() { + Map<UpgradeCasings, int[]> mucMap = getMucMap(); + int[] heaterList = mucMap.get(UpgradeCasings.Heater); + int[] insulatorList = mucMap.get(UpgradeCasings.Insulator); + int totalHeaterCount = Arrays.stream(heaterList) + .sum(); + int totalInsulatorCount = Arrays.stream(insulatorList) + .sum(); + if (totalHeaterCount + totalInsulatorCount < stackCount || totalInsulatorCount > totalHeaterCount) { + return false; + } + if (totalInsulatorCount > 0) { + // To be improved later, when more MUCs are added + // durationMultiplier = 1.0 / totalHeaterCount; + euTickMultiplier = 1.0 / totalInsulatorCount; + } + return true; + } + + @Override + public short getCasingRegistryID() { + return 0; + } + + @Override + public int getCasingMeta() { + return GT_MultiTileCasing.Distillation.getId(); + } + + @Override + protected GT_Multiblock_Tooltip_Builder createTooltip() { + final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder(); + tt.addMachineType("Coke Oven") + .addInfo("Controller for the Layered Coke Battery") + .addSeparator() + .beginVariableStructureBlock(7, 9, 2 + getMinStacks(), 2 + getMaxStacks(), 7, 9, true) + .addController("Bottom Front Center") + .addCasingInfoExactly("Test Casing", 60, false) + .addEnergyHatch("Any bottom layer casing") + .addInputHatch("Any non-optional external facing casing on the stacks") + .addInputBus("Any non-optional external facing casing on the stacks") + .addOutputHatch("Any non-optional external facing casing on the stacks") + .addOutputBus("Any non-optional external facing casing on the stacks") + .addStructureInfo( + String.format("Stackable middle stacks between %d-%d time(s).", getMinStacks(), getMaxStacks())) + .toolTipFinisher("Wildcard"); + return tt; + } + + @Override + public int getMinStacks() { + return 0; + } + + @Override + public int getMaxStacks() { + return 20; + } + + public Vec3Impl getMegaPositionOffset() { + return STRUCTURE_OFFSET_MEGA_POSITION; + } + + @Override + public Vec3Impl getStartingStackOffset() { + return STRUCTURE_OFFSET_MEGA_START; + } + + @Override + public Vec3Impl getPerStackOffset() { + return STRUCTURE_OFFSET_MEGA_STACK; + } + + @Override + public Vec3Impl getAfterLastStackOffset() { + return STRUCTURE_OFFSET_MEGA_STOP; + } + + @SideOnly(Side.CLIENT) + @Override + protected ResourceLocation getActivitySoundLoop() { + return SoundResource.IC2_MACHINES_MACERATOR_OP.resourceLocation; + } + + @Override + @Nonnull + protected LayeredCokeBatteryProcessingLogic createProcessingLogic() { + return new LayeredCokeBatteryProcessingLogic(); + } +} diff --git a/src/main/java/gregtech/common/tileentities/machines/multiblock/Macerator.java b/src/main/java/gregtech/common/tileentities/machines/multiblock/Macerator.java index dda7eb9420..dfdacfe7f2 100644 --- a/src/main/java/gregtech/common/tileentities/machines/multiblock/Macerator.java +++ b/src/main/java/gregtech/common/tileentities/machines/multiblock/Macerator.java @@ -1,6 +1,5 @@ package gregtech.common.tileentities.machines.multiblock; -import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofChain; import static com.gtnewhorizon.structurelib.structure.StructureUtility.transpose; import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.ENERGY_IN; import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.FLUID_IN; @@ -8,27 +7,20 @@ import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.FLUID_ import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.ITEM_IN; import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.ITEM_OUT; import static gregtech.api.multitileentity.multiblock.base.MultiBlockPart.NOTHING; +import static gregtech.api.util.GT_StructureUtilityMuTE.*; -import net.minecraft.item.ItemStack; -import net.minecraft.util.ResourceLocation; - -import org.apache.commons.lang3.tuple.Pair; +import javax.annotation.Nonnull; import com.gtnewhorizon.structurelib.structure.IStructureDefinition; import com.gtnewhorizon.structurelib.structure.StructureDefinition; import com.gtnewhorizon.structurelib.util.Vec3Impl; -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; -import gregtech.api.enums.SoundResource; -import gregtech.api.enums.TierEU; +import gregtech.api.multitileentity.enums.GT_MultiTileCasing; import gregtech.api.multitileentity.multiblock.base.StackableController; -import gregtech.api.recipe.RecipeMap; -import gregtech.api.recipe.RecipeMaps; import gregtech.api.util.GT_Multiblock_Tooltip_Builder; -import gregtech.api.util.GT_Recipe; +import gregtech.common.tileentities.machines.multiblock.logic.MaceratorProcessingLogic; -public class Macerator extends StackableController<Macerator> { +public class Macerator extends StackableController<Macerator, MaceratorProcessingLogic> { private static IStructureDefinition<Macerator> STRUCTURE_DEFINITION = null; @@ -45,25 +37,23 @@ public class Macerator extends StackableController<Macerator> { public IStructureDefinition<Macerator> getStructureDefinition() { if (STRUCTURE_DEFINITION == null) { STRUCTURE_DEFINITION = StructureDefinition.<Macerator>builder() - .addShape(STACKABLE_TOP, transpose(new String[][] { { " CCC ", "CCCCC", "CCCCC", "CCCCC", " CCC " }, })) + .addShape( + STACKABLE_STOP, + transpose(new String[][] { { " CCC ", "CCCCC", "CCCCC", "CCCCC", " CCC " }, })) .addShape( STACKABLE_MIDDLE, transpose(new String[][] { { " BBB ", " B---B ", "DC---CD", " B---B ", " BBB " }, })) .addShape( - STACKABLE_BOTTOM, + STACKABLE_START, transpose(new String[][] { { " G~F ", "AAAAA", "AAAAA", "AAAAA", " AAA " }, })) - .addElement('A', ofChain(addMultiTileCasing("gt.multitileentity.casings", getCasingMeta(), ENERGY_IN))) + .addElement('A', ofMuTECasings(ENERGY_IN, GT_MultiTileCasing.Macerator.getCasing())) .addElement( 'B', - ofChain( - addMultiTileCasing( - "gt.multitileentity.casings", - getCasingMeta(), - FLUID_IN | ITEM_IN | FLUID_OUT | ITEM_OUT))) - .addElement('C', addMultiTileCasing("gt.multitileentity.casings", getCasingMeta(), NOTHING)) - .addElement('D', addMultiTileCasing("gt.multitileentity.casings", getCasingMeta(), NOTHING)) - .addElement('F', addMotorCasings(NOTHING)) - .addElement('G', addMultiTileCasing("gt.multitileentity.component.casings", 10000, NOTHING)) + ofMuTECasings(FLUID_IN | ITEM_IN | FLUID_OUT | ITEM_OUT, GT_MultiTileCasing.Macerator.getCasing())) + .addElement('C', ofMuTECasings(NOTHING, GT_MultiTileCasing.Macerator.getCasing())) + .addElement('D', ofMuTECasings(NOTHING, GT_MultiTileCasing.Macerator.getCasing())) + .addElement('F', ofMuTECasings(NOTHING, MOTOR_CASINGS)) + .addElement('G', ofMuTECasings(NOTHING, INVENTORY_CASINGS)) .build(); } return STRUCTURE_DEFINITION; @@ -135,42 +125,8 @@ public class Macerator extends StackableController<Macerator> { } @Override - protected boolean checkRecipe() { - if (isSeparateInputs()) { - for (Pair<ItemStack[], String> tItemInputs : getItemInputsForEachInventory()) { - if (processRecipe(tItemInputs.getLeft(), tItemInputs.getRight())) { - return true; - } - } - return false; - } else { - ItemStack[] tItemInputs = getInventoriesForInput().getStacks() - .toArray(new ItemStack[0]); - return processRecipe(tItemInputs, null); - } - } - - private boolean processRecipe(ItemStack[] aItemInputs, String aInventory) { - RecipeMap<?> tRecipeMap = RecipeMaps.maceratorRecipes; - GT_Recipe tRecipe = tRecipeMap.findRecipe(this, false, TierEU.IV, null, aItemInputs); - if (tRecipe == null) { - return false; - } - - if (!tRecipe.isRecipeInputEqual(true, false, 1, null, aItemInputs)) { - return false; - } - - setDuration(tRecipe.mDuration); - setEut(tRecipe.mEUt); - - setItemOutputs(aInventory, tRecipe.mOutputs); - return true; - } - - @SideOnly(Side.CLIENT) - @Override - protected ResourceLocation getActivitySoundLoop() { - return SoundResource.IC2_MACHINES_MACERATOR_OP.resourceLocation; + @Nonnull + protected MaceratorProcessingLogic createProcessingLogic() { + return new MaceratorProcessingLogic(); } } diff --git a/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/AdvChemicalProcessorProcessingLogic.java b/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/AdvChemicalProcessorProcessingLogic.java new file mode 100644 index 0000000000..59879e30c7 --- /dev/null +++ b/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/AdvChemicalProcessorProcessingLogic.java @@ -0,0 +1,12 @@ +package gregtech.common.tileentities.machines.multiblock.logic; + +import gregtech.api.logic.ComplexParallelProcessingLogic; +import gregtech.api.recipe.RecipeMaps; + +public class AdvChemicalProcessorProcessingLogic + extends ComplexParallelProcessingLogic<AdvChemicalProcessorProcessingLogic> { + + public AdvChemicalProcessorProcessingLogic() { + setRecipeMap(RecipeMaps.multiblockChemicalReactorRecipes); + } +} diff --git a/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/CokeOvenProcessingLogic.java b/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/CokeOvenProcessingLogic.java index 046bb4a114..1534b05bc3 100644 --- a/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/CokeOvenProcessingLogic.java +++ b/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/CokeOvenProcessingLogic.java @@ -5,17 +5,19 @@ import static net.minecraftforge.oredict.OreDictionary.getOreID; import static net.minecraftforge.oredict.OreDictionary.getOreIDs; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import net.minecraft.init.Items; import net.minecraft.item.ItemStack; -import gregtech.api.logic.ProcessingLogic; -import gregtech.api.recipe.check.CheckRecipeResult; -import gregtech.api.recipe.check.CheckRecipeResultRegistry; +import gregtech.api.logic.FluidInventoryLogic; +import gregtech.api.logic.ItemInventoryLogic; +import gregtech.api.logic.MuTEProcessingLogic; +import gregtech.api.recipe.RecipeMap; import gregtech.api.util.GT_ModHandler; import gregtech.api.util.GT_OreDictUnificator; -public class CokeOvenProcessingLogic extends ProcessingLogic { +public class CokeOvenProcessingLogic extends MuTEProcessingLogic<CokeOvenProcessingLogic> { private static final int NORMAL_RECIPE_TIME = 1800; private static final int WOOD_ORE_ID = getOreID("logWood"); @@ -27,26 +29,33 @@ public class CokeOvenProcessingLogic extends ProcessingLogic { private static final int SUGAR_CHARCOAL_ORE_ID = getOreID("itemCharcoalSugar"); private int timeMultiplier = 1; + @Nonnull @Override - public @Nonnull CheckRecipeResult process() { - if (inputItems == null || inputItems[0] == null) { - return CheckRecipeResultRegistry.NO_RECIPE; - } - ItemStack input = inputItems[0]; - int originalStackSize = input.stackSize; - ItemStack output = findRecipe(input); - if (currentOutputItems != null && currentOutputItems[0] != null && !currentOutputItems[0].isItemEqual(output)) { - return CheckRecipeResultRegistry.NO_RECIPE; + protected Object findRecipe(@Nullable RecipeMap<?> map, @Nonnull ItemInventoryLogic itemInput, + @Nonnull FluidInventoryLogic fluidInput) { + for (ItemStack item : itemInput.getStoredItems()) { + ItemStack output = findRecipe(item); + if (output != null) { + ItemStack input = item.copy(); + input.stackSize = 1; + return null; + // return FindRecipeResult.ofSuccess( + // GT_Values.RA.stdBuilder() + // .itemInputs(input) + // .itemOutputs(output) + // .noFluidInputs() + // .noFluidOutputs() + // .duration(NORMAL_RECIPE_TIME * timeMultiplier) + // .eut(0) + // .build() + // .get()); + } } - input.stackSize -= 1; - setDuration(NORMAL_RECIPE_TIME * timeMultiplier); - setOutputItems(output); - - return originalStackSize > input.stackSize ? CheckRecipeResultRegistry.SUCCESSFUL - : CheckRecipeResultRegistry.NO_RECIPE; + return null; } - protected ItemStack findRecipe(ItemStack input) { + @Nullable + private ItemStack findRecipe(@Nonnull ItemStack input) { for (int oreId : getOreIDs(input)) { if (oreId == COAL_ORE_ID) { return GT_OreDictUnificator.get("fuelCoke", null, 1); diff --git a/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/DistillationTowerProcessingLogic.java b/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/DistillationTowerProcessingLogic.java new file mode 100644 index 0000000000..6f27c9a0e6 --- /dev/null +++ b/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/DistillationTowerProcessingLogic.java @@ -0,0 +1,7 @@ +package gregtech.common.tileentities.machines.multiblock.logic; + +import gregtech.api.logic.ComplexParallelProcessingLogic; + +public class DistillationTowerProcessingLogic extends ComplexParallelProcessingLogic<DistillationTowerProcessingLogic> { + +} diff --git a/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/LaserEngraverProcessingLogic.java b/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/LaserEngraverProcessingLogic.java new file mode 100644 index 0000000000..3f4a6bfe70 --- /dev/null +++ b/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/LaserEngraverProcessingLogic.java @@ -0,0 +1,7 @@ +package gregtech.common.tileentities.machines.multiblock.logic; + +import gregtech.api.logic.ComplexParallelProcessingLogic; + +public class LaserEngraverProcessingLogic extends ComplexParallelProcessingLogic<LaserEngraverProcessingLogic> { + +} diff --git a/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/LayeredCokeBatteryProcessingLogic.java b/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/LayeredCokeBatteryProcessingLogic.java new file mode 100644 index 0000000000..b2e43b6fa9 --- /dev/null +++ b/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/LayeredCokeBatteryProcessingLogic.java @@ -0,0 +1,7 @@ +package gregtech.common.tileentities.machines.multiblock.logic; + +import gregtech.api.logic.MuTEProcessingLogic; + +public class LayeredCokeBatteryProcessingLogic extends MuTEProcessingLogic<LayeredCokeBatteryProcessingLogic> { + +} diff --git a/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/MaceratorProcessingLogic.java b/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/MaceratorProcessingLogic.java new file mode 100644 index 0000000000..3f7d8a25f7 --- /dev/null +++ b/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/MaceratorProcessingLogic.java @@ -0,0 +1,7 @@ +package gregtech.common.tileentities.machines.multiblock.logic; + +import gregtech.api.logic.MuTEProcessingLogic; + +public class MaceratorProcessingLogic extends MuTEProcessingLogic<MaceratorProcessingLogic> { + +} diff --git a/src/main/java/gregtech/loaders/preload/GT_Loader_MultiTileEntities.java b/src/main/java/gregtech/loaders/preload/GT_Loader_MultiTileEntities.java index e88a397764..fd290935df 100644 --- a/src/main/java/gregtech/loaders/preload/GT_Loader_MultiTileEntities.java +++ b/src/main/java/gregtech/loaders/preload/GT_Loader_MultiTileEntities.java @@ -1,124 +1,15 @@ package gregtech.loaders.preload; import static gregtech.GT_Mod.GT_FML_LOGGER; -import static gregtech.api.multitileentity.enums.GT_MultiTileCasing.Chemical; -import static gregtech.api.multitileentity.enums.GT_MultiTileCasing.CokeOven; -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_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_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_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.api.multitileentity.enums.GT_MultiTileCasing.*; +import static gregtech.api.multitileentity.enums.GT_MultiTileComponentCasing.*; +import static gregtech.api.multitileentity.enums.GT_MultiTileUpgradeCasing.*; +import static gregtech.api.multitileentity.enums.GT_MultiTileUpgradeCasing.Insulator_OmegaType; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import gregtech.api.enums.Materials; -import gregtech.api.enums.MaterialsUEVplus; -import gregtech.api.enums.Mods; import gregtech.api.multitileentity.MultiTileEntityBlock; import gregtech.api.multitileentity.MultiTileEntityRegistry; import gregtech.api.multitileentity.multiblock.base.WallShareablePart; @@ -131,14 +22,25 @@ import gregtech.common.tileentities.casings.functional.Piston; import gregtech.common.tileentities.casings.functional.Pump; import gregtech.common.tileentities.casings.functional.RobotArm; import gregtech.common.tileentities.casings.functional.Sensor; +import gregtech.common.tileentities.casings.upgrade.Ampere; +import gregtech.common.tileentities.casings.upgrade.Cleanroom; +import gregtech.common.tileentities.casings.upgrade.Heater; +import gregtech.common.tileentities.casings.upgrade.Insulator; import gregtech.common.tileentities.casings.upgrade.Inventory; -import gregtech.common.tileentities.machines.multiblock.AdvChemicalReactor; +import gregtech.common.tileentities.casings.upgrade.Laser; +import gregtech.common.tileentities.casings.upgrade.Tank; +import gregtech.common.tileentities.casings.upgrade.Wireless; +import gregtech.common.tileentities.machines.multiblock.AdvChemicalProcessor; import gregtech.common.tileentities.machines.multiblock.CokeOven; +import gregtech.common.tileentities.machines.multiblock.DistillationTower; +import gregtech.common.tileentities.machines.multiblock.LaserEngraver; +import gregtech.common.tileentities.machines.multiblock.LayeredCokeBattery; import gregtech.common.tileentities.machines.multiblock.Macerator; public class GT_Loader_MultiTileEntities implements Runnable { public static final String COMPONENT_CASING_REGISTRY_NAME = "gt.multitileentity.component.casings"; + public static final String UPGRADE_CASING_REGISTRY_NAME = "gt.multitileentity.upgrade.casings"; public static final String CASING_REGISTRY_NAME = "gt.multitileentity.casings"; public static final String MACHINE_REGISTRY_NAME = "gt.multitileentity.controllers"; public static final MultiTileEntityRegistry MACHINE_REGISTRY = new MultiTileEntityRegistry(MACHINE_REGISTRY_NAME); @@ -149,6 +51,10 @@ public class GT_Loader_MultiTileEntities implements Runnable { .getOrCreate("GregTech", "casing", Material.iron, Block.soundTypeMetal, "wrench", 0, 0, 15, true, true); public static final MultiTileEntityRegistry COMPONENT_CASING_REGISTRY = new MultiTileEntityRegistry( COMPONENT_CASING_REGISTRY_NAME); + + public static final MultiTileEntityRegistry UPGRADE_CASING_REGISTRY = new MultiTileEntityRegistry( + UPGRADE_CASING_REGISTRY_NAME); + public static final MultiTileEntityBlock COMPONENT_CASING_BLOCK = MultiTileEntityBlock.getOrCreate( "GregTech", "componentCasing", @@ -163,9 +69,6 @@ public class GT_Loader_MultiTileEntities implements Runnable { @Override public void run() { - if (Mods.NewHorizonsCoreMod.isModLoaded()) { - return; - } GT_FML_LOGGER.info("GT_Mod: Registering MultiTileEntities"); registerMachines(); registerCasings(); @@ -192,12 +95,40 @@ public class GT_Loader_MultiTileEntities implements Runnable { .inputInventorySize(1) .outputInventorySize(1) .register(); - MACHINE_REGISTRY.create(1, AdvChemicalReactor.class) - .name("Advanced Chemical Reactor") + MACHINE_REGISTRY.create(1, AdvChemicalProcessor.class) + .name("Advanced Chemical Processor") .category("MultiblockController") .setBlock(MACHINE_BLOCK) // TODO: Texture - .textureFolder("advChemicalReactor") + .textureFolder("advChemicalProcessor") + .inputInventorySize(16) + .outputInventorySize(16) + .tankCapacity(128000L) + .register(); + MACHINE_REGISTRY.create(2, DistillationTower.class) + .name("Distillation Tower") + .category("MultiblockController") + .setBlock(MACHINE_BLOCK) + .textureFolder("distillationTower") + .inputInventorySize(16) + .outputInventorySize(16) + .tankCapacity(128000L) + .register(); + MACHINE_REGISTRY.create(3, LayeredCokeBattery.class) + .name("Layered Coke Battery") + .category("Multiblock Controller") + .setBlock(MACHINE_BLOCK) + .material(Materials.Iron) + .textureFolder("macerator") + .tankCapacity(128000L) + .inputInventorySize(16) + .outputInventorySize(16) + .register(); + MACHINE_REGISTRY.create(4, LaserEngraver.class) + .name("Big Laser Engraver") + .category("Multiblock Controller") + .setBlock(MACHINE_BLOCK) + .textureFolder("BigLaserEngraver") .inputInventorySize(16) .outputInventorySize(16) .tankCapacity(128000L) @@ -216,7 +147,13 @@ public class GT_Loader_MultiTileEntities implements Runnable { .name("Chemical Casing") .category("MultiBlock Casing") .setBlock(CASING_BLOCK) - .textureFolder("advChemicalReactor") + .textureFolder("advChemicalProcessor") + .register(); + CASING_REGISTRY.create(Distillation.getId(), BasicCasing.class) + .name("Distillation Casing") + .category("MultiBlock Casing") + .setBlock(CASING_BLOCK) + .textureFolder("distillationTower") .register(); CASING_REGISTRY.create(18000, BasicCasing.class) .name("Test Casing") @@ -225,6 +162,48 @@ public class GT_Loader_MultiTileEntities implements Runnable { .material(Materials.Cobalt) .textureFolder("macerator") .register(); + CASING_REGISTRY.create(LaserEngraver.getId(), BasicCasing.class) + .name("Laser Engraver Casing") + .category("MultiBlock Casing") + .setBlock(CASING_BLOCK) + .textureFolder("BigLaserEngraver") + .register(); + CASING_REGISTRY.create(Mirror.getId(), BasicCasing.class) + .name("Mirror") + .category("MultiBlock Casing") + .setBlock(CASING_BLOCK) + .textureFolder("Laserblock") + .register(); + CASING_REGISTRY.create(BlackLaserEngraverCasing.getId(), BasicCasing.class) + .name("Black Laser Engraver Casing") + .category("MultiBlock Casing") + .setBlock(CASING_BLOCK) + .textureFolder("BlackLaserEngraver") + .register(); + CASING_REGISTRY.create(LaserEngraverUpgrade1.getId(), BasicCasing.class) + .name("Crude Laser Engraving Casing") + .category("MultiBlock Casing") + .setBlock(CASING_BLOCK) + .textureFolder("laserengraverupgrade1") + .register(); + CASING_REGISTRY.create(LaserEngraverUpgrade2.getId(), BasicCasing.class) + .name("Advanced Laser Engraving Casing") + .category("MultiBlock Casing") + .setBlock(CASING_BLOCK) + .textureFolder("laserengraverupgrade2") + .register(); + CASING_REGISTRY.create(LaserEngraverUpgrade3.getId(), BasicCasing.class) + .name("Ultimate Laser Engraving Casing") + .category("MultiBlock Casing") + .setBlock(CASING_BLOCK) + .textureFolder("laserengraverupgrade3") + .register(); + CASING_REGISTRY.create(LaserEngraverUpgrade4.getId(), BasicCasing.class) + .name("Superb Laser Engraving Casing") + .category("MultiBlock Casing") + .setBlock(CASING_BLOCK) + .textureFolder("laserengraverupgrade4") + .register(); } @@ -239,24 +218,437 @@ public class GT_Loader_MultiTileEntities implements Runnable { registerSensorCasings(); registerFieldGeneratorCasings(); - COMPONENT_CASING_REGISTRY.create(20001, Inventory.class) + UPGRADE_CASING_REGISTRY.create(ULV_Inventory.getId(), Inventory.class) + .name("Inventory Upgrade ULV") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("inventory") + .upgradeInventorySize(1) + .tier(0) + .register(); + UPGRADE_CASING_REGISTRY.create(LV_Inventory.getId(), Inventory.class) .name("Inventory Upgrade LV") .category("MultiBlock Upgrade Casing") .setBlock(COMPONENT_CASING_BLOCK) - .material(MaterialsUEVplus.SpaceTime) - .textureFolder("macerator") - .upgradeInventorySize(16) + .textureFolder("inventory") + .upgradeInventorySize(4) .tier(1) .register(); - COMPONENT_CASING_REGISTRY.create(20002, Inventory.class) + UPGRADE_CASING_REGISTRY.create(MV_Inventory.getId(), Inventory.class) .name("Inventory Upgrade MV") .category("MultiBlock Upgrade Casing") .setBlock(COMPONENT_CASING_BLOCK) - .material(Materials.Neutronium) - .textureFolder("macerator") - .upgradeInventorySize(24) + .textureFolder("inventory") + .upgradeInventorySize(8) .tier(2) .register(); + UPGRADE_CASING_REGISTRY.create(HV_Inventory.getId(), Inventory.class) + .name("Inventory Upgrade HV") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("inventory") + .upgradeInventorySize(16) + .tier(3) + .register(); + UPGRADE_CASING_REGISTRY.create(EV_Inventory.getId(), Inventory.class) + .name("Inventory Upgrade EV") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("inventory") + .upgradeInventorySize(32) + .tier(4) + .register(); + UPGRADE_CASING_REGISTRY.create(IV_Inventory.getId(), Inventory.class) + .name("Inventory Upgrade IV") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("inventory") + .upgradeInventorySize(64) + .tier(5) + .register(); + UPGRADE_CASING_REGISTRY.create(LuV_Inventory.getId(), Inventory.class) + .name("Inventory Upgrade LuV") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("inventory") + .upgradeInventorySize(128) + .tier(6) + .register(); + UPGRADE_CASING_REGISTRY.create(ZPM_Inventory.getId(), Inventory.class) + .name("Inventory Upgrade ZPM") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("inventory") + .upgradeInventorySize(256) + .tier(7) + .register(); + UPGRADE_CASING_REGISTRY.create(UV_Inventory.getId(), Inventory.class) + .name("Inventory Upgrade UV") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("inventory") + .upgradeInventorySize(256) + .tier(8) + .register(); + UPGRADE_CASING_REGISTRY.create(UHV_Inventory.getId(), Inventory.class) + .name("Inventory Upgrade UHV") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("inventory") + .upgradeInventorySize(256) + .tier(9) + .register(); + UPGRADE_CASING_REGISTRY.create(UEV_Inventory.getId(), Inventory.class) + .name("Inventory Upgrade UEV") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("inventory") + .upgradeInventorySize(256) + .tier(10) + .register(); + UPGRADE_CASING_REGISTRY.create(UIV_Inventory.getId(), Inventory.class) + .name("Inventory Upgrade UIV") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("inventory") + .upgradeInventorySize(256) + .tier(11) + .register(); + UPGRADE_CASING_REGISTRY.create(UMV_Inventory.getId(), Inventory.class) + .name("Inventory Upgrade UMV") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("inventory") + .upgradeInventorySize(256) + .tier(12) + .register(); + UPGRADE_CASING_REGISTRY.create(UXV_Inventory.getId(), Inventory.class) + .name("Inventory Upgrade UXV") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("inventory") + .upgradeInventorySize(256) + .tier(13) + .register(); + UPGRADE_CASING_REGISTRY.create(MAX_Inventory.getId(), Inventory.class) + .name("Inventory Upgrade MAX") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("inventory") + .upgradeInventorySize(256) + .tier(14) + .register(); + + UPGRADE_CASING_REGISTRY.create(ULV_Tank.getId(), Tank.class) + .name("Tank Upgrade ULV") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("tank") + .upgradeTankCapacity(8_000L) + .upgradeTankCount(1) + .tier(0) + .register(); + UPGRADE_CASING_REGISTRY.create(LV_Tank.getId(), Tank.class) + .name("Tank Upgrade LV") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("tank") + .upgradeTankCapacity(16_000L) + .upgradeTankCount(2) + .tier(1) + .register(); + UPGRADE_CASING_REGISTRY.create(MV_Tank.getId(), Tank.class) + .name("Tank Upgrade MV") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("tank") + .upgradeTankCapacity(32_000L) + .upgradeTankCount(4) + .tier(2) + .register(); + UPGRADE_CASING_REGISTRY.create(HV_Tank.getId(), Tank.class) + .name("Tank Upgrade HV") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("tank") + .upgradeTankCapacity(64_000L) + .upgradeTankCount(6) + .tier(3) + .register(); + UPGRADE_CASING_REGISTRY.create(EV_Tank.getId(), Tank.class) + .name("Tank Upgrade EV") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("tank") + .upgradeTankCapacity(128_000L) + .upgradeTankCount(8) + .tier(4) + .register(); + UPGRADE_CASING_REGISTRY.create(IV_Tank.getId(), Tank.class) + .name("Tank Upgrade IV") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("tank") + .upgradeTankCapacity(256_000L) + .upgradeTankCount(10) + .tier(5) + .register(); + UPGRADE_CASING_REGISTRY.create(LuV_Tank.getId(), Tank.class) + .name("Tank Upgrade LuV") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("tank") + .upgradeTankCapacity(512_000L) + .upgradeTankCount(12) + .tier(6) + .register(); + UPGRADE_CASING_REGISTRY.create(ZPM_Tank.getId(), Tank.class) + .name("Tank Upgrade ZPM") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("tank") + .upgradeTankCapacity(1_024_000L) + .upgradeTankCount(14) + .tier(7) + .register(); + UPGRADE_CASING_REGISTRY.create(UV_Tank.getId(), Tank.class) + .name("Tank Upgrade UV") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("tank") + .upgradeTankCapacity(2_048_000L) + .upgradeTankCount(16) + .tier(8) + .register(); + UPGRADE_CASING_REGISTRY.create(UHV_Tank.getId(), Tank.class) + .name("Tank Upgrade UHV") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("tank") + .upgradeTankCapacity(4_096_000L) + .upgradeTankCount(16) + .tier(9) + .register(); + UPGRADE_CASING_REGISTRY.create(UEV_Tank.getId(), Tank.class) + .name("Tank Upgrade UEV") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("tank") + .upgradeTankCapacity(8_192_000L) + .upgradeTankCount(16) + .tier(10) + .register(); + UPGRADE_CASING_REGISTRY.create(UIV_Tank.getId(), Tank.class) + .name("Tank Upgrade UIV") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("tank") + .upgradeTankCapacity(16_384_000L) + .upgradeTankCount(16) + .tier(11) + .register(); + UPGRADE_CASING_REGISTRY.create(UMV_Tank.getId(), Tank.class) + .name("Tank Upgrade UMV") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("tank") + .upgradeTankCapacity(32_768_000L) + .upgradeTankCount(16) + .tier(12) + .register(); + UPGRADE_CASING_REGISTRY.create(UXV_Tank.getId(), Tank.class) + .name("Tank Upgrade UXV") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("tank") + .upgradeTankCapacity(65_536_000L) + .upgradeTankCount(16) + .tier(13) + .register(); + UPGRADE_CASING_REGISTRY.create(MAX_Tank.getId(), Tank.class) + .name("Tank Upgrade MAX") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("tank") + .upgradeTankCapacity(131_072_000L) + .upgradeTankCount(16) + .tier(14) + .register(); + + UPGRADE_CASING_REGISTRY.create(Amp_4.getId(), Ampere.class) + .name("Amperage Upgrade (4 A)") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("amperage") + .upgradeAmperage(4) + .tier(1) + .register(); + UPGRADE_CASING_REGISTRY.create(Amp_16.getId(), Ampere.class) + .name("Amperage Upgrade (16 A)") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("amperage") + .upgradeAmperage(16) + .tier(2) + .register(); + UPGRADE_CASING_REGISTRY.create(Amp_64.getId(), Ampere.class) + .name("Amperage Upgrade (64 A)") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("amperage") + .upgradeAmperage(64) + .tier(3) + .register(); + UPGRADE_CASING_REGISTRY.create(Amp_256.getId(), Ampere.class) + .name("Amperage Upgrade (256 A)") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("amperage") + .upgradeAmperage(256) + .tier(4) + .register(); + UPGRADE_CASING_REGISTRY.create(Amp_1_024.getId(), Ampere.class) + .name("Amperage Upgrade (1,024 A)") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("amperage") + .upgradeAmperage(1_024) + .tier(5) + .register(); + UPGRADE_CASING_REGISTRY.create(Amp_4_096.getId(), Ampere.class) + .name("Amperage Upgrade (4,096 A)") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("amperage") + .upgradeAmperage(4_096) + .tier(6) + .register(); + UPGRADE_CASING_REGISTRY.create(Amp_16_384.getId(), Ampere.class) + .name("Amperage Upgrade (16,384 A)") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("amperage") + .upgradeAmperage(16_384) + .tier(7) + .register(); + UPGRADE_CASING_REGISTRY.create(Amp_65_536.getId(), Ampere.class) + .name("Amperage Upgrade (65,536 A)") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("amperage") + .upgradeAmperage(65_536) + .tier(8) + .register(); + UPGRADE_CASING_REGISTRY.create(Amp_262_144.getId(), Ampere.class) + .name("Amperage Upgrade (262,144 A)") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("amperage") + .upgradeAmperage(262_144) + .tier(9) + .register(); + UPGRADE_CASING_REGISTRY.create(Amp_1_048_576.getId(), Ampere.class) + .name("Amperage Upgrade (1,048,576 A)") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("amperage") + .upgradeAmperage(1_048_576) + .tier(10) + .register(); + + UPGRADE_CASING_REGISTRY.create(Cleanroom.getId(), Cleanroom.class) + .name("Cleanroom Upgrade") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("cleanroom") + .tier(1) + .register(); + UPGRADE_CASING_REGISTRY.create(Laser.getId(), Laser.class) + .name("Laser Upgrade") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("laser") + .tier(8) + .register(); + UPGRADE_CASING_REGISTRY.create(Wireless.getId(), Wireless.class) + .name("Wireless Upgrade") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("wireless") + .tier(11) + .register(); + + UPGRADE_CASING_REGISTRY.create(Heater_Prototype.getId(), Heater.class) + .name("Prototype Heater Upgrade") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("heater") + .tier(1) + .register(); + UPGRADE_CASING_REGISTRY.create(Heater_IndustrialGrade.getId(), Heater.class) + .name("Industrial-Grade Heater Upgrade") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("heater") + .tier(4) + .register(); + UPGRADE_CASING_REGISTRY.create(Heater_NextGen.getId(), Heater.class) + .name("Next-Gen Heater Upgrade") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("heater") + .tier(7) + .register(); + UPGRADE_CASING_REGISTRY.create(Heater_Omnipotent.getId(), Heater.class) + .name("Omnipotent Heater Upgrade") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("heater") + .tier(10) + .register(); + UPGRADE_CASING_REGISTRY.create(Heater_OmegaType.getId(), Heater.class) + .name("OMEGA-Type Heater Upgrade") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("heater") + .tier(12) + .register(); + + UPGRADE_CASING_REGISTRY.create(Insulator_Prototype.getId(), Insulator.class) + .name("Prototype Insulator Upgrade") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("insulator") + .tier(1) + .register(); + UPGRADE_CASING_REGISTRY.create(Insulator_IndustrialGrade.getId(), Insulator.class) + .name("Industrial-Grade Insulator Upgrade") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("insulator") + .tier(4) + .register(); + UPGRADE_CASING_REGISTRY.create(Insulator_NextGen.getId(), Insulator.class) + .name("Next-Gen Insulator Upgrade") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("insulator") + .tier(7) + .register(); + UPGRADE_CASING_REGISTRY.create(Insulator_Omnipotent.getId(), Insulator.class) + .name("Omnipotent Insulator Upgrade") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("insulator") + .tier(10) + .register(); + UPGRADE_CASING_REGISTRY.create(Insulator_OmegaType.getId(), Insulator.class) + .name("OMEGA-Type Insulator Upgrade") + .category("MultiBlock Upgrade Casing") + .setBlock(COMPONENT_CASING_BLOCK) + .textureFolder("insulator") + .tier(12) + .register(); } private static void registerMotorCasings() { diff --git a/src/main/java/gregtech/loaders/preload/GT_PreLoad.java b/src/main/java/gregtech/loaders/preload/GT_PreLoad.java index a25377fdf6..c3d9b4f566 100644 --- a/src/main/java/gregtech/loaders/preload/GT_PreLoad.java +++ b/src/main/java/gregtech/loaders/preload/GT_PreLoad.java @@ -27,6 +27,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import net.minecraft.init.Blocks; +import net.minecraft.launchwrapper.Launch; import net.minecraftforge.common.config.Configuration; import org.apache.commons.lang3.StringUtils; @@ -416,6 +417,14 @@ public class GT_PreLoad { GT_Values.disableDigitalChestsExternalAccess = tMainConfig .get("machines", "disableDigitalChestsExternalAccess", false) .getBoolean(false); + GT_Values.enableMultiTileEntities = tMainConfig.get( + "machines", + "enableMultiTileEntities", + false, + "This enabled MuTEs(multitile entities) to be added to the game. MuTEs are in the start of development and its not recommended to enable them unless you know what you are doing.") + .getBoolean(false) + // Make sure MuTEs are enabled in development + || (boolean) Launch.blackboard.get("fml.deobfuscatedEnvironment"); GregTech_API.TICKS_FOR_LAG_AVERAGING = tMainConfig .get(GT_Mod.aTextGeneral, "TicksForLagAveragingWithScanner", 25) .getInt(25); diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalReactor/active.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/BigLaserEngraver/active.png Binary files differindex ffd43d8dc2..ffd43d8dc2 100644 --- a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalReactor/active.png +++ b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/BigLaserEngraver/active.png diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalReactor/active_glow.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/BigLaserEngraver/active_glow.png Binary files differindex 3bb29bbda6..3bb29bbda6 100644 --- a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalReactor/active_glow.png +++ b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/BigLaserEngraver/active_glow.png diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/BigLaserEngraver/base.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/BigLaserEngraver/base.png Binary files differnew file mode 100644 index 0000000000..b119dc1ba0 --- /dev/null +++ b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/BigLaserEngraver/base.png diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalReactor/inactive.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/BigLaserEngraver/inactive.png Binary files differindex 6092ec4c18..6092ec4c18 100644 --- a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalReactor/inactive.png +++ b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/BigLaserEngraver/inactive.png diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalReactor/inactive_glow.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/BigLaserEngraver/inactive_glow.png Binary files differindex b7955d63ab..b7955d63ab 100644 --- a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalReactor/inactive_glow.png +++ b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/BigLaserEngraver/inactive_glow.png diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/BlackLaserEngraver/base.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/BlackLaserEngraver/base.png Binary files differnew file mode 100644 index 0000000000..de4345cf43 --- /dev/null +++ b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/BlackLaserEngraver/base.png diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/Laserblock/base.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/Laserblock/base.png Binary files differnew file mode 100644 index 0000000000..2ec2c2e004 --- /dev/null +++ b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/Laserblock/base.png diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalProcessor/active.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalProcessor/active.png Binary files differnew file mode 100644 index 0000000000..ffd43d8dc2 --- /dev/null +++ b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalProcessor/active.png diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalProcessor/active_glow.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalProcessor/active_glow.png Binary files differnew file mode 100644 index 0000000000..3bb29bbda6 --- /dev/null +++ b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalProcessor/active_glow.png diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalReactor/base.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalProcessor/base.png Binary files differindex 84cd5fa9f2..84cd5fa9f2 100644 --- a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalReactor/base.png +++ b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalProcessor/base.png diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalProcessor/inactive.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalProcessor/inactive.png Binary files differnew file mode 100644 index 0000000000..6092ec4c18 --- /dev/null +++ b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalProcessor/inactive.png diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalProcessor/inactive_glow.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalProcessor/inactive_glow.png Binary files differnew file mode 100644 index 0000000000..b7955d63ab --- /dev/null +++ b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/advChemicalProcessor/inactive_glow.png diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/amperage/base.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/amperage/base.png Binary files differnew file mode 100644 index 0000000000..e05f5d89c7 --- /dev/null +++ b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/amperage/base.png diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/cleanroom/base.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/cleanroom/base.png Binary files differnew file mode 100644 index 0000000000..e05f5d89c7 --- /dev/null +++ b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/cleanroom/base.png diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/distillationTower/active.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/distillationTower/active.png Binary files differnew file mode 100644 index 0000000000..ffd43d8dc2 --- /dev/null +++ b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/distillationTower/active.png diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/distillationTower/active_glow.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/distillationTower/active_glow.png Binary files differnew file mode 100644 index 0000000000..3bb29bbda6 --- /dev/null +++ b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/distillationTower/active_glow.png diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/distillationTower/base.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/distillationTower/base.png Binary files differnew file mode 100644 index 0000000000..99f62d97a4 --- /dev/null +++ b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/distillationTower/base.png diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/distillationTower/inactive.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/distillationTower/inactive.png Binary files differnew file mode 100644 index 0000000000..6092ec4c18 --- /dev/null +++ b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/distillationTower/inactive.png diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/distillationTower/inactive_glow.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/distillationTower/inactive_glow.png Binary files differnew file mode 100644 index 0000000000..b7955d63ab --- /dev/null +++ b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/distillationTower/inactive_glow.png diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/heater/base.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/heater/base.png Binary files differnew file mode 100644 index 0000000000..e05f5d89c7 --- /dev/null +++ b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/heater/base.png diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/insulator/base.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/insulator/base.png Binary files differnew file mode 100644 index 0000000000..e05f5d89c7 --- /dev/null +++ b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/insulator/base.png diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/inventory/base.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/inventory/base.png Binary files differnew file mode 100644 index 0000000000..e05f5d89c7 --- /dev/null +++ b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/inventory/base.png diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/laser/base.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/laser/base.png Binary files differnew file mode 100644 index 0000000000..e05f5d89c7 --- /dev/null +++ b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/laser/base.png diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/laserengraverupgrade1/base.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/laserengraverupgrade1/base.png Binary files differnew file mode 100644 index 0000000000..7e644d11cb --- /dev/null +++ b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/laserengraverupgrade1/base.png diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/laserengraverupgrade2/base.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/laserengraverupgrade2/base.png Binary files differnew file mode 100644 index 0000000000..d4ee6ed402 --- /dev/null +++ b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/laserengraverupgrade2/base.png diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/laserengraverupgrade3/base.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/laserengraverupgrade3/base.png Binary files differnew file mode 100644 index 0000000000..dbc1a20f76 --- /dev/null +++ b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/laserengraverupgrade3/base.png diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/laserengraverupgrade4/base.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/laserengraverupgrade4/base.png Binary files differnew file mode 100644 index 0000000000..1587cdeca6 --- /dev/null +++ b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/laserengraverupgrade4/base.png diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/tank/base.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/tank/base.png Binary files differnew file mode 100644 index 0000000000..e05f5d89c7 --- /dev/null +++ b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/tank/base.png diff --git a/src/main/resources/assets/gregtech/textures/blocks/multitileentity/wireless/base.png b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/wireless/base.png Binary files differnew file mode 100644 index 0000000000..e05f5d89c7 --- /dev/null +++ b/src/main/resources/assets/gregtech/textures/blocks/multitileentity/wireless/base.png diff --git a/src/test/java/gregtech/globalenergymap/IGlobalWirelessEnergy_UnitTest.java b/src/test/java/gregtech/globalenergymap/IGlobalWirelessEnergy_UnitTest.java index 5288773efa..8e2b9f677e 100644 --- a/src/test/java/gregtech/globalenergymap/IGlobalWirelessEnergy_UnitTest.java +++ b/src/test/java/gregtech/globalenergymap/IGlobalWirelessEnergy_UnitTest.java @@ -3,6 +3,12 @@ package gregtech.globalenergymap; import static gregtech.common.misc.GlobalVariableStorage.GlobalEnergy; import static gregtech.common.misc.GlobalVariableStorage.GlobalEnergyName; import static gregtech.common.misc.GlobalVariableStorage.GlobalEnergyTeam; +import static gregtech.common.misc.WirelessNetworkManager.addEUToGlobalEnergyMap; +import static gregtech.common.misc.WirelessNetworkManager.clearGlobalEnergyInformationMaps; +import static gregtech.common.misc.WirelessNetworkManager.getUserEU; +import static gregtech.common.misc.WirelessNetworkManager.getUsernameFromUUID; +import static gregtech.common.misc.WirelessNetworkManager.joinUserNetwork; +import static gregtech.common.misc.WirelessNetworkManager.strongCheckOrAddUser; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -11,9 +17,7 @@ import java.math.BigInteger; import org.junit.jupiter.api.Test; -import gregtech.api.interfaces.IGlobalWirelessEnergy; - -class IGlobalWirelessEnergy_UnitTest implements IGlobalWirelessEnergy { +class IGlobalWirelessEnergy_UnitTest { static final String message = "Comparison failed"; @@ -31,7 +35,7 @@ class IGlobalWirelessEnergy_UnitTest implements IGlobalWirelessEnergy { addEUToGlobalEnergyMap(test_id, 1L); assertEquals(GlobalEnergy.get(test_id), new BigInteger("3"), message); - IGlobalWirelessEnergy.clearGlobalEnergyInformationMaps(); + clearGlobalEnergyInformationMaps(); } @Test @@ -57,7 +61,7 @@ class IGlobalWirelessEnergy_UnitTest implements IGlobalWirelessEnergy { assertTrue(addEUToGlobalEnergyMap(user_uuid, new BigInteger("-2"))); assertEquals(getUserEU(user_uuid), BigInteger.ZERO, message); - IGlobalWirelessEnergy.clearGlobalEnergyInformationMaps(); + clearGlobalEnergyInformationMaps(); } @Test @@ -70,7 +74,7 @@ class IGlobalWirelessEnergy_UnitTest implements IGlobalWirelessEnergy { assertEquals(GlobalEnergyTeam.get(user_uuid), user_uuid, message); assertEquals(GlobalEnergyName.get(user_uuid), user_name, message); - IGlobalWirelessEnergy.clearGlobalEnergyInformationMaps(); + clearGlobalEnergyInformationMaps(); } @Test @@ -98,7 +102,7 @@ class IGlobalWirelessEnergy_UnitTest implements IGlobalWirelessEnergy { assertEquals(GlobalEnergyName.get(user_uuid), user_name_0, message); assertEquals(GlobalEnergyName.get(user_name_0), user_uuid, message); - IGlobalWirelessEnergy.clearGlobalEnergyInformationMaps(); + clearGlobalEnergyInformationMaps(); } @Test @@ -154,7 +158,7 @@ class IGlobalWirelessEnergy_UnitTest implements IGlobalWirelessEnergy { assertEquals(getUserEU(user_uuid_1), BigInteger.ONE, message); assertEquals(getUserEU(user_uuid_2), BigInteger.ONE, message); - IGlobalWirelessEnergy.clearGlobalEnergyInformationMaps(); + clearGlobalEnergyInformationMaps(); } @Test @@ -168,14 +172,14 @@ class IGlobalWirelessEnergy_UnitTest implements IGlobalWirelessEnergy { strongCheckOrAddUser(user_uuid_0, user_name_0); strongCheckOrAddUser(user_uuid_1, user_name_1); - assertEquals(GetUsernameFromUUID(user_uuid_0), user_name_0, message); - assertEquals(GetUsernameFromUUID(user_uuid_1), user_name_1, message); + assertEquals(getUsernameFromUUID(user_uuid_0), user_name_0, message); + assertEquals(getUsernameFromUUID(user_uuid_1), user_name_1, message); joinUserNetwork(user_uuid_0, user_uuid_1); - assertEquals(GetUsernameFromUUID(user_uuid_0), user_name_1, message); - assertEquals(GetUsernameFromUUID(user_uuid_1), user_name_1, message); + assertEquals(getUsernameFromUUID(user_uuid_0), user_name_1, message); + assertEquals(getUsernameFromUUID(user_uuid_1), user_name_1, message); - IGlobalWirelessEnergy.clearGlobalEnergyInformationMaps(); + clearGlobalEnergyInformationMaps(); } } |