aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockController.java
diff options
context:
space:
mode:
authorMaxim <maxim235@gmx.de>2023-04-22 17:38:49 +0200
committerGitHub <noreply@github.com>2023-04-22 08:38:49 -0700
commitfdde96ab6fef30064b67e28390008ee4ba455655 (patch)
treeee169d0d4a8432433c4ec01eada1e24049a0e47a /src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockController.java
parentde864236f83dc31c53ca77a6939357a0959bca75 (diff)
downloadGT5-Unofficial-fdde96ab6fef30064b67e28390008ee4ba455655.tar.gz
GT5-Unofficial-fdde96ab6fef30064b67e28390008ee4ba455655.tar.bz2
GT5-Unofficial-fdde96ab6fef30064b67e28390008ee4ba455655.zip
MuTE overhaul and ACR (#1883)
* complex controller start * Added methods to get input fluids and items * Added logic to complex parallel mute * Added ACR and fixed many, many, many, many bugs * Added void protection setting to checkRecipe * do not init nbt, if mteID and mteRegistry are the same * Improved GUI design * Force structure check when pressing power switch * ACR Textures * Added T1 structure * Added perfect OC * Added WAILA * fix mutes resetting their nbt * Fix ACR GUI * fix npe * Added void protection for MuTEs * Fixed ACR starting recipe while another one is ongoing * nbt saving * maybe fix structure breaking * Fix complex machine disabling on startup * correctly update input tanks * move casings over * Changed logic of casings to change mode and facing in one go by sneaking * Fixed the casing target not resetting * Added side only annotations * don't leave it empty * Added power logic and tiered blocks to ACR * Change facing to wrench side if casing mode is currently none * lasers anyone? * Added ACR item chaining * Remove unncessary item lists * Use HashSet for process whitelists * Optimize list capacities * Fix potential recipe voiding bug * Rename methods for consistancy * Fix NPE * Duct tape fix structure check * allow MuTEs to connect to cables * Added separate tank inventories for input separation (#1887) * Fixed unregistering tank function * Fixed input busses not being automatable * Added fluid chaining * Fixed saving of input tanks * Forbid inventory registering with empty name * Display all input tanks in controller GUI * Fixed fluid hatch GUI height * Reset casing lists when checking the structure * Make inventory GUI size consistant * Make use of the tooltip cache * rename thing clean up * Forgot to put tooltip into map * Added tooltip to ACR * Reset whitelists when one whitelist window was opened * Refined scanner string * Fixed progress times * Fixed MuTE not consuming fluids * Properly register controller inventories * switch to ForgeDirection * switch to new Renderer * Added missing contains check on registerInventory * Fixed output tanks not registering * Fixed upgrade tank loading * fix machines not having active/inactive textures * fix overlays not loading correctly * Don't register controller directly * Remove magic strings all * fix active not setting to inactive * allow glow * item renderer * fix glow * MuTE improved hatch GUI and fluid output locking (#1889) * Allow output hatches to be fluid locked * Reworked hatch GUI * Check target before trying to open GUI * Make ACR GUI easier to look at * fix covers not rendering on mutes * fix covers not displaying above the item/fluid in/out * new folder texture structure * Reduce network traffic caused by covers * Fixed WAILA fluid locking display * Don't save everything to the itemstack NBT * Added possibility to save NBT of MuTE to its itemstack * fix textures, but make sacrifices * mah textures * Removed the need for all textures to be present * Added glow texture for active coke oven * Removed unncesssary upgrade casing textures * shorten nbt tags --------- Co-authored-by: BlueWeabo <76872108+BlueWeabo@users.noreply.github.com> Co-authored-by: Martin Robertz <dream-master@gmx.net> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Diffstat (limited to 'src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockController.java')
-rw-r--r--src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockController.java1709
1 files changed, 0 insertions, 1709 deletions
diff --git a/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockController.java b/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockController.java
deleted file mode 100644
index 1355ac13a6..0000000000
--- a/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockController.java
+++ /dev/null
@@ -1,1709 +0,0 @@
-package gregtech.api.multitileentity.multiblock.base;
-
-import static gregtech.GT_Mod.GT_FML_LOGGER;
-import static gregtech.api.enums.GT_Values.ALL_VALID_SIDES;
-import static gregtech.api.enums.GT_Values.NBT;
-
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.stream.Collectors;
-
-import net.minecraft.block.Block;
-import net.minecraft.entity.player.EntityPlayer;
-import net.minecraft.item.ItemStack;
-import net.minecraft.nbt.NBTTagCompound;
-import net.minecraft.nbt.NBTTagList;
-import net.minecraft.tileentity.TileEntity;
-import net.minecraft.util.IIcon;
-import net.minecraft.util.StatCollector;
-import net.minecraft.world.World;
-import net.minecraftforge.common.util.ForgeDirection;
-import net.minecraftforge.fluids.Fluid;
-import net.minecraftforge.fluids.FluidStack;
-import net.minecraftforge.fluids.FluidTankInfo;
-import net.minecraftforge.fluids.IFluidTank;
-
-import org.apache.commons.lang3.tuple.ImmutablePair;
-import org.apache.commons.lang3.tuple.Pair;
-import org.lwjgl.input.Keyboard;
-
-import com.gtnewhorizon.structurelib.StructureLibAPI;
-import com.gtnewhorizon.structurelib.alignment.IAlignment;
-import com.gtnewhorizon.structurelib.alignment.IAlignmentLimits;
-import com.gtnewhorizon.structurelib.alignment.constructable.IConstructable;
-import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
-import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
-import com.gtnewhorizon.structurelib.alignment.enumerable.Flip;
-import com.gtnewhorizon.structurelib.alignment.enumerable.Rotation;
-import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
-import com.gtnewhorizon.structurelib.structure.IStructureElement;
-import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
-import com.gtnewhorizon.structurelib.util.Vec3Impl;
-import com.gtnewhorizons.modularui.api.ModularUITextures;
-import com.gtnewhorizons.modularui.api.drawable.IDrawable;
-import com.gtnewhorizons.modularui.api.drawable.ItemDrawable;
-import com.gtnewhorizons.modularui.api.drawable.UITexture;
-import com.gtnewhorizons.modularui.api.forge.IItemHandlerModifiable;
-import com.gtnewhorizons.modularui.api.forge.ItemStackHandler;
-import com.gtnewhorizons.modularui.api.forge.ListItemHandler;
-import com.gtnewhorizons.modularui.api.screen.*;
-import com.gtnewhorizons.modularui.api.widget.Widget;
-import com.gtnewhorizons.modularui.common.widget.ButtonWidget;
-import com.gtnewhorizons.modularui.common.widget.DrawableWidget;
-import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget;
-import com.gtnewhorizons.modularui.common.widget.FluidSlotWidget;
-import com.gtnewhorizons.modularui.common.widget.MultiChildWidget;
-import com.gtnewhorizons.modularui.common.widget.Scrollable;
-import com.gtnewhorizons.modularui.common.widget.SlotWidget;
-import com.gtnewhorizons.modularui.common.widget.TabButton;
-import com.gtnewhorizons.modularui.common.widget.TabContainer;
-
-import cpw.mods.fml.common.network.NetworkRegistry;
-import gnu.trove.list.TIntList;
-import gnu.trove.list.array.TIntArrayList;
-import gregtech.api.enums.GT_Values;
-import gregtech.api.enums.GT_Values.NBT;
-import gregtech.api.enums.OrePrefixes;
-import gregtech.api.enums.SoundResource;
-import gregtech.api.enums.TextureSet;
-import gregtech.api.fluid.FluidTankGT;
-import gregtech.api.gui.modularui.GT_UITextures;
-import gregtech.api.interfaces.IDescribable;
-import gregtech.api.logic.PowerLogic;
-import gregtech.api.logic.ProcessingLogic;
-import gregtech.api.logic.interfaces.PowerLogicHost;
-import gregtech.api.logic.interfaces.ProcessingLogicHost;
-import gregtech.api.multitileentity.MultiTileEntityContainer;
-import gregtech.api.multitileentity.MultiTileEntityRegistry;
-import gregtech.api.multitileentity.interfaces.IMultiBlockController;
-import gregtech.api.multitileentity.interfaces.IMultiBlockPart;
-import gregtech.api.multitileentity.interfaces.IMultiTileEntity;
-import gregtech.api.multitileentity.interfaces.IMultiTileEntity.IMTE_AddToolTips;
-import gregtech.api.multitileentity.machine.MultiTileBasicMachine;
-import gregtech.api.multitileentity.multiblock.casing.FunctionalCasing;
-import gregtech.api.multitileentity.multiblock.casing.UpgradeCasing;
-import gregtech.api.objects.GT_ItemStack;
-import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
-import gregtech.api.util.GT_Utility;
-import gregtech.common.tileentities.casings.upgrade.InventoryUpgrade;
-
-public abstract class MultiBlockController<T extends MultiBlockController<T>> extends MultiTileBasicMachine implements
- IAlignment, IConstructable, IMultiBlockController, IDescribable, IMTE_AddToolTips, ISurvivalConstructable {
-
- 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 = false;
- protected boolean voidExcess = false;
- protected boolean batchMode = false;
- protected boolean recipeLock = false;
-
- // A list of sides
- // Each side has a list of parts that have a cover that need to be ticked
- protected List<LinkedList<WeakReference<IMultiBlockPart>>> registeredCoveredParts = Arrays.asList(
- new LinkedList<>(),
- new LinkedList<>(),
- new LinkedList<>(),
- new LinkedList<>(),
- new LinkedList<>(),
- new LinkedList<>());
-
- /** Registry ID of the required casing */
- public abstract short getCasingRegistryID();
-
- /** Meta ID of the required casing */
- public abstract short getCasingMeta();
-
- /**
- * Create the tooltip for this multi block controller.
- */
- protected abstract GT_Multiblock_Tooltip_Builder createTooltip();
-
- /**
- * @return The starting offset for the structure builder
- */
- public abstract Vec3Impl getStartingStructureOffset();
-
- /**
- * Due to limitation of Java type system, you might need to do an unchecked cast. HOWEVER, the returned
- * IStructureDefinition is expected to be evaluated against current instance only, and should not be used against
- * other instances, even for those of the same class.
- */
- @Override
- public abstract IStructureDefinition<T> getStructureDefinition();
-
- /**
- * Checks the Machine.
- * <p>
- * NOTE: If using `buildState` be sure to `startBuilding()` and either `endBuilding()` or `failBuilding()`
- */
- public boolean checkMachine() {
- double sum = 0;
- for (FunctionalCasing casing : functionalCasings) {
- sum += casing.getPartTier();
- }
- tier = (int) Math.floor(sum / functionalCasings.size());
- // Maximum Energy stores will have a cap of 2 minute work time of current voltage
- return tier > 0;
- }
-
- @Override
- public void writeMultiTileNBT(NBTTagCompound nbt) {
- super.writeMultiTileNBT(nbt);
-
- nbt.setBoolean(NBT.STRUCTURE_OK, structureOkay);
- nbt.setByte(
- NBT.ROTATION,
- (byte) extendedFacing.getRotation()
- .getIndex());
- nbt.setByte(
- NBT.FLIP,
- (byte) extendedFacing.getFlip()
- .getIndex());
-
- saveUpgradeInventoriesToNBT(nbt);
- }
-
- private void saveUpgradeInventoriesToNBT(NBTTagCompound nbt) {
- final NBTTagList inputInvList = new NBTTagList();
- multiBlockInputInventory.forEach((id, inv) -> {
- if (!id.equals("controller")) {
- final NBTTagCompound tTag = new NBTTagCompound();
- tTag.setString(NBT.UPGRADE_INVENTORY_UUID, id);
- tTag.setString(NBT.UPGRADE_INVENTORY_NAME, multiBlockInputInventoryNames.get(id));
- tTag.setInteger(NBT.UPGRADE_INVENTORY_SIZE, inv.getSlots());
- writeInventory(tTag, inv, NBT.INV_INPUT_LIST);
- inputInvList.appendTag(tTag);
- }
- });
- final NBTTagList outputInvList = new NBTTagList();
- multiBlockOutputInventory.forEach((id, inv) -> {
- if (!id.equals("controller")) {
- final NBTTagCompound tTag = new NBTTagCompound();
- tTag.setString(NBT.UPGRADE_INVENTORY_UUID, id);
- tTag.setString(NBT.UPGRADE_INVENTORY_NAME, multiBlockOutputInventoryNames.get(id));
- tTag.setInteger(NBT.UPGRADE_INVENTORY_SIZE, inv.getSlots());
- writeInventory(tTag, inv, NBT.INV_OUTPUT_LIST);
- outputInvList.appendTag(tTag);
- }
- });
- nbt.setTag(NBT.UPGRADE_INVENTORIES_INPUT, inputInvList);
- nbt.setTag(NBT.UPGRADE_INVENTORIES_OUTPUT, outputInvList);
- }
-
- @Override
- public void readMultiTileNBT(NBTTagCompound nbt) {
- super.readMultiTileNBT(nbt);
-
- // Multiblock inventories are a collection of inventories. The first inventory is the default internal
- // inventory, and the others are added by inventory extending blocks.
- if (inputInventory != null) multiBlockInputInventory.put("controller", inputInventory);
- if (outputInventory != null) multiBlockOutputInventory.put("controller", outputInventory);
-
- structureOkay = nbt.getBoolean(NBT.STRUCTURE_OK);
- extendedFacing = ExtendedFacing.of(
- ForgeDirection.getOrientation(getFrontFacing()),
- Rotation.byIndex(nbt.getByte(NBT.ROTATION)),
- Flip.byIndex(nbt.getByte(NBT.FLIP)));
-
- loadUpgradeInventoriesFromNBT(nbt);
- }
-
- private void loadUpgradeInventoriesFromNBT(NBTTagCompound nbt) {
- final NBTTagList listInputInventories = nbt.getTagList(NBT.UPGRADE_INVENTORIES_INPUT, 10);
- for (int i = 0; i < listInputInventories.tagCount(); i++) {
- final NBTTagCompound nbtInv = listInputInventories.getCompoundTagAt(i);
- String invUUID = nbtInv.getString(NBT.UPGRADE_INVENTORY_UUID);
- String invName = nbtInv.getString(NBT.UPGRADE_INVENTORY_NAME);
- int invSize = nbtInv.getInteger(NBT.UPGRADE_INVENTORY_SIZE);
- IItemHandlerModifiable inv = new ItemStackHandler(invSize);
- loadInventory(nbtInv, inv, NBT.INV_INPUT_LIST);
- multiBlockInputInventory.put(invUUID, inv);
- multiBlockInputInventoryNames.put(invUUID, invName);
- }
-
- final NBTTagList listOutputInventories = nbt.getTagList(NBT.UPGRADE_INVENTORIES_OUTPUT, 10);
- for (int i = 0; i < listOutputInventories.tagCount(); i++) {
- final NBTTagCompound nbtInv = listOutputInventories.getCompoundTagAt(i);
- String invUUID = nbtInv.getString(NBT.UPGRADE_INVENTORY_UUID);
- String invName = nbtInv.getString(NBT.UPGRADE_INVENTORY_NAME);
- int invSize = nbtInv.getInteger(NBT.UPGRADE_INVENTORY_SIZE);
- IItemHandlerModifiable inv = new ItemStackHandler(invSize);
- loadInventory(nbtInv, inv, NBT.INV_OUTPUT_LIST);
- multiBlockOutputInventory.put(invUUID, inv);
- multiBlockOutputInventoryNames.put(invUUID, invName);
- }
- }
-
- @Override
- public void addToolTips(List<String> aList, ItemStack aStack, boolean aF3_H) {
- aList.addAll(Arrays.asList(getDescription()));
- }
-
- @Override
- public String[] getDescription() {
- if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) {
- return getTooltip().getStructureInformation();
- } else {
- return getTooltip().getInformation();
- }
- }
-
- @Override
- protected void addDebugInfo(EntityPlayer aPlayer, int aLogLevel, ArrayList<String> tList) {
- super.addDebugInfo(aPlayer, aLogLevel, tList);
- tList.add("Structure ok: " + checkStructure(false));
- }
-
- protected int getToolTipID() {
- return getMultiTileEntityRegistryID() << 16 + getMultiTileEntityID();
- }
-
- protected GT_Multiblock_Tooltip_Builder getTooltip() {
- return createTooltip();
- }
-
- @Override
- public boolean checkStructure(boolean aForceReset) {
- if (!isServerSide()) return structureOkay;
-
- // Only trigger an update if forced (from onPostTick, generally), or if the structure has changed
- if ((structureChanged || aForceReset)) {
- structureOkay = checkMachine();
- }
- structureChanged = false;
- return structureOkay;
- }
-
- @Override
- public void onStructureChange() {
- structureChanged = true;
- }
-
- public final boolean checkPiece(String piece, Vec3Impl offset) {
- return checkPiece(piece, offset.get0(), offset.get1(), offset.get2());
- }
-
- /**
- * Explanation of the world coordinate these offset means:
- * <p>
- * Imagine you stand in front of the controller, with controller facing towards you not rotated or flipped.
- * <p>
- * The horizontalOffset would be the number of blocks on the left side of the controller, not counting controller
- * itself. The verticalOffset would be the number of blocks on the top side of the controller, not counting
- * controller itself. The depthOffset would be the number of blocks between you and controller, not counting
- * controller itself.
- * <p>
- * All these offsets can be negative.
- */
- protected final boolean checkPiece(String piece, int horizontalOffset, int verticalOffset, int depthOffset) {
- return getCastedStructureDefinition().check(
- this,
- piece,
- getWorld(),
- getExtendedFacing(),
- getXCoord(),
- getYCoord(),
- getZCoord(),
- horizontalOffset,
- verticalOffset,
- depthOffset,
- !structureOkay);
- }
-
- public final boolean buildPiece(String piece, ItemStack trigger, boolean hintsOnly, Vec3Impl offset) {
- return buildPiece(piece, trigger, hintsOnly, offset.get0(), offset.get1(), offset.get2());
- }
-
- protected final boolean buildPiece(String piece, ItemStack trigger, boolean hintOnly, int horizontalOffset,
- int verticalOffset, int depthOffset) {
- return getCastedStructureDefinition().buildOrHints(
- this,
- trigger,
- piece,
- getWorld(),
- getExtendedFacing(),
- getXCoord(),
- getYCoord(),
- getZCoord(),
- horizontalOffset,
- verticalOffset,
- depthOffset,
- hintOnly);
- }
-
- protected final int survivalBuildPiece(String piece, ItemStack trigger, Vec3Impl offset, int elementBudget,
- ISurvivalBuildEnvironment env, boolean check) {
- return survivalBuildPiece(
- piece,
- trigger,
- offset.get0(),
- offset.get1(),
- offset.get2(),
- elementBudget,
- env,
- check);
- }
-
- protected final Integer survivalBuildPiece(String piece, ItemStack trigger, int horizontalOffset,
- int verticalOffset, int depthOffset, int elementBudget, ISurvivalBuildEnvironment env, boolean check) {
- return getCastedStructureDefinition().survivalBuild(
- this,
- trigger,
- piece,
- getWorld(),
- getExtendedFacing(),
- getXCoord(),
- getYCoord(),
- getZCoord(),
- horizontalOffset,
- verticalOffset,
- depthOffset,
- elementBudget,
- env,
- check);
- }
-
- @SuppressWarnings("unchecked")
- private IStructureDefinition<MultiBlockController<T>> getCastedStructureDefinition() {
- return (IStructureDefinition<MultiBlockController<T>>) getStructureDefinition();
- }
-
- @Override
- public ExtendedFacing getExtendedFacing() {
- return extendedFacing;
- }
-
- @Override
- public void setExtendedFacing(ExtendedFacing newExtendedFacing) {
- if (extendedFacing != newExtendedFacing) {
- onStructureChange();
- if (structureOkay) stopMachine(false);
- extendedFacing = newExtendedFacing;
- structureOkay = false;
- if (isServerSide()) {
- StructureLibAPI.sendAlignment(
- this,
- new NetworkRegistry.TargetPoint(
- getWorld().provider.dimensionId,
- getXCoord(),
- getYCoord(),
- getZCoord(),
- 512));
- } else {
- issueTextureUpdate();
- }
- }
- }
-
- @Override
- public boolean onWrenchRightClick(EntityPlayer aPlayer, ItemStack tCurrentItem, byte wrenchSide, float aX, float aY,
- float aZ) {
- if (wrenchSide != getFrontFacing())
- return super.onWrenchRightClick(aPlayer, tCurrentItem, wrenchSide, aX, aY, aZ);
- if (aPlayer.isSneaking()) {
- // we won't be allowing horizontal flips, as it can be perfectly emulated by rotating twice and flipping
- // horizontally allowing an extra round of flip make it hard to draw meaningful flip markers in
- // GT_Proxy#drawGrid
- toolSetFlip(getFlip().isHorizontallyFlipped() ? Flip.NONE : Flip.HORIZONTAL);
- } else {
- toolSetRotation(null);
- }
- return true;
- }
-
- @Override
- public void registerCoveredPartOnSide(final int aSide, IMultiBlockPart part) {
- if (aSide < 0 || aSide >= 6) return;
-
- final LinkedList<WeakReference<IMultiBlockPart>> registeredCovers = registeredCoveredParts.get(aSide);
- // TODO: Make sure that we're not already registered on this side
- registeredCovers.add(new WeakReference<>(part));
- }
-
- @Override
- public void unregisterCoveredPartOnSide(final int aSide, IMultiBlockPart aPart) {
- if (aSide < 0 || aSide >= 6) return;
-
- final LinkedList<WeakReference<IMultiBlockPart>> coveredParts = registeredCoveredParts.get(aSide);
- final Iterator<WeakReference<IMultiBlockPart>> it = coveredParts.iterator();
- while (it.hasNext()) {
- final IMultiBlockPart part = (it.next()).get();
- if (part == null || part == aPart) it.remove();
- }
- }
-
- @Override
- public void onFirstTick(boolean isServerSide) {
- super.onFirstTick(isServerSide);
- if (isServerSide) {
- checkStructure(true);
- } else {
- StructureLibAPI.queryAlignment(this);
- }
- }
-
- private boolean tickCovers() {
- for (byte side : ALL_VALID_SIDES) {
- // TODO: Tick controller covers, if any
- final LinkedList<WeakReference<IMultiBlockPart>> coveredParts = this.registeredCoveredParts.get(side);
- final Iterator<WeakReference<IMultiBlockPart>> it = coveredParts.iterator();
- while (it.hasNext()) {
- final IMultiBlockPart part = (it.next()).get();
- if (part == null) {
- it.remove();
- continue;
- }
- if (!part.tickCoverAtSide(side, mTickTimer)) it.remove();
- }
- }
-
- return true;
- }
-
- @Override
- public void onTick(long timer, boolean isServerSide) {
- if (!tickCovers()) {
- return;
- }
- }
-
- @Override
- public void onPostTick(long tick, boolean isServerSide) {
- if (isServerSide) {
- if (tick % 600 == 5) {
- clearSpecialLists();
- // Recheck the structure every 30 seconds or so
- if (!checkStructure(false)) checkStructure(true);
- }
- if (structureOkay) {
- runMachine(tick);
- } else {
- stopMachine(false);
- }
- } else {
- doActivitySound(getActivitySoundLoop());
- }
- }
-
- protected void clearSpecialLists() {
- upgradeCasings.clear();
- }
-
- @Override
- public final boolean isFacingValid(byte aFacing) {
- return canSetToDirectionAny(ForgeDirection.getOrientation(aFacing));
- }
-
- @Override
- public void onFacingChange() {
- toolSetDirection(ForgeDirection.getOrientation(getFrontFacing()));
- onStructureChange();
- }
-
- @Override
- public boolean allowCoverOnSide(byte aSide, GT_ItemStack aCoverID) {
- return aSide != facing;
- }
-
- @Override
- public String[] getStructureDescription(ItemStack stackSize) {
- return getTooltip().getStructureHint();
- }
-
- @Override
- public IAlignmentLimits getAlignmentLimits() {
- return limits;
- }
-
- protected void setAlignmentLimits(IAlignmentLimits mLimits) {
- this.limits = mLimits;
- }
-
- // IMachineProgress
- @Override
- public long getProgress() {
- return progressTime;
- }
-
- @Override
- public long getMaxProgress() {
- return maxProgressTime;
- }
-
- @Override
- public boolean increaseProgress(int aProgressAmountInTicks) {
- return increaseProgressGetOverflow(aProgressAmountInTicks) != aProgressAmountInTicks;
- }
-
- @Override
- public FluidStack getDrainableFluid(byte aSide) {
- final IFluidTank tank = getFluidTankDrainable(aSide, null);
- return tank == null ? null : tank.getFluid();
- }
-
- /**
- * Increases the Progress, returns the overflown Progress.
- */
- public int increaseProgressGetOverflow(int aProgress) {
- return 0;
- }
-
- @Override
- public boolean hasThingsToDo() {
- return getMaxProgress() > 0;
- }
-
- public boolean isSeparateInputs() {
- return separateInputs;
- }
-
- public void setSeparateInputs(boolean aSeparateInputs) {
- separateInputs = aSeparateInputs;
- }
-
- // End IMachineProgress
-
- protected IAlignmentLimits getInitialAlignmentLimits() {
- return (d, r, f) -> !f.isVerticallyFliped();
- }
-
- public static class BuildState {
-
- /**
- * Utility class to keep track of the build state of a multiblock
- */
- boolean building = false;
-
- Vec3Impl currentOffset;
-
- public void startBuilding(Vec3Impl structureOffset) {
- if (building) throw new IllegalStateException("Already building!");
- building = true;
- setCurrentOffset(structureOffset);
- }
-
- public Vec3Impl setCurrentOffset(Vec3Impl structureOffset) {
- verifyBuilding();
- return (currentOffset = structureOffset);
- }
-
- private void verifyBuilding() {
- if (!building) throw new IllegalStateException("Not building!");
- }
-
- public boolean failBuilding() {
- building = false;
- currentOffset = null;
- return false;
- }
-
- public Vec3Impl stopBuilding() {
- final Vec3Impl toReturn = getCurrentOffset();
- building = false;
- currentOffset = null;
-
- return toReturn;
- }
-
- public Vec3Impl getCurrentOffset() {
- verifyBuilding();
- return currentOffset;
- }
-
- public Vec3Impl addOffset(Vec3Impl offset) {
- verifyBuilding();
- return setCurrentOffset(currentOffset.add(offset));
- }
- }
-
- public <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 != MultiBlockController.this) return false;
-
- part.setTarget(MultiBlockController.this, modes);
-
- registerSpecialCasings(part);
- return true;
- }
-
- @Override
- public boolean spawnHint(S t, World world, int x, int y, int z, ItemStack trigger) {
- if (mIcons == null) {
- mIcons = new IIcon[6];
- Arrays.fill(mIcons, TextureSet.SET_NONE.mTextures[OrePrefixes.block.mTextureIndex].getIcon());
- // Arrays.fill(mIcons, getTexture(aCasing);
- // for (byte i : ALL_VALID_SIDES) {
- // mIcons[i] = aCasing.getIcon(i, aMeta);
- // }
- }
- final short[] RGBA = DEFAULT;
- StructureLibAPI.hintParticleTinted(world, x, y, z, mIcons, RGBA);
- // StructureLibAPI.hintParticle(world, x, y, z, aCasing, aMeta);
- return true;
- }
-
- @Override
- public boolean placeBlock(S t, World world, int x, int y, int z, ItemStack trigger) {
- final MultiTileEntityRegistry tRegistry = MultiTileEntityRegistry.getRegistry(registryID);
- final MultiTileEntityContainer tContainer = tRegistry
- .getNewTileEntityContainer(world, x, y, z, meta, null);
- if (tContainer == null) {
- GT_FML_LOGGER.error("NULL CONTAINER");
- return false;
- }
- final IMultiTileEntity te = ((IMultiTileEntity) tContainer.mTileEntity);
- if (!(te instanceof MultiBlockPart)) {
- GT_FML_LOGGER.error("Not a multiblock part");
- return false;
- }
- if (world.setBlock(x, y, z, tContainer.mBlock, 15 - tContainer.mBlockMetaData, 2)) {
- tContainer.setMultiTile(world, x, y, z);
- ((MultiBlockPart) te).setTarget(MultiBlockController.this, modes);
-
- registerSpecialCasings((MultiBlockPart) te);
- }
-
- return false;
- }
-
- public IIcon getTexture(OrePrefixes aBlock) {
- return TextureSet.SET_NONE.mTextures[OrePrefixes.block.mTextureIndex].getIcon();
- }
- };
- }
-
- protected void registerSpecialCasings(MultiBlockPart part) {
- if (part instanceof UpgradeCasing) {
- upgradeCasings.add((UpgradeCasing) part);
- }
- if (part instanceof FunctionalCasing) {
- functionalCasings.add((FunctionalCasing) part);
- }
- }
-
- /**
- * Fluid - MultiBlock related Fluid Tank behaviour.
- */
- protected IFluidTank getFluidTankFillable(MultiBlockPart aPart, byte aSide, FluidStack aFluidToFill) {
- return getFluidTankFillable(aSide, aFluidToFill);
- }
-
- protected IFluidTank getFluidTankDrainable(MultiBlockPart aPart, byte aSide, FluidStack aFluidToDrain) {
- return getFluidTankDrainable(aSide, aFluidToDrain);
- }
-
- protected IFluidTank[] getFluidTanks(MultiBlockPart aPart, byte aSide) {
- return getFluidTanks(aSide);
- }
-
- @Override
- public int fill(MultiBlockPart aPart, ForgeDirection aDirection, FluidStack aFluid, boolean aDoFill) {
- if (aFluid == null || aFluid.amount <= 0) return 0;
- final IFluidTank tTank = getFluidTankFillable(aPart, (byte) aDirection.ordinal(), aFluid);
- if (tTank == null) return 0;
- final int rFilledAmount = tTank.fill(aFluid, aDoFill);
- if (rFilledAmount > 0 && aDoFill) hasInventoryChanged = true;
- return rFilledAmount;
- }
-
- @Override
- public FluidStack drain(MultiBlockPart aPart, ForgeDirection aDirection, FluidStack aFluid, boolean aDoDrain) {
- if (aFluid == null || aFluid.amount <= 0) return null;
- final IFluidTank tTank = getFluidTankDrainable(aPart, (byte) aDirection.ordinal(), aFluid);
- if (tTank == null || tTank.getFluid() == null
- || tTank.getFluidAmount() == 0
- || !tTank.getFluid()
- .isFluidEqual(aFluid))
- return null;
- final FluidStack rDrained = tTank.drain(aFluid.amount, aDoDrain);
- if (rDrained != null && aDoDrain) markInventoryBeenModified();
- return rDrained;
- }
-
- @Override
- public FluidStack drain(MultiBlockPart aPart, ForgeDirection aDirection, int aAmountToDrain, boolean aDoDrain) {
- if (aAmountToDrain <= 0) return null;
- final IFluidTank tTank = getFluidTankDrainable(aPart, (byte) aDirection.ordinal(), null);
- if (tTank == null || tTank.getFluid() == null || tTank.getFluidAmount() == 0) return null;
- final FluidStack rDrained = tTank.drain(aAmountToDrain, aDoDrain);
- if (rDrained != null && aDoDrain) markInventoryBeenModified();
- return rDrained;
- }
-
- @Override
- public boolean canFill(MultiBlockPart aPart, ForgeDirection aDirection, Fluid aFluid) {
- if (aFluid == null) return false;
- final IFluidTank tTank = getFluidTankFillable(aPart, (byte) aDirection.ordinal(), new FluidStack(aFluid, 0));
- return tTank != null && (tTank.getFluid() == null || tTank.getFluid()
- .getFluid() == aFluid);
- }
-
- @Override
- public boolean canDrain(MultiBlockPart aPart, ForgeDirection aDirection, Fluid aFluid) {
- if (aFluid == null) return false;
- final IFluidTank tTank = getFluidTankDrainable(aPart, (byte) aDirection.ordinal(), new FluidStack(aFluid, 0));
- return tTank != null && (tTank.getFluid() != null && tTank.getFluid()
- .getFluid() == aFluid);
- }
-
- @Override
- public FluidTankInfo[] getTankInfo(MultiBlockPart aPart, ForgeDirection aDirection) {
- final IFluidTank[] tTanks = getFluidTanks(aPart, (byte) aDirection.ordinal());
- if (tTanks == null || tTanks.length <= 0) return GT_Values.emptyFluidTankInfo;
- final FluidTankInfo[] rInfo = new FluidTankInfo[tTanks.length];
- for (int i = 0; i < tTanks.length; i++) rInfo[i] = new FluidTankInfo(tTanks[i]);
- return rInfo;
- }
-
- @Override
- public IFluidTank[] getFluidTanksForGUI(MultiBlockPart aPart) {
- if (aPart.modeSelected(MultiBlockPart.FLUID_IN)) return inputTanks;
- if (aPart.modeSelected(MultiBlockPart.FLUID_OUT)) return outputTanks;
- return GT_Values.emptyFluidTank;
- }
-
- // #region Energy
- @Override
- public PowerLogic getPowerLogic(IMultiBlockPart part, byte side) {
- if (!(this instanceof PowerLogicHost)) {
- return null;
- }
-
- if (part.getFrontFacing() != side) {
- return null;
- }
-
- return ((PowerLogicHost) this).getPowerLogic(side);
- }
- // #endregion Energy
-
- /**
- * Item - MultiBlock related Item behaviour.
- */
- @Override
- public void registerInventory(String aName, String aID, int aInventorySize, int aType) {
- if (aType == InventoryUpgrade.INPUT || aType == InventoryUpgrade.BOTH) {
- if (multiBlockInputInventory.containsKey(aID)) return;
- multiBlockInputInventory.put(aID, new ItemStackHandler(aInventorySize));
- multiBlockInputInventoryNames.put(aID, aName);
- }
- if (aType == InventoryUpgrade.OUTPUT || aType == InventoryUpgrade.BOTH) {
- if (multiBlockOutputInventory.containsKey(aID)) return;
- multiBlockOutputInventory.put(aID, new ItemStackHandler(aInventorySize));
- multiBlockOutputInventoryNames.put(aID, aName);
- }
- }
-
- @Override
- public void unregisterInventory(String aName, String aID, int aType) {
- if ((aType == InventoryUpgrade.INPUT || aType == InventoryUpgrade.BOTH)
- && multiBlockInputInventory.containsKey(aID)) {
- multiBlockInputInventory.remove(aID, multiBlockInputInventory.get(aID));
- multiBlockInputInventoryNames.remove(aID, aName);
- }
- if ((aType == InventoryUpgrade.OUTPUT || aType == InventoryUpgrade.BOTH)
- && multiBlockOutputInventory.containsKey(aID)) {
- multiBlockOutputInventory.remove(aID, multiBlockOutputInventory.get(aID));
- multiBlockOutputInventoryNames.remove(aID, aName);
- }
- }
-
- @Override
- public void changeInventoryName(String aName, String aID, int aType) {
- if ((aType == InventoryUpgrade.INPUT || aType == InventoryUpgrade.BOTH)
- && multiBlockInputInventoryNames.containsKey(aID)) {
- multiBlockInputInventoryNames.put(aID, aName);
- }
- if ((aType == InventoryUpgrade.OUTPUT || aType == InventoryUpgrade.BOTH)
- && multiBlockOutputInventoryNames.containsKey(aID)) {
- multiBlockOutputInventoryNames.put(aID, aName);
- }
- }
-
- @Override
- public boolean hasInventoryBeenModified(MultiBlockPart aPart) {
- if (aPart.modeSelected(MultiBlockPart.ITEM_IN)) return hasInventoryBeenModified();
- else if (aPart.modeSelected(MultiBlockPart.ITEM_OUT)) return hasOutputInventoryBeenModified();
-
- return false;
- }
-
- @Override
- public boolean isValidSlot(MultiBlockPart aPart, int aIndex) {
- return false;
- }
-
- @Override
- public IItemHandlerModifiable getInventoryForGUI(MultiBlockPart aPart) {
- if (isServerSide()) {
- for (UpgradeCasing tPart : upgradeCasings) {
- if (!(tPart instanceof InventoryUpgrade)) continue;
- tPart.issueClientUpdate();
- }
- }
- final Map<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 != null ? inv : null;
- }
- }
-
- @Override
- public boolean addStackToSlot(MultiBlockPart aPart, int aIndex, ItemStack aStack) {
- return false;
- }
-
- @Override
- public boolean addStackToSlot(MultiBlockPart aPart, int aIndex, ItemStack aStack, int aAmount) {
- return false;
- }
-
- protected Map<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);
- }
- start += inv.getSlots();
- }
- return null;
- }
-
- @Override
- public int[] getAccessibleSlotsFromSide(MultiBlockPart aPart, byte aSide) {
- 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);
- }
- return tList.toArray();
- }
-
- @Override
- public boolean canInsertItem(MultiBlockPart aPart, int aSlot, ItemStack aStack, byte aSide) {
- 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)
- }
-
- @Override
- public boolean canExtractItem(MultiBlockPart aPart, int aSlot, ItemStack aStack, byte aSide) {
- 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);
- }
-
- @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;
- }
- }
-
- @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);
- }
-
- @Override
- public ItemStack decrStackSize(MultiBlockPart aPart, int aSlot, int aDecrement) {
- final ItemStack tStack = getStackInSlot(aPart, aSlot);
- ItemStack rStack = GT_Utility.copyOrNull(tStack);
- if (tStack != null) {
- if (tStack.stackSize <= aDecrement) {
- setInventorySlotContents(aPart, aSlot, null);
- } else {
- rStack = tStack.splitStack(aDecrement);
- if (tStack.stackSize == 0) setInventorySlotContents(aPart, aSlot, null);
- }
- }
- return rStack;
- }
-
- @Override
- public ItemStack getStackInSlotOnClosing(MultiBlockPart aPart, int aSlot) {
- final Pair<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");
- inventoryNames.add("controller");
- inventoryNames.addAll(getMultiBlockInventoryNames(aPart).values());
- return inventoryNames;
- }
-
- @Override
- public List<String> getInventoryIDs(MultiBlockPart aPart) {
- final List<String> tInventoryIDs = new ArrayList<>();
- tInventoryIDs.add("all");
- tInventoryIDs.addAll(getMultiBlockInventory(aPart).keySet());
- return tInventoryIDs;
- }
-
- @Override
- public String getInventoryName(MultiBlockPart aPart) {
- final StringBuilder str = new StringBuilder();
- str.append(getInventoryName());
- if (aPart.modeSelected(MultiBlockPart.ITEM_IN)) {
- str.append(" Input");
- } else if (aPart.modeSelected(MultiBlockPart.ITEM_OUT)) {
- str.append(" Output");
- String a;
- } else {
- str.append(" Unknown");
- }
- final String lockedInventory = aPart.getLockedInventory();
- if (lockedInventory != null && !lockedInventory.equals("")) {
- str.append(" [Locked: ")
- .append(lockedInventory)
- .append("]");
- }
-
- return str.toString();
- }
-
- @Override
- public boolean hasCustomInventoryName(MultiBlockPart aPart) {
- return hasCustomInventoryName();
- }
-
- @Override
- public int getInventoryStackLimit(MultiBlockPart aPart) {
- return getInventoryStackLimit();
- }
-
- @Override
- public void markDirty(MultiBlockPart aPart) {
- markDirty();
- if (aPart.modeSelected(MultiBlockPart.ITEM_OUT)) markOutputInventoryBeenModified();
- else markInventoryBeenModified();
- }
-
- @Override
- public boolean isUseableByPlayer(MultiBlockPart aPart, EntityPlayer aPlayer) {
- return isUseableByPlayer(aPlayer);
- }
-
- @Override
- public void openInventory(MultiBlockPart aPart) {
- // TODO: MultiInventory - consider the part's inventory
- openInventory();
- }
-
- @Override
- public void closeInventory(MultiBlockPart aPart) {
- // TODO: MultiInventory - consider the part's inventory
- closeInventory();
- }
-
- @Override
- public boolean isItemValidForSlot(MultiBlockPart aPart, int aSlot, ItemStack aStack) {
- return isItemValidForSlot(aSlot, aStack);
- }
-
- /*
- * Helper Methods For Recipe checking
- */
-
- protected ItemStack[] getAllItemInputs() {
- return getInventoriesForInput().getStacks()
- .toArray(new ItemStack[0]);
- }
-
- protected ItemStack[] getAllOutputItems() {
- return getInventoriesForOutput().getStacks()
- .toArray(new ItemStack[0]);
- }
-
- protected Iterable<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 void setItemOutputs(String inventory, ItemStack... itemOutputs) {
- itemsToOutput = itemOutputs;
- inventoryName = inventory;
- }
-
- @Override
- protected void setItemOutputs(ItemStack... outputs) {
- super.setItemOutputs(outputs);
- inventoryName = null;
- }
-
- @Override
- protected void outputItems() {
- if (itemsToOutput == null) {
- return;
- }
-
- IItemHandlerModifiable inv;
- if (inventoryName != null) {
- inv = multiBlockOutputInventory.getOrDefault(inventoryName, getInventoriesForOutput());
- } else {
- inv = getInventoriesForOutput();
- }
- for (ItemStack item : itemsToOutput) {
- int index = 0;
- while (item != null && item.stackSize > 0 && index < inv.getSlots()) {
- item = inv.insertItem(index++, item.copy(), false);
- }
- }
- itemsToOutput = null;
- }
-
- protected void setFluidOutputs(String tank, FluidStack... fluidOuputs) {
- fluidsToOutput = fluidOuputs;
- tankName = tank;
- }
-
- @Override
- protected void setFluidOutputs(FluidStack... outputs) {
- super.setFluidOutputs(outputs);
- tankName = null;
- }
-
- @Override
- protected void outputFluids() {
- if (fluidsToOutput == null) {
- return;
- }
-
- List<FluidTankGT> tanks = new ArrayList<>(multiBlockOutputTank.values());
- for (FluidStack fluid : fluidsToOutput) {
- int index = 0;
- while (fluid != null && fluid.amount > 0 && index < tanks.size()) {
- int filled = tanks.get(index++)
- .fill(fluid, true);
- fluid.amount -= filled;
- }
- }
- }
-
- @Override
- protected void updateSlots() {
- IItemHandlerModifiable inv = getInventoriesForInput();
- for (int i = 0; i < inv.getSlots(); i++) {
- if (inv.getStackInSlot(i).stackSize <= 0) {
- inv.setStackInSlot(i, null);
- }
- }
- }
-
- @Override
- protected boolean checkRecipe() {
- if (!(this instanceof ProcessingLogicHost)) {
- return false;
- }
- ProcessingLogic logic = ((ProcessingLogicHost) this).getProcessingLogic();
- logic.clear();
- boolean result = false;
- if (isSeparateInputs()) {
- for (Pair<ItemStack[], String> inventory : getItemInputsForEachInventory()) {
- IItemHandlerModifiable outputInventory = multiBlockOutputInventory
- .getOrDefault(inventory.getLeft(), null);
- result = logic.setInputItems(inventory.getLeft())
- .setCurrentOutputItems(
- outputInventory != null ? outputInventory.getStacks()
- .toArray(new ItemStack[0]) : null)
- .process();
- if (result) {
- inventoryName = inventory.getRight();
- break;
- }
- logic.clear();
- }
- } else {
- result = logic.setInputItems(getAllItemInputs())
- .setCurrentOutputItems(getAllOutputItems())
- .process();
- }
- setDuration(logic.getDuration());
- setEut(logic.getEut());
- setItemOutputs(logic.getOutputItems());
- setFluidOutputs(logic.getOutputFluids());
- return result;
- }
-
- /*
- * GUI Work - Multiblock GUI related methods
- */
- @Override
- public boolean useModularUI() {
- return true;
- }
-
- @Override
- public ModularWindow createWindow(UIBuildContext buildContext) {
- System.out.println("MultiBlockController::createWindow");
- if (!useModularUI()) return null;
-
- buildContext.setValidator(getValidator());
- final ModularWindow.Builder builder = ModularWindow.builder(getGUIWidth(), getGUIHeight());
- builder.setBackground(getGUITextureSet().getMainBackground());
- builder.setGuiTint(getGUIColorization());
- if (doesBindPlayerInventory()) {
- bindPlayerInventoryUI(builder, buildContext);
- }
- addUIWidgets(builder, buildContext);
- addTitleToUI(builder);
- addCoverTabs(builder, buildContext);
- return builder.build();
- }
-
- @Override
- public boolean hasGui(byte aSide) {
- return true;
- }
-
- @Override
- protected void addTitleTextStyle(ModularWindow.Builder builder, String title) {
- // leave empty
- }
-
- @Override
- public int getGUIHeight() {
- return 192;
- }
-
- protected Widget getGregTechLogo() {
- return new DrawableWidget().setDrawable(getGUITextureSet().getGregTechLogo())
- .setSize(17, 17);
- }
-
- @Override
- public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
- if (isServerSide()) {
- for (UpgradeCasing tPart : upgradeCasings) {
- if (!(tPart instanceof InventoryUpgrade)) continue;
- tPart.issueClientUpdate();
- }
- }
- int page = 0;
- TabContainer tabs = new TabContainer().setButtonSize(20, 24);
- tabs.addTabButton(
- new TabButton(page++)
- .setBackground(
- false,
- ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0, 1f, 0.5f),
- new ItemDrawable(getStackForm(1)).withFixedSize(16, 16)
- .withOffset(2, 4))
- .setBackground(
- true,
- ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0.5f, 1f, 1f),
- new ItemDrawable(getStackForm(1)).withFixedSize(16, 16)
- .withOffset(2, 4))
- .addTooltip(getLocalName())
- .setPos(20 * (page - 1), -20))
- .addPage(createMainPage().setSize(getGUIWidth(), getGUIHeight()));
- if (hasItemInput()) {
- tabs.addTabButton(
- new TabButton(page++)
- .setBackground(
- false,
- ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0, 1f, 0.5f),
- GT_UITextures.PICTURE_ITEM_IN.withFixedSize(16, 16)
- .withOffset(2, 4))
- .setBackground(
- true,
- ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0.5f, 1f, 1f),
- GT_UITextures.PICTURE_ITEM_IN.withFixedSize(16, 16)
- .withOffset(2, 4))
- .setPos(20 * (page - 1), -20))
- .addPage(
- new MultiChildWidget().addChild(getItemInventoryInputGUI())
- .addChild(getGregTechLogo().setPos(147, 86))
- .setSize(getGUIWidth(), getGUIHeight()));
- }
-
- if (hasItemOutput()) {
- tabs.addTabButton(
- new TabButton(page++)
- .setBackground(
- false,
- ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0, 1f, 0.5f),
- GT_UITextures.PICTURE_ITEM_OUT.withFixedSize(16, 16)
- .withOffset(2, 4))
- .setBackground(
- true,
- ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0.5f, 1f, 1f),
- GT_UITextures.PICTURE_ITEM_OUT.withFixedSize(16, 16)
- .withOffset(2, 4))
- .setPos(20 * (page - 1), -20))
- .addPage(
- new MultiChildWidget().addChild(getItemInventoryOutputGUI())
- .addChild(getGregTechLogo().setPos(147, 86))
- .setSize(getGUIWidth(), getGUIHeight()));
- }
-
- if (hasFluidInput()) {
- tabs.addTabButton(
- new TabButton(page++)
- .setBackground(
- false,
- ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0, 1f, 0.5f),
- GT_UITextures.PICTURE_FLUID_IN.withFixedSize(16, 16)
- .withOffset(2, 4))
- .setBackground(
- true,
- ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0.5f, 1f, 1f),
- GT_UITextures.PICTURE_FLUID_IN.withFixedSize(16, 16)
- .withOffset(2, 4))
- .setPos(20 * (page - 1), -20))
- .addPage(
- new MultiChildWidget().addChild(getFluidInventoryInputGUI())
- .addChild(getGregTechLogo().setPos(147, 86))
- .setSize(getGUIWidth(), getGUIHeight()));
- }
-
- if (hasFluidOutput()) {
- tabs.addTabButton(
- new TabButton(page++)
- .setBackground(
- false,
- ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0, 1f, 0.5f),
- GT_UITextures.PICTURE_FLUID_OUT.withFixedSize(16, 16)
- .withOffset(2, 4))
- .setBackground(
- true,
- ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0.5f, 1f, 1f),
- GT_UITextures.PICTURE_FLUID_OUT.withFixedSize(16, 16)
- .withOffset(2, 4))
- .setPos(20 * (page - 1), -20))
- .addPage(
- new MultiChildWidget().addChild(getFluidInventoryOutputGUI())
- .addChild(getGregTechLogo().setPos(147, 86))
- .setSize(getGUIWidth(), getGUIHeight()));
- }
- builder.widget(tabs);
- }
-
- protected MultiChildWidget createMainPage() {
- MultiChildWidget page = new MultiChildWidget();
- page.addChild(
- new DrawableWidget().setDrawable(GT_UITextures.PICTURE_SCREEN_BLACK)
- .setPos(7, 4)
- .setSize(160, 75))
- .addChild(createButtons());
- return page;
- }
-
- protected MultiChildWidget createButtons() {
- MultiChildWidget buttons = new MultiChildWidget();
- buttons.setSize(16, 167)
- .setPos(7, 86);
- buttons.addChild(createPowerSwitchButton())
- .addChild(new FakeSyncWidget.BooleanSyncer(this::isAllowedToWork, val -> {
- if (val) enableWorking();
- else disableWorking();
- }))
- .addChild(createVoidExcessButton())
- .addChild(new FakeSyncWidget.BooleanSyncer(() -> voidExcess, val -> voidExcess = val))
- .addChild(createInputSeparationButton())
- .addChild(new FakeSyncWidget.BooleanSyncer(() -> separateInputs, val -> separateInputs = val))
- .addChild(createBatchModeButton())
- .addChild(new FakeSyncWidget.BooleanSyncer(() -> batchMode, val -> batchMode = val))
- .addChild(createLockToSingleRecipeButton())
- .addChild(new FakeSyncWidget.BooleanSyncer(() -> recipeLock, val -> recipeLock = val));
-
- return buttons;
- }
-
- protected Widget getItemInventoryInputGUI() {
- final IItemHandlerModifiable inv = getInventoriesForInput();
- final Scrollable scrollable = new Scrollable().setVerticalScroll();
- for (int rows = 0; rows * 4 < Math.min(inv.getSlots(), 128); rows++) {
- final int columnsToMake = Math.min(Math.min(inv.getSlots(), 128) - rows * 4, 4);
- for (int column = 0; column < columnsToMake; column++) {
- scrollable.widget(
- new SlotWidget(inv, rows * 4 + column).setPos(column * 18, rows * 18)
- .setSize(18, 18));
- }
- }
- return scrollable.setSize(18 * 4 + 4, 18 * 5)
- .setPos(52, 7);
- }
-
- protected Widget getItemInventoryOutputGUI() {
- final IItemHandlerModifiable inv = getInventoriesForOutput();
- final Scrollable scrollable = new Scrollable().setVerticalScroll();
- for (int rows = 0; rows * 4 < Math.min(inv.getSlots(), 128); rows++) {
- final int columnsToMake = Math.min(Math.min(inv.getSlots(), 128) - rows * 4, 4);
- for (int column = 0; column < columnsToMake; column++) {
- scrollable.widget(
- new SlotWidget(inv, rows * 4 + column).setPos(column * 18, rows * 18)
- .setSize(18, 18));
- }
- }
- return scrollable.setSize(18 * 4 + 4, 18 * 5)
- .setPos(52, 7);
- }
-
- protected IItemHandlerModifiable getInventoriesForInput() {
- return new ListItemHandler(multiBlockInputInventory.values());
- }
-
- protected IItemHandlerModifiable getInventoriesForOutput() {
- return new ListItemHandler(multiBlockOutputInventory.values());
- }
-
- protected Widget getFluidInventoryInputGUI() {
- final IFluidTank[] tanks = inputTanks;
- final Scrollable scrollable = new Scrollable().setVerticalScroll();
- for (int rows = 0; rows * 4 < tanks.length; rows++) {
- final int columnsToMake = Math.min(tanks.length - rows * 4, 4);
- for (int column = 0; column < columnsToMake; column++) {
- final FluidSlotWidget fluidSlot = new FluidSlotWidget(tanks[rows * 4 + column]);
- scrollable.widget(
- fluidSlot.setPos(column * 18, rows * 18)
- .setSize(18, 18));
- }
- }
- return scrollable.setSize(18 * 4 + 4, 18 * 4)
- .setPos(52, 7);
- }
-
- protected Widget getFluidInventoryOutputGUI() {
- final IFluidTank[] tanks = outputTanks;
- final Scrollable scrollable = new Scrollable().setVerticalScroll();
- for (int rows = 0; rows * 4 < tanks.length; rows++) {
- final int columnsToMake = Math.min(tanks.length - rows * 4, 4);
- for (int column = 0; column < columnsToMake; column++) {
- final FluidSlotWidget fluidSlot = new FluidSlotWidget(tanks[rows * 4 + column]);
- fluidSlot.setInteraction(true, false);
- scrollable.widget(
- fluidSlot.setPos(column * 18, rows * 18)
- .setSize(18, 18));
- }
- }
- return scrollable.setSize(18 * 4 + 4, 18 * 5)
- .setPos(52, 7);
- }
-
- protected ButtonWidget createPowerSwitchButton() {
- ButtonWidget button = new ButtonWidget().setOnClick((clickData, widget) -> {
- if (isAllowedToWork()) {
- disableWorking();
- } else {
- enableWorking();
- }
- })
- .setPlayClickSoundResource(
- () -> isAllowedToWork() ? SoundResource.GUI_BUTTON_UP.resourceLocation
- : SoundResource.GUI_BUTTON_DOWN.resourceLocation);
- button.setBackground(() -> {
- List<UITexture> ret = new ArrayList<>();
- ret.add(GT_UITextures.BUTTON_STANDARD);
- if (isAllowedToWork()) {
- ret.add(GT_UITextures.OVERLAY_BUTTON_POWER_SWITCH_ON);
- } else {
- ret.add(GT_UITextures.OVERLAY_BUTTON_POWER_SWITCH_OFF);
- }
- return ret.toArray(new IDrawable[0]);
- })
- .setPos(144, 0)
- .setSize(16, 16);
- button.addTooltip(StatCollector.translateToLocal("GT5U.gui.button.power_switch"))
- .setTooltipShowUpDelay(TOOLTIP_DELAY);
- return button;
- }
-
- protected ButtonWidget createVoidExcessButton() {
- ButtonWidget button = new ButtonWidget().setOnClick((clickData, widget) -> {
- if (isVoidExcessButtonEnabled()) {
- voidExcess = !voidExcess;
- }
- })
- .setPlayClickSound(true);
- button.setBackground(() -> {
- List<UITexture> ret = new ArrayList<>();
- ret.add(GT_UITextures.BUTTON_STANDARD);
- if (isVoidExcessButtonEnabled()) {
- if (isVoidExcessEnabled()) {
- ret.add(GT_UITextures.OVERLAY_BUTTON_VOID_EXCESS_ON);
- } else {
- ret.add(GT_UITextures.OVERLAY_BUTTON_VOID_EXCESS_OFF);
- }
- } else {
- if (isVoidExcessEnabled()) {
- ret.add(GT_UITextures.OVERLAY_BUTTON_VOID_EXCESS_ON_DISABLED);
- } else {
- ret.add(GT_UITextures.OVERLAY_BUTTON_VOID_EXCESS_OFF_DISABLED);
- }
- }
- return ret.toArray(new IDrawable[0]);
- })
- .setPos(54, 0)
- .setSize(16, 16);
- button.addTooltip(StatCollector.translateToLocal("GT5U.gui.button.void_excess"))
- .setTooltipShowUpDelay(TOOLTIP_DELAY);
- return button;
- }
-
- protected boolean isVoidExcessEnabled() {
- return voidExcess;
- }
-
- protected boolean isVoidExcessButtonEnabled() {
- return true;
- }
-
- protected ButtonWidget createInputSeparationButton() {
- Widget button = new ButtonWidget().setOnClick((clickData, widget) -> {
- if (isInputSeparationButtonEnabled()) {
- separateInputs = !separateInputs;
- }
- })
- .setPlayClickSound(true)
- .setBackground(() -> {
- List<UITexture> ret = new ArrayList<>();
- ret.add(GT_UITextures.BUTTON_STANDARD);
- if (isInputSeparationButtonEnabled()) {
- if (isInputSeparationEnabled()) {
- ret.add(GT_UITextures.OVERLAY_BUTTON_INPUT_SEPARATION_ON);
- } else {
- ret.add(GT_UITextures.OVERLAY_BUTTON_INPUT_SEPARATION_OFF);
- }
- } else {
- if (isInputSeparationEnabled()) {
- ret.add(GT_UITextures.OVERLAY_BUTTON_INPUT_SEPARATION_ON_DISABLED);
- } else {
- ret.add(GT_UITextures.OVERLAY_BUTTON_INPUT_SEPARATION_OFF_DISABLED);
- }
- }
- return ret.toArray(new IDrawable[0]);
- })
- .setPos(36, 0)
- .setSize(16, 16);
- button.addTooltip(StatCollector.translateToLocal("GT5U.gui.button.input_separation"))
- .setTooltipShowUpDelay(TOOLTIP_DELAY);
- return (ButtonWidget) button;
- }
-
- protected boolean isInputSeparationEnabled() {
- return separateInputs;
- }
-
- protected boolean isInputSeparationButtonEnabled() {
- return true;
- }
-
- protected ButtonWidget createBatchModeButton() {
- Widget button = new ButtonWidget().setOnClick((clickData, widget) -> {
- if (isBatchModeButtonEnabled()) {
- batchMode = !batchMode;
- }
- })
- .setPlayClickSound(true)
- .setBackground(() -> {
- List<UITexture> ret = new ArrayList<>();
- ret.add(GT_UITextures.BUTTON_STANDARD);
- if (isBatchModeButtonEnabled()) {
- if (isBatchModeEnabled()) {
- ret.add(GT_UITextures.OVERLAY_BUTTON_BATCH_MODE_ON);
- } else {
- ret.add(GT_UITextures.OVERLAY_BUTTON_BATCH_MODE_OFF);
- }
- } else {
- if (isBatchModeEnabled()) {
- ret.add(GT_UITextures.OVERLAY_BUTTON_BATCH_MODE_ON_DISABLED);
- } else {
- ret.add(GT_UITextures.OVERLAY_BUTTON_BATCH_MODE_OFF_DISABLED);
- }
- }
- return ret.toArray(new IDrawable[0]);
- })
- .setPos(18, 0)
- .setSize(16, 16);
- button.addTooltip(StatCollector.translateToLocal("GT5U.gui.button.batch_mode"))
- .setTooltipShowUpDelay(TOOLTIP_DELAY);
- return (ButtonWidget) button;
- }
-
- protected boolean isBatchModeButtonEnabled() {
- return true;
- }
-
- protected boolean isBatchModeEnabled() {
- return batchMode;
- }
-
- protected ButtonWidget createLockToSingleRecipeButton() {
- Widget button = new ButtonWidget().setOnClick((clickData, widget) -> {
- if (supportsSingleRecipeLocking()) {
- recipeLock = !recipeLock;
- }
- })
- .setPlayClickSound(true)
- .setBackground(() -> {
- List<UITexture> ret = new ArrayList<>();
- ret.add(GT_UITextures.BUTTON_STANDARD);
- if (supportsSingleRecipeLocking()) {
- if (isRecipeLockingEnabled()) {
- ret.add(GT_UITextures.OVERLAY_BUTTON_RECIPE_LOCKED);
- } else {
- ret.add(GT_UITextures.OVERLAY_BUTTON_RECIPE_UNLOCKED);
- }
- } else {
- if (isRecipeLockingEnabled()) {
- ret.add(GT_UITextures.OVERLAY_BUTTON_RECIPE_LOCKED_DISABLED);
- } else {
- ret.add(GT_UITextures.OVERLAY_BUTTON_RECIPE_UNLOCKED_DISABLED);
- }
- }
- return ret.toArray(new IDrawable[0]);
- })
- .setPos(0, 0)
- .setSize(16, 16);
- button.addTooltip(StatCollector.translateToLocal("GT5U.gui.button.lock_recipe"))
- .setTooltipShowUpDelay(TOOLTIP_DELAY);
- return (ButtonWidget) button;
- }
-
- protected boolean supportsSingleRecipeLocking() {
- return false;
- }
-
- protected boolean isRecipeLockingEnabled() {
- return recipeLock;
- }
-}